示例#1
0
def test_mutation(tracer):
    text = "AAAA"

    tracer.start()

    lower_text = text.lower(
    )  # Test this line does not emit a mutation of `text`.

    tracer.stop()

    assert tracer.events == [
        InitialValue(
            lineno=-1,
            target=Symbol("text"),
            value='"AAAA"',
            repr='"AAAA"',
        ),
        Binding(
            lineno=9,
            target=Symbol("lower_text"),
            value='"aaaa"',
            repr='"aaaa"',
            sources={Symbol("text")},
        ),
    ]
示例#2
0
def test_decorator_multiple_times(trace, rpc_stub):
    @trace
    def func(b):
        a = b
        return a

    func(1)

    # Test that server wait does not block user code execution.
    trace._wait_for_termination()

    assert func(2) == 2
    from cyberbrain import pprint

    pprint(trace.events)
    assert trace.events == [
        InitialValue(
            lineno=21,
            target=Symbol("b"),
            value="1",
        ),
        Binding(lineno=21,
                target=Symbol("a"),
                value="1",
                sources={Symbol("b")}),
        Return(lineno=22, value="1", sources={Symbol("a")}),
    ]

    trace.server.stop()
示例#3
0
def test_closure(tracer, mocked_responses):
    tracer.start()

    a = 1  # LOAD_CLASSDEREF

    class Foo:
        print(a)  # LOAD_CLOSURE

    class Bar(
            Foo
    ):  # LOAD_CLOSURE. If we remove super(Bar, self) it becomes LOAD_CONST
        def __init__(self):
            super(Bar, self).__init__()

    tracer.stop()

    assert tracer.events == [
        Binding(lineno=28, target=Symbol("a"), value="1"),
        Binding(
            lineno=30,
            target=Symbol("Foo"),
            value='{"py/type":"test_cellvar.test_closure.<locals>.Foo"}',
            sources={Symbol("a")},
        ),
        Binding(
            lineno=33,
            target=Symbol("Bar"),
            value='{"py/type":"test_cellvar.test_closure.<locals>.Bar"}',
            repr="<class 'test_cellvar.test_closure.<locals>.Bar'>",
            sources={Symbol("Foo")},
        ),
    ]
示例#4
0
def test_continue_in_finally(tracer, test_server):
    tracer.start()

    for x in range(2):
        try:
            pass
        finally:
            continue  # 3.8: POP_FINALLY, >= 3.9: POP_EXCEPT, RERAISE

    tracer.stop()

    assert tracer.events == [
        Binding(target=Symbol("x"), value="0", lineno=22),
        JumpBackToLoopStart(lineno=26, jump_target=16),
        Binding(target=Symbol("x"), value="1", lineno=22),
        JumpBackToLoopStart(lineno=26, jump_target=16),
    ]
    assert tracer.loops == [
        Loop(
            start_offset=16,
            end_offset=get_value({"py38": 32, "default": 24}),
            start_lineno=22,
        )
    ]

    test_server.assert_frame_sent("test_continue_in_finally")
示例#5
0
def test_continue_in_finally_with_exception(tracer, test_server):
    """Tests POP_FINALLY when tos is an exception."""

    tracer.start()

    # If the finally clause executes a return, break or continue statement, the saved
    # exception is discarded.
    for x in range(2):
        try:
            raise IndexError
        finally:
            continue  # BREAK_LOOP (3.7) POP_FINALLY (3.8)

    tracer.stop()

    assert tracer.events == [
        Binding(target=Symbol("x"), value="0", lineno=58),
        JumpBackToLoopStart(lineno=62, jump_target=16),
        Binding(target=Symbol("x"), value="1", lineno=58),
        JumpBackToLoopStart(lineno=62, jump_target=16),
    ]
    assert tracer.loops == [
        Loop(
            start_offset=16,
            end_offset=get_value({"py38": 36, "default": 40}),
            start_lineno=58,
        )
    ]

    test_server.assert_frame_sent("test_continue_in_finally_with_exception")
