annotate Lib/test/bytecode_helper.py @ 86127:a3d09c19bb93

merge with 3.3
author Georg Brandl <georg@python.org>
date Sun, 06 Oct 2013 19:24:00 +0200
parents 84d1a0e32d3b
children ce8dd299cdc4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
83659
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
1 """bytecode_helper - support tools for testing correct bytecode generation"""
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
2
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
3 import unittest
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
4 import dis
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
5 import io
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
6
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
7 _UNSPECIFIED = object()
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
8
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
9 class BytecodeTestCase(unittest.TestCase):
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
10 """Custom assertion methods for inspecting bytecode."""
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
11
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
12 def get_disassembly_as_string(self, co):
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
13 s = io.StringIO()
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
14 dis.dis(co, file=s)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
15 return s.getvalue()
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
16
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
17 def assertInstructionMatches(self, instr, expected, *, line_offset=0):
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
18 # Deliberately test opname first, since that gives a more
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
19 # meaningful error message than testing opcode
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
20 self.assertEqual(instr.opname, expected.opname)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
21 self.assertEqual(instr.opcode, expected.opcode)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
22 self.assertEqual(instr.arg, expected.arg)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
23 self.assertEqual(instr.argval, expected.argval)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
24 self.assertEqual(instr.argrepr, expected.argrepr)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
25 self.assertEqual(instr.offset, expected.offset)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
26 if expected.starts_line is None:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
27 self.assertIsNone(instr.starts_line)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
28 else:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
29 self.assertEqual(instr.starts_line,
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
30 expected.starts_line + line_offset)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
31 self.assertEqual(instr.is_jump_target, expected.is_jump_target)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
32
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
33
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
34 def assertBytecodeExactlyMatches(self, x, expected, *, line_offset=0):
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
35 """Throws AssertionError if any discrepancy is found in bytecode
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
36
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
37 *x* is the object to be introspected
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
38 *expected* is a list of dis.Instruction objects
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
39
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
40 Set *line_offset* as appropriate to adjust for the location of the
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
41 object to be disassembled within the test file. If the expected list
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
42 assumes the first line is line 1, then an appropriate offset would be
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
43 ``1 - f.__code__.co_firstlineno``.
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
44 """
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
45 actual = dis.get_instructions(x, line_offset=line_offset)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
46 self.assertEqual(list(actual), expected)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
47
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
48 def assertInBytecode(self, x, opname, argval=_UNSPECIFIED):
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
49 """Returns instr if op is found, otherwise throws AssertionError"""
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
50 for instr in dis.get_instructions(x):
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
51 if instr.opname == opname:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
52 if argval is _UNSPECIFIED or instr.argval == argval:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
53 return instr
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
54 disassembly = self.get_disassembly_as_string(x)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
55 if argval is _UNSPECIFIED:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
56 msg = '%s not found in bytecode:\n%s' % (opname, disassembly)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
57 else:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
58 msg = '(%s,%r) not found in bytecode:\n%s'
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
59 msg = msg % (opname, argval, disassembly)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
60 self.fail(msg)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
61
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
62 def assertNotInBytecode(self, x, opname, argval=_UNSPECIFIED):
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
63 """Throws AssertionError if op is found"""
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
64 for instr in dis.get_instructions(x):
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
65 if instr.opname == opname:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
66 disassembly = self.get_disassembly_as_string(co)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
67 if opargval is _UNSPECIFIED:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
68 msg = '%s occurs in bytecode:\n%s' % (opname, disassembly)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
69 elif instr.argval == argval:
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
70 msg = '(%s,%r) occurs in bytecode:\n%s'
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
71 msg = msg % (opname, argval, disassembly)
84d1a0e32d3b Issue #11816: Add missing test helper
Nick Coghlan <ncoghlan@gmail.com>
parents:
diff changeset
72 self.fail(msg)