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    fx = tempfile.TemporaryFile()
171    # cf tempfile.py TemporaryFile vs NamedTemporaryFile
172    if os.name != 'posix' or os.sys.platform == 'cygwin':
173        f = fx.file
174    else:
175        f = fx
176    stdscr.putwin(f)
177    f.seek(0)
178    curses.getwin(f)
179    fx.close()
180
181    curses.halfdelay(1)
182    curses.intrflush(1)
183    curses.meta(1)
184    curses.napms(100)
185    curses.newpad(50,50)
186    win = curses.newwin(5,5)
187    win = curses.newwin(5,5, 1,1)
188    curses.nl() ; curses.nl(1)
189    curses.putp('abc')
190    curses.qiflush()
191    curses.raw() ; curses.raw(1)
192    curses.setsyx(5,5)
193    curses.tigetflag('hc')
194    curses.tigetnum('co')
195    curses.tigetstr('cr')
196    curses.tparm('cr')
197    curses.typeahead(sys.__stdin__.fileno())
198    curses.unctrl('a')
199    curses.ungetch('a')
200    curses.use_env(1)
201
202    # Functions only available on a few platforms
203    if curses.has_colors():
204        curses.start_color()
205        curses.init_pair(2, 1,1)
206        curses.color_content(1)
207        curses.color_pair(2)
208        curses.pair_content(curses.COLOR_PAIRS - 1)
209        curses.pair_number(0)
210
211        if hasattr(curses, 'use_default_colors'):
212            curses.use_default_colors()
213
214    if hasattr(curses, 'keyname'):
215        curses.keyname(13)
216
217    if hasattr(curses, 'has_key'):
218        curses.has_key(13)
219
220    if hasattr(curses, 'getmouse'):
221        (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
222        # availmask indicates that mouse stuff not available.
223        if availmask != 0:
224            curses.mouseinterval(10)
225            # just verify these don't cause errors
226            curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
227            m = curses.getmouse()
228
229    if hasattr(curses, 'is_term_resized'):
230        curses.is_term_resized(*stdscr.getmaxyx())
231    if hasattr(curses, 'resizeterm'):
232        curses.resizeterm(*stdscr.getmaxyx())
233    if hasattr(curses, 'resize_term'):
234        curses.resize_term(*stdscr.getmaxyx())
235
236def unit_tests():
237    from curses import ascii
238    for ch, expected in [('a', 'a'), ('A', 'A'),
239                         (';', ';'), (' ', ' '),
240                         ('\x7f', '^?'), ('\n', '^J'), ('\0', '^@'),
241                         # Meta-bit characters
242                         ('\x8a', '!^J'), ('\xc1', '!A'),
243                         ]:
244        if ascii.unctrl(ch) != expected:
245            print 'curses.unctrl fails on character', repr(ch)
246
247
248def test_userptr_without_set(stdscr):
249    w = curses.newwin(10, 10)
250    p = curses.panel.new_panel(w)
251    # try to access userptr() before calling set_userptr() -- segfaults
252    try:
253        p.userptr()
254        raise RuntimeError, 'userptr should fail since not set'
255    except curses.panel.error:
256        pass
257
258def test_resize_term(stdscr):
259    if hasattr(curses, 'resizeterm'):
260        lines, cols = curses.LINES, curses.COLS
261        curses.resizeterm(lines - 1, cols + 1)
262
263        if curses.LINES != lines - 1 or curses.COLS != cols + 1:
264            raise RuntimeError, "Expected resizeterm to update LINES and COLS"
265
266def test_issue6243(stdscr):
267    curses.ungetch(1025)
268    stdscr.getkey()
269
270def main(stdscr):
271    curses.savetty()
272    try:
273        module_funcs(stdscr)
274        window_funcs(stdscr)
275        test_userptr_without_set(stdscr)
276        test_resize_term(stdscr)
277        test_issue6243(stdscr)
278    finally:
279        curses.resetty()
280
281if __name__ == '__main__':
282    curses.wrapper(main)
283    unit_tests()
284else:
285    if not sys.__stdout__.isatty():
286        raise unittest.SkipTest("sys.__stdout__ is not a tty")
287    # testing setupterm() inside initscr/endwin
288    # causes terminal breakage
289    curses.setupterm(fd=sys.__stdout__.fileno())
290    try:
291        stdscr = curses.initscr()
292        main(stdscr)
293    finally:
294        curses.endwin()
295    unit_tests()
296