blob: d12bcdae490ce6d03590ee1cb88ead1778db0477 [file] [log] [blame]
Guido van Rossumd8faa362007-04-27 19:54:29 +00001# Minimal tests for dis module
2
Nick Coghlaneae2da12010-08-17 08:03:36 +00003from test.support import run_unittest, captured_stdout
Guido van Rossumd8faa362007-04-27 19:54:29 +00004import unittest
Skip Montanaroadd0ccc2003-02-27 21:27:07 +00005import sys
6import dis
Guido van Rossum34d19282007-08-09 01:03:29 +00007import io
Skip Montanaroadd0ccc2003-02-27 21:27:07 +00008
Skip Montanaroadd0ccc2003-02-27 21:27:07 +00009
Skip Montanaroadd0ccc2003-02-27 21:27:07 +000010def _f(a):
Guido van Rossumbe19ed72007-02-09 05:37:30 +000011 print(a)
Tim Peterseabafeb2003-03-07 15:55:36 +000012 return 1
Skip Montanaroadd0ccc2003-02-27 21:27:07 +000013
14dis_f = """\
Georg Brandl88fc6642007-02-09 21:28:07 +000015 %-4d 0 LOAD_GLOBAL 0 (print)
16 3 LOAD_FAST 0 (a)
17 6 CALL_FUNCTION 1
18 9 POP_TOP
Skip Montanaroadd0ccc2003-02-27 21:27:07 +000019
Georg Brandl88fc6642007-02-09 21:28:07 +000020 %-4d 10 LOAD_CONST 1 (1)
21 13 RETURN_VALUE
Georg Brandlebbf63b2010-10-14 07:23:01 +000022""" % (_f.__code__.co_firstlineno + 1,
23 _f.__code__.co_firstlineno + 2)
Michael W. Hudson26848a32003-04-29 17:07:36 +000024
25
26def bug708901():
27 for res in range(1,
28 10):
29 pass
30
31dis_bug708901 = """\
32 %-4d 0 SETUP_LOOP 23 (to 26)
33 3 LOAD_GLOBAL 0 (range)
34 6 LOAD_CONST 1 (1)
35
36 %-4d 9 LOAD_CONST 2 (10)
37 12 CALL_FUNCTION 2
38 15 GET_ITER
39 >> 16 FOR_ITER 6 (to 25)
40 19 STORE_FAST 0 (res)
41
42 %-4d 22 JUMP_ABSOLUTE 16
43 >> 25 POP_BLOCK
44 >> 26 LOAD_CONST 0 (None)
45 29 RETURN_VALUE
Georg Brandlebbf63b2010-10-14 07:23:01 +000046""" % (bug708901.__code__.co_firstlineno + 1,
47 bug708901.__code__.co_firstlineno + 2,
48 bug708901.__code__.co_firstlineno + 3)
Skip Montanaroadd0ccc2003-02-27 21:27:07 +000049
Neal Norwitz51abbc72005-12-18 07:06:23 +000050
51def bug1333982(x=[]):
52 assert 0, ([s for s in x] +
53 1)
54 pass
55
56dis_bug1333982 = """\
57 %-4d 0 LOAD_CONST 1 (0)
Antoine Pitrouf289ae62008-12-18 11:06:25 +000058 3 JUMP_IF_TRUE 33 (to 39)
Neal Norwitz51abbc72005-12-18 07:06:23 +000059 6 POP_TOP
60 7 LOAD_GLOBAL 0 (AssertionError)
61 10 BUILD_LIST 0
Antoine Pitrouf289ae62008-12-18 11:06:25 +000062 13 LOAD_FAST 0 (x)
63 16 GET_ITER
64 >> 17 FOR_ITER 12 (to 32)
65 20 STORE_FAST 1 (s)
66 23 LOAD_FAST 1 (s)
67 26 LIST_APPEND 2
68 29 JUMP_ABSOLUTE 17
Neal Norwitz51abbc72005-12-18 07:06:23 +000069
Antoine Pitrouf289ae62008-12-18 11:06:25 +000070 %-4d >> 32 LOAD_CONST 2 (1)
71 35 BINARY_ADD
72 36 RAISE_VARARGS 2
73 >> 39 POP_TOP
Neal Norwitz51abbc72005-12-18 07:06:23 +000074
Antoine Pitrouf289ae62008-12-18 11:06:25 +000075 %-4d 40 LOAD_CONST 0 (None)
76 43 RETURN_VALUE
Georg Brandlebbf63b2010-10-14 07:23:01 +000077""" % (bug1333982.__code__.co_firstlineno + 1,
78 bug1333982.__code__.co_firstlineno + 2,
79 bug1333982.__code__.co_firstlineno + 3)
Neal Norwitz51abbc72005-12-18 07:06:23 +000080
Thomas Wouters0e3f5912006-08-11 14:57:12 +000081_BIG_LINENO_FORMAT = """\
82%3d 0 LOAD_GLOBAL 0 (spam)
83 3 POP_TOP
84 4 LOAD_CONST 0 (None)
85 7 RETURN_VALUE
86"""
87
Guido van Rossume7ba4952007-06-06 23:52:48 +000088dis_module_expected_results = """\
89Disassembly of f:
90 4 0 LOAD_CONST 0 (None)
91 3 RETURN_VALUE
92
93Disassembly of g:
94 5 0 LOAD_CONST 0 (None)
95 3 RETURN_VALUE
96
97"""
98
Nick Coghlan5c8b54e2010-07-03 07:36:51 +000099expr_str = "x + 1"
100
101dis_expr_str = """\
102 1 0 LOAD_NAME 0 (x)
103 3 LOAD_CONST 0 (1)
104 6 BINARY_ADD
105 7 RETURN_VALUE
106"""
107
108simple_stmt_str = "x = x + 1"
109
110dis_simple_stmt_str = """\
111 1 0 LOAD_NAME 0 (x)
112 3 LOAD_CONST 0 (1)
113 6 BINARY_ADD
114 7 STORE_NAME 0 (x)
115 10 LOAD_CONST 1 (None)
116 13 RETURN_VALUE
117"""
118
119compound_stmt_str = """\
120x = 0
121while 1:
122 x += 1"""
123# Trailing newline has been deliberately omitted
124
125dis_compound_stmt_str = """\
126 1 0 LOAD_CONST 0 (0)
127 3 STORE_NAME 0 (x)
128
129 2 6 SETUP_LOOP 13 (to 22)
130
131 3 >> 9 LOAD_NAME 0 (x)
132 12 LOAD_CONST 1 (1)
133 15 INPLACE_ADD
134 16 STORE_NAME 0 (x)
135 19 JUMP_ABSOLUTE 9
136 >> 22 LOAD_CONST 2 (None)
137 25 RETURN_VALUE
138"""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000139
Skip Montanaroadd0ccc2003-02-27 21:27:07 +0000140class DisTests(unittest.TestCase):
Michael W. Hudson26848a32003-04-29 17:07:36 +0000141 def do_disassembly_test(self, func, expected):
Guido van Rossum34d19282007-08-09 01:03:29 +0000142 s = io.StringIO()
Michael W. Hudson26848a32003-04-29 17:07:36 +0000143 save_stdout = sys.stdout
144 sys.stdout = s
145 dis.dis(func)
146 sys.stdout = save_stdout
147 got = s.getvalue()
148 # Trim trailing blanks (if any).
149 lines = got.split('\n')
150 lines = [line.rstrip() for line in lines]
151 expected = expected.split("\n")
152 import difflib
153 if expected != lines:
154 self.fail(
155 "events did not match expectation:\n" +
156 "\n".join(difflib.ndiff(expected,
157 lines)))
158
Skip Montanaroadd0ccc2003-02-27 21:27:07 +0000159 def test_opmap(self):
160 self.assertEqual(dis.opmap["STOP_CODE"], 0)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000161 self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst)
162 self.assertIn(dis.opmap["STORE_NAME"], dis.hasname)
Skip Montanaroadd0ccc2003-02-27 21:27:07 +0000163
164 def test_opname(self):
165 self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST")
166
167 def test_boundaries(self):
168 self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG)
169 self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT)
170
171 def test_dis(self):
Michael W. Hudson26848a32003-04-29 17:07:36 +0000172 self.do_disassembly_test(_f, dis_f)
173
174 def test_bug_708901(self):
175 self.do_disassembly_test(bug708901, dis_bug708901)
Skip Montanaroadd0ccc2003-02-27 21:27:07 +0000176
Neal Norwitz51abbc72005-12-18 07:06:23 +0000177 def test_bug_1333982(self):
Guido van Rossume7ba4952007-06-06 23:52:48 +0000178 # XXX: re-enable this test!
Tim Peters83a8c392005-12-25 22:52:32 +0000179 # This one is checking bytecodes generated for an `assert` statement,
180 # so fails if the tests are run with -O. Skip this test then.
Nick Coghlan650f0d02007-04-15 12:05:43 +0000181 pass # Test has been disabled due to change in the way
182 # list comps are handled. The byte code now includes
183 # a memory address and a file location, so they change from
184 # run to run.
185 # if __debug__:
186 # self.do_disassembly_test(bug1333982, dis_bug1333982)
Neal Norwitz51abbc72005-12-18 07:06:23 +0000187
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000188 def test_big_linenos(self):
189 def func(count):
190 namespace = {}
191 func = "def foo():\n " + "".join(["\n "] * count + ["spam\n"])
Georg Brandl7cae87c2006-09-06 06:51:57 +0000192 exec(func, namespace)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000193 return namespace['foo']
194
195 # Test all small ranges
Guido van Rossum805365e2007-05-07 22:24:25 +0000196 for i in range(1, 300):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000197 expected = _BIG_LINENO_FORMAT % (i + 2)
198 self.do_disassembly_test(func(i), expected)
199
200 # Test some larger ranges too
Guido van Rossum805365e2007-05-07 22:24:25 +0000201 for i in range(300, 5000, 10):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000202 expected = _BIG_LINENO_FORMAT % (i + 2)
203 self.do_disassembly_test(func(i), expected)
204
Guido van Rossume7ba4952007-06-06 23:52:48 +0000205 def test_big_linenos(self):
206 from test import dis_module
207 self.do_disassembly_test(dis_module, dis_module_expected_results)
208
Nick Coghlan5c8b54e2010-07-03 07:36:51 +0000209 def test_disassemble_str(self):
210 self.do_disassembly_test(expr_str, dis_expr_str)
211 self.do_disassembly_test(simple_stmt_str, dis_simple_stmt_str)
212 self.do_disassembly_test(compound_stmt_str, dis_compound_stmt_str)
213
Nick Coghlaneae2da12010-08-17 08:03:36 +0000214code_info_code_info = """\
215Name: code_info
Nick Coghlan46e63802010-08-17 11:28:07 +0000216Filename: (.*)
Nick Coghlaneae2da12010-08-17 08:03:36 +0000217Argument count: 1
218Kw-only arguments: 0
219Number of locals: 1
220Stack size: 4
221Flags: OPTIMIZED, NEWLOCALS, NOFREE
222Constants:
Georg Brandlebbf63b2010-10-14 07:23:01 +0000223 0: %r
Nick Coghlaneae2da12010-08-17 08:03:36 +0000224 1: '__func__'
225 2: '__code__'
226 3: '<code_info>'
227 4: 'co_code'
Georg Brandlebbf63b2010-10-14 07:23:01 +0000228 5: "don't know how to disassemble %%s objects"
229%sNames:
Nick Coghlaneae2da12010-08-17 08:03:36 +0000230 0: hasattr
231 1: __func__
232 2: __code__
233 3: isinstance
234 4: str
235 5: _try_compile
236 6: _format_code_info
237 7: TypeError
238 8: type
239 9: __name__
240Variable names:
Georg Brandlebbf63b2010-10-14 07:23:01 +0000241 0: x""" % (('Formatted details of methods, functions, or code.', ' 6: None\n')
242 if sys.flags.optimize < 2 else (None, ''))
Nick Coghlaneae2da12010-08-17 08:03:36 +0000243
244@staticmethod
245def tricky(x, y, z=True, *args, c, d, e=[], **kwds):
246 def f(c=c):
247 print(x, y, z, c, d, e, f)
248 yield x, y, z, c, d, e, f
249
Nick Coghlaneae2da12010-08-17 08:03:36 +0000250code_info_tricky = """\
251Name: tricky
Nick Coghlan46e63802010-08-17 11:28:07 +0000252Filename: (.*)
Nick Coghlaneae2da12010-08-17 08:03:36 +0000253Argument count: 3
254Kw-only arguments: 3
255Number of locals: 8
256Stack size: 7
257Flags: OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, GENERATOR
258Constants:
259 0: None
Nick Coghlan46e63802010-08-17 11:28:07 +0000260 1: <code object f at (.*), file "(.*)", line (.*)>
Nick Coghlaneae2da12010-08-17 08:03:36 +0000261Variable names:
262 0: x
263 1: y
264 2: z
265 3: c
266 4: d
267 5: e
268 6: args
269 7: kwds
270Cell variables:
271 0: e
272 1: d
273 2: f
274 3: y
275 4: x
Nick Coghlan46e63802010-08-17 11:28:07 +0000276 5: z"""
277
278co_tricky_nested_f = tricky.__func__.__code__.co_consts[1]
Nick Coghlaneae2da12010-08-17 08:03:36 +0000279
280code_info_tricky_nested_f = """\
281Name: f
Nick Coghlan46e63802010-08-17 11:28:07 +0000282Filename: (.*)
Nick Coghlaneae2da12010-08-17 08:03:36 +0000283Argument count: 1
284Kw-only arguments: 0
285Number of locals: 1
286Stack size: 8
287Flags: OPTIMIZED, NEWLOCALS, NESTED
288Constants:
289 0: None
290Names:
291 0: print
292Variable names:
293 0: c
294Free variables:
295 0: e
296 1: d
297 2: f
298 3: y
299 4: x
Nick Coghlan46e63802010-08-17 11:28:07 +0000300 5: z"""
Nick Coghlaneae2da12010-08-17 08:03:36 +0000301
302code_info_expr_str = """\
303Name: <module>
304Filename: <code_info>
305Argument count: 0
306Kw-only arguments: 0
307Number of locals: 0
308Stack size: 2
309Flags: NOFREE
310Constants:
311 0: 1
312Names:
313 0: x"""
314
315code_info_simple_stmt_str = """\
316Name: <module>
317Filename: <code_info>
318Argument count: 0
319Kw-only arguments: 0
320Number of locals: 0
321Stack size: 2
322Flags: NOFREE
323Constants:
324 0: 1
325 1: None
326Names:
327 0: x"""
328
329code_info_compound_stmt_str = """\
330Name: <module>
331Filename: <code_info>
332Argument count: 0
333Kw-only arguments: 0
334Number of locals: 0
335Stack size: 2
336Flags: NOFREE
337Constants:
338 0: 0
339 1: 1
340 2: None
341Names:
342 0: x"""
343
344class CodeInfoTests(unittest.TestCase):
345 test_pairs = [
346 (dis.code_info, code_info_code_info),
347 (tricky, code_info_tricky),
348 (co_tricky_nested_f, code_info_tricky_nested_f),
349 (expr_str, code_info_expr_str),
350 (simple_stmt_str, code_info_simple_stmt_str),
351 (compound_stmt_str, code_info_compound_stmt_str),
352 ]
353
354 def test_code_info(self):
355 self.maxDiff = 1000
356 for x, expected in self.test_pairs:
Nick Coghlan77203ad2010-08-17 09:25:57 +0000357 self.assertRegexpMatches(dis.code_info(x), expected)
Nick Coghlaneae2da12010-08-17 08:03:36 +0000358
359 def test_show_code(self):
360 self.maxDiff = 1000
361 for x, expected in self.test_pairs:
362 with captured_stdout() as output:
363 dis.show_code(x)
Nick Coghlan77203ad2010-08-17 09:25:57 +0000364 self.assertRegexpMatches(output.getvalue(), expected+"\n")
Nick Coghlaneae2da12010-08-17 08:03:36 +0000365
Skip Montanaroadd0ccc2003-02-27 21:27:07 +0000366def test_main():
Nick Coghlaneae2da12010-08-17 08:03:36 +0000367 run_unittest(DisTests, CodeInfoTests)
Skip Montanaroadd0ccc2003-02-27 21:27:07 +0000368
Skip Montanaroadd0ccc2003-02-27 21:27:07 +0000369if __name__ == "__main__":
370 test_main()