Ejemplo n.º 1
0
    def test_simple_control_dependency_2(self):
        # If condition evaluated to false, with two relevant variables (but no influence on result)
        def func() -> int:
            foo = 1
            bar = 2
            result = 3

            if foo == bar:
                result = 1

            return result

        init_basic_block = BasicBlock([
            # result = 3
            Instr("LOAD_CONST", arg=3),
            Instr("STORE_FAST", arg="result"),
        ])
        return_basic_block = BasicBlock([
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE")
        ])

        expected_instructions = []
        expected_instructions.extend(init_basic_block)
        expected_instructions.extend(return_basic_block)

        dynamic_slice = slice_function_at_return(func.__code__)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 2
0
    def test_call_without_arguments(self):
        module_block = BasicBlock([
            # def callee():
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="callee"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("STORE_NAME", arg="callee"),
            # result = callee()
            Instr("LOAD_NAME", arg="callee"),
            Instr("CALL_FUNCTION", arg=0),
            Instr("STORE_NAME", arg="result"),
            # return result
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])
        callee_block = BasicBlock([
            Instr("LOAD_CONST", arg=0),
            Instr("RETURN_VALUE")
        ])

        expected_instructions = []
        expected_instructions.extend(module_block)
        expected_instructions.extend(callee_block)

        module_file = "simple_call.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 3
0
    def test_simple_control_dependency_4(self):
        # If-elif-else with else branch true
        def func() -> int:
            foo = 1
            bar = 2

            if foo == bar:
                result = 1
            elif foo > bar:
                result = 2
            else:
                result = 3

            return result

        return_block = BasicBlock([
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE")
        ])
        else_block = BasicBlock([
            # result = 3
            Instr("LOAD_CONST", arg=3),
            Instr("STORE_FAST", arg="result")
        ])
        elif_cond = BasicBlock([
            # elif foo == 1:
            Instr("LOAD_FAST", arg="foo"),
            Instr("LOAD_FAST", arg="bar"),
            Instr("COMPARE_OP", arg=Compare.GT),
            Instr("POP_JUMP_IF_FALSE", arg=else_block),
        ])
        if_cond = BasicBlock([
            # if foo == bar
            Instr("LOAD_FAST", arg="foo"),
            Instr("LOAD_FAST", arg="bar"),
            Instr("COMPARE_OP", arg=Compare.EQ),
            Instr("POP_JUMP_IF_FALSE", arg=elif_cond),
        ])
        init_block = BasicBlock([
            # foo = 1
            Instr("LOAD_CONST", arg=1),
            Instr("STORE_FAST", arg="foo"),
            # bar = 2
            Instr("LOAD_CONST", arg=2),
            Instr("STORE_FAST", arg="bar"),
        ])

        expected_instructions = []
        expected_instructions.extend(init_block)
        expected_instructions.extend(if_cond)
        expected_instructions.extend(elif_cond)
        expected_instructions.extend(else_block)
        expected_instructions.extend(return_block)

        dynamic_slice = slice_function_at_return(func.__code__)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 4
0
    def test_data_dependency_3(self):
        # Transitive explicit (full cover) dependencies
        def func() -> int:
            foo = 1
            result = 1 + foo
            return result

        expected_instructions = [
            # foo = 1
            Instr("LOAD_CONST", arg=1),
            Instr("STORE_FAST", arg="foo"),
            # result = 1 + foo
            Instr("LOAD_CONST", arg=1),
            Instr("LOAD_FAST", arg="foo"),
            Instr("BINARY_ADD"),
            Instr("STORE_FAST", arg="result"),
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ]

        dynamic_slice = slice_function_at_return(func.__code__)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 5
