(root)/
Python-3.12.0/
Lib/
test/
test_lltrace.py
       1  import dis
       2  import textwrap
       3  import unittest
       4  
       5  from test import support
       6  from test.support import os_helper
       7  from test.support.script_helper import assert_python_ok
       8  
       9  def example():
      10      x = []
      11      for i in range(0):
      12          x.append(i)
      13      x = "this is"
      14      y = "an example"
      15      print(x, y)
      16  
      17  
      18  @unittest.skipUnless(support.Py_DEBUG, "lltrace requires Py_DEBUG")
      19  class ESC[4;38;5;81mTestLLTrace(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      20  
      21      def run_code(self, code):
      22          code = textwrap.dedent(code).strip()
      23          with open(os_helper.TESTFN, 'w', encoding='utf-8') as fd:
      24              self.addCleanup(os_helper.unlink, os_helper.TESTFN)
      25              fd.write(code)
      26          status, stdout, stderr = assert_python_ok(os_helper.TESTFN)
      27          self.assertEqual(stderr, b"")
      28          self.assertEqual(status, 0)
      29          result = stdout.decode('utf-8')
      30          if support.verbose:
      31              print("\n\n--- code ---")
      32              print(code)
      33              print("\n--- stdout ---")
      34              print(result)
      35              print()
      36          return result
      37  
      38      def test_lltrace(self):
      39          stdout = self.run_code("""
      40              def dont_trace_1():
      41                  a = "a"
      42                  a = 10 * a
      43              def trace_me():
      44                  for i in range(3):
      45                      +i
      46              def dont_trace_2():
      47                  x = 42
      48                  y = -x
      49              dont_trace_1()
      50              __lltrace__ = 1
      51              trace_me()
      52              del __lltrace__
      53              dont_trace_2()
      54          """)
      55          self.assertIn("GET_ITER", stdout)
      56          self.assertIn("FOR_ITER", stdout)
      57          self.assertIn("CALL_INTRINSIC_1", stdout)
      58          self.assertIn("POP_TOP", stdout)
      59          self.assertNotIn("BINARY_OP", stdout)
      60          self.assertNotIn("UNARY_NEGATIVE", stdout)
      61  
      62          self.assertIn("'trace_me' in module '__main__'", stdout)
      63          self.assertNotIn("dont_trace_1", stdout)
      64          self.assertNotIn("'dont_trace_2' in module", stdout)
      65  
      66      def test_lltrace_different_module(self):
      67          stdout = self.run_code("""
      68              from test import test_lltrace
      69              test_lltrace.__lltrace__ = 1
      70              test_lltrace.example()
      71          """)
      72          self.assertIn("'example' in module 'test.test_lltrace'", stdout)
      73          self.assertIn('LOAD_CONST', stdout)
      74          self.assertIn('FOR_ITER', stdout)
      75          self.assertIn('this is an example', stdout)
      76  
      77          # check that offsets match the output of dis.dis()
      78          instr_map = {i.offset: i for i in dis.get_instructions(example, adaptive=True)}
      79          for line in stdout.splitlines():
      80              offset, colon, opname_oparg = line.partition(":")
      81              if not colon:
      82                  continue
      83              offset = int(offset)
      84              opname_oparg = opname_oparg.split()
      85              if len(opname_oparg) == 2:
      86                  opname, oparg = opname_oparg
      87                  oparg = int(oparg)
      88              else:
      89                  (opname,) = opname_oparg
      90                  oparg = None
      91              self.assertEqual(instr_map[offset].opname, opname)
      92              self.assertEqual(instr_map[offset].arg, oparg)
      93  
      94      def test_lltrace_does_not_crash_on_subscript_operator(self):
      95          # If this test fails, it will reproduce a crash reported as
      96          # bpo-34113. The crash happened at the command line console of
      97          # debug Python builds with __lltrace__ enabled (only possible in console),
      98          # when the internal Python stack was negatively adjusted
      99          stdout = self.run_code("""
     100              import code
     101  
     102              console = code.InteractiveConsole()
     103              console.push('__lltrace__ = 1')
     104              console.push('a = [1, 2, 3]')
     105              console.push('a[0] = 1')
     106              print('unreachable if bug exists')
     107          """)
     108          self.assertIn("unreachable if bug exists", stdout)
     109  
     110  if __name__ == "__main__":
     111      unittest.main()