"""Tests for scripts in the Tools directory. This file contains regression tests for some of the scripts found in the Tools directory of a Python checkout or tarball, such as reindent.py. """ import os import runpy import sys import unittest import shutil from cStringIO import StringIO import subprocess import sysconfig import tempfile import textwrap from test import test_support from test.script_helper import assert_python_ok, temp_dir if not sysconfig.is_python_build(): # XXX some installers do contain the tools, should we detect that # and run the tests in that case too? raise unittest.SkipTest('test irrelevant for an installed Python') basepath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'Tools') scriptsdir = os.path.join(basepath, 'scripts') class ReindentTests(unittest.TestCase): script = os.path.join(scriptsdir, 'reindent.py') def test_noargs(self): assert_python_ok(self.script) def test_help(self): rc, out, err = assert_python_ok(self.script, '-h') self.assertEqual(out, b'') self.assertGreater(err, b'') class PindentTests(unittest.TestCase): script = os.path.join(scriptsdir, 'pindent.py') def assertFileEqual(self, fn1, fn2): with open(fn1) as f1, open(fn2) as f2: self.assertEqual(f1.readlines(), f2.readlines()) def pindent(self, source, *args): proc = subprocess.Popen( (sys.executable, self.script) + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) out, err = proc.communicate(source) self.assertIsNone(err) return out def lstriplines(self, data): return '\n'.join(line.lstrip() for line in data.splitlines()) + '\n' def test_selftest(self): self.maxDiff = None with temp_dir() as directory: data_path = os.path.join(directory, '_test.py') with open(self.script) as f: closed = f.read() with open(data_path, 'w') as f: f.write(closed) rc, out, err = assert_python_ok(self.script, '-d', data_path) self.assertEqual(out, b'') self.assertEqual(err, b'') backup = data_path + '~' self.assertTrue(os.path.exists(backup)) with open(backup) as f: self.assertEqual(f.read(), closed) with open(data_path) as f: clean = f.read() compile(clean, '_test.py', 'exec') self.assertEqual(self.pindent(clean, '-c'), closed) self.assertEqual(self.pindent(closed, '-d'), clean) rc, out, err = assert_python_ok(self.script, '-c', data_path) self.assertEqual(out, b'') self.assertEqual(err, b'') with open(backup) as f: self.assertEqual(f.read(), clean) with open(data_path) as f: self.assertEqual(f.read(), closed) broken = self.lstriplines(closed) with open(data_path, 'w') as f: f.write(broken) rc, out, err = assert_python_ok(self.script, '-r', data_path) self.assertEqual(out, b'') self.assertEqual(err, b'') with open(backup) as f: self.assertEqual(f.read(), broken) with open(data_path) as f: indented = f.read() compile(indented, '_test.py', 'exec') self.assertEqual(self.pindent(broken, '-r'), indented) def pindent_test(self, clean, closed): self.assertEqual(self.pindent(clean, '-c'), closed) self.assertEqual(self.pindent(closed, '-d'), clean) broken = self.lstriplines(closed) self.assertEqual(self.pindent(broken, '-r', '-e', '-s', '4'), closed) def test_statements(self): clean = textwrap.dedent("""\ if a: pass if a: pass else: pass if a: pass elif: pass else: pass while a: break while a: break else: pass for i in a: break for i in a: break else: pass try: pass finally: pass try: pass except TypeError: pass except ValueError: pass else: pass try: pass except TypeError: pass except ValueError: pass finally: pass with a: pass class A: pass def f(): pass """) closed = textwrap.dedent("""\ if a: pass # end if if a: pass else: pass # end if if a: pass elif: pass else: pass # end if while a: break # end while while a: break else: pass # end while for i in a: break # end for for i in a: break else: pass # end for try: pass finally: pass # end try try: pass except TypeError: pass except ValueError: pass else: pass # end try try: pass except TypeError: pass except ValueError: pass finally: pass # end try with a: pass # end with class A: pass # end class A def f(): pass # end def f """) self.pindent_test(clean, closed) def test_multilevel(self): clean = textwrap.dedent("""\ def foobar(a, b): if a == b: a = a+1 elif a < b: b = b-1 if b > a: a = a-1 else: print 'oops!' """) closed = textwrap.dedent("""\ def foobar(a, b): if a == b: a = a+1 elif a < b: b = b-1 if b > a: a = a-1 # end if else: print 'oops!' # end if # end def foobar """) self.pindent_test(clean, closed) def test_preserve_indents(self): clean = textwrap.dedent("""\ if a: if b: pass """) closed = textwrap.dedent("""\ if a: if b: pass # end if # end if """) self.assertEqual(self.pindent(clean, '-c'), closed) self.assertEqual(self.pindent(closed, '-d'), clean) broken = self.lstriplines(closed) self.assertEqual(self.pindent(broken, '-r', '-e', '-s', '9'), closed) clean = textwrap.dedent("""\ if a: \tif b: \t\tpass """) closed = textwrap.dedent("""\ if a: \tif b: \t\tpass \t# end if # end if """) self.assertEqual(self.pindent(clean, '-c'), closed) self.assertEqual(self.pindent(closed, '-d'), clean) broken = self.lstriplines(closed) self.assertEqual(self.pindent(broken, '-r'), closed) def test_escaped_newline(self): clean = textwrap.dedent("""\ class\\ \\ A: def\ \\ f: pass """) closed = textwrap.dedent("""\ class\\ \\ A: def\ \\ f: pass # end def f # end class A """) self.assertEqual(self.pindent(clean, '-c'), closed) self.assertEqual(self.pindent(closed, '-d'), clean) def test_empty_line(self): clean = textwrap.dedent("""\ if a: pass """) closed = textwrap.dedent("""\ if a: pass # end if """) self.pindent_test(clean, closed) def test_oneline(self): clean = textwrap.dedent("""\ if a: pass """) closed = textwrap.dedent("""\ if a: pass # end if """) self.pindent_test(clean, closed) class FixcidTests(unittest.TestCase): def test_parse_strings(self): old1 = 'int xx = "xx\\"xx"[xx];\n' old2 = "int xx = 'x\\'xx' + xx;\n" output = self.run_script(old1 + old2) new1 = 'int yy = "xx\\"xx"[yy];\n' new2 = "int yy = 'x\\'xx' + yy;\n" self.assertMultiLineEqual(output, "1\n" "< {old1}" "> {new1}" "{new1}" "2\n" "< {old2}" "> {new2}" "{new2}".format(old1=old1, old2=old2, new1=new1, new2=new2) ) def test_alter_comments(self): output = self.run_script( substfile= "xx yy\n" "*aa bb\n", args=("-c", "-",), input= "/* xx altered */\n" "int xx;\n" "/* aa unaltered */\n" "int aa;\n", ) self.assertMultiLineEqual(output, "1\n" "< /* xx altered */\n" "> /* yy altered */\n" "/* yy altered */\n" "2\n" "< int xx;\n" "> int yy;\n" "int yy;\n" "/* aa unaltered */\n" "4\n" "< int aa;\n" "> int bb;\n" "int bb;\n" ) def test_directory(self): os.mkdir(test_support.TESTFN) self.addCleanup(test_support.rmtree, test_support.TESTFN) c_filename = os.path.join(test_support.TESTFN, "file.c") with open(c_filename, "w") as file: file.write("int xx;\n") with open(os.path.join(test_support.TESTFN, "file.py"), "w") as file: file.write("xx = 'unaltered'\n") script = os.path.join(scriptsdir, "fixcid.py") # ignore dbg() messages with test_support.captured_stderr() as stderr: output = self.run_script(args=(test_support.TESTFN,)) self.assertMultiLineEqual(output, "{}:\n" "1\n" '< int xx;\n' '> int yy;\n'.format(c_filename), "stderr: %s" % stderr.getvalue() ) def run_script(self, input="", args=("-",), substfile="xx yy\n"): substfilename = test_support.TESTFN + ".subst" with open(substfilename, "w") as file: file.write(substfile) self.addCleanup(test_support.unlink, substfilename) argv = ["fixcid.py", "-s", substfilename] + list(args) script = os.path.join(scriptsdir, "fixcid.py") with test_support.swap_attr(sys, "argv", argv), \ test_support.swap_attr(sys, "stdin", StringIO(input)), \ test_support.captured_stdout() as output: try: runpy.run_path(script, run_name="__main__") except SystemExit as exit: self.assertEqual(exit.code, 0) return output.getvalue() def test_main(): test_support.run_unittest(*[obj for obj in globals().values() if isinstance(obj, type)]) if __name__ == '__main__': unittest.main()