diff options
author | Dennis Sweeney <36520290+sweeneyde@users.noreply.github.com> | 2022-04-16 21:36:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-16 21:36:29 (GMT) |
commit | 8560f4a0f288fec33ba49f85bb872353d631a4dc (patch) | |
tree | bde96f3f8e2e1efefd8810d7ec48714567696fc3 /Lib | |
parent | 25af5ea40f286df0a578c738c67ab54faceda90a (diff) | |
download | cpython-8560f4a0f288fec33ba49f85bb872353d631a4dc.zip cpython-8560f4a0f288fec33ba49f85bb872353d631a4dc.tar.gz cpython-8560f4a0f288fec33ba49f85bb872353d631a4dc.tar.bz2 |
gh-91462: Make lltrace output human-readable. (GH-91463)
* Transform opcodes into opnames
* Print the whole stack at each opcode, and eliminate prtrace output at each (push/pop/stackadj)
* Display info about the function at each resume_frame
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_lltrace.py | 97 |
1 files changed, 89 insertions, 8 deletions
diff --git a/Lib/test/test_lltrace.py b/Lib/test/test_lltrace.py index 06e33f4..75b377b 100644 --- a/Lib/test/test_lltrace.py +++ b/Lib/test/test_lltrace.py @@ -1,21 +1,103 @@ -import os +import dis +import sys import textwrap import unittest -from test.support import os_helper +from test.support import os_helper, verbose from test.support.script_helper import assert_python_ok +def example(): + x = [] + for i in range(1): + x.append(i) + x = "this is" + y = "an example" + print(x, y) +Py_DEBUG = hasattr(sys, 'gettotalrefcount') + +@unittest.skipUnless(Py_DEBUG, "lltrace requires Py_DEBUG") class TestLLTrace(unittest.TestCase): + def run_code(self, code): + code = textwrap.dedent(code).strip() + with open(os_helper.TESTFN, 'w', encoding='utf-8') as fd: + self.addCleanup(os_helper.unlink, os_helper.TESTFN) + fd.write(code) + status, stdout, stderr = assert_python_ok(os_helper.TESTFN) + self.assertEqual(stderr, b"") + self.assertEqual(status, 0) + result = stdout.decode('utf-8') + if verbose: + print("\n\n--- code ---") + print(code) + print("\n--- stdout ---") + print(result) + print() + return result + + def test_lltrace(self): + stdout = self.run_code(""" + def dont_trace_1(): + a = "a" + a = 10 * a + def trace_me(): + for i in range(3): + +i + def dont_trace_2(): + x = 42 + y = -x + dont_trace_1() + __ltrace__ = 1 + trace_me() + del __ltrace__ + dont_trace_2() + """) + self.assertIn("GET_ITER", stdout) + self.assertIn("FOR_ITER", stdout) + self.assertIn("UNARY_POSITIVE", stdout) + self.assertIn("POP_TOP", stdout) + self.assertNotIn("BINARY_OP", stdout) + self.assertNotIn("UNARY_NEGATIVE", stdout) + + self.assertIn("'trace_me' in module '__main__'", stdout) + self.assertNotIn("dont_trace_1", stdout) + self.assertNotIn("'dont_trace_2' in module", stdout) + + def test_lltrace_different_module(self): + stdout = self.run_code(""" + from test import test_lltrace + test_lltrace.__ltrace__ = 1 + test_lltrace.example() + """) + self.assertIn("'example' in module 'test.test_lltrace'", stdout) + self.assertIn('LOAD_CONST', stdout) + self.assertIn('FOR_ITER', stdout) + self.assertIn('this is an example', stdout) + + # check that offsets match the output of dis.dis() + instr_map = {i.offset: i for i in dis.get_instructions(example)} + for line in stdout.splitlines(): + offset, colon, opname_oparg = line.partition(":") + if not colon: + continue + offset = int(offset) + opname_oparg = opname_oparg.split() + if len(opname_oparg) == 2: + opname, oparg = opname_oparg + oparg = int(oparg) + else: + (opname,) = opname_oparg + oparg = None + self.assertEqual(instr_map[offset].opname, opname) + self.assertEqual(instr_map[offset].arg, oparg) + def test_lltrace_does_not_crash_on_subscript_operator(self): # If this test fails, it will reproduce a crash reported as # bpo-34113. The crash happened at the command line console of # debug Python builds with __ltrace__ enabled (only possible in console), # when the internal Python stack was negatively adjusted - with open(os_helper.TESTFN, 'w', encoding='utf-8') as fd: - self.addCleanup(os_helper.unlink, os_helper.TESTFN) - fd.write(textwrap.dedent("""\ + stdout = self.run_code(""" import code console = code.InteractiveConsole() @@ -23,9 +105,8 @@ class TestLLTrace(unittest.TestCase): console.push('a = [1, 2, 3]') console.push('a[0] = 1') print('unreachable if bug exists') - """)) - - assert_python_ok(os_helper.TESTFN) + """) + self.assertIn("unreachable if bug exists", stdout) if __name__ == "__main__": unittest.main() |