blob: e08fe12adfc5b5ca938f8286ff2409ad2665cc9b [file] [log] [blame]
Andrew M. Kuchling2158df02001-10-22 15:26:09 +00001#
2# Test script for the curses module
3#
4# This script doesn't actually display anything very coherent. but it
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +03005# does call (nearly) every method and function.
Andrew M. Kuchling2158df02001-10-22 15:26:09 +00006#
7# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr(),
Neal Norwitz88bbd732006-01-10 07:05:44 +00008# init_color()
9# Only called, not tested: getmouse(), ungetmouse()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000010#
11
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030012import os
Serhiy Storchaka41833872016-06-18 22:08:49 +030013import string
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030014import sys
15import tempfile
16import unittest
17
18from test.test_support import requires, import_module, verbose, run_unittest
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000019
20# Optionally test curses module. This currently requires that the
21# 'curses' resource be given on the regrtest command line using the -u
22# option. If not available, nothing after this line will be executed.
Neal Norwitz9f39f682006-01-06 04:18:21 +000023requires('curses')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030024
25# If either of these don't exist, skip the tests.
R. David Murray3db8a342009-03-30 23:05:48 +000026curses = import_module('curses')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030027import_module('curses.panel')
28import_module('curses.ascii')
Neal Norwitz9f39f682006-01-06 04:18:21 +000029
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030030def requires_curses_func(name):
31 return unittest.skipUnless(hasattr(curses, name),
32 'requires curses.%s' % name)
Mark Dickinson45ad8012010-02-21 13:37:53 +000033
Neal Norwitz9f39f682006-01-06 04:18:21 +000034term = os.environ.get('TERM')
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000035
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030036# If newterm was supported we could use it instead of initscr and not exit
37@unittest.skipIf(not term or term == 'unknown',
38 "$TERM=%r, calling initscr() may cause exit" % term)
39@unittest.skipIf(sys.platform == "cygwin",
40 "cygwin's curses mostly just hangs")
41class TestCurses(unittest.TestCase):
Anthony Baxter76801852006-04-04 13:32:08 +000042
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030043 @classmethod
44 def setUpClass(cls):
45 if not sys.__stdout__.isatty():
46 # Temporary skip tests on non-tty
47 raise unittest.SkipTest('sys.__stdout__ is not a tty')
48 cls.tmp = tempfile.TemporaryFile()
49 fd = cls.tmp.fileno()
50 else:
51 cls.tmp = None
52 fd = sys.__stdout__.fileno()
53 # testing setupterm() inside initscr/endwin
54 # causes terminal breakage
55 curses.setupterm(fd=fd)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000056
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030057 @classmethod
58 def tearDownClass(cls):
59 if cls.tmp:
60 cls.tmp.close()
61 del cls.tmp
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000062
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030063 def setUp(self):
64 if verbose:
65 # just to make the test output a little more readable
66 print()
67 self.stdscr = curses.initscr()
68 curses.savetty()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000069
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030070 def tearDown(self):
71 curses.resetty()
72 curses.endwin()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000073
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030074 def test_window_funcs(self):
75 "Test the methods of windows"
76 stdscr = self.stdscr
77 win = curses.newwin(10,10)
78 win = curses.newwin(5,5, 5,5)
79 win2 = curses.newwin(15,15, 5,5)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000080
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030081 for meth in [stdscr.addch, stdscr.addstr]:
82 for args in [('a'), ('a', curses.A_BOLD),
83 (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
84 meth(*args)
85
86 for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
87 stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
88 stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
89 stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
90 stdscr.getparyx, stdscr.getyx, stdscr.inch,
91 stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
92 win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
93 stdscr.standout, stdscr.standend, stdscr.syncdown,
94 stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
95 meth()
96
97 stdscr.addnstr('1234', 3)
98 stdscr.addnstr('1234', 3, curses.A_BOLD)
99 stdscr.addnstr(4,4, '1234', 3)
100 stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
101
102 stdscr.attron(curses.A_BOLD)
103 stdscr.attroff(curses.A_BOLD)
104 stdscr.attrset(curses.A_BOLD)
105 stdscr.bkgd(' ')
106 stdscr.bkgd(' ', curses.A_REVERSE)
107 stdscr.bkgdset(' ')
108 stdscr.bkgdset(' ', curses.A_REVERSE)
109
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000110 win.border(65, 66, 67, 68,
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300111 69, 70, 71, 72)
112 win.border('|', '!', '-', '_',
113 '+', '\\', '#', '/')
114 with self.assertRaises(TypeError,
115 msg="Expected win.border() to raise TypeError"):
116 win.border(65, 66, 67, 68,
117 69, [], 71, 72)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000118
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300119 stdscr.clearok(1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000120
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300121 win4 = stdscr.derwin(2,2)
122 win4 = stdscr.derwin(1,1, 5,5)
123 win4.mvderwin(9,9)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000124
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300125 stdscr.echochar('a')
126 stdscr.echochar('a', curses.A_BOLD)
127 stdscr.hline('-', 5)
128 stdscr.hline('-', 5, curses.A_BOLD)
129 stdscr.hline(1,1,'-', 5)
130 stdscr.hline(1,1,'-', 5, curses.A_BOLD)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000131
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300132 stdscr.idcok(1)
133 stdscr.idlok(1)
134 stdscr.immedok(1)
135 stdscr.insch('c')
136 stdscr.insdelln(1)
137 stdscr.insnstr('abc', 3)
138 stdscr.insnstr('abc', 3, curses.A_BOLD)
139 stdscr.insnstr(5, 5, 'abc', 3)
140 stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000141
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300142 stdscr.insstr('def')
143 stdscr.insstr('def', curses.A_BOLD)
144 stdscr.insstr(5, 5, 'def')
145 stdscr.insstr(5, 5, 'def', curses.A_BOLD)
146 stdscr.is_linetouched(0)
147 stdscr.keypad(1)
148 stdscr.leaveok(1)
149 stdscr.move(3,3)
150 win.mvwin(2,2)
151 stdscr.nodelay(1)
152 stdscr.notimeout(1)
153 win2.overlay(win)
154 win2.overwrite(win)
155 win2.overlay(win, 1, 2, 2, 1, 3, 3)
156 win2.overwrite(win, 1, 2, 2, 1, 3, 3)
157 stdscr.redrawln(1,2)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000158
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300159 stdscr.scrollok(1)
160 stdscr.scroll()
161 stdscr.scroll(2)
162 stdscr.scroll(-3)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000163
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300164 stdscr.move(12, 2)
165 stdscr.setscrreg(10,15)
166 win3 = stdscr.subwin(10,10)
167 win3 = stdscr.subwin(10,10, 5,5)
168 stdscr.syncok(1)
169 stdscr.timeout(5)
170 stdscr.touchline(5,5)
171 stdscr.touchline(5,5,0)
172 stdscr.vline('a', 3)
173 stdscr.vline('a', 3, curses.A_STANDOUT)
174 stdscr.chgat(5, 2, 3, curses.A_BLINK)
175 stdscr.chgat(3, curses.A_BOLD)
176 stdscr.chgat(5, 8, curses.A_UNDERLINE)
177 stdscr.chgat(curses.A_BLINK)
178 stdscr.refresh()
Andrew M. Kuchling400a49b2007-04-11 13:39:00 +0000179
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300180 stdscr.vline(1,1, 'a', 3)
181 stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000182
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300183 if hasattr(curses, 'resize'):
184 stdscr.resize()
185 if hasattr(curses, 'enclose'):
186 stdscr.enclose()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000187
188
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300189 def test_module_funcs(self):
190 "Test module-level functions"
191 for func in [curses.baudrate, curses.beep, curses.can_change_color,
192 curses.cbreak, curses.def_prog_mode, curses.doupdate,
193 curses.filter, curses.flash, curses.flushinp,
194 curses.has_colors, curses.has_ic, curses.has_il,
195 curses.isendwin, curses.killchar, curses.longname,
196 curses.nocbreak, curses.noecho, curses.nonl,
197 curses.noqiflush, curses.noraw,
198 curses.reset_prog_mode, curses.termattrs,
199 curses.termname, curses.erasechar, curses.getsyx]:
200 func()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000201
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300202 # Functions that actually need arguments
203 if curses.tigetstr("cnorm"):
204 curses.curs_set(1)
205 curses.delay_output(1)
206 curses.echo() ; curses.echo(1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000207
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300208 with tempfile.TemporaryFile() as f:
209 self.stdscr.putwin(f)
210 f.seek(0)
211 curses.getwin(f)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000212
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300213 curses.halfdelay(1)
214 curses.intrflush(1)
215 curses.meta(1)
216 curses.napms(100)
217 curses.newpad(50,50)
218 win = curses.newwin(5,5)
219 win = curses.newwin(5,5, 1,1)
220 curses.nl() ; curses.nl(1)
221 curses.putp(b'abc')
222 curses.qiflush()
223 curses.raw() ; curses.raw(1)
224 curses.setsyx(5,5)
225 curses.tigetflag('hc')
226 curses.tigetnum('co')
227 curses.tigetstr('cr')
228 curses.tparm(b'cr')
229 curses.typeahead(sys.__stdin__.fileno())
230 curses.unctrl('a')
231 curses.ungetch('a')
232 curses.use_env(1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000233
234 # Functions only available on a few platforms
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300235 def test_colors_funcs(self):
236 if not curses.has_colors():
237 self.skip('requires colors support')
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000238 curses.start_color()
239 curses.init_pair(2, 1,1)
240 curses.color_content(1)
241 curses.color_pair(2)
Andrew M. Kuchlingd1badac2005-06-15 18:44:23 +0000242 curses.pair_content(curses.COLOR_PAIRS - 1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000243 curses.pair_number(0)
244
Michael W. Hudson2b3feec2004-08-07 15:27:16 +0000245 if hasattr(curses, 'use_default_colors'):
246 curses.use_default_colors()
Andrew M. Kuchling69f31eb2003-08-13 23:11:04 +0000247
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300248 @requires_curses_func('keyname')
249 def test_keyname(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000250 curses.keyname(13)
251
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300252 @requires_curses_func('has_key')
253 def test_has_key(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000254 curses.has_key(13)
255
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300256 @requires_curses_func('getmouse')
257 def test_getmouse(self):
Anthony Baxtere94e3b42006-04-06 07:12:39 +0000258 (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300259 if availmask == 0:
260 self.skip('mouse stuff not available')
261 curses.mouseinterval(10)
262 # just verify these don't cause errors
263 curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
264 m = curses.getmouse()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000265
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300266 def test_userptr_without_set(self):
267 w = curses.newwin(10, 10)
268 p = curses.panel.new_panel(w)
269 # try to access userptr() before calling set_userptr() -- segfaults
270 with self.assertRaises(curses.panel.error,
271 msg='userptr should fail since not set'):
272 p.userptr()
Walter Dörwald4994d952006-06-19 08:07:50 +0000273
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300274 def test_userptr_memory_leak(self):
275 w = curses.newwin(10, 10)
276 p = curses.panel.new_panel(w)
277 obj = object()
278 nrefs = sys.getrefcount(obj)
279 for i in range(100):
280 p.set_userptr(obj)
Tim Peters58eb11c2004-01-18 20:29:55 +0000281
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300282 p.set_userptr(None)
283 self.assertEqual(sys.getrefcount(obj), nrefs,
284 "set_userptr leaked references")
Andrew M. Kuchlinge752e202003-08-29 18:37:37 +0000285
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300286 def test_userptr_segfault(self):
287 panel = curses.panel.new_panel(self.stdscr)
288 class A:
289 def __del__(self):
290 panel.set_userptr(None)
291 panel.set_userptr(A())
292 panel.set_userptr(None)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000293
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300294 def test_new_curses_panel(self):
295 panel = curses.panel.new_panel(self.stdscr)
296 self.assertRaises(TypeError, type(panel))
Andrew Kuchlinga49dcc52013-06-15 13:53:10 -0400297
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300298 @requires_curses_func('is_term_resized')
299 def test_is_term_resized(self):
300 curses.is_term_resized(*self.stdscr.getmaxyx())
Andrew Kuchlinga49dcc52013-06-15 13:53:10 -0400301
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300302 @requires_curses_func('resize_term')
303 def test_resize_term(self):
304 curses.resize_term(*self.stdscr.getmaxyx())
Andrew Kuchlingaa6c2972013-06-22 12:33:05 -0400305
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300306 @requires_curses_func('resizeterm')
307 def test_resizeterm(self):
308 stdscr = self.stdscr
Walter Dörwaldd391f082007-03-06 20:38:57 +0000309 lines, cols = curses.LINES, curses.COLS
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300310 new_lines = lines - 1
311 new_cols = cols + 1
312 curses.resizeterm(new_lines, new_cols)
Tim Petersea5962f2007-03-12 18:07:52 +0000313
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300314 self.assertEqual(curses.LINES, new_lines)
315 self.assertEqual(curses.COLS, new_cols)
Walter Dörwaldd391f082007-03-06 20:38:57 +0000316
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300317 def test_issue6243(self):
318 curses.ungetch(1025)
319 self.stdscr.getkey()
Andrew M. Kuchlingb49e53e2009-09-25 22:23:54 +0000320
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300321 def test_issue10570(self):
322 b = curses.tparm(curses.tigetstr("cup"), 5, 3)
323 self.assertIs(type(b), bytes)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000324
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300325
326class TestAscii(unittest.TestCase):
327
Serhiy Storchaka41833872016-06-18 22:08:49 +0300328 def test_controlnames(self):
329 for name in curses.ascii.controlnames:
330 self.assertTrue(hasattr(curses.ascii, name), name)
331
332 def test_ctypes(self):
333 def check(func, expected):
334 self.assertEqual(func(i), expected)
335 self.assertEqual(func(c), expected)
336
337 for i in range(256):
338 c = b = chr(i)
339 check(curses.ascii.isalnum, b.isalnum())
340 check(curses.ascii.isalpha, b.isalpha())
341 check(curses.ascii.isdigit, b.isdigit())
342 check(curses.ascii.islower, b.islower())
343 check(curses.ascii.isspace, b.isspace())
344 check(curses.ascii.isupper, b.isupper())
345
346 check(curses.ascii.isascii, i < 128)
347 check(curses.ascii.ismeta, i >= 128)
348 check(curses.ascii.isctrl, i < 32)
349 check(curses.ascii.iscntrl, i < 32 or i == 127)
350 check(curses.ascii.isblank, c in ' \t')
351 check(curses.ascii.isgraph, 32 < i <= 126)
352 check(curses.ascii.isprint, 32 <= i <= 126)
353 check(curses.ascii.ispunct, c in string.punctuation)
354 check(curses.ascii.isxdigit, c in string.hexdigits)
355
356 def test_ascii(self):
357 ascii = curses.ascii.ascii
358 self.assertEqual(ascii('\xc1'), 'A')
359 self.assertEqual(ascii('A'), 'A')
360 self.assertEqual(ascii(ord('\xc1')), ord('A'))
361
362 def test_ctrl(self):
363 ctrl = curses.ascii.ctrl
364 self.assertEqual(ctrl('J'), '\n')
365 self.assertEqual(ctrl('\n'), '\n')
366 self.assertEqual(ctrl('@'), '\0')
367 self.assertEqual(ctrl(ord('J')), ord('\n'))
368
369 def test_alt(self):
370 alt = curses.ascii.alt
371 self.assertEqual(alt('\n'), '\x8a')
372 self.assertEqual(alt('A'), '\xc1')
373 self.assertEqual(alt(ord('A')), 0xc1)
374
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300375 def test_unctrl(self):
376 unctrl = curses.ascii.unctrl
377 self.assertEqual(unctrl('a'), 'a')
378 self.assertEqual(unctrl('A'), 'A')
379 self.assertEqual(unctrl(';'), ';')
380 self.assertEqual(unctrl(' '), ' ')
381 self.assertEqual(unctrl('\x7f'), '^?')
382 self.assertEqual(unctrl('\n'), '^J')
383 self.assertEqual(unctrl('\0'), '^@')
Serhiy Storchaka41833872016-06-18 22:08:49 +0300384 self.assertEqual(unctrl(ord('A')), 'A')
385 self.assertEqual(unctrl(ord('\n')), '^J')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300386 # Meta-bit characters
387 self.assertEqual(unctrl('\x8a'), '!^J')
388 self.assertEqual(unctrl('\xc1'), '!A')
Serhiy Storchaka41833872016-06-18 22:08:49 +0300389 self.assertEqual(unctrl(ord('\x8a')), '!^J')
390 self.assertEqual(unctrl(ord('\xc1')), '!A')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300391
392
393def test_main():
394 run_unittest(TestCurses, TestAscii)
395
396
397if __name__ == "__main__":
398 unittest.main()