blob: 8a39cd0ae47c4072ad5a46856582227bf45fab8b [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
Martin Panterad6a99c2016-09-10 10:38:22 +000066 print('')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030067 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
Benjamin Petersonf6701202016-08-13 18:15:28 -0700188 self.assertRaises(ValueError, stdscr.getstr, -400)
189 self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
Benjamin Peterson505989c2016-08-15 21:40:14 -0700190 self.assertRaises(ValueError, stdscr.instr, -2)
191 self.assertRaises(ValueError, stdscr.instr, 2, 3, -2)
Benjamin Petersonf6701202016-08-13 18:15:28 -0700192
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000193
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300194 def test_module_funcs(self):
195 "Test module-level functions"
196 for func in [curses.baudrate, curses.beep, curses.can_change_color,
197 curses.cbreak, curses.def_prog_mode, curses.doupdate,
198 curses.filter, curses.flash, curses.flushinp,
199 curses.has_colors, curses.has_ic, curses.has_il,
200 curses.isendwin, curses.killchar, curses.longname,
201 curses.nocbreak, curses.noecho, curses.nonl,
202 curses.noqiflush, curses.noraw,
203 curses.reset_prog_mode, curses.termattrs,
204 curses.termname, curses.erasechar, curses.getsyx]:
205 func()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000206
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300207 # Functions that actually need arguments
208 if curses.tigetstr("cnorm"):
209 curses.curs_set(1)
210 curses.delay_output(1)
211 curses.echo() ; curses.echo(1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000212
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300213 with tempfile.TemporaryFile() as f:
214 self.stdscr.putwin(f)
215 f.seek(0)
216 curses.getwin(f)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000217
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300218 curses.halfdelay(1)
219 curses.intrflush(1)
220 curses.meta(1)
221 curses.napms(100)
222 curses.newpad(50,50)
223 win = curses.newwin(5,5)
224 win = curses.newwin(5,5, 1,1)
225 curses.nl() ; curses.nl(1)
226 curses.putp(b'abc')
227 curses.qiflush()
228 curses.raw() ; curses.raw(1)
229 curses.setsyx(5,5)
230 curses.tigetflag('hc')
231 curses.tigetnum('co')
232 curses.tigetstr('cr')
233 curses.tparm(b'cr')
234 curses.typeahead(sys.__stdin__.fileno())
235 curses.unctrl('a')
236 curses.ungetch('a')
237 curses.use_env(1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000238
239 # Functions only available on a few platforms
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300240 def test_colors_funcs(self):
241 if not curses.has_colors():
242 self.skip('requires colors support')
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000243 curses.start_color()
244 curses.init_pair(2, 1,1)
245 curses.color_content(1)
246 curses.color_pair(2)
Andrew M. Kuchlingd1badac2005-06-15 18:44:23 +0000247 curses.pair_content(curses.COLOR_PAIRS - 1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000248 curses.pair_number(0)
249
Michael W. Hudson2b3feec2004-08-07 15:27:16 +0000250 if hasattr(curses, 'use_default_colors'):
251 curses.use_default_colors()
Andrew M. Kuchling69f31eb2003-08-13 23:11:04 +0000252
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300253 @requires_curses_func('keyname')
254 def test_keyname(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000255 curses.keyname(13)
256
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300257 @requires_curses_func('has_key')
258 def test_has_key(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000259 curses.has_key(13)
260
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300261 @requires_curses_func('getmouse')
262 def test_getmouse(self):
Anthony Baxtere94e3b42006-04-06 07:12:39 +0000263 (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300264 if availmask == 0:
265 self.skip('mouse stuff not available')
266 curses.mouseinterval(10)
267 # just verify these don't cause errors
268 curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
269 m = curses.getmouse()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000270
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300271 def test_userptr_without_set(self):
272 w = curses.newwin(10, 10)
273 p = curses.panel.new_panel(w)
274 # try to access userptr() before calling set_userptr() -- segfaults
275 with self.assertRaises(curses.panel.error,
276 msg='userptr should fail since not set'):
277 p.userptr()
Walter Dörwald4994d952006-06-19 08:07:50 +0000278
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300279 def test_userptr_memory_leak(self):
280 w = curses.newwin(10, 10)
281 p = curses.panel.new_panel(w)
282 obj = object()
283 nrefs = sys.getrefcount(obj)
284 for i in range(100):
285 p.set_userptr(obj)
Tim Peters58eb11c2004-01-18 20:29:55 +0000286
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300287 p.set_userptr(None)
288 self.assertEqual(sys.getrefcount(obj), nrefs,
289 "set_userptr leaked references")
Andrew M. Kuchlinge752e202003-08-29 18:37:37 +0000290
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300291 def test_userptr_segfault(self):
292 panel = curses.panel.new_panel(self.stdscr)
293 class A:
294 def __del__(self):
295 panel.set_userptr(None)
296 panel.set_userptr(A())
297 panel.set_userptr(None)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000298
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300299 def test_new_curses_panel(self):
300 panel = curses.panel.new_panel(self.stdscr)
301 self.assertRaises(TypeError, type(panel))
Andrew Kuchlinga49dcc52013-06-15 13:53:10 -0400302
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300303 @requires_curses_func('is_term_resized')
304 def test_is_term_resized(self):
305 curses.is_term_resized(*self.stdscr.getmaxyx())
Andrew Kuchlinga49dcc52013-06-15 13:53:10 -0400306
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300307 @requires_curses_func('resize_term')
308 def test_resize_term(self):
309 curses.resize_term(*self.stdscr.getmaxyx())
Andrew Kuchlingaa6c2972013-06-22 12:33:05 -0400310
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300311 @requires_curses_func('resizeterm')
312 def test_resizeterm(self):
313 stdscr = self.stdscr
Walter Dörwaldd391f082007-03-06 20:38:57 +0000314 lines, cols = curses.LINES, curses.COLS
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300315 new_lines = lines - 1
316 new_cols = cols + 1
317 curses.resizeterm(new_lines, new_cols)
Tim Petersea5962f2007-03-12 18:07:52 +0000318
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300319 self.assertEqual(curses.LINES, new_lines)
320 self.assertEqual(curses.COLS, new_cols)
Walter Dörwaldd391f082007-03-06 20:38:57 +0000321
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300322 def test_issue6243(self):
323 curses.ungetch(1025)
324 self.stdscr.getkey()
Andrew M. Kuchlingb49e53e2009-09-25 22:23:54 +0000325
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300326 def test_issue10570(self):
327 b = curses.tparm(curses.tigetstr("cup"), 5, 3)
328 self.assertIs(type(b), bytes)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000329
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300330
331class TestAscii(unittest.TestCase):
332
Serhiy Storchaka41833872016-06-18 22:08:49 +0300333 def test_controlnames(self):
334 for name in curses.ascii.controlnames:
335 self.assertTrue(hasattr(curses.ascii, name), name)
336
337 def test_ctypes(self):
338 def check(func, expected):
339 self.assertEqual(func(i), expected)
340 self.assertEqual(func(c), expected)
341
342 for i in range(256):
343 c = b = chr(i)
344 check(curses.ascii.isalnum, b.isalnum())
345 check(curses.ascii.isalpha, b.isalpha())
346 check(curses.ascii.isdigit, b.isdigit())
347 check(curses.ascii.islower, b.islower())
348 check(curses.ascii.isspace, b.isspace())
349 check(curses.ascii.isupper, b.isupper())
350
351 check(curses.ascii.isascii, i < 128)
352 check(curses.ascii.ismeta, i >= 128)
353 check(curses.ascii.isctrl, i < 32)
354 check(curses.ascii.iscntrl, i < 32 or i == 127)
355 check(curses.ascii.isblank, c in ' \t')
356 check(curses.ascii.isgraph, 32 < i <= 126)
357 check(curses.ascii.isprint, 32 <= i <= 126)
358 check(curses.ascii.ispunct, c in string.punctuation)
359 check(curses.ascii.isxdigit, c in string.hexdigits)
360
361 def test_ascii(self):
362 ascii = curses.ascii.ascii
363 self.assertEqual(ascii('\xc1'), 'A')
364 self.assertEqual(ascii('A'), 'A')
365 self.assertEqual(ascii(ord('\xc1')), ord('A'))
366
367 def test_ctrl(self):
368 ctrl = curses.ascii.ctrl
369 self.assertEqual(ctrl('J'), '\n')
370 self.assertEqual(ctrl('\n'), '\n')
371 self.assertEqual(ctrl('@'), '\0')
372 self.assertEqual(ctrl(ord('J')), ord('\n'))
373
374 def test_alt(self):
375 alt = curses.ascii.alt
376 self.assertEqual(alt('\n'), '\x8a')
377 self.assertEqual(alt('A'), '\xc1')
378 self.assertEqual(alt(ord('A')), 0xc1)
379
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300380 def test_unctrl(self):
381 unctrl = curses.ascii.unctrl
382 self.assertEqual(unctrl('a'), 'a')
383 self.assertEqual(unctrl('A'), 'A')
384 self.assertEqual(unctrl(';'), ';')
385 self.assertEqual(unctrl(' '), ' ')
386 self.assertEqual(unctrl('\x7f'), '^?')
387 self.assertEqual(unctrl('\n'), '^J')
388 self.assertEqual(unctrl('\0'), '^@')
Serhiy Storchaka41833872016-06-18 22:08:49 +0300389 self.assertEqual(unctrl(ord('A')), 'A')
390 self.assertEqual(unctrl(ord('\n')), '^J')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300391 # Meta-bit characters
392 self.assertEqual(unctrl('\x8a'), '!^J')
393 self.assertEqual(unctrl('\xc1'), '!A')
Serhiy Storchaka41833872016-06-18 22:08:49 +0300394 self.assertEqual(unctrl(ord('\x8a')), '!^J')
395 self.assertEqual(unctrl(ord('\xc1')), '!A')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300396
397
398def test_main():
399 run_unittest(TestCurses, TestAscii)
400
401
402if __name__ == "__main__":
403 unittest.main()