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