def test_renaming_given_3_scopes(self): as_tree = AstBuilder().string_build( dedent("""\ class Foo(): x = 1 def __init__(self): x = 2 x = 3 f = Foo(2) """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L2": dedent("""\ Assign: (x_0,) = 1 Assign: (__init___0,) = Proxy to the object: Function __init__ in scope Class "Foo" in scope Module """), "L4": "Assign: (x_0,) = 2", "L5": dedent("""\ Assign: (x_0,) = 3 Assign: (f_0,) = Call: Foo_0((2,)) """), }, )
def test_get_dunder_binop(self): as_tree = AstBuilder().string_build("""\ a = 1 a - 2 class F: def __add__(self, other): pass f = F() """) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() with self.assertRaises(exceptions.OperationIncompatible) as e: list( protocols.get_custom_dunder_method(as_tree.body[1].value.left, "-")) assert e.exception.msg == "the node: 1 is not of type ClassInstance" meth = list( protocols.get_custom_dunder_method(as_tree.body[-1].targets[0], "+"))[0] assert str( meth ) == 'Proxy to the object: Function __add__ in scope Class "F" in scope Module' with self.assertRaises(exceptions.DunderUnimplemented) as e: list( protocols.get_custom_dunder_method(as_tree.body[-1].targets[0], "<")) assert e.exception.method_name == "__lt__"
def test_renaming_nameconstant(self): as_tree = AstBuilder().string_build( dedent("""\ if True: x = True else: x = None if False: pass """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L1": dedent("""\ True """), "L4": "Assign: (x_1,) = None", "L5": dedent("""\ Assign: (x_2,) = Phi(x_0, x_1) False """), }, )
def test_renaming_multiple_scope(self): as_tree = AstBuilder().string_build( dedent("""\ def foo(x): a = 3 return x a = 2 foo(a) """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L2": dedent("""\ Assign: (ret_val_0,) = x_0 Assign: (a_0,) = 3 """), "L5": dedent("""\ Assign: (a_0,) = 2 Call: foo_0((a_0,)) """), }, )
def test_renaming_args_attribute(self): as_tree = AstBuilder().string_build( dedent("""\ class Temp: def __init__(self): pass def foo(x): return x + 1 y = Temp() y.z = 3 foo(y.z) """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L9": dedent("""\ Assign: (y_0.z_0,) = 3 Call: foo_0((y_0.z_0,)) """) }, )
def test_renaming_str_format(self): as_tree = AstBuilder().string_build( dedent("""\ v = 1 s = "some{}".format(v) """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa()
def test_renaming_for_var(self): as_tree = AstBuilder().string_build( dedent("""\ for line in something: if x: line = "s".join('y') else: line = "z".join('y') line.strip() """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa()
def test_locals_dict_if(self): as_tree = AstBuilder().string_build( dedent("""\ x = 1 y = 2 if x < 2: pass """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() assert as_tree.locals == { "x_0": as_tree.body[0].value, "y_0": as_tree.body[1].value }
def test_locals_dict_functiondef(self): as_tree = AstBuilder().string_build( dedent("""\ def foo(x): y = 2 return y """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assert_locals_str( { "x_0": "Arg: 'x'", "y_0": "2", "ret_val_0": "y_0" }, as_tree.body[0].locals)
def test_locals_dict_multiple_assignment(self): as_tree = AstBuilder().string_build( dedent("""\ y = 3 x = 1 z = y x = 1 """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() assert as_tree.locals == { "y_0": as_tree.body[0].value, "x_0": as_tree.body[1].value, "z_0": as_tree.body[2].value, "x_1": as_tree.body[3].value, }
def test_renaming_globals_var_1_var(self): as_tree = AstBuilder().string_build( dedent("""\ def foo(x): x = y """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L2": dedent("""\ Assign: (x_1,) = y """) }, )
def test_locals_functiondef_default_args(self): as_tree = AstBuilder().string_build( dedent("""\ def foo(x, y=1.5): f = 4 """), name="test_mod", ) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() # y_0 = Arg: y because handling of default arg will be `infer_arg` job self.assert_locals_str( { "x_0": "Arg: 'x'", "y_0": "Arg: 'y'", "f_0": "4" }, as_tree.body[0].locals)
def test_renaming_tuple_packing_unpacking(self): as_tree = AstBuilder().string_build( dedent("""\ a = b = 1 (a, b) = (1, 1) """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L1": dedent("""\ Assign: (a_0, b_0) = 1 Assign: ((a_1, b_1),) = (1, 1) """) }, )
def test_renaming_starred_var(self): as_tree = AstBuilder().string_build( dedent("""\ a = b = 1 a, *b = (1, 1) """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L1": dedent("""\ Assign: (a_0, b_0) = 1 Assign: ((a_1, *b_1),) = (1, 1) """) }, )
def test_locals_phi_function(self): as_tree = AstBuilder().string_build( dedent("""\ if True: x = 1 else: x = 2 y = x """), name="test_mod", ) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assert_locals_str( { "x_0": "1", "x_1": "2", "x_2": "Phi(x_0, x_1)", "y_0": "x_2" }, as_tree.locals)
def test_renaming_phi_func_elif(self): as_tree = AstBuilder().string_build( dedent("""\ class C: def Top(self): # IO: have 55 io in each local block self.max_rlc = 55 self.nlc = (self.number -1)/self.max_rlc + 1 self.pp_key_num = self.pp_key_num + self.re if(self.pp_en): self.nlc = 3 self.pp_key_num = self.pp_key_num + self.re self.number = self.number + self.nlc * self.re self.number_2lc = 0 res = "d" if self.nlc == 1: res = "a" elif self.nlc == 2: self.number_2lc = self.number - self.number_1lc elif self.nlc == 3: self.number_2lc = self.nio_2lc * 2 z = self.number_2lc """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L25": dedent("""\ Assign: (res_2,) = Phi(res_1, res_0) Assign: (self_0.number_2lc_3,) = Phi(self_0.number_2lc_0, self_0.number_2lc_1, self_0.number_2lc_2) Assign: (z_0,) = self_0.number_2lc_3""") }, )
def test_renaming_list_phi_values(self): as_tree = AstBuilder().string_build( dedent("""\ if True: l = [1, 2, 3, "s"] else: l = [4, 5, 6, True] s = l[1:] """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L5": dedent("""\ Assign: (l_2,) = Phi(l_0, l_1) Assign: (s_0,) = l_2[1:'':''] """) }, )
def test_locals_nested_functiondef(self): as_tree = AstBuilder().string_build( dedent("""\ def foo(x): def fee(y): y = 2 return y """), name="test_mod", ) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assert_locals_str( { "x_0": "Arg: 'x'", "fee_0": "Proxy to the object: Function fee in scope Function foo in scope Module test_mod", }, as_tree.body[0].locals, )
def test_renaming_import_as(self): as_tree = AstBuilder().string_build( dedent("""\ import abc from abc import s import abc as abc abc.s = 1 """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L1": dedent("""\ import (abc_0 ,) from abc import (s_0 ,) import (abc as abc_1,) Assign: (abc_1.s_0,) = 1 """) }, )
def test_renaming_list_simple(self): as_tree = AstBuilder().string_build( dedent("""\ a = 2 a = 1 + 2 - 3 l = [1, 2, a, "s"] s = l[a + 1:a + 3] """)) str(as_tree.body[-1].value.slice) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L1": dedent("""\ Assign: (a_0,) = 2 Assign: (a_1,) = BinOp: BinOp: 1 + 2 - 3 Assign: (l_0,) = [1, 2, a_1, 's'] Assign: (s_0,) = l_0[BinOp: a_1 + 1:BinOp: a_1 + 3:''] """) }, )
def test_renaming_for_while(self): as_tree = AstBuilder().string_build( dedent("""\ bi = 1 b = 2 cycle = False first = True while cycle or first: while b is None or (bi < b and b > o): for c in [c] * repeat: yield c """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L6": dedent("""\ Assign: (c_1,) = Phi(c_0, c_3) b_0 is None or bi_0 < b_0 and b_0 > o """) }, )
def test_renaming_for(self): as_tree = AstBuilder().string_build( dedent("""\ for i in iter(): z = i z = i """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L1": dedent("""\ Assign: (i_0,) = Phi(i, i_1) Assign: (z_0,) = Phi(z, z_1) Assign: (i_1,) = ForIter: Call: iter(()) """), "L2": "Assign: (z_1,) = i_1", "L3": "Assign: (z_2,) = i_1", }, )
def test_renaming_functiondef_replaced(self): as_tree = AstBuilder().string_build( dedent("""\ def foo(x): return x def foo(): pass a = 2 foo(a) """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L7": dedent("""\ Assign: (a_0,) = 2 Call: foo_1((a_0,)) """) }, )
def test_renaming_args_expression(self): as_tree = AstBuilder().string_build( dedent("""\ def foo(x): return x + 1 y = 2 y = 3 z = 4 foo(y + 2 / z * 43) """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L3": dedent("""\ Assign: (y_0,) = 2 Assign: (y_1,) = 3 Assign: (z_0,) = 4 Call: foo_0((BinOp: y_1 + BinOp: BinOp: 2 / z_0 * 43,)) """) }, )
def test_renaming_subscript_assignment(self): as_tree = AstBuilder().string_build( dedent("""\ l = [1, 2, 3] l[2] = 4 l[1:] = [2, 3] l[1] = 5 l[2] = 10 """)) cfg_real = Cfg(as_tree) cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "L1": dedent("""\ Assign: (l_0,) = [1, 2, 3] Assign: (l_0[2]_0,) = 4 Assign: (l_0[1:'':'']_0,) = [2, 3] Assign: (l_0[1]_0,) = 5 Assign: (l_0[2]_1,) = 10 """) }, )
def test_renaming_given_loop(self): r""" A | B <---- / \ | C D | \ / | E -----| """ blocks, as_tree = self.build_arbitrary_blocks( block_links={ "A": ["B"], "B": ["C", "D"], "C": ["E"], "D": ["E"], "E": ["B"], "F": ["A"] }, block_type={"F": ParentScopeBlock}, code={ "A": dedent("""\ j = 1 k = 1 I = 0 """), "B": dedent("""\ I < 29 """), "C": dedent("""\ j = j + 1 k = k + 1 """), "D": dedent("""\ j = j + 2 k = k + 2 """), "E": dedent("""\ temp = 1 """), "F": "", }, ) cfg_real = Cfg() cfg_real.block_list = blocks cfg_real.as_tree = as_tree cfg_real.root = cfg_real.block_list[-1] for blk in cfg_real.block_list[:-1]: blk.scope = cfg_real.block_list[-1] cfg_real.root.ast_node = as_tree cfg_real.root.ssa_code.code_list.append(as_tree) cfg_real.root.blocks = blocks cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "A": dedent("""\ Assign: (j_0,) = 1 Assign: (k_0,) = 1 Assign: (I_0,) = 0 """), "B": dedent("""\ Assign: (temp_0,) = Phi(temp, temp_1) Assign: (k_1,) = Phi(k_0, k_4) Assign: (j_1,) = Phi(j_0, j_4) I_0 < 29 """), "C": dedent("""\ Assign: (j_2,) = BinOp: j_1 + 1 Assign: (k_2,) = BinOp: k_1 + 1 """), "D": dedent("""\ Assign: (j_3,) = BinOp: j_1 + 2 Assign: (k_3,) = BinOp: k_1 + 2 """), "E": dedent("""\ Assign: (k_4,) = Phi(k_2, k_3) Assign: (j_4,) = Phi(j_2, j_3) Assign: (temp_1,) = 1 """), "F": "Module ", }, )
def setup_cfg(ast_str): as_tree = AstBuilder().string_build(ast_str) cfg = Cfg(as_tree) cfg.convert_to_ssa() return cfg
def test_3_blocks_with_loops(self): r""" A | B <-- | | | --- C """ blocks, as_tree = self.build_arbitrary_blocks( block_links={ "A": ["B"], "B": ["C", "B"], "C": [], "D": ["A"] }, block_type={"D": ParentScopeBlock}, code={ "A": dedent("""\ b = 2 c = 1 a = 0 """), "B": dedent("""\ b = a + 1 c = c + b a = b * 2 a < c """), "C": dedent("""\ c = c """), "D": "", }, ) cfg_real = Cfg() cfg_real.block_list = blocks cfg_real.as_tree = as_tree cfg_real.root = cfg_real.block_list[-1] for blk in cfg_real.block_list[:-1]: blk.scope = cfg_real.block_list[-1] cfg_real.root.ast_node = as_tree cfg_real.root.ssa_code.code_list.append(as_tree) cfg_real.root.blocks = blocks cfg_real.convert_to_ssa() self.assertBlockSsaList( cfg_real.block_list, { "A": dedent("""\ Assign: (b_0,) = 2 Assign: (c_0,) = 1 Assign: (a_0,) = 0 """), "B": dedent("""\ Assign: (a_1,) = Phi(a_0, a_2) Assign: (c_1,) = Phi(c_0, c_2) Assign: (b_1,) = Phi(b_0, b_2) Assign: (b_2,) = BinOp: a_1 + 1 Assign: (c_2,) = BinOp: c_1 + b_2 Assign: (a_2,) = BinOp: b_2 * 2 a_2 < c_2 """), "C": dedent("""\ Assign: (c_3,) = c_2 """), }, )