1import dis 2from test.support.import_helper import import_module 3import unittest 4import opcode 5 6_opcode = import_module("_opcode") 7from _opcode import stack_effect 8 9 10class OpcodeTests(unittest.TestCase): 11 12 def test_stack_effect(self): 13 self.assertEqual(stack_effect(dis.opmap['POP_TOP']), -1) 14 self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 0), -1) 15 self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 1), -1) 16 self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 3), -2) 17 self.assertRaises(ValueError, stack_effect, 30000) 18 self.assertRaises(ValueError, stack_effect, dis.opmap['BUILD_SLICE']) 19 self.assertRaises(ValueError, stack_effect, dis.opmap['POP_TOP'], 0) 20 # All defined opcodes 21 for name, code in filter(lambda item: item[0] not in dis.deoptmap, dis.opmap.items()): 22 with self.subTest(opname=name): 23 if code < dis.HAVE_ARGUMENT: 24 stack_effect(code) 25 self.assertRaises(ValueError, stack_effect, code, 0) 26 else: 27 stack_effect(code, 0) 28 self.assertRaises(ValueError, stack_effect, code) 29 # All not defined opcodes 30 for code in set(range(256)) - set(dis.opmap.values()): 31 with self.subTest(opcode=code): 32 self.assertRaises(ValueError, stack_effect, code) 33 self.assertRaises(ValueError, stack_effect, code, 0) 34 35 def test_stack_effect_jump(self): 36 JUMP_IF_TRUE_OR_POP = dis.opmap['JUMP_IF_TRUE_OR_POP'] 37 self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0), 0) 38 self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0, jump=True), 0) 39 self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0, jump=False), -1) 40 FOR_ITER = dis.opmap['FOR_ITER'] 41 self.assertEqual(stack_effect(FOR_ITER, 0), 1) 42 self.assertEqual(stack_effect(FOR_ITER, 0, jump=True), -1) 43 self.assertEqual(stack_effect(FOR_ITER, 0, jump=False), 1) 44 JUMP_FORWARD = dis.opmap['JUMP_FORWARD'] 45 self.assertEqual(stack_effect(JUMP_FORWARD, 0), 0) 46 self.assertEqual(stack_effect(JUMP_FORWARD, 0, jump=True), 0) 47 self.assertEqual(stack_effect(JUMP_FORWARD, 0, jump=False), 0) 48 # All defined opcodes 49 has_jump = dis.hasjabs + dis.hasjrel 50 for name, code in filter(lambda item: item[0] not in dis.deoptmap, dis.opmap.items()): 51 with self.subTest(opname=name): 52 if code < dis.HAVE_ARGUMENT: 53 common = stack_effect(code) 54 jump = stack_effect(code, jump=True) 55 nojump = stack_effect(code, jump=False) 56 else: 57 common = stack_effect(code, 0) 58 jump = stack_effect(code, 0, jump=True) 59 nojump = stack_effect(code, 0, jump=False) 60 if code in has_jump: 61 self.assertEqual(common, max(jump, nojump)) 62 else: 63 self.assertEqual(jump, common) 64 self.assertEqual(nojump, common) 65 66 67class SpecializationStatsTests(unittest.TestCase): 68 def test_specialization_stats(self): 69 stat_names = opcode._specialization_stats 70 71 specialized_opcodes = [ 72 op[:-len("_ADAPTIVE")].lower() for 73 op in opcode._specialized_instructions 74 if op.endswith("_ADAPTIVE")] 75 self.assertIn('load_attr', specialized_opcodes) 76 self.assertIn('binary_subscr', specialized_opcodes) 77 78 stats = _opcode.get_specialization_stats() 79 if stats is not None: 80 self.assertIsInstance(stats, dict) 81 self.assertCountEqual(stats.keys(), specialized_opcodes) 82 self.assertCountEqual( 83 stats['load_attr'].keys(), 84 stat_names + ['failure_kinds']) 85 for sn in stat_names: 86 self.assertIsInstance(stats['load_attr'][sn], int) 87 self.assertIsInstance( 88 stats['load_attr']['failure_kinds'], 89 tuple) 90 for v in stats['load_attr']['failure_kinds']: 91 self.assertIsInstance(v, int) 92 93 94if __name__ == "__main__": 95 unittest.main() 96