0
    def test_builtin_addresses(self):
        def func():
            test_dict = {1: "one", 2: "two"}
            # noinspection PyListCreation
            test_list = [1, 2]

            test_list.append(3)

            result = test_dict.get(1)
            return result

        function_block = BasicBlock([
            # test_dict = {1: "one", 2: "two"}
            Instr("LOAD_CONST", arg="one"),
            Instr("LOAD_CONST", arg="two"),
            Instr("LOAD_CONST", arg=(1, 2)),
            Instr("BUILD_CONST_KEY_MAP", arg=2),
            Instr("STORE_FAST", arg="test_dict"),

            # result = test_dict.get(1)
            Instr("LOAD_FAST", arg="test_dict"),
            Instr("LOAD_METHOD", arg="get"),
            Instr("LOAD_CONST", arg=1),
            Instr("CALL_METHOD", arg=1),
            Instr("STORE_FAST", arg="result"),
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(function_block)
        dynamic_slice = slice_function_at_return(func.__code__, test_name="test_builtin_addresses")
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 6
0
    def test_nested_class(self):
        def func():
            # STORE_DEREF, LOAD_CLOSURE, LOAD_CLASSDEREF
            x = []

            class NestedClass:
                y = x

            class_attr = NestedClass.y

            result = class_attr
            return result

        freevar_x = FreeVar("x")
        cellvar_x = CellVar("x")
        function_block = BasicBlock([
            # x = []
            Instr("BUILD_LIST", arg=0),
            Instr("STORE_DEREF", arg=cellvar_x),

            # class NestedClass:
            Instr("LOAD_BUILD_CLASS"),
            Instr("LOAD_CLOSURE", arg=cellvar_x),
            Instr("BUILD_TUPLE", arg=1),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="NestedClass"),
            Instr("MAKE_FUNCTION", arg=8),
            Instr("LOAD_CONST", arg="NestedClass"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_FAST", arg="NestedClass"),

            # class_attr = NestedClass.y
            Instr("LOAD_FAST", arg="NestedClass"),
            Instr("LOAD_ATTR", arg="y"),
            Instr("STORE_FAST", arg="class_attr"),

            # result = class_attr
            Instr("LOAD_FAST", arg="class_attr"),
            Instr("STORE_FAST", arg="result"),

            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ])

        nested_class_block = BasicBlock([
            # y = x
            Instr("LOAD_CLASSDEREF", arg=freevar_x),
            Instr("STORE_NAME", arg="y"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(function_block)
        expected_instructions.extend(nested_class_block)
        dynamic_slice = slice_function_at_return(func.__code__, test_name="test_nested_class")
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 7
0
    def test_closures(self):
        # Closure function

        freevar_foo = FreeVar("foo")
        cellvar_foo = CellVar("foo")
        module_block = BasicBlock([
            # def outer_function(foo):
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="outer_function"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("STORE_NAME", arg="outer_function"),

            # inner = outer_function('a')
            Instr("LOAD_NAME", arg="outer_function"),
            Instr("LOAD_CONST", arg="a"),
            Instr("CALL_FUNCTION", arg=1),
            Instr("STORE_NAME", arg="inner"),

            # result = inner("abc")
            Instr("LOAD_NAME", arg="inner"),
            Instr("LOAD_CONST", arg="abc"),
            Instr("CALL_FUNCTION", arg=1),
            Instr("STORE_NAME", arg="result"),

            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])
        outer_function_block = BasicBlock([
            # def inner_function(bar):
            Instr("LOAD_CLOSURE", arg=cellvar_foo),
            Instr("BUILD_TUPLE", arg=1),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="outer_function.<locals>.inner_function"),
            Instr("MAKE_FUNCTION", arg=8),
            Instr("STORE_FAST", arg="inner_function"),

            # return inner
            Instr("LOAD_FAST", arg="inner_function"),
            Instr("RETURN_VALUE"),
        ])
        inner_function_block = BasicBlock([
            # return foo in bar
            Instr("LOAD_DEREF", arg=freevar_foo),
            Instr("LOAD_FAST", arg="bar"),
            Instr("COMPARE_OP", arg=Compare.IN),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(module_block)
        expected_instructions.extend(outer_function_block)
        expected_instructions.extend(inner_function_block)

        module_file = "closure.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)
        self.assertEqual(len(expected_instructions), len(dynamic_slice.sliced_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 8
0
def __evaltest(agent,spec):
    rawaddr  = spec['query']['rawaddr']
    expected = spec['result']
    print("rawaddr = '%s'" % rawaddr)
    print("expected = %s" % expected)
    response = agent.get_lookup(rawaddr)
    print("response = %s" % response)
    status = compare(response,expected)
    print("status = %s" % status)
Ejemplo n.º 9
0
    def test_data_dependency_4(self):
        # Explicit attribute dependencies (full cover)
        module_block = BasicBlock([
            # class Foo:
            Instr("LOAD_BUILD_CLASS"),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="Foo"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("LOAD_CONST", arg="Foo"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_NAME", arg="Foo"),
            # ob.attr1 = 1
            Instr("LOAD_CONST", arg=1),
            Instr("LOAD_NAME", arg="ob"),
            Instr("STORE_ATTR", arg="attr1"),
            # ob.attr2 = ob.attr2.append(ob.attr1)
            Instr("LOAD_NAME", arg="ob"),
            Instr("LOAD_ATTR", arg="attr2"),
            Instr("LOAD_METHOD", arg="append"),
            Instr("LOAD_NAME", arg="ob"),
            Instr("LOAD_ATTR", arg="attr1"),
            Instr("CALL_METHOD", arg=1),
            Instr("LOAD_NAME", arg="ob"),
            Instr("STORE_ATTR", arg="attr2"),

            # result = ob.attr2
            Instr("LOAD_NAME", arg="ob"),
            Instr("LOAD_ATTR", arg="attr2"),
            Instr("STORE_NAME", arg="result"),
            # return
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])
        class_attr_block = BasicBlock([
            # attr2 = [1, 2, 3]
            Instr("LOAD_CONST", arg=1),
            Instr("LOAD_CONST", arg=2),
            Instr("LOAD_CONST", arg=3),
            Instr("BUILD_LIST", arg=3),
            Instr("STORE_NAME", arg="attr2"),
            # return
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])

        expected_instructions = []
        expected_instructions.extend(module_block)
        expected_instructions.extend(class_attr_block)

        module_file = "attribute_dependencies.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
def evaltest(agent,r):
    print("::: eval r = %s" % r)
    print("::: eval query = %s" % r['query'])
    print("::: eval expected = %s" % r['result'])
    _bbl = r['query'].get('bbl')
    _bin = r['query'].get('bin')
    expected = r['result']
    bldg_list = agent.get_buildings(_bbl,_bin)
    print("building.type = %s" % type(bldg_list))
    # print("building.len = %d" % len(bldg_list))
    print("building = %s" % bldg_list)
    status = compare(bldg_list,expected)
    print("status = %s" % status)
Ejemplo n.º 11
0
    def test_call_unused_argument(self):
        # Call with two arguments, one of which is used in the callee

        module_block = BasicBlock([
            # def callee():
            Instr("LOAD_NAME", arg="int"),
            Instr("LOAD_NAME", arg="int"),
            Instr("LOAD_CONST", arg=('a', 'b')),
            Instr("BUILD_CONST_KEY_MAP", arg=2),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="callee"),
            Instr("MAKE_FUNCTION", arg=4),
            Instr("STORE_NAME", arg="callee"),
            # foo = 1
            Instr("LOAD_CONST", arg=1),
            Instr("STORE_NAME", arg="foo"),
            # bar = 2
            # This argument is not used by the callee and should therefore be excluded.
            # But it is an implicit data dependency of the call and is incorrectly and imprecisely included.
            # Instr("LOAD_CONST", arg=2),
            # Instr("STORE_NAME", arg="bar"),

            # result = callee()
            Instr("LOAD_NAME", arg="callee"),
            Instr("LOAD_NAME", arg="foo"),
            # Instr("LOAD_NAME", arg="bar"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_NAME", arg="result"),
            # return result
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])
        callee_block = BasicBlock([
            # return a
            Instr("LOAD_FAST", arg="a"),
            Instr("RETURN_VALUE")
        ])

        expected_instructions = []
        expected_instructions.extend(module_block)
        expected_instructions.extend(callee_block)

        module_file = "simple_call_arg.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 12
0
def evaltest(agent,r):
    query = r['query']
    result = r['result']
    if ARGS.loud:
        print("query = %s" % query)
    try:
        taxlot = perform(agent,query)
    except Exception as e:
        print("FAILED: %s" % e)
        if ARGS.fail:
            raise e
        return False
    if ARGS.loud:
        print("result = %s" % result)
        print("taxlot = %s" % taxlot)
    return compare(taxlot,result)
Ejemplo n.º 13
0
def evaltest(endpoint,agent,spec):
    query = spec['query']
    expected = spec['result']
    if LOUD:
        print("query    = '%s'" % query)
        print("expected = %s" % expected)
    try:
        response = agent.dispatch(endpoint,query)
        if LOUD:
            print("response = %s" % response)
        return compare(response,expected)
    except Exception as e:
        print("EXCEPT %s" % str(e))
        if THROW:
            raise e
        return False
Ejemplo n.º 14
0
    def test_simple_loop(self):
        def func():
            result = 0
            for i in range(0, 3):
                result += i
            return result

        return_block = BasicBlock([
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE")
        ])
        loop_header = BasicBlock([
            Instr("FOR_ITER", arg=return_block),
        ])
        loop_block = BasicBlock([
            # result += i
            Instr("STORE_FAST", arg="i"),
            Instr("LOAD_FAST", arg="result"),
            Instr("LOAD_FAST", arg="i"),
            Instr("INPLACE_ADD"),
            Instr("STORE_FAST", arg="result"),
            Instr("JUMP_ABSOLUTE", arg=loop_header),
        ])
        loop_setup = BasicBlock([
            # for i in range(0, 3):
            Instr("LOAD_GLOBAL", arg="range"),
            Instr("LOAD_CONST", arg=0),
            Instr("LOAD_CONST", arg=3),
            Instr("CALL_FUNCTION", arg=2),
            Instr("GET_ITER"),
        ])
        init_block = BasicBlock([
            Instr("LOAD_CONST", arg=0),
            Instr("STORE_FAST", arg="result"),
        ])

        expected_instructions = []
        expected_instructions.extend(init_block)
        expected_instructions.extend(loop_setup)
        expected_instructions.extend(loop_header)
        expected_instructions.extend(loop_block)
        expected_instructions.extend(return_block)

        dynamic_slice = slice_function_at_return(func.__code__, test_name="test_simple_loop")
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 15
0
    def test_call_with_arguments(self):
        # Call with two arguments, one of which is used in the callee

        module_block = BasicBlock([
            # def callee():
            Instr("LOAD_NAME", arg="int"),
            Instr("LOAD_NAME", arg="int"),
            Instr("LOAD_CONST", arg=('a', 'b')),
            Instr("BUILD_CONST_KEY_MAP", arg=2),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="callee"),
            Instr("MAKE_FUNCTION", arg=4),
            Instr("STORE_NAME", arg="callee"),
            # foo = 1
            Instr("LOAD_CONST", arg=1),
            Instr("STORE_NAME", arg="foo"),
            # bar = 2
            Instr("LOAD_CONST", arg=2),
            Instr("STORE_NAME", arg="bar"),

            # result = callee()
            Instr("LOAD_NAME", arg="callee"),
            Instr("LOAD_NAME", arg="foo"),
            Instr("LOAD_NAME", arg="bar"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_NAME", arg="result"),
            # return result
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])
        callee_block = BasicBlock([
            # return a
            Instr("LOAD_FAST", arg="a"),
            Instr("RETURN_VALUE")
        ])

        expected_instructions = []
        expected_instructions.extend(module_block)
        expected_instructions.extend(callee_block)

        module_file = "simple_call_arg.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 16
0
    def test_simple_control_dependency_1(self):
        # If condition evaluated to true, with relevant variable foo
        def func() -> int:
            foo = 1
            result = 3

            if foo == 1:
                result = 1

            return result

        return_basic_block = BasicBlock([
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE")
        ])
        if_basic_block = BasicBlock([
            # result = 1
            Instr("LOAD_CONST", arg=1),
            Instr("STORE_FAST", arg="result"),
        ])
        init_basic_block = BasicBlock([
            # foo = 1
            Instr("LOAD_CONST", arg=1),
            Instr("STORE_FAST", arg="foo"),
            # if foo == 1
            Instr("LOAD_FAST", arg="foo"),
            Instr("LOAD_CONST", arg=1),
            Instr("COMPARE_OP", arg=Compare.EQ),
            Instr("POP_JUMP_IF_FALSE", arg=return_basic_block),
        ])

        expected_instructions = []
        expected_instructions.extend(init_basic_block)
        expected_instructions.extend(if_basic_block)
        expected_instructions.extend(return_basic_block)

        dynamic_slice = slice_function_at_return(func.__code__)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 17
0
    def test_with_extended_arg(self):
        def func():
            p = [1, 2, 3, 4, 5, 6]
            # noinspection PyUnusedLocal
            unused = p
            q, r, *s, t = p  # With extended argument

            result = q, r
            return result

        module_block = BasicBlock([
            # p = [1, 2, 3, 4, 5, 6]
            Instr("LOAD_CONST", arg=1),
            Instr("LOAD_CONST", arg=2),
            Instr("LOAD_CONST", arg=3),
            Instr("LOAD_CONST", arg=4),
            Instr("LOAD_CONST", arg=5),
            Instr("LOAD_CONST", arg=6),
            Instr("BUILD_LIST", arg=6),
            Instr("STORE_FAST", arg="p"),
            # q, r, *s, t = p
            Instr("LOAD_FAST", arg="p"),
            # Instr("EXTENDED_ARG", arg=1),  # EXTENDED_ARG can not be in a slice
            Instr("UNPACK_EX", arg=258),
            Instr("STORE_FAST", arg="q"),
            Instr("STORE_FAST", arg="r"),

            # result = q
            Instr("LOAD_FAST", arg="q"),
            Instr("LOAD_FAST", arg="r"),
            Instr("BUILD_TUPLE", arg=2),
            Instr("STORE_FAST", arg="result"),
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(module_block)
        dynamic_slice = slice_function_at_return(func.__code__, test_name="test_with_extended_arg")
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 18
0
    def test_data_dependency_1(self):
        # Implicit data dependency at return, explicit (full cover) for result
        def func() -> int:
            result = 1
            return result

        expected_instructions = [
            # result = 1
            Instr("LOAD_CONST", arg=1),
            Instr("STORE_FAST", arg="result"),
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ]

        dynamic_slice = slice_function_at_return(func.__code__)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 19
0
    def test_mod_untraced_object(self):
        def func():
            lst = [('foo', '3'), ('bar', '1'), ('foobar', '2')]
            lst.sort(
            )  # This is incorrectly excluded, since it is not known that the method modifies the list

            result = lst
            return result

        function_block = BasicBlock([
            # lst = [('foo', '3'), ('bar', '1'), ('foobar', '2')]
            Instr("LOAD_CONST", arg=('foo', '3')),
            Instr("LOAD_CONST", arg=('bar', '1')),
            Instr("LOAD_CONST", arg=('foobar', '2')),
            Instr("BUILD_LIST", arg=3),
            Instr("STORE_FAST", arg="lst"),

            # lst.sort()
            # This is incorrectly excluded, since it is not known that the method modifies the list
            Instr("LOAD_FAST", arg="lst"),
            Instr("LOAD_METHOD", arg="sort"),
            Instr("CALL_METHOD", arg=0),
            Instr("POP_TOP"),

            # result = lst
            Instr("LOAD_FAST", arg="lst"),
            Instr("STORE_FAST", arg="result"),

            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(function_block)
        dynamic_slice = slice_function_at_return(
            func.__code__, test_name="test_mod_untraced_object")
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 20
0
    def test_import_star(self):
        # IMPORT_STAR with access to immutable variable
        main_module_block = BasicBlock([
            # from tests.slicer.example_modules.import_star_def import *
            Instr("IMPORT_NAME",
                  "tests.slicer.example_modules.import_star_def"),
            Instr("IMPORT_STAR"),

            # result = Foo.test
            Instr("LOAD_NAME", arg="star_imported"),
            Instr("STORE_NAME", arg="result"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])
        dependency_module_block = BasicBlock([
            # star_imported = "test"
            Instr("LOAD_CONST", arg="test"),
            Instr("STORE_NAME", arg="star_imported"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])

        expected_instructions = []
        expected_instructions.extend(main_module_block)
        expected_instructions.extend(dependency_module_block)

        module_dependency_file = "import_star_def.py"
        module_dependency_path = example_modules_path + module_dependency_file
        instrument_module(module_dependency_path)

        module_file = "import_star_main.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)

        compile_module(module_dependency_path)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 21
0
    def test_data_dependency_composite(self):
        # Composite type dependencies, which are way to broad
        def func():
            # noinspection PyListCreation
            foo_list = [1, 2,
                        3]  # the only list operation which should be included
            foo_list.append(
                4
            )  # should no be included, and is not included (good and limitation at the same time)
            foo_list += [5]  # should no be included, but is
            foo_list[2:3] = [0, 0]  # should no be included, but is

            result = foo_list[0]  # correctly included
            return result  # correctly included

        expected_instructions = [
            # foo_list = [1, 2, 3]
            Instr("LOAD_CONST", arg=1),
            Instr("LOAD_CONST", arg=2),
            Instr("LOAD_CONST", arg=3),
            Instr("BUILD_LIST", arg=3),
            Instr("STORE_FAST", arg="foo_list"),

            # result = foo_list[0]
            Instr("LOAD_FAST", arg="foo_list"),
            Instr("LOAD_CONST", arg=0),
            Instr("BINARY_SUBSCR"),
            Instr("STORE_FAST", arg="result"),
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ]

        dynamic_slice = slice_function_at_return(func.__code__)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 22
0
    def test_lambda(self):
        def func():
            x = lambda a: a + 10

            result = x(1)
            return result

        function_block = BasicBlock([
            # x = lambda a: a + 10
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="IntegrationTestLanguageFeatures.test_lambda.<locals>.func.<locals>.<lambda>"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("STORE_FAST", arg="x"),

            # result = x(1)
            Instr("LOAD_FAST", arg="x"),
            Instr("LOAD_CONST", arg=1),
            Instr("CALL_FUNCTION", arg=1),
            Instr("STORE_FAST", arg="result"),
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ])

        lambda_block = BasicBlock([
            # lambda a: a + 10
            Instr("LOAD_FAST", arg="a"),
            Instr("LOAD_CONST", arg=10),
            Instr("BINARY_ADD"),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(function_block)
        expected_instructions.extend(lambda_block)
        dynamic_slice = slice_function_at_return(func.__code__, test_name="test_lambda")
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 23
0
    def test_object_modification_call(self):
        def func():
            class NestedClass:
                def __init__(self):
                    self.x = 1

                def inc_x(self):
                    self.x = self.x + 1

            ob = NestedClass()
            ob.inc_x()

            result = ob.x
            return result

        function_block = BasicBlock([
            # class NestedClass:
            Instr("LOAD_BUILD_CLASS"),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="NestedClass"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("LOAD_CONST", arg="NestedClass"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_FAST", arg="NestedClass"),

            # ob = NestedClass()
            Instr("LOAD_FAST", arg="NestedClass"),
            Instr("CALL_FUNCTION", arg=0),
            Instr("STORE_FAST", arg="ob"),

            # ob.inc_x()
            Instr("LOAD_FAST", arg="ob"),
            Instr("LOAD_METHOD", arg="inc_x"),
            Instr("CALL_METHOD", arg=0),

            # result = ob.x
            Instr("LOAD_FAST", arg="ob"),
            Instr("LOAD_ATTR", arg="x"),
            Instr("STORE_FAST", arg="result"),

            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ])

        nested_class_block = BasicBlock([
            # Definition of dunder methods are wrongly excluded, since these are not explicitly loaded
            # def __init__(self):
            # Instr("LOAD_CONST", arg=dummy_code_object),
            # Instr("LOAD_CONST", arg="IntegrationTestLanguageFeatures.test_object_modification_call.<locals>."
            #                         "func.<locals>.NestedClass.__init__"),
            # Instr("MAKE_FUNCTION", arg=0),
            # Instr("STORE_NAME", arg="__init__"),

            # def inc_x(self):
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="IntegrationTestLanguageFeatures.test_object_modification_call.<locals>."
                                    "func.<locals>.NestedClass.inc_x"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("STORE_NAME", arg="inc_x"),

            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])

        init_block = BasicBlock([
            # self.x = 1
            Instr("LOAD_CONST", arg=1),
            Instr("LOAD_FAST", arg="self"),
            Instr("STORE_ATTR", arg="x"),

            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])

        inc_x_block = BasicBlock([
            # self.x = self.x + 1
            Instr("LOAD_FAST", arg="self"),
            Instr("LOAD_ATTR", arg="x"),
            Instr("LOAD_CONST", arg=1),
            Instr("BINARY_ADD"),
            Instr("LOAD_FAST", arg="self"),
            Instr("STORE_ATTR", arg="x"),

            # This "None return" is not included, because the return value is not used
            # Instr("LOAD_CONST", arg=None),
            # Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(function_block)
        expected_instructions.extend(nested_class_block)
        expected_instructions.extend(init_block)
        expected_instructions.extend(inc_x_block)
        dynamic_slice = slice_function_at_return(func.__code__, test_name="test_object_modification_call")
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 24
0
    def test_dunder_definition(self):
        def func():
            class NestedClass:
                def __init__(
                    self
                ):  # Definition of dunder methods wrongly excluded, these are not explicitly loaded
                    self.x = 1

            result = NestedClass()
            return result

        function_block = BasicBlock([
            # class NestedClass:
            Instr("LOAD_BUILD_CLASS"),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="NestedClass"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("LOAD_CONST", arg="NestedClass"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_FAST", arg="NestedClass"),

            # result = NestedClass()
            Instr("LOAD_FAST", arg="NestedClass"),
            Instr("CALL_FUNCTION", arg=0),
            Instr("STORE_FAST", arg="result"),

            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ])

        nested_class_block = BasicBlock([
            # Definition of dunder methods are wrongly excluded, since these are not explicitly loaded
            # def __init__(self):
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr(
                "LOAD_CONST",
                arg=
                "IntegrationTestLanguageFeatures.test_object_modification_call.<locals>."
                "func.<locals>.NestedClass.__init__"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("STORE_NAME", arg="__init__"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])

        init_block = BasicBlock([
            # self.x = 1
            Instr("LOAD_CONST", arg=1),
            Instr("LOAD_FAST", arg="self"),
            Instr("STORE_ATTR", arg="x"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(function_block)
        expected_instructions.extend(nested_class_block)
        expected_instructions.extend(init_block)
        dynamic_slice = slice_function_at_return(
            func.__code__, test_name="test_dunder_definition")
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 25
0
    def test_exception(self):
        # Exception
        def func():
            foo = 1
            bar = 0

            try:
                result = 0 / 0
            except ZeroDivisionError:
                result = foo + bar

            return result

        self.assertEqual(func(), 1)

        dummy_block = BasicBlock([])

        return_block = BasicBlock([
            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE")
        ])
        try_block = BasicBlock([
            # result = foo / bar <- did somehow effect slicing criterion...
            Instr("LOAD_FAST", arg="foo"),
            Instr("LOAD_FAST", arg="bar"),
            Instr("BINARY_TRUE_DIVIDE"),

            # except ZeroDivisionError:
            Instr("DUP_TOP"),
            Instr("LOAD_GLOBAL", arg="ZeroDivisionError"),
            Instr("COMPARE_OP", arg=Compare.EXC_MATCH),
            Instr("POP_JUMP_IF_FALSE", arg=dummy_block),
        ])
        except_block = BasicBlock([
            # result = foo + bar
            Instr("LOAD_FAST", arg="foo"),
            Instr("LOAD_FAST", arg="bar"),
            Instr("BINARY_ADD"),
            Instr("STORE_FAST", arg="result"),
            Instr("JUMP_FORWARD", arg=dummy_block),
        ])
        function_block = BasicBlock([
            # foo = 1
            Instr("LOAD_CONST",
                  arg=1),  # <- excluded because no stack simulation
            Instr("STORE_FAST", arg="foo"),
            # bar = 0
            Instr("LOAD_CONST",
                  arg=0),  # <- excluded because no stack simulation
            Instr("STORE_FAST", arg="bar"),

            # try:
            # Instr("SETUP_FINALLY", arg=try_block),
        ])

        expected_instructions = []
        expected_instructions.extend(return_block)
        expected_instructions.extend(except_block)
        expected_instructions.extend(function_block)
        expected_instructions.extend(try_block)

        dynamic_slice = slice_function_at_return(func.__code__)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 26
0
    def test_nested_class_2(self):
        # Critical test to ensure that the attributes converted to variables
        # are taken from the correct scope.

        def func():
            # STORE_DEREF, LOAD_CLOSURE, LOAD_CLASSDEREF
            x1 = [1]
            x2 = [2]

            class Bar:
                foo = x1  # included!

                class Foo:
                    foo = x2  # NOT included
                    y = x2  # included

                y = Foo.y  # NOT included

            class_attr = Bar.foo
            class_attr2 = Bar.Foo.y

            result = class_attr + class_attr2
            return result

        freevar_x1 = FreeVar("x1")
        cellvar_x1 = CellVar("x1")
        freevar_x2 = FreeVar("x2")
        cellvar_x2 = CellVar("x2")
        function_block = BasicBlock([
            # x1 = [1]
            Instr("LOAD_CONST", arg=1),
            Instr("BUILD_LIST", arg=1),
            Instr("STORE_DEREF", arg=cellvar_x1),
            # x2 = [2]
            Instr("LOAD_CONST", arg=2),
            Instr("BUILD_LIST", arg=1),
            Instr("STORE_DEREF", arg=cellvar_x2),

            # class Bar:
            Instr("LOAD_BUILD_CLASS"),
            Instr("LOAD_CLOSURE", arg=cellvar_x1),
            Instr("LOAD_CLOSURE", arg=freevar_x2),
            Instr("BUILD_TUPLE", arg=2),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="Bar"),
            Instr("MAKE_FUNCTION", arg=8),
            Instr("LOAD_CONST", arg="Bar"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_FAST", arg="Bar"),

            # class_attr = Bar.y
            Instr("LOAD_FAST", arg="Bar"),
            Instr("LOAD_ATTR", arg="foo"),
            Instr("STORE_FAST", arg="class_attr"),

            # class_attr2 = Bar.Foo.y
            Instr("LOAD_FAST", arg="Bar"),
            Instr("LOAD_ATTR", arg="Foo"),
            Instr("LOAD_ATTR", arg="y"),
            Instr("STORE_FAST", arg="class_attr2"),

            # result = class_attr + class_attr2
            Instr("LOAD_FAST", arg="class_attr"),
            Instr("LOAD_FAST", arg="class_attr2"),
            Instr("BINARY_ADD"),
            Instr("STORE_FAST", arg="result"),

            # return result
            Instr("LOAD_FAST", arg="result"),
            Instr("RETURN_VALUE"),
        ])

        bar_block = BasicBlock([
            # class Foo:
            Instr("LOAD_BUILD_CLASS"),
            Instr("LOAD_CLOSURE", arg=cellvar_x2),
            Instr("BUILD_TUPLE", arg=1),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="Foo"),
            Instr("MAKE_FUNCTION", arg=8),
            Instr("LOAD_CONST", arg="Foo"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_NAME", arg="Foo"),

            # foo = x1
            Instr("LOAD_CLASSDEREF", arg=freevar_x1),
            Instr("STORE_NAME", arg="foo"),

            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])

        foo_block = BasicBlock([
            # y = x2
            Instr("LOAD_CLASSDEREF", arg=freevar_x2),
            Instr("STORE_NAME", arg="y"),

            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(function_block)
        expected_instructions.extend(foo_block)
        expected_instructions.extend(bar_block)
        dynamic_slice = slice_function_at_return(func.__code__, test_name="test_nested_class_2")
        self.assertEqual(func(), [1, 2])
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 27
0
    def test_generators(self):
        # YIELD_VALUE and YIELD_FROM
        abc_generator = BasicBlock([
            # a = "a"
            Instr("LOAD_CONST", arg="a"),
            Instr("STORE_FAST", arg="a"),
            # yield a
            Instr("LOAD_FAST", arg="a"),
            Instr("YIELD_VALUE"),
        ])

        abc_xyz_generator = BasicBlock([
            # x = "x"
            Instr("LOAD_CONST", arg="x"),
            Instr("STORE_FAST", arg="x"),

            # yield from abc_generator()
            Instr("LOAD_GLOBAL", arg="abc_generator"),
            Instr("CALL_FUNCTION", arg=0),
            Instr("GET_YIELD_FROM_ITER"),
            Instr("LOAD_CONST", arg=None),
            Instr("YIELD_FROM"),
            # yield x
            Instr("LOAD_FAST", arg="x"),
            Instr("YIELD_VALUE"),
        ])

        end_block = BasicBlock([
            # return result
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])
        loop_block = BasicBlock([
            Instr("STORE_NAME", arg="letter"),
        ])
        loop_header = BasicBlock([
            Instr("FOR_ITER", arg=end_block),
        ])
        loop_if_true_block = BasicBlock([
            Instr("LOAD_NAME", arg="result"),
            Instr("LOAD_NAME", arg="letter"),
            Instr("INPLACE_ADD"),
            Instr("STORE_NAME", arg="result"),
            Instr("JUMP_ABSOLUTE", arg=loop_header),
        ])
        loop_if_x_block = BasicBlock([
            Instr("LOAD_NAME", arg="letter"),
            Instr("LOAD_CONST", arg="x"),
            Instr("COMPARE_OP", arg=Compare.EQ),
            Instr("POP_JUMP_IF_TRUE", arg=loop_if_true_block),
        ])
        loop_if_a_block = BasicBlock([
            Instr("LOAD_NAME", arg="letter"),
            Instr("LOAD_CONST", arg="a"),
            Instr("COMPARE_OP", arg=Compare.EQ),
            Instr("POP_JUMP_IF_FALSE", arg=loop_header)
        ])
        module_block = BasicBlock([
            # def abc_generator():
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="abc_generator"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("STORE_NAME", arg="abc_generator"),
            # def abc_xyz_generator():
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="abc_xyz_generator"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("STORE_NAME", arg="abc_xyz_generator"),
            # generator = abc_xyz_generator()
            Instr("LOAD_NAME", arg="abc_xyz_generator"),
            Instr("CALL_FUNCTION", arg=0),
            Instr("STORE_NAME", arg="generator"),
            # result = ""
            Instr("LOAD_CONST", arg=""),
            Instr("STORE_NAME", arg="result"),
            # for letter in generator:
            Instr("LOAD_NAME", arg="generator"),
            Instr("GET_ITER"),
        ])

        expected_instructions = []
        expected_instructions.extend(module_block)
        expected_instructions.extend(loop_header)
        expected_instructions.extend(loop_block)
        expected_instructions.extend(loop_if_x_block)
        expected_instructions.extend(loop_if_a_block)
        expected_instructions.extend(loop_if_true_block)
        expected_instructions.extend(end_block)
        expected_instructions.extend(abc_xyz_generator)
        expected_instructions.extend(abc_generator)

        module_file = "generator.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)
        self.assertEqual(len(dynamic_slice.sliced_instructions), len(expected_instructions))
        self.assertTrue(compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 28
0
    def test_equal_variable_names(self):
        # Data dependencies across modules (explicit, full cover)
        main_module_block = BasicBlock([
            # class Foo:
            Instr("LOAD_BUILD_CLASS"),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="Foo"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("LOAD_CONST", arg="Foo"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_NAME", arg="Foo"),

            # duplicate_var = "foo_dup"
            Instr("LOAD_CONST", arg="foo_dup"),
            Instr("STORE_NAME", arg="duplicate_var"),

            # import tests.slicer.integration.example_modules.equal_variable_names_def
            # Instr("LOAD_CONST", arg=0),
            # Instr("LOAD_CONST", arg=None),
            # Instr("IMPORT_NAME", arg="tests.slicer.integration.example_modules.equal_variable_names_def"),
            # Instr("STORE_NAME", arg="tests"),

            # test = duplicate_var
            Instr("LOAD_NAME", arg="duplicate_var"),
            Instr("STORE_NAME", arg="test"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),

            # result = Foo.test
            Instr("LOAD_NAME", arg="Foo"),
            Instr("LOAD_ATTR", arg="test"),
            Instr("STORE_NAME", arg="result"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])
        dependency_module_block = BasicBlock([
            # duplicate_var = "bar_dup"
            # Instr("LOAD_CONST", arg="bar_dup"),
            # Instr("STORE_NAME", arg="duplicate_var"),

            # Instr("LOAD_CONST", arg=None),
            # Instr("RETURN_VALUE")
        ])

        expected_instructions = []
        expected_instructions.extend(main_module_block)
        expected_instructions.extend(dependency_module_block)

        module_dependency_file = "equal_variable_names_def.py"
        module_dependency_path = example_modules_path + module_dependency_file
        instrument_module(module_dependency_path)

        module_file = "equal_variable_names_main.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)

        compile_module(module_dependency_path)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))
Ejemplo n.º 29
0
    def test_data_dependency_6(self):
        # Data dependencies across modules (explicit, full cover)
        main_module_block = BasicBlock([
            # from tests.slicer.integration.example_modules.module_dependency_def import module_list, Foo
            Instr("LOAD_CONST", arg=0),
            Instr("LOAD_CONST", arg=('module_list', 'unused_list', 'Foo')),
            Instr("IMPORT_NAME",
                  arg="tests.slicer.example_modules.module_dependency_def"),
            Instr("IMPORT_FROM", arg="module_list"),
            Instr("STORE_NAME", arg="module_list"),
            # Instr("IMPORT_FROM", arg="unused_list"),
            # Instr("STORE_NAME", arg="unused_list"),
            Instr("IMPORT_FROM", arg="Foo"),
            Instr("STORE_NAME", arg="Foo"),

            # result = module_list + Foo.get_class_list()
            Instr("LOAD_NAME", arg="module_list"),
            Instr("LOAD_NAME", arg="Foo"),
            Instr("LOAD_METHOD", arg="get_class_list"),
            Instr("CALL_METHOD", arg=0),
            Instr("BINARY_ADD"),
            Instr("STORE_NAME", arg="result"),
            # return
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE")
        ])
        dependency_module_block = BasicBlock([
            # module_list = [1, 2, 3]
            Instr("LOAD_CONST", arg=1),
            Instr("LOAD_CONST", arg=2),
            Instr("LOAD_CONST", arg=3),
            Instr("BUILD_LIST", arg=3),
            Instr("STORE_NAME", arg="module_list"),

            # class Foo:
            Instr("LOAD_BUILD_CLASS"),
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="Foo"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("LOAD_CONST", arg="Foo"),
            Instr("CALL_FUNCTION", arg=2),
            Instr("STORE_NAME", arg="Foo"),

            # class_list = [4, 5, 6]
            Instr("LOAD_CONST", arg=7),
            Instr("LOAD_CONST", arg=8),
            Instr("LOAD_CONST", arg=9),
            Instr("BUILD_LIST", arg=3),
            Instr("STORE_NAME", arg="class_list"),

            # @staticmethod
            Instr("LOAD_NAME", arg="staticmethod"),

            # def get_class_list():
            Instr("LOAD_CONST", arg=dummy_code_object),
            Instr("LOAD_CONST", arg="Foo.get_class_list"),
            Instr("MAKE_FUNCTION", arg=0),
            Instr("CALL_FUNCTION", arg=1),
            Instr("STORE_NAME", arg="get_class_list"),

            # return Foo.class_list
            Instr("LOAD_GLOBAL", arg="Foo"),
            Instr("LOAD_ATTR", arg="class_list"),
            Instr("RETURN_VALUE"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
            Instr("LOAD_CONST", arg=None),
            Instr("RETURN_VALUE"),
        ])

        expected_instructions = []
        expected_instructions.extend(main_module_block)
        expected_instructions.extend(dependency_module_block)

        module_dependency_file = "module_dependency_def.py"
        module_dependency_path = example_modules_path + module_dependency_file
        instrument_module(module_dependency_path)

        module_file = "module_dependency_main.py"
        module_path = example_modules_path + module_file
        dynamic_slice = slice_module_at_return(module_path)

        compile_module(module_dependency_path)
        self.assertEqual(len(dynamic_slice.sliced_instructions),
                         len(expected_instructions))
        self.assertTrue(
            compare(dynamic_slice.sliced_instructions, expected_instructions))