blob: 3b442fe6a4b7aa8876255c1ca203049cb3bd4b9c [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
Zachary Warebaf45c52014-10-17 13:59:18 -05005# 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
Zachary Warebaf45c52014-10-17 13:59:18 -050012import os
Serhiy Storchaka514f9732016-06-18 22:08:11 +030013import string
Zachary Warebaf45c52014-10-17 13:59:18 -050014import sys
15import tempfile
16import unittest
17
Victor Stinner19f68302017-10-31 03:14:01 -070018from test.support import requires, import_module, verbose, SaveSignals
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.
Larry Hastings9147a962014-05-04 04:41:18 -070023import inspect
Neal Norwitz9f39f682006-01-06 04:18:21 +000024requires('curses')
25
R. David Murraya21e4ca2009-03-31 23:16:50 +000026# If either of these don't exist, skip the tests.
27curses = import_module('curses')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030028import_module('curses.ascii')
Serhiy Storchakabdf9e0e2016-12-28 10:16:06 +020029import_module('curses.textpad')
Serhiy Storchakabaac01e2017-10-31 13:56:44 +020030try:
31 import curses.panel
32except ImportError:
33 pass
R. David Murraya21e4ca2009-03-31 23:16:50 +000034
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030035def requires_curses_func(name):
36 return unittest.skipUnless(hasattr(curses, name),
37 'requires curses.%s' % name)
Mark Dickinson945e2422010-02-21 13:42:03 +000038
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030039term = os.environ.get('TERM')
40
41# If newterm was supported we could use it instead of initscr and not exit
42@unittest.skipIf(not term or term == 'unknown',
Zachary Warebaf45c52014-10-17 13:59:18 -050043 "$TERM=%r, calling initscr() may cause exit" % term)
44@unittest.skipIf(sys.platform == "cygwin",
45 "cygwin's curses mostly just hangs")
46class TestCurses(unittest.TestCase):
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030047
Zachary Warebaf45c52014-10-17 13:59:18 -050048 @classmethod
49 def setUpClass(cls):
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030050 if not sys.__stdout__.isatty():
Serhiy Storchaka53a00352016-05-22 18:16:20 +030051 # Temporary skip tests on non-tty
Serhiy Storchaka0a91e432016-05-22 18:23:36 +030052 raise unittest.SkipTest('sys.__stdout__ is not a tty')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030053 cls.tmp = tempfile.TemporaryFile()
54 fd = cls.tmp.fileno()
55 else:
56 cls.tmp = None
57 fd = sys.__stdout__.fileno()
58 # testing setupterm() inside initscr/endwin
59 # causes terminal breakage
60 curses.setupterm(fd=fd)
61
62 @classmethod
63 def tearDownClass(cls):
64 if cls.tmp:
65 cls.tmp.close()
66 del cls.tmp
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000067
Zachary Warebaf45c52014-10-17 13:59:18 -050068 def setUp(self):
Victor Stinner19f68302017-10-31 03:14:01 -070069 self.save_signals = SaveSignals()
70 self.save_signals.save()
Zachary Warebaf45c52014-10-17 13:59:18 -050071 if verbose:
72 # just to make the test output a little more readable
73 print()
74 self.stdscr = curses.initscr()
75 curses.savetty()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000076
Zachary Warebaf45c52014-10-17 13:59:18 -050077 def tearDown(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000078 curses.resetty()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000079 curses.endwin()
Victor Stinner19f68302017-10-31 03:14:01 -070080 self.save_signals.restore()
Zachary Warebaf45c52014-10-17 13:59:18 -050081
82 def test_window_funcs(self):
83 "Test the methods of windows"
84 stdscr = self.stdscr
85 win = curses.newwin(10,10)
86 win = curses.newwin(5,5, 5,5)
87 win2 = curses.newwin(15,15, 5,5)
88
89 for meth in [stdscr.addch, stdscr.addstr]:
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +030090 for args in [('a',), ('a', curses.A_BOLD),
Zachary Warebaf45c52014-10-17 13:59:18 -050091 (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +030092 with self.subTest(meth=meth.__qualname__, args=args):
93 meth(*args)
Zachary Warebaf45c52014-10-17 13:59:18 -050094
Serhiy Storchaka4f469c02017-11-01 20:48:49 +020095 for meth in [stdscr.clear, stdscr.clrtobot,
Zachary Warebaf45c52014-10-17 13:59:18 -050096 stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
97 stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
98 stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
99 stdscr.getparyx, stdscr.getyx, stdscr.inch,
100 stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
101 win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
102 stdscr.standout, stdscr.standend, stdscr.syncdown,
103 stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300104 with self.subTest(meth=meth.__qualname__):
105 meth()
Zachary Warebaf45c52014-10-17 13:59:18 -0500106
107 stdscr.addnstr('1234', 3)
108 stdscr.addnstr('1234', 3, curses.A_BOLD)
109 stdscr.addnstr(4,4, '1234', 3)
110 stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
111
112 stdscr.attron(curses.A_BOLD)
113 stdscr.attroff(curses.A_BOLD)
114 stdscr.attrset(curses.A_BOLD)
115 stdscr.bkgd(' ')
116 stdscr.bkgd(' ', curses.A_REVERSE)
117 stdscr.bkgdset(' ')
118 stdscr.bkgdset(' ', curses.A_REVERSE)
119
120 win.border(65, 66, 67, 68,
121 69, 70, 71, 72)
122 win.border('|', '!', '-', '_',
123 '+', '\\', '#', '/')
124 with self.assertRaises(TypeError,
125 msg="Expected win.border() to raise TypeError"):
126 win.border(65, 66, 67, 68,
127 69, [], 71, 72)
128
Serhiy Storchaka4f469c02017-11-01 20:48:49 +0200129 win.box(65, 67)
130 win.box('!', '_')
131 win.box(b':', b'~')
132 self.assertRaises(TypeError, win.box, 65, 66, 67)
133 self.assertRaises(TypeError, win.box, 65)
134 win.box()
135
Zachary Warebaf45c52014-10-17 13:59:18 -0500136 stdscr.clearok(1)
137
138 win4 = stdscr.derwin(2,2)
139 win4 = stdscr.derwin(1,1, 5,5)
140 win4.mvderwin(9,9)
141
142 stdscr.echochar('a')
143 stdscr.echochar('a', curses.A_BOLD)
144 stdscr.hline('-', 5)
145 stdscr.hline('-', 5, curses.A_BOLD)
146 stdscr.hline(1,1,'-', 5)
147 stdscr.hline(1,1,'-', 5, curses.A_BOLD)
148
149 stdscr.idcok(1)
150 stdscr.idlok(1)
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200151 if hasattr(stdscr, 'immedok'):
152 stdscr.immedok(1)
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200153 stdscr.immedok(0)
Zachary Warebaf45c52014-10-17 13:59:18 -0500154 stdscr.insch('c')
155 stdscr.insdelln(1)
156 stdscr.insnstr('abc', 3)
157 stdscr.insnstr('abc', 3, curses.A_BOLD)
158 stdscr.insnstr(5, 5, 'abc', 3)
159 stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
160
161 stdscr.insstr('def')
162 stdscr.insstr('def', curses.A_BOLD)
163 stdscr.insstr(5, 5, 'def')
164 stdscr.insstr(5, 5, 'def', curses.A_BOLD)
165 stdscr.is_linetouched(0)
166 stdscr.keypad(1)
167 stdscr.leaveok(1)
168 stdscr.move(3,3)
169 win.mvwin(2,2)
170 stdscr.nodelay(1)
171 stdscr.notimeout(1)
172 win2.overlay(win)
173 win2.overwrite(win)
174 win2.overlay(win, 1, 2, 2, 1, 3, 3)
175 win2.overwrite(win, 1, 2, 2, 1, 3, 3)
176 stdscr.redrawln(1,2)
177
178 stdscr.scrollok(1)
179 stdscr.scroll()
180 stdscr.scroll(2)
181 stdscr.scroll(-3)
182
183 stdscr.move(12, 2)
184 stdscr.setscrreg(10,15)
185 win3 = stdscr.subwin(10,10)
186 win3 = stdscr.subwin(10,10, 5,5)
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200187 if hasattr(stdscr, 'syncok') and not sys.platform.startswith("sunos"):
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200188 stdscr.syncok(1)
Zachary Warebaf45c52014-10-17 13:59:18 -0500189 stdscr.timeout(5)
190 stdscr.touchline(5,5)
191 stdscr.touchline(5,5,0)
192 stdscr.vline('a', 3)
193 stdscr.vline('a', 3, curses.A_STANDOUT)
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200194 if hasattr(stdscr, 'chgat'):
195 stdscr.chgat(5, 2, 3, curses.A_BLINK)
196 stdscr.chgat(3, curses.A_BOLD)
197 stdscr.chgat(5, 8, curses.A_UNDERLINE)
198 stdscr.chgat(curses.A_BLINK)
Zachary Warebaf45c52014-10-17 13:59:18 -0500199 stdscr.refresh()
200
201 stdscr.vline(1,1, 'a', 3)
202 stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
203
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200204 if hasattr(stdscr, 'resize'):
205 stdscr.resize(25, 80)
206 if hasattr(stdscr, 'enclose'):
207 stdscr.enclose(10, 10)
Zachary Warebaf45c52014-10-17 13:59:18 -0500208
Benjamin Peterson40a77c32016-08-13 18:15:28 -0700209 self.assertRaises(ValueError, stdscr.getstr, -400)
210 self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
Benjamin Peterson432ea4f2016-08-15 21:40:14 -0700211 self.assertRaises(ValueError, stdscr.instr, -2)
212 self.assertRaises(ValueError, stdscr.instr, 2, 3, -2)
Benjamin Peterson40a77c32016-08-13 18:15:28 -0700213
Serhiy Storchakaf7eae0a2017-06-28 08:30:06 +0300214 def test_embedded_null_chars(self):
215 # reject embedded null bytes and characters
216 stdscr = self.stdscr
217 for arg in ['a', b'a']:
218 with self.subTest(arg=arg):
219 self.assertRaises(ValueError, stdscr.addstr, 'a\0')
220 self.assertRaises(ValueError, stdscr.addnstr, 'a\0', 1)
221 self.assertRaises(ValueError, stdscr.insstr, 'a\0')
222 self.assertRaises(ValueError, stdscr.insnstr, 'a\0', 1)
Zachary Warebaf45c52014-10-17 13:59:18 -0500223
224 def test_module_funcs(self):
225 "Test module-level functions"
Zachary Warebaf45c52014-10-17 13:59:18 -0500226 for func in [curses.baudrate, curses.beep, curses.can_change_color,
227 curses.cbreak, curses.def_prog_mode, curses.doupdate,
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200228 curses.flash, curses.flushinp,
Zachary Warebaf45c52014-10-17 13:59:18 -0500229 curses.has_colors, curses.has_ic, curses.has_il,
230 curses.isendwin, curses.killchar, curses.longname,
231 curses.nocbreak, curses.noecho, curses.nonl,
232 curses.noqiflush, curses.noraw,
233 curses.reset_prog_mode, curses.termattrs,
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200234 curses.termname, curses.erasechar]:
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300235 with self.subTest(func=func.__qualname__):
236 func()
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200237 if hasattr(curses, 'filter'):
238 curses.filter()
239 if hasattr(curses, 'getsyx'):
240 curses.getsyx()
Zachary Warebaf45c52014-10-17 13:59:18 -0500241
242 # Functions that actually need arguments
243 if curses.tigetstr("cnorm"):
244 curses.curs_set(1)
245 curses.delay_output(1)
246 curses.echo() ; curses.echo(1)
247
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300248 with tempfile.TemporaryFile() as f:
249 self.stdscr.putwin(f)
250 f.seek(0)
251 curses.getwin(f)
Zachary Warebaf45c52014-10-17 13:59:18 -0500252
253 curses.halfdelay(1)
254 curses.intrflush(1)
255 curses.meta(1)
256 curses.napms(100)
257 curses.newpad(50,50)
258 win = curses.newwin(5,5)
259 win = curses.newwin(5,5, 1,1)
260 curses.nl() ; curses.nl(1)
261 curses.putp(b'abc')
262 curses.qiflush()
263 curses.raw() ; curses.raw(1)
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200264 if hasattr(curses, 'setsyx'):
265 curses.setsyx(5,5)
Zachary Warebaf45c52014-10-17 13:59:18 -0500266 curses.tigetflag('hc')
267 curses.tigetnum('co')
268 curses.tigetstr('cr')
269 curses.tparm(b'cr')
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200270 if hasattr(curses, 'typeahead'):
271 curses.typeahead(sys.__stdin__.fileno())
Zachary Warebaf45c52014-10-17 13:59:18 -0500272 curses.unctrl('a')
273 curses.ungetch('a')
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200274 if hasattr(curses, 'use_env'):
275 curses.use_env(1)
Zachary Warebaf45c52014-10-17 13:59:18 -0500276
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300277 # Functions only available on a few platforms
278 def test_colors_funcs(self):
279 if not curses.has_colors():
Xavier de Gaye645bc802017-01-06 09:50:27 +0100280 self.skipTest('requires colors support')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300281 curses.start_color()
282 curses.init_pair(2, 1,1)
283 curses.color_content(1)
284 curses.color_pair(2)
285 curses.pair_content(curses.COLOR_PAIRS - 1)
286 curses.pair_number(0)
Zachary Warebaf45c52014-10-17 13:59:18 -0500287
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300288 if hasattr(curses, 'use_default_colors'):
289 curses.use_default_colors()
Zachary Warebaf45c52014-10-17 13:59:18 -0500290
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300291 @requires_curses_func('keyname')
292 def test_keyname(self):
293 curses.keyname(13)
Zachary Warebaf45c52014-10-17 13:59:18 -0500294
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300295 @requires_curses_func('has_key')
296 def test_has_key(self):
297 curses.has_key(13)
Zachary Warebaf45c52014-10-17 13:59:18 -0500298
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300299 @requires_curses_func('getmouse')
300 def test_getmouse(self):
301 (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
302 if availmask == 0:
Xavier de Gaye645bc802017-01-06 09:50:27 +0100303 self.skipTest('mouse stuff not available')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300304 curses.mouseinterval(10)
305 # just verify these don't cause errors
306 curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
307 m = curses.getmouse()
Zachary Warebaf45c52014-10-17 13:59:18 -0500308
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200309 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500310 def test_userptr_without_set(self):
311 w = curses.newwin(10, 10)
312 p = curses.panel.new_panel(w)
313 # try to access userptr() before calling set_userptr() -- segfaults
314 with self.assertRaises(curses.panel.error,
315 msg='userptr should fail since not set'):
316 p.userptr()
317
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200318 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500319 def test_userptr_memory_leak(self):
320 w = curses.newwin(10, 10)
321 p = curses.panel.new_panel(w)
322 obj = object()
323 nrefs = sys.getrefcount(obj)
324 for i in range(100):
325 p.set_userptr(obj)
326
327 p.set_userptr(None)
328 self.assertEqual(sys.getrefcount(obj), nrefs,
329 "set_userptr leaked references")
330
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200331 @requires_curses_func('panel')
Zachary Warebaf45c52014-10-17 13:59:18 -0500332 def test_userptr_segfault(self):
Serhiy Storchakaa7723d82017-11-03 20:29:33 +0200333 w = curses.newwin(10, 10)
334 panel = curses.panel.new_panel(w)
Zachary Warebaf45c52014-10-17 13:59:18 -0500335 class A:
336 def __del__(self):
337 panel.set_userptr(None)
338 panel.set_userptr(A())
339 panel.set_userptr(None)
340
Serhiy Storchakabaac01e2017-10-31 13:56:44 +0200341 @requires_curses_func('panel')
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300342 def test_new_curses_panel(self):
Serhiy Storchakaa7723d82017-11-03 20:29:33 +0200343 w = curses.newwin(10, 10)
344 panel = curses.panel.new_panel(w)
Serhiy Storchakae3f1b092016-05-08 20:46:22 +0300345 self.assertRaises(TypeError, type(panel))
346
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300347 @requires_curses_func('is_term_resized')
348 def test_is_term_resized(self):
349 curses.is_term_resized(*self.stdscr.getmaxyx())
350
351 @requires_curses_func('resize_term')
Zachary Warebaf45c52014-10-17 13:59:18 -0500352 def test_resize_term(self):
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300353 curses.resize_term(*self.stdscr.getmaxyx())
354
355 @requires_curses_func('resizeterm')
356 def test_resizeterm(self):
357 stdscr = self.stdscr
Zachary Warebaf45c52014-10-17 13:59:18 -0500358 lines, cols = curses.LINES, curses.COLS
359 new_lines = lines - 1
360 new_cols = cols + 1
361 curses.resizeterm(new_lines, new_cols)
362
363 self.assertEqual(curses.LINES, new_lines)
364 self.assertEqual(curses.COLS, new_cols)
365
366 def test_issue6243(self):
367 curses.ungetch(1025)
368 self.stdscr.getkey()
369
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300370 @requires_curses_func('unget_wch')
Serhiy Storchaka7e687902017-11-01 16:03:40 +0200371 # XXX Remove the decorator when ncurses on OpenBSD be updated
372 @unittest.skipIf(sys.platform.startswith("openbsd"),
373 "OpenBSD's curses (v.5.7) has bugs")
Zachary Warebaf45c52014-10-17 13:59:18 -0500374 def test_unget_wch(self):
375 stdscr = self.stdscr
376 encoding = stdscr.encoding
377 for ch in ('a', '\xe9', '\u20ac', '\U0010FFFF'):
378 try:
379 ch.encode(encoding)
380 except UnicodeEncodeError:
381 continue
382 try:
383 curses.unget_wch(ch)
384 except Exception as err:
385 self.fail("unget_wch(%a) failed with encoding %s: %s"
386 % (ch, stdscr.encoding, err))
387 read = stdscr.get_wch()
388 self.assertEqual(read, ch)
389
390 code = ord(ch)
391 curses.unget_wch(code)
392 read = stdscr.get_wch()
393 self.assertEqual(read, ch)
394
395 def test_issue10570(self):
396 b = curses.tparm(curses.tigetstr("cup"), 5, 3)
397 self.assertIs(type(b), bytes)
Zachary Warebaf45c52014-10-17 13:59:18 -0500398
399 def test_encoding(self):
400 stdscr = self.stdscr
401 import codecs
402 encoding = stdscr.encoding
403 codecs.lookup(encoding)
Zachary Warebaf45c52014-10-17 13:59:18 -0500404 with self.assertRaises(TypeError):
405 stdscr.encoding = 10
Zachary Warebaf45c52014-10-17 13:59:18 -0500406 stdscr.encoding = encoding
407 with self.assertRaises(TypeError):
408 del stdscr.encoding
409
410 def test_issue21088(self):
411 stdscr = self.stdscr
412 #
413 # http://bugs.python.org/issue21088
414 #
415 # the bug:
416 # when converting curses.window.addch to Argument Clinic
417 # the first two parameters were switched.
418
419 # if someday we can represent the signature of addch
420 # we will need to rewrite this test.
421 try:
422 signature = inspect.signature(stdscr.addch)
423 self.assertFalse(signature)
424 except ValueError:
425 # not generating a signature is fine.
426 pass
427
428 # So. No signature for addch.
429 # But Argument Clinic gave us a human-readable equivalent
430 # as the first line of the docstring. So we parse that,
431 # and ensure that the parameters appear in the correct order.
432 # Since this is parsing output from Argument Clinic, we can
433 # be reasonably certain the generated parsing code will be
434 # correct too.
435 human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300436 self.assertIn("[y, x,]", human_readable_signature)
437
Serhiy Storchakabdf9e0e2016-12-28 10:16:06 +0200438 def test_issue13051(self):
439 stdscr = self.stdscr
Serhiy Storchaka894ebd02017-11-01 14:34:20 +0200440 if not hasattr(stdscr, 'resize'):
441 raise unittest.SkipTest('requires curses.window.resize')
Serhiy Storchakabdf9e0e2016-12-28 10:16:06 +0200442 box = curses.textpad.Textbox(stdscr, insert_mode=True)
443 lines, cols = stdscr.getmaxyx()
444 stdscr.resize(lines-2, cols-2)
445 # this may cause infinite recursion, leading to a RuntimeError
446 box._insert_printable_char('a')
447
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300448
449class MiscTests(unittest.TestCase):
Zachary Warebaf45c52014-10-17 13:59:18 -0500450
Berker Peksag53926f12016-08-19 17:59:01 +0300451 @requires_curses_func('update_lines_cols')
Steve Dowerd2bc3892015-04-15 18:06:05 -0400452 def test_update_lines_cols(self):
453 # this doesn't actually test that LINES and COLS are updated,
454 # because we can't automate changing them. See Issue #4254 for
455 # a manual test script. We can only test that the function
456 # can be called.
457 curses.update_lines_cols()
458
Alexandre Vassalotti5ff02352009-07-22 21:27:53 +0000459
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300460class TestAscii(unittest.TestCase):
461
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300462 def test_controlnames(self):
463 for name in curses.ascii.controlnames:
464 self.assertTrue(hasattr(curses.ascii, name), name)
465
466 def test_ctypes(self):
467 def check(func, expected):
468 with self.subTest(ch=c, func=func):
469 self.assertEqual(func(i), expected)
470 self.assertEqual(func(c), expected)
471
472 for i in range(256):
473 c = chr(i)
474 b = bytes([i])
475 check(curses.ascii.isalnum, b.isalnum())
476 check(curses.ascii.isalpha, b.isalpha())
477 check(curses.ascii.isdigit, b.isdigit())
478 check(curses.ascii.islower, b.islower())
479 check(curses.ascii.isspace, b.isspace())
480 check(curses.ascii.isupper, b.isupper())
481
482 check(curses.ascii.isascii, i < 128)
483 check(curses.ascii.ismeta, i >= 128)
484 check(curses.ascii.isctrl, i < 32)
485 check(curses.ascii.iscntrl, i < 32 or i == 127)
486 check(curses.ascii.isblank, c in ' \t')
487 check(curses.ascii.isgraph, 32 < i <= 126)
488 check(curses.ascii.isprint, 32 <= i <= 126)
489 check(curses.ascii.ispunct, c in string.punctuation)
490 check(curses.ascii.isxdigit, c in string.hexdigits)
491
Serhiy Storchaka283de2b2016-12-28 10:04:27 +0200492 for i in (-2, -1, 256, sys.maxunicode, sys.maxunicode+1):
493 self.assertFalse(curses.ascii.isalnum(i))
494 self.assertFalse(curses.ascii.isalpha(i))
495 self.assertFalse(curses.ascii.isdigit(i))
496 self.assertFalse(curses.ascii.islower(i))
497 self.assertFalse(curses.ascii.isspace(i))
498 self.assertFalse(curses.ascii.isupper(i))
499
500 self.assertFalse(curses.ascii.isascii(i))
501 self.assertFalse(curses.ascii.isctrl(i))
502 self.assertFalse(curses.ascii.iscntrl(i))
503 self.assertFalse(curses.ascii.isblank(i))
504 self.assertFalse(curses.ascii.isgraph(i))
505 self.assertFalse(curses.ascii.isprint(i))
506 self.assertFalse(curses.ascii.ispunct(i))
507 self.assertFalse(curses.ascii.isxdigit(i))
508
509 self.assertFalse(curses.ascii.ismeta(-1))
510
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300511 def test_ascii(self):
512 ascii = curses.ascii.ascii
513 self.assertEqual(ascii('\xc1'), 'A')
514 self.assertEqual(ascii('A'), 'A')
515 self.assertEqual(ascii(ord('\xc1')), ord('A'))
516
517 def test_ctrl(self):
518 ctrl = curses.ascii.ctrl
519 self.assertEqual(ctrl('J'), '\n')
520 self.assertEqual(ctrl('\n'), '\n')
521 self.assertEqual(ctrl('@'), '\0')
522 self.assertEqual(ctrl(ord('J')), ord('\n'))
523
524 def test_alt(self):
525 alt = curses.ascii.alt
526 self.assertEqual(alt('\n'), '\x8a')
527 self.assertEqual(alt('A'), '\xc1')
528 self.assertEqual(alt(ord('A')), 0xc1)
529
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300530 def test_unctrl(self):
531 unctrl = curses.ascii.unctrl
532 self.assertEqual(unctrl('a'), 'a')
533 self.assertEqual(unctrl('A'), 'A')
534 self.assertEqual(unctrl(';'), ';')
535 self.assertEqual(unctrl(' '), ' ')
536 self.assertEqual(unctrl('\x7f'), '^?')
537 self.assertEqual(unctrl('\n'), '^J')
538 self.assertEqual(unctrl('\0'), '^@')
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300539 self.assertEqual(unctrl(ord('A')), 'A')
540 self.assertEqual(unctrl(ord('\n')), '^J')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300541 # Meta-bit characters
542 self.assertEqual(unctrl('\x8a'), '!^J')
543 self.assertEqual(unctrl('\xc1'), '!A')
Serhiy Storchaka514f9732016-06-18 22:08:11 +0300544 self.assertEqual(unctrl(ord('\x8a')), '!^J')
545 self.assertEqual(unctrl(ord('\xc1')), '!A')
Serhiy Storchaka0eb39e72016-05-21 21:36:11 +0300546
547
Alexandre Vassalotti5ff02352009-07-22 21:27:53 +0000548if __name__ == '__main__':
Zachary Warebaf45c52014-10-17 13:59:18 -0500549 unittest.main()