• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Tests for scripts in the Tools directory.
2
3This file contains regression tests for some of the scripts found in the
4Tools directory of a Python checkout or tarball, such as reindent.py.
5"""
6
7import os
8import runpy
9import sys
10import unittest
11import shutil
12from cStringIO import StringIO
13import subprocess
14import sysconfig
15import tempfile
16import textwrap
17from test import test_support
18from test.script_helper import assert_python_ok, temp_dir
19
20if 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
25basepath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
26                        'Tools')
27scriptsdir = os.path.join(basepath, 'scripts')
28
29
30class 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
42class 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
364class 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
445def test_main():
446    test_support.run_unittest(*[obj for obj in globals().values()
447                                    if isinstance(obj, type)])
448
449
450if __name__ == '__main__':
451    unittest.main()
452