blob: 347d60337d763b5fe1da073eef269a52d5f55b6e [file] [log] [blame]
Nick Coghlan37c74652013-05-07 08:28:21 +10001"""bytecode_helper - support tools for testing correct bytecode generation"""
2
3import unittest
4import dis
5import io
6
7_UNSPECIFIED = object()
8
9class BytecodeTestCase(unittest.TestCase):
10 """Custom assertion methods for inspecting bytecode."""
11
12 def get_disassembly_as_string(self, co):
13 s = io.StringIO()
14 dis.dis(co, file=s)
15 return s.getvalue()
16
Nick Coghlan37c74652013-05-07 08:28:21 +100017 def assertInBytecode(self, x, opname, argval=_UNSPECIFIED):
18 """Returns instr if op is found, otherwise throws AssertionError"""
19 for instr in dis.get_instructions(x):
20 if instr.opname == opname:
21 if argval is _UNSPECIFIED or instr.argval == argval:
22 return instr
23 disassembly = self.get_disassembly_as_string(x)
24 if argval is _UNSPECIFIED:
25 msg = '%s not found in bytecode:\n%s' % (opname, disassembly)
26 else:
27 msg = '(%s,%r) not found in bytecode:\n%s'
28 msg = msg % (opname, argval, disassembly)
29 self.fail(msg)
30
31 def assertNotInBytecode(self, x, opname, argval=_UNSPECIFIED):
32 """Throws AssertionError if op is found"""
33 for instr in dis.get_instructions(x):
34 if instr.opname == opname:
Victor Stinner47b91b02016-01-19 08:48:48 +010035 disassembly = self.get_disassembly_as_string(x)
36 if argval is _UNSPECIFIED:
Nick Coghlan37c74652013-05-07 08:28:21 +100037 msg = '%s occurs in bytecode:\n%s' % (opname, disassembly)
38 elif instr.argval == argval:
39 msg = '(%s,%r) occurs in bytecode:\n%s'
40 msg = msg % (opname, argval, disassembly)
41 self.fail(msg)