44# This script doesn't actually display anything very coherent. but it
55# does call (nearly) every method and function.
66#
7- # Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr(),
8- # init_color()
7+ # Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr()
98# Only called, not tested: getmouse(), ungetmouse()
109#
1110
1211import os
1312import string
1413import sys
1514import tempfile
15+ import functools
1616import unittest
1717
1818from test .support import requires , import_module , verbose , SaveSignals
@@ -36,7 +36,17 @@ def requires_curses_func(name):
3636 return unittest .skipUnless (hasattr (curses , name ),
3737 'requires curses.%s' % name )
3838
39+ def requires_colors (test ):
40+ @functools .wraps (test )
41+ def wrapped (self , * args , ** kwargs ):
42+ if not curses .has_colors ():
43+ self .skipTest ('requires colors support' )
44+ curses .start_color ()
45+ test (self , * args , ** kwargs )
46+ return wrapped
47+
3948term = os .environ .get ('TERM' )
49+ SHORT_MAX = 0x7fff
4050
4151# If newterm was supported we could use it instead of initscr and not exit
4252@unittest .skipIf (not term or term == 'unknown' ,
@@ -47,6 +57,8 @@ class TestCurses(unittest.TestCase):
4757
4858 @classmethod
4959 def setUpClass (cls ):
60+ if verbose :
61+ print (f'TERM={ term } ' , file = sys .stderr , flush = True )
5062 # testing setupterm() inside initscr/endwin
5163 # causes terminal breakage
5264 stdout_fd = sys .__stdout__ .fileno ()
@@ -304,18 +316,111 @@ def test_module_funcs(self):
304316 curses .use_env (1 )
305317
306318 # Functions only available on a few platforms
307- def test_colors_funcs (self ):
308- if not curses .has_colors ():
309- self .skipTest ('requires colors support' )
310- curses .start_color ()
311- curses .init_pair (2 , 1 ,1 )
312- curses .color_content (1 )
313- curses .color_pair (2 )
314- curses .pair_content (min (curses .COLOR_PAIRS - 1 , 0x7fff ))
315- curses .pair_number (0 )
316-
317- if hasattr (curses , 'use_default_colors' ):
318- curses .use_default_colors ()
319+
320+ def bad_colors (self ):
321+ return (- 2 ** 31 - 1 , 2 ** 31 , - 2 ** 63 - 1 , 2 ** 63 , 2 ** 64 )
322+
323+ def bad_pairs (self ):
324+ return (- 2 ** 31 - 1 , 2 ** 31 , - 2 ** 63 - 1 , 2 ** 63 , 2 ** 64 )
325+
326+ @requires_colors
327+ def test_color_content (self ):
328+ self .assertEqual (curses .color_content (curses .COLOR_BLACK ), (0 , 0 , 0 ))
329+ curses .color_content (0 )
330+ curses .color_content (min (curses .COLORS - 1 , SHORT_MAX ))
331+
332+ for color in self .bad_colors ():
333+ self .assertRaises (OverflowError , curses .color_content , color )
334+ if curses .COLORS <= SHORT_MAX :
335+ self .assertRaises (curses .error , curses .color_content , curses .COLORS )
336+ self .assertRaises (curses .error , curses .color_content , - 1 )
337+
338+ @requires_colors
339+ def test_init_color (self ):
340+ if not curses .can_change_color :
341+ self .skipTest ('cannot change color' )
342+
343+ old = curses .color_content (0 )
344+ try :
345+ curses .init_color (0 , * old )
346+ except curses .error :
347+ self .skipTest ('cannot change color (init_color() failed)' )
348+ self .addCleanup (curses .init_color , 0 , * old )
349+ curses .init_color (0 , 0 , 0 , 0 )
350+ self .assertEqual (curses .color_content (0 ), (0 , 0 , 0 ))
351+ curses .init_color (0 , 1000 , 1000 , 1000 )
352+ self .assertEqual (curses .color_content (0 ), (1000 , 1000 , 1000 ))
353+
354+ maxcolor = min (curses .COLORS - 1 , SHORT_MAX )
355+ old = curses .color_content (maxcolor )
356+ curses .init_color (maxcolor , * old )
357+ self .addCleanup (curses .init_color , maxcolor , * old )
358+ curses .init_color (maxcolor , 0 , 500 , 1000 )
359+ self .assertEqual (curses .color_content (maxcolor ), (0 , 500 , 1000 ))
360+
361+ for color in self .bad_colors ():
362+ self .assertRaises (OverflowError , curses .init_color , color , 0 , 0 , 0 )
363+ if curses .COLORS <= SHORT_MAX :
364+ self .assertRaises (curses .error , curses .init_color , curses .COLORS , 0 , 0 , 0 )
365+ self .assertRaises (curses .error , curses .init_color , - 1 , 0 , 0 , 0 )
366+ for comp in (- 1 , 1001 ):
367+ self .assertRaises (curses .error , curses .init_color , 0 , comp , 0 , 0 )
368+ self .assertRaises (curses .error , curses .init_color , 0 , 0 , comp , 0 )
369+ self .assertRaises (curses .error , curses .init_color , 0 , 0 , 0 , comp )
370+
371+ @requires_colors
372+ def test_pair_content (self ):
373+ if not hasattr (curses , 'use_default_colors' ):
374+ self .assertEqual (curses .pair_content (0 ),
375+ (curses .COLOR_WHITE , curses .COLOR_BLACK ))
376+ curses .pair_content (0 )
377+ curses .pair_content (min (curses .COLOR_PAIRS - 1 , SHORT_MAX ))
378+
379+ for pair in self .bad_pairs ():
380+ self .assertRaises (OverflowError , curses .pair_content , pair )
381+ self .assertRaises (curses .error , curses .pair_content , - 1 )
382+
383+ @requires_colors
384+ def test_init_pair (self ):
385+ old = curses .pair_content (1 )
386+ curses .init_pair (1 , * old )
387+ self .addCleanup (curses .init_pair , 1 , * old )
388+
389+ curses .init_pair (1 , 0 , 0 )
390+ self .assertEqual (curses .pair_content (1 ), (0 , 0 ))
391+ maxcolor = min (curses .COLORS - 1 , SHORT_MAX )
392+ curses .init_pair (1 , maxcolor , maxcolor )
393+ self .assertEqual (curses .pair_content (1 ), (maxcolor , maxcolor ))
394+ maxpair = min (curses .COLOR_PAIRS - 1 , SHORT_MAX )
395+ curses .init_pair (maxpair , 2 , 3 )
396+ self .assertEqual (curses .pair_content (maxpair ), (2 , 3 ))
397+
398+ for pair in self .bad_pairs ():
399+ self .assertRaises (OverflowError , curses .init_pair , pair , 0 , 0 )
400+ self .assertRaises (curses .error , curses .init_pair , - 1 , 0 , 0 )
401+ for color in self .bad_colors ():
402+ self .assertRaises (OverflowError , curses .init_pair , 1 , color , 0 )
403+ self .assertRaises (OverflowError , curses .init_pair , 1 , 0 , color )
404+ if curses .COLORS <= SHORT_MAX :
405+ self .assertRaises (curses .error , curses .init_pair , 1 , curses .COLORS , 0 )
406+ self .assertRaises (curses .error , curses .init_pair , 1 , 0 , curses .COLORS )
407+
408+ @requires_colors
409+ def test_color_attrs (self ):
410+ for pair in 0 , 1 , 255 :
411+ attr = curses .color_pair (pair )
412+ self .assertEqual (curses .pair_number (attr ), pair , attr )
413+ self .assertEqual (curses .pair_number (attr | curses .A_BOLD ), pair )
414+ self .assertEqual (curses .color_pair (0 ), 0 )
415+ self .assertEqual (curses .pair_number (0 ), 0 )
416+
417+ @requires_curses_func ('use_default_colors' )
418+ @requires_colors
419+ def test_use_default_colors (self ):
420+ self .assertIn (curses .pair_content (0 ),
421+ ((curses .COLOR_WHITE , curses .COLOR_BLACK ), (- 1 , - 1 )))
422+ curses .use_default_colors ()
423+ self .assertEqual (curses .pair_content (0 ), (- 1 , - 1 ))
319424
320425 @requires_curses_func ('keyname' )
321426 def test_keyname (self ):
0 commit comments