blob: 84b6bfddca533c5b3a541fbabeef7e2c19677f0d [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')
Serhiy Storchaka4d42af12016-12-28 10:16:06 +020029import_module('curses.textpad')
Neal Norwitz9f39f682006-01-06 04:18:21 +000030
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030031def requires_curses_func(name):
32 return unittest.skipUnless(hasattr(curses, name),
33 'requires curses.%s' % name)
Mark Dickinson45ad8012010-02-21 13:37:53 +000034
Neal Norwitz9f39f682006-01-06 04:18:21 +000035term = os.environ.get('TERM')
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000036
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030037# If newterm was supported we could use it instead of initscr and not exit
38@unittest.skipIf(not term or term == 'unknown',
39 "$TERM=%r, calling initscr() may cause exit" % term)
40@unittest.skipIf(sys.platform == "cygwin",
41 "cygwin's curses mostly just hangs")
42class TestCurses(unittest.TestCase):
Anthony Baxter76801852006-04-04 13:32:08 +000043
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030044 @classmethod
45 def setUpClass(cls):
46 if not sys.__stdout__.isatty():
47 # Temporary skip tests on non-tty
48 raise unittest.SkipTest('sys.__stdout__ is not a tty')
49 cls.tmp = tempfile.TemporaryFile()
50 fd = cls.tmp.fileno()
51 else:
52 cls.tmp = None
53 fd = sys.__stdout__.fileno()
54 # testing setupterm() inside initscr/endwin
55 # causes terminal breakage
56 curses.setupterm(fd=fd)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000057
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030058 @classmethod
59 def tearDownClass(cls):
60 if cls.tmp:
61 cls.tmp.close()
62 del cls.tmp
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000063
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030064 def setUp(self):
65 if verbose:
66 # just to make the test output a little more readable
Martin Panterad6a99c2016-09-10 10:38:22 +000067 print('')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030068 self.stdscr = curses.initscr()
69 curses.savetty()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000070
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030071 def tearDown(self):
72 curses.resetty()
73 curses.endwin()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000074
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030075 def test_window_funcs(self):
76 "Test the methods of windows"
77 stdscr = self.stdscr
78 win = curses.newwin(10,10)
79 win = curses.newwin(5,5, 5,5)
80 win2 = curses.newwin(15,15, 5,5)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000081
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +030082 for meth in [stdscr.addch, stdscr.addstr]:
83 for args in [('a'), ('a', curses.A_BOLD),
84 (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
85 meth(*args)
86
87 for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
88 stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
89 stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
90 stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
91 stdscr.getparyx, stdscr.getyx, stdscr.inch,
92 stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
93 win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
94 stdscr.standout, stdscr.standend, stdscr.syncdown,
95 stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
96 meth()
97
98 stdscr.addnstr('1234', 3)
99 stdscr.addnstr('1234', 3, curses.A_BOLD)
100 stdscr.addnstr(4,4, '1234', 3)
101 stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
102
103 stdscr.attron(curses.A_BOLD)
104 stdscr.attroff(curses.A_BOLD)
105 stdscr.attrset(curses.A_BOLD)
106 stdscr.bkgd(' ')
107 stdscr.bkgd(' ', curses.A_REVERSE)
108 stdscr.bkgdset(' ')
109 stdscr.bkgdset(' ', curses.A_REVERSE)
110
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000111 win.border(65, 66, 67, 68,
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300112 69, 70, 71, 72)
113 win.border('|', '!', '-', '_',
114 '+', '\\', '#', '/')
115 with self.assertRaises(TypeError,
116 msg="Expected win.border() to raise TypeError"):
117 win.border(65, 66, 67, 68,
118 69, [], 71, 72)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000119
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300120 stdscr.clearok(1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000121
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300122 win4 = stdscr.derwin(2,2)
123 win4 = stdscr.derwin(1,1, 5,5)
124 win4.mvderwin(9,9)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000125
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300126 stdscr.echochar('a')
127 stdscr.echochar('a', curses.A_BOLD)
128 stdscr.hline('-', 5)
129 stdscr.hline('-', 5, curses.A_BOLD)
130 stdscr.hline(1,1,'-', 5)
131 stdscr.hline(1,1,'-', 5, curses.A_BOLD)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000132
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300133 stdscr.idcok(1)
134 stdscr.idlok(1)
135 stdscr.immedok(1)
136 stdscr.insch('c')
137 stdscr.insdelln(1)
138 stdscr.insnstr('abc', 3)
139 stdscr.insnstr('abc', 3, curses.A_BOLD)
140 stdscr.insnstr(5, 5, 'abc', 3)
141 stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000142
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300143 stdscr.insstr('def')
144 stdscr.insstr('def', curses.A_BOLD)
145 stdscr.insstr(5, 5, 'def')
146 stdscr.insstr(5, 5, 'def', curses.A_BOLD)
147 stdscr.is_linetouched(0)
148 stdscr.keypad(1)
149 stdscr.leaveok(1)
150 stdscr.move(3,3)
151 win.mvwin(2,2)
152 stdscr.nodelay(1)
153 stdscr.notimeout(1)
154 win2.overlay(win)
155 win2.overwrite(win)
156 win2.overlay(win, 1, 2, 2, 1, 3, 3)
157 win2.overwrite(win, 1, 2, 2, 1, 3, 3)
158 stdscr.redrawln(1,2)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000159
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300160 stdscr.scrollok(1)
161 stdscr.scroll()
162 stdscr.scroll(2)
163 stdscr.scroll(-3)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000164
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300165 stdscr.move(12, 2)
166 stdscr.setscrreg(10,15)
167 win3 = stdscr.subwin(10,10)
168 win3 = stdscr.subwin(10,10, 5,5)
169 stdscr.syncok(1)
170 stdscr.timeout(5)
171 stdscr.touchline(5,5)
172 stdscr.touchline(5,5,0)
173 stdscr.vline('a', 3)
174 stdscr.vline('a', 3, curses.A_STANDOUT)
175 stdscr.chgat(5, 2, 3, curses.A_BLINK)
176 stdscr.chgat(3, curses.A_BOLD)
177 stdscr.chgat(5, 8, curses.A_UNDERLINE)
178 stdscr.chgat(curses.A_BLINK)
179 stdscr.refresh()
Andrew M. Kuchling400a49b2007-04-11 13:39:00 +0000180
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300181 stdscr.vline(1,1, 'a', 3)
182 stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000183
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300184 if hasattr(curses, 'resize'):
185 stdscr.resize()
186 if hasattr(curses, 'enclose'):
187 stdscr.enclose()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000188
Benjamin Petersonf6701202016-08-13 18:15:28 -0700189 self.assertRaises(ValueError, stdscr.getstr, -400)
190 self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
Benjamin Peterson505989c2016-08-15 21:40:14 -0700191 self.assertRaises(ValueError, stdscr.instr, -2)
192 self.assertRaises(ValueError, stdscr.instr, 2, 3, -2)
Benjamin Petersonf6701202016-08-13 18:15:28 -0700193
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000194
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300195 def test_module_funcs(self):
196 "Test module-level functions"
197 for func in [curses.baudrate, curses.beep, curses.can_change_color,
198 curses.cbreak, curses.def_prog_mode, curses.doupdate,
199 curses.filter, curses.flash, curses.flushinp,
200 curses.has_colors, curses.has_ic, curses.has_il,
201 curses.isendwin, curses.killchar, curses.longname,
202 curses.nocbreak, curses.noecho, curses.nonl,
203 curses.noqiflush, curses.noraw,
204 curses.reset_prog_mode, curses.termattrs,
205 curses.termname, curses.erasechar, curses.getsyx]:
206 func()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000207
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300208 # Functions that actually need arguments
209 if curses.tigetstr("cnorm"):
210 curses.curs_set(1)
211 curses.delay_output(1)
212 curses.echo() ; curses.echo(1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000213
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300214 with tempfile.TemporaryFile() as f:
215 self.stdscr.putwin(f)
216 f.seek(0)
217 curses.getwin(f)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000218
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300219 curses.halfdelay(1)
220 curses.intrflush(1)
221 curses.meta(1)
222 curses.napms(100)
223 curses.newpad(50,50)
224 win = curses.newwin(5,5)
225 win = curses.newwin(5,5, 1,1)
226 curses.nl() ; curses.nl(1)
227 curses.putp(b'abc')
228 curses.qiflush()
229 curses.raw() ; curses.raw(1)
230 curses.setsyx(5,5)
231 curses.tigetflag('hc')
232 curses.tigetnum('co')
233 curses.tigetstr('cr')
234 curses.tparm(b'cr')
235 curses.typeahead(sys.__stdin__.fileno())
236 curses.unctrl('a')
237 curses.ungetch('a')
238 curses.use_env(1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000239
240 # Functions only available on a few platforms
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300241 def test_colors_funcs(self):
242 if not curses.has_colors():
Xavier de Gaye92201112017-01-06 09:44:36 +0100243 self.skipTest('requires colors support')
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000244 curses.start_color()
245 curses.init_pair(2, 1,1)
246 curses.color_content(1)
247 curses.color_pair(2)
Andrew M. Kuchlingd1badac2005-06-15 18:44:23 +0000248 curses.pair_content(curses.COLOR_PAIRS - 1)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000249 curses.pair_number(0)
250
Michael W. Hudson2b3feec2004-08-07 15:27:16 +0000251 if hasattr(curses, 'use_default_colors'):
252 curses.use_default_colors()
Andrew M. Kuchling69f31eb2003-08-13 23:11:04 +0000253
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300254 @requires_curses_func('keyname')
255 def test_keyname(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000256 curses.keyname(13)
257
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300258 @requires_curses_func('has_key')
259 def test_has_key(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000260 curses.has_key(13)
261
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300262 @requires_curses_func('getmouse')
263 def test_getmouse(self):
Anthony Baxtere94e3b42006-04-06 07:12:39 +0000264 (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300265 if availmask == 0:
Xavier de Gaye92201112017-01-06 09:44:36 +0100266 self.skipTest('mouse stuff not available')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300267 curses.mouseinterval(10)
268 # just verify these don't cause errors
269 curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
270 m = curses.getmouse()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000271
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300272 def test_userptr_without_set(self):
273 w = curses.newwin(10, 10)
274 p = curses.panel.new_panel(w)
275 # try to access userptr() before calling set_userptr() -- segfaults
276 with self.assertRaises(curses.panel.error,
277 msg='userptr should fail since not set'):
278 p.userptr()
Walter Dörwald4994d952006-06-19 08:07:50 +0000279
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300280 def test_userptr_memory_leak(self):
281 w = curses.newwin(10, 10)
282 p = curses.panel.new_panel(w)
283 obj = object()
284 nrefs = sys.getrefcount(obj)
285 for i in range(100):
286 p.set_userptr(obj)
Tim Peters58eb11c2004-01-18 20:29:55 +0000287
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300288 p.set_userptr(None)
289 self.assertEqual(sys.getrefcount(obj), nrefs,
290 "set_userptr leaked references")
Andrew M. Kuchlinge752e202003-08-29 18:37:37 +0000291
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300292 def test_userptr_segfault(self):
293 panel = curses.panel.new_panel(self.stdscr)
294 class A:
295 def __del__(self):
296 panel.set_userptr(None)
297 panel.set_userptr(A())
298 panel.set_userptr(None)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000299
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300300 def test_new_curses_panel(self):
301 panel = curses.panel.new_panel(self.stdscr)
302 self.assertRaises(TypeError, type(panel))
Andrew Kuchlinga49dcc52013-06-15 13:53:10 -0400303
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300304 @requires_curses_func('is_term_resized')
305 def test_is_term_resized(self):
306 curses.is_term_resized(*self.stdscr.getmaxyx())
Andrew Kuchlinga49dcc52013-06-15 13:53:10 -0400307
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300308 @requires_curses_func('resize_term')
309 def test_resize_term(self):
310 curses.resize_term(*self.stdscr.getmaxyx())
Andrew Kuchlingaa6c2972013-06-22 12:33:05 -0400311
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300312 @requires_curses_func('resizeterm')
313 def test_resizeterm(self):
314 stdscr = self.stdscr
Walter Dörwaldd391f082007-03-06 20:38:57 +0000315 lines, cols = curses.LINES, curses.COLS
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300316 new_lines = lines - 1
317 new_cols = cols + 1
318 curses.resizeterm(new_lines, new_cols)
Tim Petersea5962f2007-03-12 18:07:52 +0000319
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300320 self.assertEqual(curses.LINES, new_lines)
321 self.assertEqual(curses.COLS, new_cols)
Walter Dörwaldd391f082007-03-06 20:38:57 +0000322
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300323 def test_issue6243(self):
324 curses.ungetch(1025)
325 self.stdscr.getkey()
Andrew M. Kuchlingb49e53e2009-09-25 22:23:54 +0000326
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300327 def test_issue10570(self):
328 b = curses.tparm(curses.tigetstr("cup"), 5, 3)
329 self.assertIs(type(b), bytes)
Andrew M. Kuchling2158df02001-10-22 15:26:09 +0000330
Serhiy Storchaka4d42af12016-12-28 10:16:06 +0200331 def test_issue13051(self):
332 stdscr = self.stdscr
333 box = curses.textpad.Textbox(stdscr, insert_mode=True)
334 lines, cols = stdscr.getmaxyx()
335 stdscr.resize(lines-2, cols-2)
336 # this may cause infinite recursion, leading to a RuntimeError
337 box._insert_printable_char('a')
338
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300339
340class TestAscii(unittest.TestCase):
341
Serhiy Storchaka41833872016-06-18 22:08:49 +0300342 def test_controlnames(self):
343 for name in curses.ascii.controlnames:
344 self.assertTrue(hasattr(curses.ascii, name), name)
345
346 def test_ctypes(self):
347 def check(func, expected):
348 self.assertEqual(func(i), expected)
349 self.assertEqual(func(c), expected)
350
351 for i in range(256):
352 c = b = chr(i)
353 check(curses.ascii.isalnum, b.isalnum())
354 check(curses.ascii.isalpha, b.isalpha())
355 check(curses.ascii.isdigit, b.isdigit())
356 check(curses.ascii.islower, b.islower())
357 check(curses.ascii.isspace, b.isspace())
358 check(curses.ascii.isupper, b.isupper())
359
360 check(curses.ascii.isascii, i < 128)
361 check(curses.ascii.ismeta, i >= 128)
362 check(curses.ascii.isctrl, i < 32)
363 check(curses.ascii.iscntrl, i < 32 or i == 127)
364 check(curses.ascii.isblank, c in ' \t')
365 check(curses.ascii.isgraph, 32 < i <= 126)
366 check(curses.ascii.isprint, 32 <= i <= 126)
367 check(curses.ascii.ispunct, c in string.punctuation)
368 check(curses.ascii.isxdigit, c in string.hexdigits)
369
Serhiy Storchakaf77fe6b2016-12-28 10:04:27 +0200370 for i in (-2, -1, 256, sys.maxunicode, sys.maxunicode+1):
371 self.assertFalse(curses.ascii.isalnum(i))
372 self.assertFalse(curses.ascii.isalpha(i))
373 self.assertFalse(curses.ascii.isdigit(i))
374 self.assertFalse(curses.ascii.islower(i))
375 self.assertFalse(curses.ascii.isspace(i))
376 self.assertFalse(curses.ascii.isupper(i))
377
378 self.assertFalse(curses.ascii.isascii(i))
379 self.assertFalse(curses.ascii.isctrl(i))
380 self.assertFalse(curses.ascii.iscntrl(i))
381 self.assertFalse(curses.ascii.isblank(i))
382 self.assertFalse(curses.ascii.isgraph(i))
383 self.assertFalse(curses.ascii.isprint(i))
384 self.assertFalse(curses.ascii.ispunct(i))
385 self.assertFalse(curses.ascii.isxdigit(i))
386
387 self.assertFalse(curses.ascii.ismeta(-1))
388
Serhiy Storchaka41833872016-06-18 22:08:49 +0300389 def test_ascii(self):
390 ascii = curses.ascii.ascii
391 self.assertEqual(ascii('\xc1'), 'A')
392 self.assertEqual(ascii('A'), 'A')
393 self.assertEqual(ascii(ord('\xc1')), ord('A'))
394
395 def test_ctrl(self):
396 ctrl = curses.ascii.ctrl
397 self.assertEqual(ctrl('J'), '\n')
398 self.assertEqual(ctrl('\n'), '\n')
399 self.assertEqual(ctrl('@'), '\0')
400 self.assertEqual(ctrl(ord('J')), ord('\n'))
401
402 def test_alt(self):
403 alt = curses.ascii.alt
404 self.assertEqual(alt('\n'), '\x8a')
405 self.assertEqual(alt('A'), '\xc1')
406 self.assertEqual(alt(ord('A')), 0xc1)
407
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300408 def test_unctrl(self):
409 unctrl = curses.ascii.unctrl
410 self.assertEqual(unctrl('a'), 'a')
411 self.assertEqual(unctrl('A'), 'A')
412 self.assertEqual(unctrl(';'), ';')
413 self.assertEqual(unctrl(' '), ' ')
414 self.assertEqual(unctrl('\x7f'), '^?')
415 self.assertEqual(unctrl('\n'), '^J')
416 self.assertEqual(unctrl('\0'), '^@')
Serhiy Storchaka41833872016-06-18 22:08:49 +0300417 self.assertEqual(unctrl(ord('A')), 'A')
418 self.assertEqual(unctrl(ord('\n')), '^J')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300419 # Meta-bit characters
420 self.assertEqual(unctrl('\x8a'), '!^J')
421 self.assertEqual(unctrl('\xc1'), '!A')
Serhiy Storchaka41833872016-06-18 22:08:49 +0300422 self.assertEqual(unctrl(ord('\x8a')), '!^J')
423 self.assertEqual(unctrl(ord('\xc1')), '!A')
Serhiy Storchakaa8a259e2016-05-22 18:24:48 +0300424
425
426def test_main():
427 run_unittest(TestCurses, TestAscii)
428
429
430if __name__ == "__main__":
431 unittest.main()