示例#6
0
def test_continue_in_finally_with_exception(tracer, rpc_stub):
    """Tests POP_FINALLY when tos is an exception."""

    tracer.start()

    # If the finally clause executes a return, break or continue statement, the saved
    # exception is discarded.
    for x in range(2):
        try:
            raise IndexError
        finally:
            continue  # BREAK_LOOP (3.7) POP_FINALLY (3.8)

    tracer.stop()

    assert tracer.events == [
        Binding(target=Symbol("x"), value=0, lineno=52),
        JumpBackToLoopStart(lineno=56, jump_target=16),
        Binding(target=Symbol("x"), value=1, lineno=52),
        JumpBackToLoopStart(lineno=56, jump_target=16),
    ]
    assert tracer.loops == [
        Loop(start_offset=16, end_offset=36, start_lineno=52)
    ]

    assert_GetFrame(rpc_stub, "test_continue_in_finally_with_exception")
示例#7
0
def test_telephone(trace, check_golden_file):
    @trace
    def test_telephone_inner():
        args = argparse.Namespace(
            mutations=0.6,
            seed=2,
            text="The quick brown fox jumps over the lazy dog.")
        text = args.text
        random.seed(args.seed)
        alpha = "".join(sorted(string.ascii_letters + string.punctuation))
        len_text = len(text)
        num_mutations = round(args.mutations * len_text)
        new_text = text

        for i in random.sample(range(len_text), num_mutations):
            new_char = random.choice(alpha.replace(new_text[i], ""))
            new_text = new_text[:i] + new_char + new_text[i + 1:]

        print(f'You said: "{text}"\nI heard : "{new_text}"')

    test_telephone_inner()

    # Events should exclude modules.
    assert_that(trace.events,
                not_(has_item(has_property("target", Symbol("random")))))
    assert_that(
        trace.events,
        has_item(
            has_properties({
                "target": Symbol("i"),
                "sources": {Symbol("len_text"),
                            Symbol("num_mutations")},
            })),
    )
示例#8
0
def test_recursion_decorator(trace):
    @trace
    def fib(n):
        if n <= 1:
            return n
        else:
            return fib(n - 1) + fib(n - 2)

    print(fib(3))

    assert trace.events == [
        InitialValue(
            lineno=7,
            target=Symbol("n"),
            value="3",
            repr="3",
        ),
        InitialValue(
            lineno=10,
            target=Symbol("fib"),
            value=
            '{"repr": "<function test_recursion_decorator.<locals>.fib>"}',
            repr="<function test_recursion_decorator.<locals>.fib>",
        ),
        Return(
            lineno=10,
            value="2",
            repr="2",
            sources={Symbol("fib"), Symbol("n")},
        ),
    ]
示例#9
0
def test_unary_operations(tracer, mocked_responses):
    a = 1

    tracer.start()

    b = +a  # UNARY_POSITIVE
    b = -a  # UNARY_NEGATIVE
    b = not a  # UNARY_NOT
    b = ~a  # UNARY_INVERT

    tracer.stop()

    assert tracer.events == [
        InitialValue(target=Symbol("a"), value="1", lineno=-1),
        Binding(target=Symbol("b"), value="1", sources={Symbol("a")},
                lineno=9),
        Binding(target=Symbol("b"),
                value="-1",
                sources={Symbol("a")},
                lineno=10),
        Binding(target=Symbol("b"),
                value="false",
                sources={Symbol("a")},
                lineno=11),
        Binding(target=Symbol("b"),
                value="-2",
                sources={Symbol("a")},
                lineno=12),
    ]
