blob: bd7d4fca8bee8f8fd2528b19f887832d9db985bb [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
13import sys
14import tempfile
15import unittest
16
17from test.support import requires, import_module, verbose
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000018
19# Optionally test curses module. This currently requires that the
20# 'curses' resource be given on the regrtest command line using the -u
21# option. If not available, nothing after this line will be executed.
Larry Hastings9147a962014-05-04 04:41:18 -070022import inspect
Neal Norwitz9f39f682006-01-06 04:18:21 +000023requires('curses')
24
R. David Murraya21e4ca2009-03-31 23:16:50 +000025# If either of these don't exist, skip the tests.
26curses = import_module('curses')
27curses.panel = import_module('curses.panel')
28
Zachary Warebaf45c52014-10-17 13:59:18 -050029term = os.environ.get('TERM', 'unknown')
Mark Dickinson945e2422010-02-21 13:42:03 +000030
Zachary Warebaf45c52014-10-17 13:59:18 -050031@unittest.skipUnless(sys.__stdout__.isatty(), 'sys.__stdout__ is not a tty')
32@unittest.skipIf(term == 'unknown',
33 "$TERM=%r, calling initscr() may cause exit" % term)
34@unittest.skipIf(sys.platform == "cygwin",
35 "cygwin's curses mostly just hangs")
36class TestCurses(unittest.TestCase):
37 @classmethod
38 def setUpClass(cls):
39 curses.setupterm(fd=sys.__stdout__.fileno())
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000040
Zachary Warebaf45c52014-10-17 13:59:18 -050041 def setUp(self):
42 if verbose:
43 # just to make the test output a little more readable
44 print()
45 self.stdscr = curses.initscr()
46 curses.savetty()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000047
Zachary Warebaf45c52014-10-17 13:59:18 -050048 def tearDown(self):
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000049 curses.resetty()
Andrew M. Kuchling2158df02001-10-22 15:26:09 +000050 curses.endwin()
Zachary Warebaf45c52014-10-17 13:59:18 -050051
52 def test_window_funcs(self):
53 "Test the methods of windows"
54 stdscr = self.stdscr
55 win = curses.newwin(10,10)
56 win = curses.newwin(5,5, 5,5)
57 win2 = curses.newwin(15,15, 5,5)
58
59 for meth in [stdscr.addch, stdscr.addstr]:
60 for args in [('a'), ('a', curses.A_BOLD),
61 (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
62 meth(*args)
63
64 for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
65 stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
66 stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
67 stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
68 stdscr.getparyx, stdscr.getyx, stdscr.inch,
69 stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
70 win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
71 stdscr.standout, stdscr.standend, stdscr.syncdown,
72 stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
73 meth()
74
75 stdscr.addnstr('1234', 3)
76 stdscr.addnstr('1234', 3, curses.A_BOLD)
77 stdscr.addnstr(4,4, '1234', 3)
78 stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
79
80 stdscr.attron(curses.A_BOLD)
81 stdscr.attroff(curses.A_BOLD)
82 stdscr.attrset(curses.A_BOLD)
83 stdscr.bkgd(' ')
84 stdscr.bkgd(' ', curses.A_REVERSE)
85 stdscr.bkgdset(' ')
86 stdscr.bkgdset(' ', curses.A_REVERSE)
87
88 win.border(65, 66, 67, 68,
89 69, 70, 71, 72)
90 win.border('|', '!', '-', '_',
91 '+', '\\', '#', '/')
92 with self.assertRaises(TypeError,
93 msg="Expected win.border() to raise TypeError"):
94 win.border(65, 66, 67, 68,
95 69, [], 71, 72)
96
97 stdscr.clearok(1)
98
99 win4 = stdscr.derwin(2,2)
100 win4 = stdscr.derwin(1,1, 5,5)
101 win4.mvderwin(9,9)
102
103 stdscr.echochar('a')
104 stdscr.echochar('a', curses.A_BOLD)
105 stdscr.hline('-', 5)
106 stdscr.hline('-', 5, curses.A_BOLD)
107 stdscr.hline(1,1,'-', 5)
108 stdscr.hline(1,1,'-', 5, curses.A_BOLD)
109
110 stdscr.idcok(1)
111 stdscr.idlok(1)
112 stdscr.immedok(1)
113 stdscr.insch('c')
114 stdscr.insdelln(1)
115 stdscr.insnstr('abc', 3)
116 stdscr.insnstr('abc', 3, curses.A_BOLD)
117 stdscr.insnstr(5, 5, 'abc', 3)
118 stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
119
120 stdscr.insstr('def')
121 stdscr.insstr('def', curses.A_BOLD)
122 stdscr.insstr(5, 5, 'def')
123 stdscr.insstr(5, 5, 'def', curses.A_BOLD)
124 stdscr.is_linetouched(0)
125 stdscr.keypad(1)
126 stdscr.leaveok(1)
127 stdscr.move(3,3)
128 win.mvwin(2,2)
129 stdscr.nodelay(1)
130 stdscr.notimeout(1)
131 win2.overlay(win)
132 win2.overwrite(win)
133 win2.overlay(win, 1, 2, 2, 1, 3, 3)
134 win2.overwrite(win, 1, 2, 2, 1, 3, 3)
135 stdscr.redrawln(1,2)
136
137 stdscr.scrollok(1)
138 stdscr.scroll()
139 stdscr.scroll(2)
140 stdscr.scroll(-3)
141
142 stdscr.move(12, 2)
143 stdscr.setscrreg(10,15)
144 win3 = stdscr.subwin(10,10)
145 win3 = stdscr.subwin(10,10, 5,5)
146 stdscr.syncok(1)
147 stdscr.timeout(5)
148 stdscr.touchline(5,5)
149 stdscr.touchline(5,5,0)
150 stdscr.vline('a', 3)
151 stdscr.vline('a', 3, curses.A_STANDOUT)
152 stdscr.chgat(5, 2, 3, curses.A_BLINK)
153 stdscr.chgat(3, curses.A_BOLD)
154 stdscr.chgat(5, 8, curses.A_UNDERLINE)
155 stdscr.chgat(curses.A_BLINK)
156 stdscr.refresh()
157
158 stdscr.vline(1,1, 'a', 3)
159 stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
160
161 if hasattr(curses, 'resize'):
162 stdscr.resize()
163 if hasattr(curses, 'enclose'):
164 stdscr.enclose()
165
166
167 def test_module_funcs(self):
168 "Test module-level functions"
169 stdscr = self.stdscr
170 for func in [curses.baudrate, curses.beep, curses.can_change_color,
171 curses.cbreak, curses.def_prog_mode, curses.doupdate,
172 curses.filter, curses.flash, curses.flushinp,
173 curses.has_colors, curses.has_ic, curses.has_il,
174 curses.isendwin, curses.killchar, curses.longname,
175 curses.nocbreak, curses.noecho, curses.nonl,
176 curses.noqiflush, curses.noraw,
177 curses.reset_prog_mode, curses.termattrs,
178 curses.termname, curses.erasechar, curses.getsyx]:
179 func()
180
181 # Functions that actually need arguments
182 if curses.tigetstr("cnorm"):
183 curses.curs_set(1)
184 curses.delay_output(1)
185 curses.echo() ; curses.echo(1)
186
187 f = tempfile.TemporaryFile()
188 stdscr.putwin(f)
189 f.seek(0)
190 curses.getwin(f)
191 f.close()
192
193 curses.halfdelay(1)
194 curses.intrflush(1)
195 curses.meta(1)
196 curses.napms(100)
197 curses.newpad(50,50)
198 win = curses.newwin(5,5)
199 win = curses.newwin(5,5, 1,1)
200 curses.nl() ; curses.nl(1)
201 curses.putp(b'abc')
202 curses.qiflush()
203 curses.raw() ; curses.raw(1)
204 curses.setsyx(5,5)
205 curses.tigetflag('hc')
206 curses.tigetnum('co')
207 curses.tigetstr('cr')
208 curses.tparm(b'cr')
209 curses.typeahead(sys.__stdin__.fileno())
210 curses.unctrl('a')
211 curses.ungetch('a')
212 curses.use_env(1)
213
214 # Functions only available on a few platforms
215 if curses.has_colors():
216 curses.start_color()
217 curses.init_pair(2, 1,1)
218 curses.color_content(1)
219 curses.color_pair(2)
220 curses.pair_content(curses.COLOR_PAIRS - 1)
221 curses.pair_number(0)
222
223 if hasattr(curses, 'use_default_colors'):
224 curses.use_default_colors()
225
226 if hasattr(curses, 'keyname'):
227 curses.keyname(13)
228
229 if hasattr(curses, 'has_key'):
230 curses.has_key(13)
231
232 if hasattr(curses, 'getmouse'):
233 (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
234 # availmask indicates that mouse stuff not available.
235 if availmask != 0:
236 curses.mouseinterval(10)
237 # just verify these don't cause errors
238 curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
239 m = curses.getmouse()
240
241 if hasattr(curses, 'is_term_resized'):
242 curses.is_term_resized(*stdscr.getmaxyx())
243 if hasattr(curses, 'resizeterm'):
244 curses.resizeterm(*stdscr.getmaxyx())
245 if hasattr(curses, 'resize_term'):
246 curses.resize_term(*stdscr.getmaxyx())
247
248 def test_unctrl(self):
249 from curses import ascii
250 for ch, expected in [('a', 'a'), ('A', 'A'),
251 (';', ';'), (' ', ' '),
252 ('\x7f', '^?'), ('\n', '^J'), ('\0', '^@'),
253 # Meta-bit characters
254 ('\x8a', '!^J'), ('\xc1', '!A'),
255 ]:
256 self.assertEqual(ascii.unctrl(ch), expected,
257 'curses.unctrl fails on character %r' % ch)
258
259
260 def test_userptr_without_set(self):
261 w = curses.newwin(10, 10)
262 p = curses.panel.new_panel(w)
263 # try to access userptr() before calling set_userptr() -- segfaults
264 with self.assertRaises(curses.panel.error,
265 msg='userptr should fail since not set'):
266 p.userptr()
267
268 def test_userptr_memory_leak(self):
269 w = curses.newwin(10, 10)
270 p = curses.panel.new_panel(w)
271 obj = object()
272 nrefs = sys.getrefcount(obj)
273 for i in range(100):
274 p.set_userptr(obj)
275
276 p.set_userptr(None)
277 self.assertEqual(sys.getrefcount(obj), nrefs,
278 "set_userptr leaked references")
279
280 def test_userptr_segfault(self):
281 panel = curses.panel.new_panel(self.stdscr)
282 class A:
283 def __del__(self):
284 panel.set_userptr(None)
285 panel.set_userptr(A())
286 panel.set_userptr(None)
287
288 @unittest.skipUnless(hasattr(curses, 'resizeterm'),
289 'resizeterm not available')
290 def test_resize_term(self):
291 lines, cols = curses.LINES, curses.COLS
292 new_lines = lines - 1
293 new_cols = cols + 1
294 curses.resizeterm(new_lines, new_cols)
295
296 self.assertEqual(curses.LINES, new_lines)
297 self.assertEqual(curses.COLS, new_cols)
298
299 def test_issue6243(self):
300 curses.ungetch(1025)
301 self.stdscr.getkey()
302
303 @unittest.skipUnless(hasattr(curses, 'unget_wch'),
304 'unget_wch not available')
305 def test_unget_wch(self):
306 stdscr = self.stdscr
307 encoding = stdscr.encoding
308 for ch in ('a', '\xe9', '\u20ac', '\U0010FFFF'):
309 try:
310 ch.encode(encoding)
311 except UnicodeEncodeError:
312 continue
313 try:
314 curses.unget_wch(ch)
315 except Exception as err:
316 self.fail("unget_wch(%a) failed with encoding %s: %s"
317 % (ch, stdscr.encoding, err))
318 read = stdscr.get_wch()
319 self.assertEqual(read, ch)
320
321 code = ord(ch)
322 curses.unget_wch(code)
323 read = stdscr.get_wch()
324 self.assertEqual(read, ch)
325
326 def test_issue10570(self):
327 b = curses.tparm(curses.tigetstr("cup"), 5, 3)
328 self.assertIs(type(b), bytes)
329 curses.putp(b)
330
331 def test_encoding(self):
332 stdscr = self.stdscr
333 import codecs
334 encoding = stdscr.encoding
335 codecs.lookup(encoding)
336
337 with self.assertRaises(TypeError):
338 stdscr.encoding = 10
339
340 stdscr.encoding = encoding
341 with self.assertRaises(TypeError):
342 del stdscr.encoding
343
344 def test_issue21088(self):
345 stdscr = self.stdscr
346 #
347 # http://bugs.python.org/issue21088
348 #
349 # the bug:
350 # when converting curses.window.addch to Argument Clinic
351 # the first two parameters were switched.
352
353 # if someday we can represent the signature of addch
354 # we will need to rewrite this test.
355 try:
356 signature = inspect.signature(stdscr.addch)
357 self.assertFalse(signature)
358 except ValueError:
359 # not generating a signature is fine.
360 pass
361
362 # So. No signature for addch.
363 # But Argument Clinic gave us a human-readable equivalent
364 # as the first line of the docstring. So we parse that,
365 # and ensure that the parameters appear in the correct order.
366 # Since this is parsing output from Argument Clinic, we can
367 # be reasonably certain the generated parsing code will be
368 # correct too.
369 human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
370 offset = human_readable_signature.find("[y, x,]")
371 assert offset >= 0, ""
372
Alexandre Vassalotti5ff02352009-07-22 21:27:53 +0000373
374if __name__ == '__main__':
Zachary Warebaf45c52014-10-17 13:59:18 -0500375 unittest.main()