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