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