Home | History | Annotate | Download | only in test
      1 """Tests for scripts in the Tools directory.
      2 
      3 This file contains regression tests for some of the scripts found in the
      4 Tools directory of a Python checkout or tarball, such as reindent.py.
      5 """
      6 
      7 import os
      8 import runpy
      9 import sys
     10 import unittest
     11 import shutil
     12 from cStringIO import StringIO
     13 import subprocess
     14 import sysconfig
     15 import tempfile
     16 import textwrap
     17 from test import test_support
     18 from test.script_helper import assert_python_ok, temp_dir
     19 
     20 if not sysconfig.is_python_build():
     21     # XXX some installers do contain the tools, should we detect that
     22     # and run the tests in that case too?
     23     raise unittest.SkipTest('test irrelevant for an installed Python')
     24 
     25 basepath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
     26                         'Tools')
     27 scriptsdir = os.path.join(basepath, 'scripts')
     28 
     29 
     30 class ReindentTests(unittest.TestCase):
     31     script = os.path.join(scriptsdir, 'reindent.py')
     32 
     33     def test_noargs(self):
     34         assert_python_ok(self.script)
     35 
     36     def test_help(self):
     37         rc, out, err = assert_python_ok(self.script, '-h')
     38         self.assertEqual(out, b'')
     39         self.assertGreater(err, b'')
     40 
     41 
     42 class PindentTests(unittest.TestCase):
     43     script = os.path.join(scriptsdir, 'pindent.py')
     44 
     45     def assertFileEqual(self, fn1, fn2):
     46         with open(fn1) as f1, open(fn2) as f2:
     47             self.assertEqual(f1.readlines(), f2.readlines())
     48 
     49     def pindent(self, source, *args):
     50         proc = subprocess.Popen(
     51                 (sys.executable, self.script) + args,
     52                 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
     53                 universal_newlines=True)
     54         out, err = proc.communicate(source)
     55         self.assertIsNone(err)
     56         return out
     57 
     58     def lstriplines(self, data):
     59         return '\n'.join(line.lstrip() for line in data.splitlines()) + '\n'
     60 
     61     def test_selftest(self):
     62         self.maxDiff = None
     63         with temp_dir() as directory:
     64             data_path = os.path.join(directory, '_test.py')
     65             with open(self.script) as f:
     66                 closed = f.read()
     67             with open(data_path, 'w') as f:
     68                 f.write(closed)
     69 
     70             rc, out, err = assert_python_ok(self.script, '-d', data_path)
     71             self.assertEqual(out, b'')
     72             self.assertEqual(err, b'')
     73             backup = data_path + '~'
     74             self.assertTrue(os.path.exists(backup))
     75             with open(backup) as f:
     76                 self.assertEqual(f.read(), closed)
     77             with open(data_path) as f:
     78                 clean = f.read()
     79             compile(clean, '_test.py', 'exec')
     80             self.assertEqual(self.pindent(clean, '-c'), closed)
     81             self.assertEqual(self.pindent(closed, '-d'), clean)
     82 
     83             rc, out, err = assert_python_ok(self.script, '-c', data_path)
     84             self.assertEqual(out, b'')
     85             self.assertEqual(err, b'')
     86             with open(backup) as f:
     87                 self.assertEqual(f.read(), clean)
     88             with open(data_path) as f:
     89                 self.assertEqual(f.read(), closed)
     90 
     91             broken = self.lstriplines(closed)
     92             with open(data_path, 'w') as f:
     93                 f.write(broken)
     94             rc, out, err = assert_python_ok(self.script, '-r', data_path)
     95             self.assertEqual(out, b'')
     96             self.assertEqual(err, b'')
     97             with open(backup) as f:
     98                 self.assertEqual(f.read(), broken)
     99             with open(data_path) as f:
    100                 indented = f.read()
    101             compile(indented, '_test.py', 'exec')
    102             self.assertEqual(self.pindent(broken, '-r'), indented)
    103 
    104     def pindent_test(self, clean, closed):
    105         self.assertEqual(self.pindent(clean, '-c'), closed)
    106         self.assertEqual(self.pindent(closed, '-d'), clean)
    107         broken = self.lstriplines(closed)
    108         self.assertEqual(self.pindent(broken, '-r', '-e', '-s', '4'), closed)
    109 
    110     def test_statements(self):
    111         clean = textwrap.dedent("""\
    112             if a:
    113                 pass
    114 
    115             if a:
    116                 pass
    117             else:
    118                 pass
    119 
    120             if a:
    121                 pass
    122             elif:
    123                 pass
    124             else:
    125                 pass
    126 
    127             while a:
    128                 break
    129 
    130             while a:
    131                 break
    132             else:
    133                 pass
    134 
    135             for i in a:
    136                 break
    137 
    138             for i in a:
    139                 break
    140             else:
    141                 pass
    142 
    143             try:
    144                 pass
    145             finally:
    146                 pass
    147 
    148             try:
    149                 pass
    150             except TypeError:
    151                 pass
    152             except ValueError:
    153                 pass
    154             else:
    155                 pass
    156 
    157             try:
    158                 pass
    159             except TypeError:
    160                 pass
    161             except ValueError:
    162                 pass
    163             finally:
    164                 pass
    165 
    166             with a:
    167                 pass
    168 
    169             class A:
    170                 pass
    171 
    172             def f():
    173                 pass
    174             """)
    175 
    176         closed = textwrap.dedent("""\
    177             if a:
    178                 pass
    179             # end if
    180 
    181             if a:
    182                 pass
    183             else:
    184                 pass
    185             # end if
    186 
    187             if a:
    188                 pass
    189             elif:
    190                 pass
    191             else:
    192                 pass
    193             # end if
    194 
    195             while a:
    196                 break
    197             # end while
    198 
    199             while a:
    200                 break
    201             else:
    202                 pass
    203             # end while
    204 
    205             for i in a:
    206                 break
    207             # end for
    208 
    209             for i in a:
    210                 break
    211             else:
    212                 pass
    213             # end for
    214 
    215             try:
    216                 pass
    217             finally:
    218                 pass
    219             # end try
    220 
    221             try:
    222                 pass
    223             except TypeError:
    224                 pass
    225             except ValueError:
    226                 pass
    227             else:
    228                 pass
    229             # end try
    230 
    231             try:
    232                 pass
    233             except TypeError:
    234                 pass
    235             except ValueError:
    236                 pass
    237             finally:
    238                 pass
    239             # end try
    240 
    241             with a:
    242                 pass
    243             # end with
    244 
    245             class A:
    246                 pass
    247             # end class A
    248 
    249             def f():
    250                 pass
    251             # end def f
    252             """)
    253         self.pindent_test(clean, closed)
    254 
    255     def test_multilevel(self):
    256         clean = textwrap.dedent("""\
    257             def foobar(a, b):
    258                 if a == b:
    259                     a = a+1
    260                 elif a < b:
    261                     b = b-1
    262                     if b > a: a = a-1
    263                 else:
    264                     print 'oops!'
    265             """)
    266         closed = textwrap.dedent("""\
    267             def foobar(a, b):
    268                 if a == b:
    269                     a = a+1
    270                 elif a < b:
    271                     b = b-1
    272                     if b > a: a = a-1
    273                     # end if
    274                 else:
    275                     print 'oops!'
    276                 # end if
    277             # end def foobar
    278             """)
    279         self.pindent_test(clean, closed)
    280 
    281     def test_preserve_indents(self):
    282         clean = textwrap.dedent("""\
    283             if a:
    284                      if b:
    285                               pass
    286             """)
    287         closed = textwrap.dedent("""\
    288             if a:
    289                      if b:
    290                               pass
    291                      # end if
    292             # end if
    293             """)
    294         self.assertEqual(self.pindent(clean, '-c'), closed)
    295         self.assertEqual(self.pindent(closed, '-d'), clean)
    296         broken = self.lstriplines(closed)
    297         self.assertEqual(self.pindent(broken, '-r', '-e', '-s', '9'), closed)
    298         clean = textwrap.dedent("""\
    299             if a:
    300             \tif b:
    301             \t\tpass
    302             """)
    303         closed = textwrap.dedent("""\
    304             if a:
    305             \tif b:
    306             \t\tpass
    307             \t# end if
    308             # end if
    309             """)
    310         self.assertEqual(self.pindent(clean, '-c'), closed)
    311         self.assertEqual(self.pindent(closed, '-d'), clean)
    312         broken = self.lstriplines(closed)
    313         self.assertEqual(self.pindent(broken, '-r'), closed)
    314 
    315     def test_escaped_newline(self):
    316         clean = textwrap.dedent("""\
    317             class\\
    318             \\
    319              A:
    320                def\
    321             \\
    322             f:
    323                   pass
    324             """)
    325         closed = textwrap.dedent("""\
    326             class\\
    327             \\
    328              A:
    329                def\
    330             \\
    331             f:
    332                   pass
    333                # end def f
    334             # end class A
    335             """)
    336         self.assertEqual(self.pindent(clean, '-c'), closed)
    337         self.assertEqual(self.pindent(closed, '-d'), clean)
    338 
    339     def test_empty_line(self):
    340         clean = textwrap.dedent("""\
    341             if a:
    342 
    343                 pass
    344             """)
    345         closed = textwrap.dedent("""\
    346             if a:
    347 
    348                 pass
    349             # end if
    350             """)
    351         self.pindent_test(clean, closed)
    352 
    353     def test_oneline(self):
    354         clean = textwrap.dedent("""\
    355             if a: pass
    356             """)
    357         closed = textwrap.dedent("""\
    358             if a: pass
    359             # end if
    360             """)
    361         self.pindent_test(clean, closed)
    362 
    363 
    364 class FixcidTests(unittest.TestCase):
    365     def test_parse_strings(self):
    366         old1 = 'int xx = "xx\\"xx"[xx];\n'
    367         old2 = "int xx = 'x\\'xx' + xx;\n"
    368         output = self.run_script(old1 + old2)
    369         new1 = 'int yy = "xx\\"xx"[yy];\n'
    370         new2 = "int yy = 'x\\'xx' + yy;\n"
    371         self.assertMultiLineEqual(output,
    372             "1\n"
    373             "< {old1}"
    374             "> {new1}"
    375             "{new1}"
    376             "2\n"
    377             "< {old2}"
    378             "> {new2}"
    379             "{new2}".format(old1=old1, old2=old2, new1=new1, new2=new2)
    380         )
    381 
    382     def test_alter_comments(self):
    383         output = self.run_script(
    384             substfile=
    385                 "xx yy\n"
    386                 "*aa bb\n",
    387             args=("-c", "-",),
    388             input=
    389                 "/* xx altered */\n"
    390                 "int xx;\n"
    391                 "/* aa unaltered */\n"
    392                 "int aa;\n",
    393         )
    394         self.assertMultiLineEqual(output,
    395             "1\n"
    396             "< /* xx altered */\n"
    397             "> /* yy altered */\n"
    398             "/* yy altered */\n"
    399             "2\n"
    400             "< int xx;\n"
    401             "> int yy;\n"
    402             "int yy;\n"
    403             "/* aa unaltered */\n"
    404             "4\n"
    405             "< int aa;\n"
    406             "> int bb;\n"
    407             "int bb;\n"
    408         )
    409 
    410     def test_directory(self):
    411         os.mkdir(test_support.TESTFN)
    412         self.addCleanup(test_support.rmtree, test_support.TESTFN)
    413         c_filename = os.path.join(test_support.TESTFN, "file.c")
    414         with open(c_filename, "w") as file:
    415             file.write("int xx;\n")
    416         with open(os.path.join(test_support.TESTFN, "file.py"), "w") as file:
    417             file.write("xx = 'unaltered'\n")
    418         script = os.path.join(scriptsdir, "fixcid.py")
    419         output = self.run_script(args=(test_support.TESTFN,))
    420         self.assertMultiLineEqual(output,
    421             "{}:\n"
    422             "1\n"
    423             '< int xx;\n'
    424             '> int yy;\n'.format(c_filename)
    425         )
    426 
    427     def run_script(self, input="", args=("-",), substfile="xx yy\n"):
    428         substfilename = test_support.TESTFN + ".subst"
    429         with open(substfilename, "w") as file:
    430             file.write(substfile)
    431         self.addCleanup(test_support.unlink, substfilename)
    432 
    433         argv = ["fixcid.py", "-s", substfilename] + list(args)
    434         script = os.path.join(scriptsdir, "fixcid.py")
    435         with test_support.swap_attr(sys, "argv", argv), \
    436                 test_support.swap_attr(sys, "stdin", StringIO(input)), \
    437                 test_support.captured_stdout() as output:
    438             try:
    439                 runpy.run_path(script, run_name="__main__")
    440             except SystemExit as exit:
    441                 self.assertEqual(exit.code, 0)
    442         return output.getvalue()
    443 
    444 
    445 def test_main():
    446     test_support.run_unittest(*[obj for obj in globals().values()
    447                                     if isinstance(obj, type)])
    448 
    449 
    450 if __name__ == '__main__':
    451     unittest.main()
    452