test_dis.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. # Minimal tests for dis module
  2. from test.test_support import run_unittest
  3. import unittest
  4. import sys
  5. import dis
  6. import StringIO
  7. def _f(a):
  8. print a
  9. return 1
  10. dis_f = """\
  11. %3d 0 LOAD_FAST 0 (a)
  12. 3 PRINT_ITEM
  13. 4 PRINT_NEWLINE
  14. %3d 5 LOAD_CONST 1 (1)
  15. 8 RETURN_VALUE
  16. """%(_f.func_code.co_firstlineno + 1,
  17. _f.func_code.co_firstlineno + 2)
  18. def bug708901():
  19. for res in range(1,
  20. 10):
  21. pass
  22. dis_bug708901 = """\
  23. %3d 0 SETUP_LOOP 23 (to 26)
  24. 3 LOAD_GLOBAL 0 (range)
  25. 6 LOAD_CONST 1 (1)
  26. %3d 9 LOAD_CONST 2 (10)
  27. 12 CALL_FUNCTION 2
  28. 15 GET_ITER
  29. >> 16 FOR_ITER 6 (to 25)
  30. 19 STORE_FAST 0 (res)
  31. %3d 22 JUMP_ABSOLUTE 16
  32. >> 25 POP_BLOCK
  33. >> 26 LOAD_CONST 0 (None)
  34. 29 RETURN_VALUE
  35. """%(bug708901.func_code.co_firstlineno + 1,
  36. bug708901.func_code.co_firstlineno + 2,
  37. bug708901.func_code.co_firstlineno + 3)
  38. def bug1333982(x=[]):
  39. assert 0, ([s for s in x] +
  40. 1)
  41. pass
  42. dis_bug1333982 = """\
  43. %3d 0 LOAD_CONST 1 (0)
  44. 3 POP_JUMP_IF_TRUE 41
  45. 6 LOAD_GLOBAL 0 (AssertionError)
  46. 9 BUILD_LIST 0
  47. 12 LOAD_FAST 0 (x)
  48. 15 GET_ITER
  49. >> 16 FOR_ITER 12 (to 31)
  50. 19 STORE_FAST 1 (s)
  51. 22 LOAD_FAST 1 (s)
  52. 25 LIST_APPEND 2
  53. 28 JUMP_ABSOLUTE 16
  54. %3d >> 31 LOAD_CONST 2 (1)
  55. 34 BINARY_ADD
  56. 35 CALL_FUNCTION 1
  57. 38 RAISE_VARARGS 1
  58. %3d >> 41 LOAD_CONST 0 (None)
  59. 44 RETURN_VALUE
  60. """%(bug1333982.func_code.co_firstlineno + 1,
  61. bug1333982.func_code.co_firstlineno + 2,
  62. bug1333982.func_code.co_firstlineno + 3)
  63. _BIG_LINENO_FORMAT = """\
  64. %3d 0 LOAD_GLOBAL 0 (spam)
  65. 3 POP_TOP
  66. 4 LOAD_CONST 0 (None)
  67. 7 RETURN_VALUE
  68. """
  69. class DisTests(unittest.TestCase):
  70. def do_disassembly_test(self, func, expected):
  71. s = StringIO.StringIO()
  72. save_stdout = sys.stdout
  73. sys.stdout = s
  74. dis.dis(func)
  75. sys.stdout = save_stdout
  76. got = s.getvalue()
  77. # Trim trailing blanks (if any).
  78. lines = got.split('\n')
  79. lines = [line.rstrip() for line in lines]
  80. expected = expected.split("\n")
  81. import difflib
  82. if expected != lines:
  83. self.fail(
  84. "events did not match expectation:\n" +
  85. "\n".join(difflib.ndiff(expected,
  86. lines)))
  87. def test_opmap(self):
  88. self.assertEqual(dis.opmap["STOP_CODE"], 0)
  89. self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst)
  90. self.assertIn(dis.opmap["STORE_NAME"], dis.hasname)
  91. def test_opname(self):
  92. self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST")
  93. def test_boundaries(self):
  94. self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG)
  95. self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT)
  96. def test_dis(self):
  97. self.do_disassembly_test(_f, dis_f)
  98. def test_bug_708901(self):
  99. self.do_disassembly_test(bug708901, dis_bug708901)
  100. def test_bug_1333982(self):
  101. # This one is checking bytecodes generated for an `assert` statement,
  102. # so fails if the tests are run with -O. Skip this test then.
  103. if __debug__:
  104. self.do_disassembly_test(bug1333982, dis_bug1333982)
  105. else:
  106. self.skipTest('need asserts, run without -O')
  107. def test_big_linenos(self):
  108. def func(count):
  109. namespace = {}
  110. func = "def foo():\n " + "".join(["\n "] * count + ["spam\n"])
  111. exec func in namespace
  112. return namespace['foo']
  113. # Test all small ranges
  114. for i in xrange(1, 300):
  115. expected = _BIG_LINENO_FORMAT % (i + 2)
  116. self.do_disassembly_test(func(i), expected)
  117. # Test some larger ranges too
  118. for i in xrange(300, 5000, 10):
  119. expected = _BIG_LINENO_FORMAT % (i + 2)
  120. self.do_disassembly_test(func(i), expected)
  121. def test_main():
  122. run_unittest(DisTests)
  123. if __name__ == "__main__":
  124. test_main()