Home | History | Annotate | Download | only in test
      1 import unittest
      2 import re
      3 import subprocess
      4 import sys
      5 import os
      6 from test import support
      7 
      8 # Skip this test if the _tkinter module wasn't built.
      9 _tkinter = support.import_module('_tkinter')
     10 
     11 import tkinter
     12 from tkinter import Tcl
     13 from _tkinter import TclError
     14 
     15 try:
     16     from _testcapi import INT_MAX, PY_SSIZE_T_MAX
     17 except ImportError:
     18     INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
     19 
     20 tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.')))
     21 
     22 _tk_patchlevel = None
     23 def get_tk_patchlevel():
     24     global _tk_patchlevel
     25     if _tk_patchlevel is None:
     26         tcl = Tcl()
     27         patchlevel = tcl.call('info', 'patchlevel')
     28         m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel)
     29         major, minor, releaselevel, serial = m.groups()
     30         major, minor, serial = int(major), int(minor), int(serial)
     31         releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel]
     32         if releaselevel == 'final':
     33             _tk_patchlevel = major, minor, serial, releaselevel, 0
     34         else:
     35             _tk_patchlevel = major, minor, 0, releaselevel, serial
     36     return _tk_patchlevel
     37 
     38 
     39 class TkinterTest(unittest.TestCase):
     40 
     41     def testFlattenLen(self):
     42         # flatten(<object with no length>)
     43         self.assertRaises(TypeError, _tkinter._flatten, True)
     44 
     45 
     46 class TclTest(unittest.TestCase):
     47 
     48     def setUp(self):
     49         self.interp = Tcl()
     50         self.wantobjects = self.interp.tk.wantobjects()
     51 
     52     def testEval(self):
     53         tcl = self.interp
     54         tcl.eval('set a 1')
     55         self.assertEqual(tcl.eval('set a'),'1')
     56 
     57     def test_eval_null_in_result(self):
     58         tcl = self.interp
     59         self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
     60 
     61     def testEvalException(self):
     62         tcl = self.interp
     63         self.assertRaises(TclError,tcl.eval,'set a')
     64 
     65     def testEvalException2(self):
     66         tcl = self.interp
     67         self.assertRaises(TclError,tcl.eval,'this is wrong')
     68 
     69     def testCall(self):
     70         tcl = self.interp
     71         tcl.call('set','a','1')
     72         self.assertEqual(tcl.call('set','a'),'1')
     73 
     74     def testCallException(self):
     75         tcl = self.interp
     76         self.assertRaises(TclError,tcl.call,'set','a')
     77 
     78     def testCallException2(self):
     79         tcl = self.interp
     80         self.assertRaises(TclError,tcl.call,'this','is','wrong')
     81 
     82     def testSetVar(self):
     83         tcl = self.interp
     84         tcl.setvar('a','1')
     85         self.assertEqual(tcl.eval('set a'),'1')
     86 
     87     def testSetVarArray(self):
     88         tcl = self.interp
     89         tcl.setvar('a(1)','1')
     90         self.assertEqual(tcl.eval('set a(1)'),'1')
     91 
     92     def testGetVar(self):
     93         tcl = self.interp
     94         tcl.eval('set a 1')
     95         self.assertEqual(tcl.getvar('a'),'1')
     96 
     97     def testGetVarArray(self):
     98         tcl = self.interp
     99         tcl.eval('set a(1) 1')
    100         self.assertEqual(tcl.getvar('a(1)'),'1')
    101 
    102     def testGetVarException(self):
    103         tcl = self.interp
    104         self.assertRaises(TclError,tcl.getvar,'a')
    105 
    106     def testGetVarArrayException(self):
    107         tcl = self.interp
    108         self.assertRaises(TclError,tcl.getvar,'a(1)')
    109 
    110     def testUnsetVar(self):
    111         tcl = self.interp
    112         tcl.setvar('a',1)
    113         self.assertEqual(tcl.eval('info exists a'),'1')
    114         tcl.unsetvar('a')
    115         self.assertEqual(tcl.eval('info exists a'),'0')
    116 
    117     def testUnsetVarArray(self):
    118         tcl = self.interp
    119         tcl.setvar('a(1)',1)
    120         tcl.setvar('a(2)',2)
    121         self.assertEqual(tcl.eval('info exists a(1)'),'1')
    122         self.assertEqual(tcl.eval('info exists a(2)'),'1')
    123         tcl.unsetvar('a(1)')
    124         self.assertEqual(tcl.eval('info exists a(1)'),'0')
    125         self.assertEqual(tcl.eval('info exists a(2)'),'1')
    126 
    127     def testUnsetVarException(self):
    128         tcl = self.interp
    129         self.assertRaises(TclError,tcl.unsetvar,'a')
    130 
    131     def get_integers(self):
    132         integers = (0, 1, -1, 2**31-1, -2**31, 2**31, -2**31-1, 2**63-1, -2**63)
    133         # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
    134         if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
    135             (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
    136             integers += (2**63, -2**63-1, 2**1000, -2**1000)
    137         return integers
    138 
    139     def test_getint(self):
    140         tcl = self.interp.tk
    141         for i in self.get_integers():
    142             self.assertEqual(tcl.getint(' %d ' % i), i)
    143             if tcl_version >= (8, 5):
    144                 self.assertEqual(tcl.getint(' %#o ' % i), i)
    145             self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i)
    146             self.assertEqual(tcl.getint(' %#x ' % i), i)
    147         if tcl_version < (8, 5):  # bignum was added in Tcl 8.5
    148             self.assertRaises(TclError, tcl.getint, str(2**1000))
    149         self.assertEqual(tcl.getint(42), 42)
    150         self.assertRaises(TypeError, tcl.getint)
    151         self.assertRaises(TypeError, tcl.getint, '42', '10')
    152         self.assertRaises(TypeError, tcl.getint, b'42')
    153         self.assertRaises(TypeError, tcl.getint, 42.0)
    154         self.assertRaises(TclError, tcl.getint, 'a')
    155         self.assertRaises((TypeError, ValueError, TclError),
    156                           tcl.getint, '42\0')
    157         self.assertRaises((UnicodeEncodeError, ValueError, TclError),
    158                           tcl.getint, '42\ud800')
    159 
    160     def test_getdouble(self):
    161         tcl = self.interp.tk
    162         self.assertEqual(tcl.getdouble(' 42 '), 42.0)
    163         self.assertEqual(tcl.getdouble(' 42.5 '), 42.5)
    164         self.assertEqual(tcl.getdouble(42.5), 42.5)
    165         self.assertEqual(tcl.getdouble(42), 42.0)
    166         self.assertRaises(TypeError, tcl.getdouble)
    167         self.assertRaises(TypeError, tcl.getdouble, '42.5', '10')
    168         self.assertRaises(TypeError, tcl.getdouble, b'42.5')
    169         self.assertRaises(TclError, tcl.getdouble, 'a')
    170         self.assertRaises((TypeError, ValueError, TclError),
    171                           tcl.getdouble, '42.5\0')
    172         self.assertRaises((UnicodeEncodeError, ValueError, TclError),
    173                           tcl.getdouble, '42.5\ud800')
    174 
    175     def test_getboolean(self):
    176         tcl = self.interp.tk
    177         self.assertIs(tcl.getboolean('on'), True)
    178         self.assertIs(tcl.getboolean('1'), True)
    179         self.assertIs(tcl.getboolean(42), True)
    180         self.assertIs(tcl.getboolean(0), False)
    181         self.assertRaises(TypeError, tcl.getboolean)
    182         self.assertRaises(TypeError, tcl.getboolean, 'on', '1')
    183         self.assertRaises(TypeError, tcl.getboolean, b'on')
    184         self.assertRaises(TypeError, tcl.getboolean, 1.0)
    185         self.assertRaises(TclError, tcl.getboolean, 'a')
    186         self.assertRaises((TypeError, ValueError, TclError),
    187                           tcl.getboolean, 'on\0')
    188         self.assertRaises((UnicodeEncodeError, ValueError, TclError),
    189                           tcl.getboolean, 'on\ud800')
    190 
    191     def testEvalFile(self):
    192         tcl = self.interp
    193         with open(support.TESTFN, 'w') as f:
    194             self.addCleanup(support.unlink, support.TESTFN)
    195             f.write("""set a 1
    196             set b 2
    197             set c [ expr $a + $b ]
    198             """)
    199         tcl.evalfile(support.TESTFN)
    200         self.assertEqual(tcl.eval('set a'),'1')
    201         self.assertEqual(tcl.eval('set b'),'2')
    202         self.assertEqual(tcl.eval('set c'),'3')
    203 
    204     def test_evalfile_null_in_result(self):
    205         tcl = self.interp
    206         with open(support.TESTFN, 'w') as f:
    207             self.addCleanup(support.unlink, support.TESTFN)
    208             f.write("""
    209             set a "a\0b"
    210             set b "a\\0b"
    211             """)
    212         tcl.evalfile(support.TESTFN)
    213         self.assertEqual(tcl.eval('set a'), 'a\x00b')
    214         self.assertEqual(tcl.eval('set b'), 'a\x00b')
    215 
    216     def testEvalFileException(self):
    217         tcl = self.interp
    218         filename = "doesnotexists"
    219         try:
    220             os.remove(filename)
    221         except Exception as e:
    222             pass
    223         self.assertRaises(TclError,tcl.evalfile,filename)
    224 
    225     def testPackageRequireException(self):
    226         tcl = self.interp
    227         self.assertRaises(TclError,tcl.eval,'package require DNE')
    228 
    229     @unittest.skipUnless(sys.platform == 'win32', 'Requires Windows')
    230     def testLoadWithUNC(self):
    231         # Build a UNC path from the regular path.
    232         # Something like
    233         #   \\%COMPUTERNAME%\c$\python27\python.exe
    234 
    235         fullname = os.path.abspath(sys.executable)
    236         if fullname[1] != ':':
    237             raise unittest.SkipTest('Absolute path should have drive part')
    238         unc_name = r'\\%s\%s$\%s' % (os.environ['COMPUTERNAME'],
    239                                     fullname[0],
    240                                     fullname[3:])
    241         if not os.path.exists(unc_name):
    242             raise unittest.SkipTest('Cannot connect to UNC Path')
    243 
    244         with support.EnvironmentVarGuard() as env:
    245             env.unset("TCL_LIBRARY")
    246             stdout = subprocess.check_output(
    247                     [unc_name, '-c', 'import tkinter; print(tkinter)'])
    248 
    249         self.assertIn(b'tkinter', stdout)
    250 
    251     def test_exprstring(self):
    252         tcl = self.interp
    253         tcl.call('set', 'a', 3)
    254         tcl.call('set', 'b', 6)
    255         def check(expr, expected):
    256             result = tcl.exprstring(expr)
    257             self.assertEqual(result, expected)
    258             self.assertIsInstance(result, str)
    259 
    260         self.assertRaises(TypeError, tcl.exprstring)
    261         self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6')
    262         self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6')
    263         self.assertRaises(TclError, tcl.exprstring, 'spam')
    264         check('', '0')
    265         check('8.2 + 6', '14.2')
    266         check('3.1 + $a', '6.1')
    267         check('2 + "$a.$b"', '5.6')
    268         check('4*[llength "6 2"]', '8')
    269         check('{word one} < "word $a"', '0')
    270         check('4*2 < 7', '0')
    271         check('hypot($a, 4)', '5.0')
    272         check('5 / 4', '1')
    273         check('5 / 4.0', '1.25')
    274         check('5 / ( [string length "abcd"] + 0.0 )', '1.25')
    275         check('20.0/5.0', '4.0')
    276         check('"0x03" > "2"', '1')
    277         check('[string length "a\xbd\u20ac"]', '3')
    278         check(r'[string length "a\xbd\u20ac"]', '3')
    279         check('"abc"', 'abc')
    280         check('"a\xbd\u20ac"', 'a\xbd\u20ac')
    281         check(r'"a\xbd\u20ac"', 'a\xbd\u20ac')
    282         check(r'"a\0b"', 'a\x00b')
    283         if tcl_version >= (8, 5):  # bignum was added in Tcl 8.5
    284             check('2**64', str(2**64))
    285 
    286     def test_exprdouble(self):
    287         tcl = self.interp
    288         tcl.call('set', 'a', 3)
    289         tcl.call('set', 'b', 6)
    290         def check(expr, expected):
    291             result = tcl.exprdouble(expr)
    292             self.assertEqual(result, expected)
    293             self.assertIsInstance(result, float)
    294 
    295         self.assertRaises(TypeError, tcl.exprdouble)
    296         self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6')
    297         self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6')
    298         self.assertRaises(TclError, tcl.exprdouble, 'spam')
    299         check('', 0.0)
    300         check('8.2 + 6', 14.2)
    301         check('3.1 + $a', 6.1)
    302         check('2 + "$a.$b"', 5.6)
    303         check('4*[llength "6 2"]', 8.0)
    304         check('{word one} < "word $a"', 0.0)
    305         check('4*2 < 7', 0.0)
    306         check('hypot($a, 4)', 5.0)
    307         check('5 / 4', 1.0)
    308         check('5 / 4.0', 1.25)
    309         check('5 / ( [string length "abcd"] + 0.0 )', 1.25)
    310         check('20.0/5.0', 4.0)
    311         check('"0x03" > "2"', 1.0)
    312         check('[string length "a\xbd\u20ac"]', 3.0)
    313         check(r'[string length "a\xbd\u20ac"]', 3.0)
    314         self.assertRaises(TclError, tcl.exprdouble, '"abc"')
    315         if tcl_version >= (8, 5):  # bignum was added in Tcl 8.5
    316             check('2**64', float(2**64))
    317 
    318     def test_exprlong(self):
    319         tcl = self.interp
    320         tcl.call('set', 'a', 3)
    321         tcl.call('set', 'b', 6)
    322         def check(expr, expected):
    323             result = tcl.exprlong(expr)
    324             self.assertEqual(result, expected)
    325             self.assertIsInstance(result, int)
    326 
    327         self.assertRaises(TypeError, tcl.exprlong)
    328         self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6')
    329         self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6')
    330         self.assertRaises(TclError, tcl.exprlong, 'spam')
    331         check('', 0)
    332         check('8.2 + 6', 14)
    333         check('3.1 + $a', 6)
    334         check('2 + "$a.$b"', 5)
    335         check('4*[llength "6 2"]', 8)
    336         check('{word one} < "word $a"', 0)
    337         check('4*2 < 7', 0)
    338         check('hypot($a, 4)', 5)
    339         check('5 / 4', 1)
    340         check('5 / 4.0', 1)
    341         check('5 / ( [string length "abcd"] + 0.0 )', 1)
    342         check('20.0/5.0', 4)
    343         check('"0x03" > "2"', 1)
    344         check('[string length "a\xbd\u20ac"]', 3)
    345         check(r'[string length "a\xbd\u20ac"]', 3)
    346         self.assertRaises(TclError, tcl.exprlong, '"abc"')
    347         if tcl_version >= (8, 5):  # bignum was added in Tcl 8.5
    348             self.assertRaises(TclError, tcl.exprlong, '2**64')
    349 
    350     def test_exprboolean(self):
    351         tcl = self.interp
    352         tcl.call('set', 'a', 3)
    353         tcl.call('set', 'b', 6)
    354         def check(expr, expected):
    355             result = tcl.exprboolean(expr)
    356             self.assertEqual(result, expected)
    357             self.assertIsInstance(result, int)
    358             self.assertNotIsInstance(result, bool)
    359 
    360         self.assertRaises(TypeError, tcl.exprboolean)
    361         self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6')
    362         self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6')
    363         self.assertRaises(TclError, tcl.exprboolean, 'spam')
    364         check('', False)
    365         for value in ('0', 'false', 'no', 'off'):
    366             check(value, False)
    367             check('"%s"' % value, False)
    368             check('{%s}' % value, False)
    369         for value in ('1', 'true', 'yes', 'on'):
    370             check(value, True)
    371             check('"%s"' % value, True)
    372             check('{%s}' % value, True)
    373         check('8.2 + 6', True)
    374         check('3.1 + $a', True)
    375         check('2 + "$a.$b"', True)
    376         check('4*[llength "6 2"]', True)
    377         check('{word one} < "word $a"', False)
    378         check('4*2 < 7', False)
    379         check('hypot($a, 4)', True)
    380         check('5 / 4', True)
    381         check('5 / 4.0', True)
    382         check('5 / ( [string length "abcd"] + 0.0 )', True)
    383         check('20.0/5.0', True)
    384         check('"0x03" > "2"', True)
    385         check('[string length "a\xbd\u20ac"]', True)
    386         check(r'[string length "a\xbd\u20ac"]', True)
    387         self.assertRaises(TclError, tcl.exprboolean, '"abc"')
    388         if tcl_version >= (8, 5):  # bignum was added in Tcl 8.5
    389             check('2**64', True)
    390 
    391     @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5')
    392     def test_booleans(self):
    393         tcl = self.interp
    394         def check(expr, expected):
    395             result = tcl.call('expr', expr)
    396             if tcl.wantobjects():
    397                 self.assertEqual(result, expected)
    398                 self.assertIsInstance(result, int)
    399             else:
    400                 self.assertIn(result, (expr, str(int(expected))))
    401                 self.assertIsInstance(result, str)
    402         check('true', True)
    403         check('yes', True)
    404         check('on', True)
    405         check('false', False)
    406         check('no', False)
    407         check('off', False)
    408         check('1 < 2', True)
    409         check('1 > 2', False)
    410 
    411     def test_expr_bignum(self):
    412         tcl = self.interp
    413         for i in self.get_integers():
    414             result = tcl.call('expr', str(i))
    415             if self.wantobjects:
    416                 self.assertEqual(result, i)
    417                 self.assertIsInstance(result, int)
    418             else:
    419                 self.assertEqual(result, str(i))
    420                 self.assertIsInstance(result, str)
    421         if tcl_version < (8, 5):  # bignum was added in Tcl 8.5
    422             self.assertRaises(TclError, tcl.call, 'expr', str(2**1000))
    423 
    424     def test_passing_values(self):
    425         def passValue(value):
    426             return self.interp.call('set', '_', value)
    427 
    428         self.assertEqual(passValue(True), True if self.wantobjects else '1')
    429         self.assertEqual(passValue(False), False if self.wantobjects else '0')
    430         self.assertEqual(passValue('string'), 'string')
    431         self.assertEqual(passValue('string\u20ac'), 'string\u20ac')
    432         self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
    433         self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd')
    434         self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
    435         self.assertEqual(passValue(b'str\x00ing'),
    436                          b'str\x00ing' if self.wantobjects else 'str\x00ing')
    437         self.assertEqual(passValue(b'str\xc0\x80ing'),
    438                          b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing')
    439         self.assertEqual(passValue(b'str\xbding'),
    440                          b'str\xbding' if self.wantobjects else 'str\xbding')
    441         for i in self.get_integers():
    442             self.assertEqual(passValue(i), i if self.wantobjects else str(i))
    443         if tcl_version < (8, 5):  # bignum was added in Tcl 8.5
    444             self.assertEqual(passValue(2**1000), str(2**1000))
    445         for f in (0.0, 1.0, -1.0, 1/3,
    446                   sys.float_info.min, sys.float_info.max,
    447                   -sys.float_info.min, -sys.float_info.max):
    448             if self.wantobjects:
    449                 self.assertEqual(passValue(f), f)
    450             else:
    451                 self.assertEqual(float(passValue(f)), f)
    452         if self.wantobjects:
    453             f = passValue(float('nan'))
    454             self.assertNotEqual(f, f)
    455             self.assertEqual(passValue(float('inf')), float('inf'))
    456             self.assertEqual(passValue(-float('inf')), -float('inf'))
    457         else:
    458             self.assertEqual(float(passValue(float('inf'))), float('inf'))
    459             self.assertEqual(float(passValue(-float('inf'))), -float('inf'))
    460             # XXX NaN representation can be not parsable by float()
    461         self.assertEqual(passValue((1, '2', (3.4,))),
    462                          (1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
    463         self.assertEqual(passValue(['a', ['b', 'c']]),
    464                          ('a', ('b', 'c')) if self.wantobjects else 'a {b c}')
    465 
    466     def test_user_command(self):
    467         result = None
    468         def testfunc(arg):
    469             nonlocal result
    470             result = arg
    471             return arg
    472         self.interp.createcommand('testfunc', testfunc)
    473         self.addCleanup(self.interp.tk.deletecommand, 'testfunc')
    474         def check(value, expected=None, *, eq=self.assertEqual):
    475             if expected is None:
    476                 expected = value
    477             nonlocal result
    478             result = None
    479             r = self.interp.call('testfunc', value)
    480             self.assertIsInstance(result, str)
    481             eq(result, expected)
    482             self.assertIsInstance(r, str)
    483             eq(r, expected)
    484         def float_eq(actual, expected):
    485             self.assertAlmostEqual(float(actual), expected,
    486                                    delta=abs(expected) * 1e-10)
    487 
    488         check(True, '1')
    489         check(False, '0')
    490         check('string')
    491         check('string\xbd')
    492         check('string\u20ac')
    493         check('')
    494         check(b'string', 'string')
    495         check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
    496         check(b'string\xbd', 'string\xbd')
    497         check(b'', '')
    498         check('str\x00ing')
    499         check('str\x00ing\xbd')
    500         check('str\x00ing\u20ac')
    501         check(b'str\x00ing', 'str\x00ing')
    502         check(b'str\xc0\x80ing', 'str\xc0\x80ing')
    503         check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac')
    504         for i in self.get_integers():
    505             check(i, str(i))
    506         if tcl_version < (8, 5):  # bignum was added in Tcl 8.5
    507             check(2**1000, str(2**1000))
    508         for f in (0.0, 1.0, -1.0):
    509             check(f, repr(f))
    510         for f in (1/3.0, sys.float_info.min, sys.float_info.max,
    511                   -sys.float_info.min, -sys.float_info.max):
    512             check(f, eq=float_eq)
    513         check(float('inf'), eq=float_eq)
    514         check(-float('inf'), eq=float_eq)
    515         # XXX NaN representation can be not parsable by float()
    516         check((), '')
    517         check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
    518         check([1, [2,], [3, 4], '5 6', []], '1 2 {3 4} {5 6} {}')
    519 
    520     def test_splitlist(self):
    521         splitlist = self.interp.tk.splitlist
    522         call = self.interp.tk.call
    523         self.assertRaises(TypeError, splitlist)
    524         self.assertRaises(TypeError, splitlist, 'a', 'b')
    525         self.assertRaises(TypeError, splitlist, 2)
    526         testcases = [
    527             ('2', ('2',)),
    528             ('', ()),
    529             ('{}', ('',)),
    530             ('""', ('',)),
    531             ('a\n b\t\r c\n ', ('a', 'b', 'c')),
    532             (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
    533             ('a \u20ac', ('a', '\u20ac')),
    534             (b'a \xe2\x82\xac', ('a', '\u20ac')),
    535             (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
    536             ('a {b c}', ('a', 'b c')),
    537             (r'a b\ c', ('a', 'b c')),
    538             (('a', 'b c'), ('a', 'b c')),
    539             ('a 2', ('a', '2')),
    540             (('a', 2), ('a', 2)),
    541             ('a 3.4', ('a', '3.4')),
    542             (('a', 3.4), ('a', 3.4)),
    543             ((), ()),
    544             ([], ()),
    545             (['a', ['b', 'c']], ('a', ['b', 'c'])),
    546             (call('list', 1, '2', (3.4,)),
    547                 (1, '2', (3.4,)) if self.wantobjects else
    548                 ('1', '2', '3.4')),
    549         ]
    550         tk_patchlevel = get_tk_patchlevel()
    551         if tcl_version >= (8, 5):
    552             if not self.wantobjects or tk_patchlevel < (8, 5, 5):
    553                 # Before 8.5.5 dicts were converted to lists through string
    554                 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
    555             else:
    556                 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
    557             testcases += [
    558                 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
    559                     expected),
    560             ]
    561         dbg_info = ('want objects? %s, Tcl version: %s, Tk patchlevel: %s'
    562                     % (self.wantobjects, tcl_version, tk_patchlevel))
    563         for arg, res in testcases:
    564             self.assertEqual(splitlist(arg), res,
    565                              'arg=%a, %s' % (arg, dbg_info))
    566         self.assertRaises(TclError, splitlist, '{')
    567 
    568     def test_split(self):
    569         split = self.interp.tk.split
    570         call = self.interp.tk.call
    571         self.assertRaises(TypeError, split)
    572         self.assertRaises(TypeError, split, 'a', 'b')
    573         self.assertRaises(TypeError, split, 2)
    574         testcases = [
    575             ('2', '2'),
    576             ('', ''),
    577             ('{}', ''),
    578             ('""', ''),
    579             ('{', '{'),
    580             ('a\n b\t\r c\n ', ('a', 'b', 'c')),
    581             (b'a\n b\t\r c\n ', ('a', 'b', 'c')),
    582             ('a \u20ac', ('a', '\u20ac')),
    583             (b'a \xe2\x82\xac', ('a', '\u20ac')),
    584             (b'a\xc0\x80b', 'a\x00b'),
    585             (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
    586             (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'),
    587             ('a {b c}', ('a', ('b', 'c'))),
    588             (r'a b\ c', ('a', ('b', 'c'))),
    589             (('a', b'b c'), ('a', ('b', 'c'))),
    590             (('a', 'b c'), ('a', ('b', 'c'))),
    591             ('a 2', ('a', '2')),
    592             (('a', 2), ('a', 2)),
    593             ('a 3.4', ('a', '3.4')),
    594             (('a', 3.4), ('a', 3.4)),
    595             (('a', (2, 3.4)), ('a', (2, 3.4))),
    596             ((), ()),
    597             ([], ()),
    598             (['a', 'b c'], ('a', ('b', 'c'))),
    599             (['a', ['b', 'c']], ('a', ('b', 'c'))),
    600             (call('list', 1, '2', (3.4,)),
    601                 (1, '2', (3.4,)) if self.wantobjects else
    602                 ('1', '2', '3.4')),
    603         ]
    604         if tcl_version >= (8, 5):
    605             if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
    606                 # Before 8.5.5 dicts were converted to lists through string
    607                 expected = ('12', '\u20ac', '\xe2\x82\xac', '3.4')
    608             else:
    609                 expected = (12, '\u20ac', b'\xe2\x82\xac', (3.4,))
    610             testcases += [
    611                 (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)),
    612                     expected),
    613             ]
    614         for arg, res in testcases:
    615             self.assertEqual(split(arg), res, msg=arg)
    616 
    617     def test_splitdict(self):
    618         splitdict = tkinter._splitdict
    619         tcl = self.interp.tk
    620 
    621         arg = '-a {1 2 3} -something foo status {}'
    622         self.assertEqual(splitdict(tcl, arg, False),
    623             {'-a': '1 2 3', '-something': 'foo', 'status': ''})
    624         self.assertEqual(splitdict(tcl, arg),
    625             {'a': '1 2 3', 'something': 'foo', 'status': ''})
    626 
    627         arg = ('-a', (1, 2, 3), '-something', 'foo', 'status', '{}')
    628         self.assertEqual(splitdict(tcl, arg, False),
    629             {'-a': (1, 2, 3), '-something': 'foo', 'status': '{}'})
    630         self.assertEqual(splitdict(tcl, arg),
    631             {'a': (1, 2, 3), 'something': 'foo', 'status': '{}'})
    632 
    633         self.assertRaises(RuntimeError, splitdict, tcl, '-a b -c ')
    634         self.assertRaises(RuntimeError, splitdict, tcl, ('-a', 'b', '-c'))
    635 
    636         arg = tcl.call('list',
    637                         '-a', (1, 2, 3), '-something', 'foo', 'status', ())
    638         self.assertEqual(splitdict(tcl, arg),
    639             {'a': (1, 2, 3) if self.wantobjects else '1 2 3',
    640              'something': 'foo', 'status': ''})
    641 
    642         if tcl_version >= (8, 5):
    643             arg = tcl.call('dict', 'create',
    644                            '-a', (1, 2, 3), '-something', 'foo', 'status', ())
    645             if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5):
    646                 # Before 8.5.5 dicts were converted to lists through string
    647                 expected = {'a': '1 2 3', 'something': 'foo', 'status': ''}
    648             else:
    649                 expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
    650             self.assertEqual(splitdict(tcl, arg), expected)
    651 
    652     def test_join(self):
    653         join = tkinter._join
    654         tcl = self.interp.tk
    655         def unpack(s):
    656             return tcl.call('lindex', s, 0)
    657         def check(value):
    658             self.assertEqual(unpack(join([value])), value)
    659             self.assertEqual(unpack(join([value, 0])), value)
    660             self.assertEqual(unpack(unpack(join([[value]]))), value)
    661             self.assertEqual(unpack(unpack(join([[value, 0]]))), value)
    662             self.assertEqual(unpack(unpack(join([[value], 0]))), value)
    663             self.assertEqual(unpack(unpack(join([[value, 0], 0]))), value)
    664         check('')
    665         check('spam')
    666         check('sp am')
    667         check('sp\tam')
    668         check('sp\nam')
    669         check(' \t\n')
    670         check('{spam}')
    671         check('{sp am}')
    672         check('"spam"')
    673         check('"sp am"')
    674         check('{"spam"}')
    675         check('"{spam}"')
    676         check('sp\\am')
    677         check('"sp\\am"')
    678         check('"{}" "{}"')
    679         check('"\\')
    680         check('"{')
    681         check('"}')
    682         check('\n\\')
    683         check('\n{')
    684         check('\n}')
    685         check('\\\n')
    686         check('{\n')
    687         check('}\n')
    688 
    689     def test_new_tcl_obj(self):
    690         self.assertRaises(TypeError, _tkinter.Tcl_Obj)
    691 
    692 class BigmemTclTest(unittest.TestCase):
    693 
    694     def setUp(self):
    695         self.interp = Tcl()
    696 
    697     @support.cpython_only
    698     @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
    699     @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False)
    700     def test_huge_string_call(self, size):
    701         value = ' ' * size
    702         self.assertRaises(OverflowError, self.interp.call, 'string', 'index', value, 0)
    703 
    704     @support.cpython_only
    705     @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
    706     @support.bigmemtest(size=INT_MAX + 1, memuse=2, dry_run=False)
    707     def test_huge_string_builtins(self, size):
    708         tk = self.interp.tk
    709         value = '1' + ' ' * size
    710         self.assertRaises(OverflowError, tk.getint, value)
    711         self.assertRaises(OverflowError, tk.getdouble, value)
    712         self.assertRaises(OverflowError, tk.getboolean, value)
    713         self.assertRaises(OverflowError, tk.eval, value)
    714         self.assertRaises(OverflowError, tk.evalfile, value)
    715         self.assertRaises(OverflowError, tk.record, value)
    716         self.assertRaises(OverflowError, tk.adderrorinfo, value)
    717         self.assertRaises(OverflowError, tk.setvar, value, 'x', 'a')
    718         self.assertRaises(OverflowError, tk.setvar, 'x', value, 'a')
    719         self.assertRaises(OverflowError, tk.unsetvar, value)
    720         self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
    721         self.assertRaises(OverflowError, tk.adderrorinfo, value)
    722         self.assertRaises(OverflowError, tk.exprstring, value)
    723         self.assertRaises(OverflowError, tk.exprlong, value)
    724         self.assertRaises(OverflowError, tk.exprboolean, value)
    725         self.assertRaises(OverflowError, tk.splitlist, value)
    726         self.assertRaises(OverflowError, tk.split, value)
    727         self.assertRaises(OverflowError, tk.createcommand, value, max)
    728         self.assertRaises(OverflowError, tk.deletecommand, value)
    729 
    730     @support.cpython_only
    731     @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX")
    732     @support.bigmemtest(size=INT_MAX + 1, memuse=6, dry_run=False)
    733     def test_huge_string_builtins2(self, size):
    734         # These commands require larger memory for possible error messages
    735         tk = self.interp.tk
    736         value = '1' + ' ' * size
    737         self.assertRaises(OverflowError, tk.evalfile, value)
    738         self.assertRaises(OverflowError, tk.unsetvar, value)
    739         self.assertRaises(OverflowError, tk.unsetvar, 'x', value)
    740 
    741 
    742 def setUpModule():
    743     if support.verbose:
    744         tcl = Tcl()
    745         print('patchlevel =', tcl.call('info', 'patchlevel'))
    746 
    747 
    748 def test_main():
    749     support.run_unittest(TclTest, TkinterTest, BigmemTclTest)
    750 
    751 if __name__ == "__main__":
    752     test_main()
    753