test_curses.py revision aa6c297316a62baed42f10508cf21d781b0fbee4
1#
2# Test script for the curses module
3#
4# This script doesn't actually display anything very coherent. but it
5# does call every method and function.
6#
7# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr(),
8# init_color()
9# Only called, not tested: getmouse(), ungetmouse()
10#
11
12import sys, tempfile, os
13
14# Optionally test curses module.  This currently requires that the
15# 'curses' resource be given on the regrtest command line using the -u
16# option.  If not available, nothing after this line will be executed.
17
18import unittest
19from test.test_support import requires, import_module
20requires('curses')
21curses = import_module('curses')
22curses.panel = import_module('curses.panel')
23
24
25# XXX: if newterm was supported we could use it instead of initscr and not exit
26term = os.environ.get('TERM')
27if not term or term == 'unknown':
28    raise unittest.SkipTest, "$TERM=%r, calling initscr() may cause exit" % term
29
30if sys.platform == "cygwin":
31    raise unittest.SkipTest("cygwin's curses mostly just hangs")
32
33def window_funcs(stdscr):
34    "Test the methods of windows"
35    win = curses.newwin(10,10)
36    win = curses.newwin(5,5, 5,5)
37    win2 = curses.newwin(15,15, 5,5)
38
39    for meth in [stdscr.addch, stdscr.addstr]:
40        for args in [('a'), ('a', curses.A_BOLD),
41                     (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
42            meth(*args)
43
44    for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
45                 stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
46                 stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
47                 stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
48                 stdscr.getparyx, stdscr.getyx, stdscr.inch,
49                 stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
50                 win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
51                 stdscr.standout, stdscr.standend, stdscr.syncdown,
52                 stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
53        meth()
54
55    stdscr.addnstr('1234', 3)
56    stdscr.addnstr('1234', 3, curses.A_BOLD)
57    stdscr.addnstr(4,4, '1234', 3)
58    stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
59
60    stdscr.attron(curses.A_BOLD)
61    stdscr.attroff(curses.A_BOLD)
62    stdscr.attrset(curses.A_BOLD)
63    stdscr.bkgd(' ')
64    stdscr.bkgd(' ', curses.A_REVERSE)
65    stdscr.bkgdset(' ')
66    stdscr.bkgdset(' ', curses.A_REVERSE)
67
68    win.border(65, 66, 67, 68,
69               69, 70, 71, 72)
70    win.border('|', '!', '-', '_',
71               '+', '\\', '#', '/')
72    try:
73        win.border(65, 66, 67, 68,
74                   69, [], 71, 72)
75    except TypeError:
76        pass
77    else:
78        raise RuntimeError, "Expected win.border() to raise TypeError"
79
80    stdscr.clearok(1)
81
82    win4 = stdscr.derwin(2,2)
83    win4 = stdscr.derwin(1,1, 5,5)
84    win4.mvderwin(9,9)
85
86    stdscr.echochar('a')
87    stdscr.echochar('a', curses.A_BOLD)
88    stdscr.hline('-', 5)
89    stdscr.hline('-', 5, curses.A_BOLD)
90    stdscr.hline(1,1,'-', 5)
91    stdscr.hline(1,1,'-', 5, curses.A_BOLD)
92
93    stdscr.idcok(1)
94    stdscr.idlok(1)
95    stdscr.immedok(1)
96    stdscr.insch('c')
97    stdscr.insdelln(1)
98    stdscr.insnstr('abc', 3)
99    stdscr.insnstr('abc', 3, curses.A_BOLD)
100    stdscr.insnstr(5, 5, 'abc', 3)
101    stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
102
103    stdscr.insstr('def')
104    stdscr.insstr('def', curses.A_BOLD)
105    stdscr.insstr(5, 5, 'def')
106    stdscr.insstr(5, 5, 'def', curses.A_BOLD)
107    stdscr.is_linetouched(0)
108    stdscr.keypad(1)
109    stdscr.leaveok(1)
110    stdscr.move(3,3)
111    win.mvwin(2,2)
112    stdscr.nodelay(1)
113    stdscr.notimeout(1)
114    win2.overlay(win)
115    win2.overwrite(win)
116    win2.overlay(win, 1, 2, 3, 3, 2, 1)
117    win2.overwrite(win, 1, 2, 3, 3, 2, 1)
118    stdscr.redrawln(1,2)
119
120    stdscr.scrollok(1)
121    stdscr.scroll()
122    stdscr.scroll(2)
123    stdscr.scroll(-3)
124
125    stdscr.move(12, 2)
126    stdscr.setscrreg(10,15)
127    win3 = stdscr.subwin(10,10)
128    win3 = stdscr.subwin(10,10, 5,5)
129    stdscr.syncok(1)
130    stdscr.timeout(5)
131    stdscr.touchline(5,5)
132    stdscr.touchline(5,5,0)
133    stdscr.vline('a', 3)
134    stdscr.vline('a', 3, curses.A_STANDOUT)
135    stdscr.chgat(5, 2, 3, curses.A_BLINK)
136    stdscr.chgat(3, curses.A_BOLD)
137    stdscr.chgat(5, 8, curses.A_UNDERLINE)
138    stdscr.chgat(curses.A_BLINK)
139    stdscr.refresh()
140
141    stdscr.vline(1,1, 'a', 3)
142    stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
143
144    if hasattr(curses, 'resize'):
145        stdscr.resize()
146    if hasattr(curses, 'enclose'):
147        stdscr.enclose()
148
149
150def module_funcs(stdscr):
151    "Test module-level functions"
152
153    for func in [curses.baudrate, curses.beep, curses.can_change_color,
154                 curses.cbreak, curses.def_prog_mode, curses.doupdate,
155                 curses.filter, curses.flash, curses.flushinp,
156                 curses.has_colors, curses.has_ic, curses.has_il,
157                 curses.isendwin, curses.killchar, curses.longname,
158                 curses.nocbreak, curses.noecho, curses.nonl,
159                 curses.noqiflush, curses.noraw,
160                 curses.reset_prog_mode, curses.termattrs,
161                 curses.termname, curses.erasechar, curses.getsyx]:
162        func()
163
164    # Functions that actually need arguments
165    if curses.tigetstr("cnorm"):
166        curses.curs_set(1)
167    curses.delay_output(1)
168    curses.echo() ; curses.echo(1)
169
170    f = tempfile.TemporaryFile()
171    stdscr.putwin(f)
172    f.seek(0)
173    curses.getwin(f)
174    f.close()
175
176    curses.halfdelay(1)
177    curses.intrflush(1)
178    curses.meta(1)
179    curses.napms(100)
180    curses.newpad(50,50)
181    win = curses.newwin(5,5)
182    win = curses.newwin(5,5, 1,1)
183    curses.nl() ; curses.nl(1)
184    curses.putp('abc')
185    curses.qiflush()
186    curses.raw() ; curses.raw(1)
187    curses.setsyx(5,5)
188    curses.tigetflag('hc')
189    curses.tigetnum('co')
190    curses.tigetstr('cr')
191    curses.tparm('cr')
192    curses.typeahead(sys.__stdin__.fileno())
193    curses.unctrl('a')
194    curses.ungetch('a')
195    curses.use_env(1)
196
197    # Functions only available on a few platforms
198    if curses.has_colors():
199        curses.start_color()
200        curses.init_pair(2, 1,1)
201        curses.color_content(1)
202        curses.color_pair(2)
203        curses.pair_content(curses.COLOR_PAIRS - 1)
204        curses.pair_number(0)
205
206        if hasattr(curses, 'use_default_colors'):
207            curses.use_default_colors()
208
209    if hasattr(curses, 'keyname'):
210        curses.keyname(13)
211
212    if hasattr(curses, 'has_key'):
213        curses.has_key(13)
214
215    if hasattr(curses, 'getmouse'):
216        (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
217        # availmask indicates that mouse stuff not available.
218        if availmask != 0:
219            curses.mouseinterval(10)
220            # just verify these don't cause errors
221            curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
222            m = curses.getmouse()
223
224    if hasattr(curses, 'is_term_resized'):
225        curses.is_term_resized(*stdscr.getmaxyx())
226    if hasattr(curses, 'resizeterm'):
227        curses.resizeterm(*stdscr.getmaxyx())
228    if hasattr(curses, 'resize_term'):
229        curses.resize_term(*stdscr.getmaxyx())
230
231def unit_tests():
232    from curses import ascii
233    for ch, expected in [('a', 'a'), ('A', 'A'),
234                         (';', ';'), (' ', ' '),
235                         ('\x7f', '^?'), ('\n', '^J'), ('\0', '^@'),
236                         # Meta-bit characters
237                         ('\x8a', '!^J'), ('\xc1', '!A'),
238                         ]:
239        if ascii.unctrl(ch) != expected:
240            print 'curses.unctrl fails on character', repr(ch)
241
242
243def test_userptr_without_set(stdscr):
244    w = curses.newwin(10, 10)
245    p = curses.panel.new_panel(w)
246    # try to access userptr() before calling set_userptr() -- segfaults
247    try:
248        p.userptr()
249        raise RuntimeError, 'userptr should fail since not set'
250    except curses.panel.error:
251        pass
252
253def test_userptr_memory_leak(stdscr):
254    w = curses.newwin(10, 10)
255    p = curses.panel.new_panel(w)
256    obj = object()
257    nrefs = sys.getrefcount(obj)
258    for i in range(100):
259        p.set_userptr(obj)
260
261    p.set_userptr(None)
262    if sys.getrefcount(obj) != nrefs:
263        raise RuntimeError, "set_userptr leaked references"
264
265def test_userptr_segfault(stdscr):
266    panel = curses.panel.new_panel(stdscr)
267    class A:
268        def __del__(self):
269            panel.set_userptr(None)
270    panel.set_userptr(A())
271    panel.set_userptr(None)
272
273def test_resize_term(stdscr):
274    if hasattr(curses, 'resizeterm'):
275        lines, cols = curses.LINES, curses.COLS
276        curses.resizeterm(lines - 1, cols + 1)
277
278        if curses.LINES != lines - 1 or curses.COLS != cols + 1:
279            raise RuntimeError, "Expected resizeterm to update LINES and COLS"
280
281def test_issue6243(stdscr):
282    curses.ungetch(1025)
283    stdscr.getkey()
284
285def main(stdscr):
286    curses.savetty()
287    try:
288        module_funcs(stdscr)
289        window_funcs(stdscr)
290        test_userptr_without_set(stdscr)
291        test_userptr_memory_leak(stdscr)
292        test_userptr_segfault(stdscr)
293        test_resize_term(stdscr)
294        test_issue6243(stdscr)
295    finally:
296        curses.resetty()
297
298if __name__ == '__main__':
299    curses.wrapper(main)
300    unit_tests()
301else:
302    if not sys.__stdout__.isatty():
303        raise unittest.SkipTest("sys.__stdout__ is not a tty")
304    # testing setupterm() inside initscr/endwin
305    # causes terminal breakage
306    curses.setupterm(fd=sys.__stdout__.fileno())
307    try:
308        stdscr = curses.initscr()
309        main(stdscr)
310    finally:
311        curses.endwin()
312    unit_tests()
313