ยปCore Development>Code coverage>Lib/test/test_tools.py

Python code coverage for Lib/test/test_tools.py

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