示例#10
0
def test_unary_operations(tracer, rpc_stub):
    a = 1

    tracer.start()

    b = +a  # UNARY_POSITIVE
    b = -a  # UNARY_NEGATIVE
    b = not a  # UNARY_NOT
    b = ~a  # UNARY_INVERT

    tracer.stop()

    assert tracer.events == [
        InitialValue(target=Symbol("a"), value=1, lineno=10),
        Binding(target=Symbol("b"), value=1, sources={Symbol("a")}, lineno=10),
        Binding(target=Symbol("b"), value=-1, sources={Symbol("a")},
                lineno=11),
        Binding(target=Symbol("b"),
                value=False,
                sources={Symbol("a")},
                lineno=12),
        Binding(target=Symbol("b"), value=-2, sources={Symbol("a")},
                lineno=13),
    ]

    assert_GetFrame(rpc_stub, "test_unary_operations")
示例#11
0
def test_ref_outside(trace, mocked_responses):
    @trace
    def test_ref_outside_inner():
        a = f()

    test_ref_outside_inner()

    assert trace.events == [
        InitialValue(lineno=-1, target=Symbol("f"), value='{"repr": "<function f>"}'),
        Binding(lineno=11, target=Symbol("a"), value="1", sources={Symbol("f")}),
        Return(lineno=11, value="null", sources=set()),
    ]
示例#12
0
def test_existing_variable_emit_initial_value(tracer, test_server):
    x = "foo"
    tracer.start()
    y = x
    tracer.stop()

    assert tracer.events == [
        InitialValue(target=Symbol("x"), value='"foo"', lineno=7),
        Binding(target=Symbol("y"), value='"foo"', sources={Symbol("x")}, lineno=7),
    ]

    test_server.assert_frame_sent("test_existing_variable_emit_initial_value")
示例#13
0
def test_module():
    assert tracer.events == [
        InitialValue(target=Symbol("x"), value="1", lineno=-1),
        Deletion(target=Symbol("x"), lineno=8),
        InitialValue(target=Symbol("__annotations__"), value="{}", lineno=-1),
        Mutation(
            target=Symbol("__annotations__"),
            value='{"y":{"py/type":"builtins.int"}}',
            sources={Symbol("__annotations__")
                     },  # `int` is a built-in so is excluded from sources.
            lineno=9,
        ),
    ]
def test_existing_variable_emit_initial_value(tracer, mocked_responses):
    x = "foo"
    tracer.start()
    y = x
    tracer.stop()

    assert tracer.events == [
        InitialValue(target=Symbol("x"), value='"foo"', lineno=7),
        Binding(target=Symbol("y"),
                value='"foo"',
                sources={Symbol("x")},
                lineno=7),
    ]
示例#15
0
def test_import(tracer):
    tracer.start()

    import os  # IMPORT_NAME
    from os import path  # IMPORT_FROM, loads module
    from sys import settrace  # IMPORT_FROM, loads function

    tracer.stop()

    print(os, path, settrace)  # Prevent PyCharm from removing unused imports.

    assert_that(
        tracer.events,
        contains_exactly(
            all_of(
                instance_of(Binding),
                has_properties(
                    {
                        "target": Symbol("os"),
                        "value": contains_string("<module 'os'"),
                        "sources": set(),
                        "lineno": 9,
                    }
                ),
            ),
            all_of(
                instance_of(Binding),
                has_properties(
                    {
                        "target": Symbol("path"),
                        "value": all_of(
                            contains_string("<module"), contains_string("path")
                        ),
                        "sources": set(),
                        "lineno": 10,
                    }
                ),
            ),
            all_of(
                instance_of(Binding),
                has_properties(
                    {
                        "target": Symbol("settrace"),
                        "value": '{"repr": "<built-in function settrace>"}',
                        "sources": set(),
                        "lineno": 11,
                    }
                ),
            ),
        ),
    )
示例#16
0
def test_ref_outside(trace, test_server):
    @trace
    def test_ref_outside_inner():
        a = f()

    test_ref_outside_inner()

    assert trace.events == [
        InitialValue(lineno=11, target=Symbol("f"), value='{"repr": "<function f>"}'),
        Binding(lineno=11, target=Symbol("a"), value="1", sources={Symbol("f")}),
        Return(lineno=11, value="null", sources=set()),
    ]

    test_server.assert_frame_sent("test_ref_outside_inner")
