blob: 9403da71fb6533e2ae75a8dce474f1d14f8043e7 [file] [log] [blame]
Éric Araujob4656242012-02-25 16:57:04 +01001"""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
R David Murray54ac8322012-04-04 21:28:14 -04008import sys
R David Murrayd3af6342012-04-05 22:59:13 -04009import imp
Éric Araujob4656242012-02-25 16:57:04 +010010import unittest
Serhiy Storchaka6840a542013-01-11 12:04:23 +020011import shutil
12import subprocess
Éric Araujob4656242012-02-25 16:57:04 +010013import sysconfig
R David Murrayd3af6342012-04-05 22:59:13 -040014import tempfile
Serhiy Storchaka6840a542013-01-11 12:04:23 +020015import textwrap
Éric Araujob4656242012-02-25 16:57:04 +010016from test import support
Serhiy Storchaka6840a542013-01-11 12:04:23 +020017from test.script_helper import assert_python_ok, temp_dir
Éric Araujob4656242012-02-25 16:57:04 +010018
19if not sysconfig.is_python_build():
20 # XXX some installers do contain the tools, should we detect that
21 # and run the tests in that case too?
22 raise unittest.SkipTest('test irrelevant for an installed Python')
23
doko@ubuntu.com01beb692012-09-10 14:19:42 +020024basepath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
25 'Tools')
R David Murray54ac8322012-04-04 21:28:14 -040026scriptsdir = os.path.join(basepath, 'scripts')
Éric Araujob4656242012-02-25 16:57:04 +010027
28
29class ReindentTests(unittest.TestCase):
R David Murray54ac8322012-04-04 21:28:14 -040030 script = os.path.join(scriptsdir, 'reindent.py')
Éric Araujob4656242012-02-25 16:57:04 +010031
32 def test_noargs(self):
33 assert_python_ok(self.script)
34
35 def test_help(self):
36 rc, out, err = assert_python_ok(self.script, '-h')
37 self.assertEqual(out, b'')
38 self.assertGreater(err, b'')
39
40
Serhiy Storchaka6840a542013-01-11 12:04:23 +020041class PindentTests(unittest.TestCase):
42 script = os.path.join(scriptsdir, 'pindent.py')
43
44 def assertFileEqual(self, fn1, fn2):
45 with open(fn1) as f1, open(fn2) as f2:
46 self.assertEqual(f1.readlines(), f2.readlines())
47
48 def pindent(self, source, *args):
49 with subprocess.Popen(
50 (sys.executable, self.script) + args,
51 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
52 universal_newlines=True) as proc:
53 out, err = proc.communicate(source.encode())
54 self.assertIsNone(err)
55 return out
56
57 def lstriplines(self, data):
58 return '\n'.join(line.lstrip() for line in data.splitlines()) + '\n'
59
60 def test_selftest(self):
Serhiy Storchakaa3a01b62013-01-11 22:18:17 +020061 self.maxDiff = None
Serhiy Storchaka6840a542013-01-11 12:04:23 +020062 with temp_dir() as directory:
63 data_path = os.path.join(directory, '_test.py')
64 with open(self.script) as f:
65 closed = f.read()
66 with open(data_path, 'w') as f:
67 f.write(closed)
68
69 rc, out, err = assert_python_ok(self.script, '-d', data_path)
70 self.assertEqual(out, b'')
71 self.assertEqual(err, b'')
72 backup = data_path + '~'
73 self.assertTrue(os.path.exists(backup))
74 with open(backup) as f:
75 self.assertEqual(f.read(), closed)
76 with open(data_path) as f:
77 clean = f.read()
78 compile(clean, '_test.py', 'exec')
79 self.assertEqual(self.pindent(clean, '-c'), closed)
80 self.assertEqual(self.pindent(closed, '-d'), clean)
81
82 rc, out, err = assert_python_ok(self.script, '-c', data_path)
83 self.assertEqual(out, b'')
84 self.assertEqual(err, b'')
85 with open(backup) as f:
86 self.assertEqual(f.read(), clean)
87 with open(data_path) as f:
88 self.assertEqual(f.read(), closed)
89
90 broken = self.lstriplines(closed)
91 with open(data_path, 'w') as f:
92 f.write(broken)
93 rc, out, err = assert_python_ok(self.script, '-r', data_path)
94 self.assertEqual(out, b'')
95 self.assertEqual(err, b'')
96 with open(backup) as f:
97 self.assertEqual(f.read(), broken)
98 with open(data_path) as f:
99 indented = f.read()
100 compile(indented, '_test.py', 'exec')
101 self.assertEqual(self.pindent(broken, '-r'), indented)
102
103 def pindent_test(self, clean, closed):
104 self.assertEqual(self.pindent(clean, '-c'), closed)
105 self.assertEqual(self.pindent(closed, '-d'), clean)
106 broken = self.lstriplines(closed)
107 self.assertEqual(self.pindent(broken, '-r', '-e', '-s', '4'), closed)
108
109 def test_statements(self):
110 clean = textwrap.dedent("""\
111 if a:
112 pass
113
114 if a:
115 pass
116 else:
117 pass
118
119 if a:
120 pass
121 elif:
122 pass
123 else:
124 pass
125
126 while a:
127 break
128
129 while a:
130 break
131 else:
132 pass
133
134 for i in a:
135 break
136
137 for i in a:
138 break
139 else:
140 pass
141
142 try:
143 pass
144 finally:
145 pass
146
147 try:
148 pass
149 except TypeError:
150 pass
151 except ValueError:
152 pass
153 else:
154 pass
155
156 try:
157 pass
158 except TypeError:
159 pass
160 except ValueError:
161 pass
162 finally:
163 pass
164
165 with a:
166 pass
167
168 class A:
169 pass
170
171 def f():
172 pass
173 """)
174
175 closed = textwrap.dedent("""\
176 if a:
177 pass
178 # end if
179
180 if a:
181 pass
182 else:
183 pass
184 # end if
185
186 if a:
187 pass
188 elif:
189 pass
190 else:
191 pass
192 # end if
193
194 while a:
195 break
196 # end while
197
198 while a:
199 break
200 else:
201 pass
202 # end while
203
204 for i in a:
205 break
206 # end for
207
208 for i in a:
209 break
210 else:
211 pass
212 # end for
213
214 try:
215 pass
216 finally:
217 pass
218 # end try
219
220 try:
221 pass
222 except TypeError:
223 pass
224 except ValueError:
225 pass
226 else:
227 pass
228 # end try
229
230 try:
231 pass
232 except TypeError:
233 pass
234 except ValueError:
235 pass
236 finally:
237 pass
238 # end try
239
240 with a:
241 pass
242 # end with
243
244 class A:
245 pass
246 # end class A
247
248 def f():
249 pass
250 # end def f
251 """)
252 self.pindent_test(clean, closed)
253
254 def test_multilevel(self):
255 clean = textwrap.dedent("""\
256 def foobar(a, b):
257 if a == b:
258 a = a+1
259 elif a < b:
260 b = b-1
261 if b > a: a = a-1
262 else:
263 print 'oops!'
264 """)
265 closed = textwrap.dedent("""\
266 def foobar(a, b):
267 if a == b:
268 a = a+1
269 elif a < b:
270 b = b-1
271 if b > a: a = a-1
272 # end if
273 else:
274 print 'oops!'
275 # end if
276 # end def foobar
277 """)
278 self.pindent_test(clean, closed)
279
280 def test_preserve_indents(self):
281 clean = textwrap.dedent("""\
282 if a:
283 if b:
284 pass
285 """)
286 closed = textwrap.dedent("""\
287 if a:
288 if b:
289 pass
290 # end if
291 # end if
292 """)
293 self.assertEqual(self.pindent(clean, '-c'), closed)
294 self.assertEqual(self.pindent(closed, '-d'), clean)
295 broken = self.lstriplines(closed)
296 self.assertEqual(self.pindent(broken, '-r', '-e', '-s', '9'), closed)
297 clean = textwrap.dedent("""\
298 if a:
299 \tif b:
300 \t\tpass
301 """)
302 closed = textwrap.dedent("""\
303 if a:
304 \tif b:
305 \t\tpass
306 \t# end if
307 # end if
308 """)
309 self.assertEqual(self.pindent(clean, '-c'), closed)
310 self.assertEqual(self.pindent(closed, '-d'), clean)
311 broken = self.lstriplines(closed)
312 self.assertEqual(self.pindent(broken, '-r'), closed)
313
314 def test_escaped_newline(self):
315 clean = textwrap.dedent("""\
316 class\\
317 \\
318 A:
319 def\
320 \\
321 f:
322 pass
323 """)
324 closed = textwrap.dedent("""\
325 class\\
326 \\
327 A:
328 def\
329 \\
330 f:
331 pass
332 # end def f
333 # end class A
334 """)
335 self.assertEqual(self.pindent(clean, '-c'), closed)
336 self.assertEqual(self.pindent(closed, '-d'), clean)
337
338 def test_empty_line(self):
339 clean = textwrap.dedent("""\
340 if a:
341
342 pass
343 """)
344 closed = textwrap.dedent("""\
345 if a:
346
347 pass
348 # end if
349 """)
350 self.pindent_test(clean, closed)
351
352 def test_oneline(self):
353 clean = textwrap.dedent("""\
354 if a: pass
355 """)
356 closed = textwrap.dedent("""\
357 if a: pass
358 # end if
359 """)
360 self.pindent_test(clean, closed)
361
362
R David Murray54ac8322012-04-04 21:28:14 -0400363class TestSundryScripts(unittest.TestCase):
364 # At least make sure the rest don't have syntax errors. When tests are
365 # added for a script it should be added to the whitelist below.
366
367 # scripts that have independent tests.
368 whitelist = ['reindent.py']
369 # scripts that can't be imported without running
370 blacklist = ['make_ctype.py']
371 # scripts that use windows-only modules
372 windows_only = ['win_add2path.py']
373 # blacklisted for other reasons
374 other = ['analyze_dxp.py']
375
376 skiplist = blacklist + whitelist + windows_only + other
377
378 def setUp(self):
379 cm = support.DirsOnSysPath(scriptsdir)
380 cm.__enter__()
381 self.addCleanup(cm.__exit__)
382
383 def test_sundry(self):
384 for fn in os.listdir(scriptsdir):
385 if fn.endswith('.py') and fn not in self.skiplist:
386 __import__(fn[:-3])
387
388 @unittest.skipIf(sys.platform != "win32", "Windows-only test")
389 def test_sundry_windows(self):
390 for fn in self.windows_only:
391 __import__(fn[:-3])
392
R David Murrayca60b362012-04-04 22:37:50 -0400393 @unittest.skipIf(not support.threading, "test requires _thread module")
R David Murray54ac8322012-04-04 21:28:14 -0400394 def test_analyze_dxp_import(self):
395 if hasattr(sys, 'getdxp'):
396 import analyze_dxp
397 else:
398 with self.assertRaises(RuntimeError):
399 import analyze_dxp
400
401
R David Murrayd3af6342012-04-05 22:59:13 -0400402class PdepsTests(unittest.TestCase):
403
404 @classmethod
405 def setUpClass(self):
406 path = os.path.join(scriptsdir, 'pdeps.py')
407 self.pdeps = imp.load_source('pdeps', path)
408
409 @classmethod
410 def tearDownClass(self):
411 if 'pdeps' in sys.modules:
412 del sys.modules['pdeps']
413
414 def test_process_errors(self):
415 # Issue #14492: m_import.match(line) can be None.
416 with tempfile.TemporaryDirectory() as tmpdir:
417 fn = os.path.join(tmpdir, 'foo')
418 with open(fn, 'w') as stream:
419 stream.write("#!/this/will/fail")
420 self.pdeps.process(fn, {})
421
422 def test_inverse_attribute_error(self):
423 # Issue #14492: this used to fail with an AttributeError.
424 self.pdeps.inverse({'a': []})
425
426
Éric Araujob4656242012-02-25 16:57:04 +0100427def test_main():
R David Murray54ac8322012-04-04 21:28:14 -0400428 support.run_unittest(*[obj for obj in globals().values()
429 if isinstance(obj, type)])
Éric Araujob4656242012-02-25 16:57:04 +0100430
431
432if __name__ == '__main__':
433 unittest.main()