def test_negative_size_build_const_map(self): code = Bytecode() code.first_lineno = 1 code.extend( [Instr("LOAD_CONST", ("a", )), Instr("BUILD_CONST_KEY_MAP", 1)]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_not_enough_rot(self): opnames = ["ROT_TWO", "ROT_THREE"] if sys.version_info >= (3, 8): opnames.append("ROT_FOUR") for opname in opnames: with self.subTest(): code = Bytecode() code.first_lineno = 1 code.extend([Instr("LOAD_CONST", 1), Instr(opname)]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_negative_size_unpack(self): opnames = ( "UNPACK_SEQUENCE", "UNPACK_EX", ) for opname in opnames: with self.subTest(): code = Bytecode() code.first_lineno = 1 code.extend([Instr(opname, 1)]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_negative_size_unary(self): opnames = ( "UNARY_POSITIVE", "UNARY_NEGATIVE", "UNARY_NOT", "UNARY_INVERT", ) for opname in opnames: with self.subTest(): code = Bytecode() code.first_lineno = 1 code.extend([Instr(opname)]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_negative_size_build(self): opnames = ( "BUILD_TUPLE", "BUILD_LIST", "BUILD_SET", ) if sys.version_info >= (3, 6): opnames = (*opnames, "BUILD_STRING") for opname in opnames: with self.subTest(): code = Bytecode() code.first_lineno = 1 code.extend([Instr(opname, 1)]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_for_iter_stack_effect_computation(self): with self.subTest(): code = Bytecode() code.first_lineno = 1 lab1 = Label() lab2 = Label() code.extend([ lab1, Instr("FOR_ITER", lab2), Instr("STORE_FAST", "i"), Instr("JUMP_ABSOLUTE", lab1), lab2, ]) with self.assertRaises(RuntimeError): # Use compute_stacksize since the code is so broken that conversion # to from concrete is actually broken code.compute_stacksize(check_pre_and_post=False)
def test_huge_code_with_numerous_blocks(self): def base_func(x): pass def mk_if_then_else(depth): instructions = [] for i in range(depth): label_else = Label() instructions.extend([ Instr("LOAD_FAST", "x"), Instr("POP_JUMP_IF_FALSE", label_else), Instr("LOAD_GLOBAL", "f{}".format(i)), Instr("RETURN_VALUE"), label_else, ]) instructions.extend( [Instr("LOAD_CONST", None), Instr("RETURN_VALUE")]) return instructions bytecode = Bytecode(mk_if_then_else(5000)) bytecode.compute_stacksize()
def test_handling_of_set_lineno(self): code = Bytecode() code.first_lineno = 3 code.extend([ Instr("LOAD_CONST", 7), Instr("STORE_NAME", "x"), SetLineno(4), Instr("LOAD_CONST", 8), Instr("STORE_NAME", "y"), SetLineno(5), Instr("LOAD_CONST", 9), Instr("STORE_NAME", "z"), ]) self.assertEqual(code.compute_stacksize(), 1)
def test_negative_size_binary(self): opnames = ( "BINARY_POWER", "BINARY_MULTIPLY", "BINARY_MATRIX_MULTIPLY", "BINARY_FLOOR_DIVIDE", "BINARY_TRUE_DIVIDE", "BINARY_MODULO", "BINARY_ADD", "BINARY_SUBTRACT", "BINARY_SUBSCR", "BINARY_LSHIFT", "BINARY_RSHIFT", "BINARY_AND", "BINARY_XOR", "BINARY_OR", ) for opname in opnames: with self.subTest(): code = Bytecode() code.first_lineno = 1 code.extend([Instr("LOAD_CONST", 1), Instr(opname)]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_not_enough_dup(self): code = Bytecode() code.first_lineno = 1 code.extend([Instr("LOAD_CONST", 1), Instr("DUP_TOP_TWO")]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_empty_dup(self): code = Bytecode() code.first_lineno = 1 code.extend([Instr("DUP_TOP")]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_negative_size_call(self): code = Bytecode() code.first_lineno = 1 code.extend([Instr("CALL_FUNCTION", 0)]) with self.assertRaises(RuntimeError): code.compute_stacksize()
def test_invalid_stacksize(self): code = Bytecode() code.extend([Instr("STORE_NAME", "x")]) with self.assertRaises(RuntimeError): code.compute_stacksize()