示例#17
0
def test_attribute(tracer, rpc_stub):
    class A:
        pass

    a1 = A()
    a2 = A()
    a2.y = 1

    tracer.start()

    a1.x = a2  # STORE_ATTR
    a1.x.y = 2  # LOAD_ATTR, STORE_ATTR
    del a1.x  # DELETE_ATTR

    tracer.stop()

    assert tracer.events == [
        InitialValue(
            lineno=14,
            target=Symbol("a2"),
            value='{"y": 1}',
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
        InitialValue(
            lineno=14,
            target=Symbol("a1"),
            value="{}",
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
        Mutation(
            lineno=14,
            target=Symbol("a1"),
            sources={Symbol("a2"), Symbol("a1")},
            value='{"x": {"y": 1}}',
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
        Mutation(
            lineno=15,
            target=Symbol("a1"),
            sources={Symbol("a1")},
            value='{"x": {"y": 2}}',
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
        Mutation(
            lineno=16,
            target=Symbol("a1"),
            sources={Symbol("a1")},
            value="{}",
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
    ]

    from utils import assert_GetFrame

    assert_GetFrame(rpc_stub, "test_attribute")
示例#18
0
def test_existing_variable_emit_initial_value(tracer, rpc_stub):
    x = "foo"
    tracer.start()
    y = x
    tracer.stop()

    assert tracer.events == [
        InitialValue(target=Symbol("x"), value="foo", lineno=8),
        Binding(target=Symbol("y"),
                value="foo",
                sources={Symbol("x")},
                lineno=8),
    ]

    assert_GetFrame(rpc_stub, "test_existing_variable_emit_initial_value")
示例#19
0
def test_module(rpc_stub):
    assert tracer.events == [
        InitialValue(target=Symbol("x"), value=1, lineno=10),
        Deletion(target=Symbol("x"), lineno=10),
        InitialValue(target=Symbol("__annotations__"), value={}, lineno=11),
        Mutation(
            target=Symbol("__annotations__"),
            value={"y": int},
            sources={Symbol("__annotations__")
                     },  # `int` is a built-in so is excluded from sources.
            lineno=11,
        ),
    ]

    assert_GetFrame(rpc_stub, "test_outside_func")
示例#20
0
def test_numpy(tracer, test_server):
    tracer.start()
    x = np.array([6, 7, 8])
    tracer.stop()

    from utils import get_os_type, get_value

    int_type = get_value({
        "windows": "int32",
        "linux": "int64",
        "mac": "int64"
    })

    assert tracer.events == [
        Binding(
            lineno=8,
            target=Symbol("x"),
            value=f'{{"dtype":"{int_type}","values":[6,7,8]}}',
            repr="array([6,7,8])",
            sources=set(),
        )
    ]

    if get_os_type() != "windows":
        test_server.assert_frame_sent("test_numpy")
示例#21
0
def test_ref_outside(trace, rpc_stub):
    @trace
    def test_ref_outside_inner():
        a = f()

    test_ref_outside_inner()

    assert trace.events == [
        InitialValue(lineno=11, target=Symbol("f"), value=f),
        Binding(lineno=11, target=Symbol("a"), value=1, sources={Symbol("f")}),
        Return(lineno=11, value=None, sources=set()),
    ]

    from utils import assert_GetFrame

    assert_GetFrame(rpc_stub, "test_ref_outside_inner")
示例#22
0
def test_trace_decorated_function(trace):
    def my_decorator(f):
        def inner(*args):
            a = 1
            f(*args)
            b = a

        return inner

    @my_decorator
    @trace
    def original_func():
        a = [1, 2, 3]

    original_func()

    assert trace.events == [
        Binding(
            lineno=16,
            target=Symbol("a"),
            value="[1,2,3]",
            repr="[1, 2, 3]",
            sources=set(),
        ),
        Return(
            lineno=16,
            value="null",
            repr="None",
            sources=set(),
        ),
    ]
示例#23
0
def test_yield_from(trace, mocked_responses):
    def inner():
        for i in range(2):
            yield i

    @trace
    def yield_from_function():
        yield from inner()  # CALL_FUNCTION, GET_YIELD_FROM_ITER, LOAD_CONST
        # The above line triggers two return events for sys.settrace

    for output in yield_from_function():
        print(output)

    trace.stop()

    assert trace.events == [
        InitialValue(
            lineno=75,
            target=Symbol("inner"),
            value='{"repr": "<function test_yield_from.<locals>.inner>"}',
            repr="<function test_yield_from.<locals>.inner>",
        ),
        Return(
            lineno=75,
            value="null",
            repr="None",
            sources=set(),
        ),
    ]
示例#24
0
def test_while_jump_to_zero(trace):
    @trace
    def while_jump_to_zero(count):
        while count > 0:
            count -= 1

    while_jump_to_zero(2)

    assert trace.events == [
        InitialValue(
            lineno=103,
            target=Symbol("count"),
            value="2",
            repr="2",
        ),
        Binding(
            lineno=104,
            target=Symbol("count"),
            value="1",
            repr="1",
            sources={Symbol("count")},
        ),
        JumpBackToLoopStart(lineno=104,
                            jump_target=get_value({
                                "py37": 2,
                                "default": 0
                            })),
        Binding(
            lineno=104,
            target=Symbol("count"),
            value="0",
            repr="0",
            sources={Symbol("count")},
        ),
        JumpBackToLoopStart(lineno=104,
                            jump_target=get_value({
                                "py37": 2,
                                "default": 0
                            })),
        Return(
            lineno=104,
            value="null",
            repr="None",
            sources=set(),
        ),
    ]
示例#25
0
def test_api_tracer(tracer, mocked_responses):
    tracer.start()
    a = 1
    tracer.stop()

    assert tracer.events == [
        Binding(lineno=6, target=Symbol("a"), value="1", sources=set())
    ]
示例#26
0
def test_attribute(tracer, mocked_responses):
    class A:
        pass

    a1 = A()
    a2 = A()
    a2.y = 1

    tracer.start()

    a1.x = a2  # STORE_ATTR
    a1.x.y = 2  # LOAD_ATTR, STORE_ATTR
    del a1.x  # DELETE_ATTR

    tracer.stop()

    assert tracer.events == [
        InitialValue(
            lineno=-1,
            target=Symbol("a2"),
            value='{"y":1}',
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
        InitialValue(
            lineno=-1,
            target=Symbol("a1"),
            value="{}",
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
        Mutation(
            lineno=14,
            target=Symbol("a1"),
            sources={Symbol("a2"), Symbol("a1")},
            value='{"x":{"y":1}}',
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
        Mutation(
            lineno=15,
            target=Symbol("a1"),
            sources={Symbol("a1")},
            value='{"x":{"y":2}}',
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
        Mutation(
            lineno=16,
            target=Symbol("a1"),
            sources={Symbol("a1")},
            value="{}",
            repr="<test_attribute.test_attribute.<locals>.A object>",
        ),
    ]
示例#27
0
def test_pandas(tracer, mocked_responses):
    tracer.start()
    baby_data_set = [
        ("Bob", 968),
        ("Jessica", 155),
        ("Mary", 77),
        ("John", 578),
        ("Mel", 973),
    ]
    df = pd.DataFrame(data=baby_data_set, columns=["Names", "Births"])
    tracer.stop()

    from utils import get_value

    eol = get_value({"windows": r"\r\n", "linux": r"\n", "mac": "\\n"})

    assert tracer.events == [
        Binding(
            lineno=get_value({"py37": 13, "default": 8}),
            target=Symbol("baby_data_set"),
            value='[["Bob",968],["Jessica",155],["Mary",77],["John",578],["Mel",973]]',
            repr=(
                "[('Bob', 968), ('Jessica', 155), "
                "('Mary', 77), ('John', 578), ('Mel', 973)]"
            ),
            sources=set(),
        ),
        Binding(
            lineno=15,
            target=Symbol("df"),
            value=(
                f'{{"values":"Names,Births{eol}Bob,968{eol}Jessica,155{eol}'
                f'Mary,77{eol}John,578{eol}Mel,973{eol}"'
                ',"txt":true,"meta":{"dtypes":{"Names":"object","Births":"int64"},'
                '"index":"{\\"py/object\\":\\"pandas.core.indexes.range.RangeIndex\\"'
                ',\\"values\\":\\"[0,1,2,3,4]\\",\\"txt\\":true,\\"meta\\":{\\"dtype\\"'
                ':\\"int64\\",\\"name\\":null}}",'
                '"column_level_names":[null],"header":[0]}}'
            ),
            repr=(
                "     Names  Births\n0      Bob     968\n1  Jessica     155\n2"
                "     Mary      77\n3     John     578\n4      Mel     973"
            ),
            sources={Symbol("baby_data_set")},
        ),
    ]
示例#28
0
def test_hello(tracer, rpc_stub):
    tracer.start()
    x = "hello world"  # LOAD_CONST, STORE_FAST
    y = x  # LOAD_FAST, STORE_FAST
    x, y = y, x  # ROT_TWO, STORE_FAST
    tracer.stop()

    assert tracer.events == [
        Binding(target=Symbol("x"), value="hello world", lineno=6),
        Binding(target=Symbol("y"),
                value="hello world",
                sources={Symbol("x")},
                lineno=7),
        Binding(target=Symbol("x"),
                value="hello world",
                sources={Symbol("y")},
                lineno=8),
        Binding(target=Symbol("y"),
                value="hello world",
                sources={Symbol("x")},
                lineno=8),
    ]

    from utils import assert_GetFrame

    assert_GetFrame(rpc_stub, "test_hello")
示例#29
0
def test_jump(tracer, rpc_stub):
    a = []
    b = "b"
    c = "c"

    tracer.start()

    if a:  # POP_JUMP_IF_FALSE
        pass  # JUMP_FORWARD
    else:
        x = 1

    if not a:  # POP_JUMP_IF_TRUE
        x = 2

    x = a != b != c  # JUMP_IF_FALSE_OR_POP
    x = a == b or c  # JUMP_IF_TRUE_OR_POP

    # TODO: Test JUMP_ABSOLUTE. This requires loop instructions to be Implemented.

    tracer.stop()

    assert tracer.events == [
        InitialValue(target=Symbol("a"), value=[], lineno=12),
        Binding(target=Symbol("x"), value=1, lineno=15),
        Binding(target=Symbol("x"), value=2, lineno=18),
        InitialValue(target=Symbol("b"), value="b", lineno=20),
        InitialValue(target=Symbol("c"), value="c", lineno=20),
        # This is a known defect. We have no way to know `x` comes from `a`, because
        # the result of `a != b` only determines whether to jump to execute `b != c`
        # I think it's fine though.
        Binding(
            target=Symbol("x"),
            value=True,
            sources={Symbol("b"), Symbol("c")},
            lineno=20,
        ),
        # Same defect here.
        Binding(target=Symbol("x"),
                value="c",
                sources={Symbol("c")},
                lineno=21),
    ]

    assert_GetFrame(rpc_stub, "test_jump")
示例#30
0
def test_decorator_multiple_times(trace, mocked_responses):
    @trace
    def func(b):
        a = b
        return a

    func(1)

    assert func(2) == 2
    assert trace.events == [
        InitialValue(
            lineno=21,
            target=Symbol("b"),
            value="1",
        ),
        Binding(lineno=21, target=Symbol("a"), value="1", sources={Symbol("b")}),
        Return(lineno=22, value="1", sources={Symbol("a")}),
    ]