Пример #1
0
def test_tracing_vars(LineMatcher):
    lines = StringIO()
    with hunter.trace(actions=[
            VarsPrinter('b', stream=lines),
            CodePrinter(stream=lines)
    ]):

        def a():
            b = 1
            b = 2
            return 1

        b = a()
        b = 2
        try:
            raise Exception("BOOM!")
        except Exception:
            pass
    print(lines.getvalue())
    lm = LineMatcher(lines.getvalue().splitlines())
    lm.fnmatch_lines([
        "*test_hunter.py* call              def a():",
        "*test_hunter.py* line                  b = 1",
        "* vars      b => 1",
        "*test_hunter.py* line                  b = 2",
        "* vars      b => 2",
        "*test_hunter.py* line                  return 1",
        "* vars      b => 2",
        "*test_hunter.py* return                return 1",
        "* ...       return value: 1",
    ])
Пример #2
0
def test_pid_prefix(LineMatcher, Action, force_pid, capfd):
    def main():
        a = 1
        pid = os.fork()
        if pid:
            os.waitpid(pid, 0)
        else:
            os._exit(0)  # child

    with hunter.trace(actions=[
            Action(force_pid=force_pid, stream=sys.stdout),
            VarsPrinter('a', force_pid=force_pid, stream=sys.stdout)
    ],
                      stdlib=False,
                      threading_support=True):
        main()
    out, err = capfd.readouterr()
    print('OUT', out)
    print('ERR', err)
    lm = LineMatcher(out.splitlines())
    prefix = '[[]*[]] *' if force_pid else ''
    lm.fnmatch_lines_random([
        prefix + "MainThread  *test_hunter.py:*  line * a = 1",
        prefix + "MainThread  *test_hunter.py:*  line * if pid:",
        prefix + "MainThread  *               *  vars * a => 1",
        prefix + "MainThread  *test_hunter.py:*  line * os.waitpid(pid, 0)",
        "[[]*[]] *MainThread  *test_hunter.py:*  line * os._exit(0)  # child",
        "[[]*[]] *MainThread  *               *  vars * a => 1",
    ])
Пример #3
0
 def run():
     output = StringIO()
     with t.trace(
             Q(~Q(module_in=['re', 'sre', 'sre_parse'])
               & ~Q(module_startswith='namedtuple') & Q(kind="call"),
               actions=[
                   CodePrinter(stream=output),
                   VarsPrinter('line', globals=True, stream=output)
               ])):
         _bulky_func_that_use_stdlib()
Пример #4
0
def test_tracing_printing_failures(LineMatcher):
    lines = StringIO()
    with trace(actions=[
            CodePrinter(stream=lines),
            VarsPrinter("x", stream=lines)
    ]):

        class Bad(object):
            __slots__ = []

            def __repr__(self):
                raise RuntimeError("I'm a bad class!")

        def a():
            x = Bad()
            return x

        def b():
            x = Bad()
            raise Exception(x)

        a()
        try:
            b()
        except Exception as exc:
            pass
    lm = LineMatcher(lines.getvalue().splitlines())
    lm.fnmatch_lines([
        """*tests*test_hunter.py:* call              class Bad(object):""",
        """*tests*test_hunter.py:* line              class Bad(object):""",
        """*tests*test_hunter.py:* line                  def __repr__(self):""",
        """*tests*test_hunter.py:* return                def __repr__(self):""",
        """* ...       return value: *""",
        """*tests*test_hunter.py:* call              def a():""",
        """*tests*test_hunter.py:* line                  x = Bad()""",
        """*tests*test_hunter.py:* line                  return x""",
        """* vars      x => !!! FAILED REPR: RuntimeError("I'm a bad class!"*)""",
        """*tests*test_hunter.py:* return                return x""",
        """* ...       return value: !!! FAILED REPR: RuntimeError("I'm a bad class!"*)""",
        """* vars      x => !!! FAILED REPR: RuntimeError("I'm a bad class!"*)""",
        """*tests*test_hunter.py:* call              def b():""",
        """*tests*test_hunter.py:* line                  x = Bad()""",
        """*tests*test_hunter.py:* line                  raise Exception(x)""",
        """* vars      x => !!! FAILED REPR: RuntimeError("I'm a bad class!"*)""",
        """*tests*test_hunter.py:* exception             raise Exception(x)""",
        """* ...       exception value: !!! FAILED REPR: RuntimeError("I'm a bad class!"*)""",
        """* vars      x => !!! FAILED REPR: RuntimeError("I'm a bad class!"*)""",
        """*tests*test_hunter.py:* return                raise Exception(x)""",
        """* ...       return value: None""",
        """* vars      x => !!! FAILED REPR: RuntimeError("I'm a bad class!"*)""",
    ])
Пример #5
0
def test_trace_api_expansion():
    # simple use
    with trace(function="foobar") as t:
        assert t.handler == When(Q(function="foobar"), CallPrinter)

    # "or" by expression
    with trace(module="foo", function="foobar") as t:
        assert t.handler == When(Q(module="foo", function="foobar"),
                                 CallPrinter)

    # pdb.set_trace
    with trace(function="foobar", action=Debugger) as t:
        assert str(t.handler) == str(When(Q(function="foobar"), Debugger))

    # pdb.set_trace on any hits
    with trace(module="foo", function="foobar", action=Debugger) as t:
        assert str(t.handler) == str(
            When(Q(module="foo", function="foobar"), Debugger))

    # pdb.set_trace when function is foobar, otherwise just print when module is foo
    with trace(Q(function="foobar", action=Debugger), module="foo") as t:
        assert str(t.handler) == str(
            When(And(When(Q(function="foobar"), Debugger), Q(module="foo")),
                 CallPrinter))

    # dumping variables from stack
    with trace(Q(function="foobar", action=VarsPrinter("foobar")),
               module="foo") as t:
        assert str(t.handler) == str(
            When(
                And(
                    When(Q(function="foobar"), VarsPrinter("foobar")),
                    Q(module="foo"),
                ), CallPrinter))

    with trace(Q(function="foobar", action=VarsPrinter("foobar",
                                                       "mumbojumbo")),
               module="foo") as t:
        assert str(t.handler) == str(
            When(
                And(
                    When(Q(function="foobar"),
                         VarsPrinter("foobar", "mumbojumbo")),
                    Q(module="foo"),
                ), CallPrinter))

    # multiple actions
    with trace(Q(function="foobar", actions=[VarsPrinter("foobar"), Debugger]),
               module="foo") as t:
        assert str(t.handler) == str(
            When(
                And(
                    When(Q(function="foobar"), VarsPrinter("foobar"),
                         Debugger),
                    Q(module="foo"),
                ), CallPrinter))
Пример #6
0
def test_tracing_vars_expressions(LineMatcher):
    lines = StringIO()
    with hunter.trace(actions=[VarsPrinter('Foo.bar', 'vars(Foo)', 'len(range(2))', 'Foo.__dict__["bar"]', stream=lines)]):
        def main():
            class Foo(object):
                bar = 1

        main()
    print(lines.getvalue())
    lm = LineMatcher(lines.getvalue().splitlines())
    lm.fnmatch_lines_random([
        '*    [[]Foo.bar => 1[]]',
        '*    [[]vars(Foo) => *[]]',
        '*    [[]len(range(2)) => 2[]]',
        '*    [[]Foo.__dict__[[]"bar"[]] => 1[]]',
    ])
Пример #7
0
def test_threading_support(LineMatcher):
    lines = StringIO()
    idents = set()
    names = set()
    started = threading.Event()

    def record(event):
        idents.add(event.threadid)
        names.add(event.threadname)
        return True

    with hunter.trace(record,
                      actions=[
                          CodePrinter(stream=lines),
                          VarsPrinter('a', stream=lines),
                          CallPrinter(stream=lines)
                      ],
                      threading_support=True):

        def foo(a=1):
            started.set()
            print(a)

        def main():
            foo()

        t = threading.Thread(target=foo)
        t.start()
        started.wait(10)
        main()

    lm = LineMatcher(lines.getvalue().splitlines())
    assert idents - {t.ident} == {None}
    assert 'MainThread' in names
    assert any(name.startswith('Thread-') for name in names)
    lm.fnmatch_lines_random([
        'Thread-*   *test_hunter.py:*   call              def foo(a=1):',
        'Thread-*   *                   vars      a => 1',
        'Thread-*   *test_hunter.py:*   call         => foo(a=1)',
        'Thread-*   *                   vars      a => 1',
        'MainThread *test_hunter.py:*   call              def foo(a=1):',
        'MainThread *                   vars      a => 1',
        'MainThread *test_hunter.py:*   call         => foo(a=1)',
        'MainThread *                   vars      a => 1',
    ])
Пример #8
0
def test_thread_filtering(LineMatcher, query):
    lines = StringIO()
    idents = set()
    names = set()
    started = threading.Event()

    def record(event):
        idents.add(event.threadid)
        names.add(event.threadname)
        return True

    with hunter.trace(~Q(**query),
                      record,
                      actions=[
                          CodePrinter(stream=lines),
                          VarsPrinter('a', stream=lines),
                          CallPrinter(stream=lines)
                      ],
                      threading_support=True):

        def foo(a=1):
            started.set()
            print(a)

        def main():
            foo()

        t = threading.Thread(target=foo)
        t.start()
        started.wait(10)
        main()

    lm = LineMatcher(lines.getvalue().splitlines())
    print(lines.getvalue())
    assert None not in idents
    assert 'MainThread' not in names
    pprint(lm.lines)
    lm.fnmatch_lines_random([
        'Thread-*   *test_hunter.py:*   call              def foo(a=1):',
        'Thread-*   *                   vars      a => 1',
        'Thread-*   *test_hunter.py:*   call         => foo(a=1)',
        'Thread-*   *                   vars      a => 1',
    ])
Пример #9
0
def test_debugger(LineMatcher):
    out = StringIO()
    calls = []

    class FakePDB:
        def __init__(self, foobar=1):
            calls.append(foobar)

        def set_trace(self, frame):
            calls.append(frame.f_code.co_name)

    with hunter.trace(lambda event: event.locals.get("node") == "Foobar",
                      module="test_hunter",
                      function="foo",
                      actions=[
                          CodePrinter,
                          VarsPrinter("a",
                                      "node",
                                      "foo",
                                      "test_debugger",
                                      globals=True,
                                      stream=out),
                          Debugger(klass=FakePDB, foobar=2)
                      ]):

        def foo():
            a = 1
            node = "Foobar"
            node += "x"
            a += 2
            return a

        foo()
    print(out.getvalue())
    assert calls == [2, 'foo']
    lm = LineMatcher(out.getvalue().splitlines())
    pprint(lm.lines)
    lm.fnmatch_lines_random([
        "*      test_debugger => <function test_debugger at *",
        "*      node => 'Foobar'",
        "*      a => 1",
    ])
Пример #10
0
def test_debugger(LineMatcher):
    out = StringIO()
    calls = []

    class FakePDB:
        def __init__(self, foobar=1):
            calls.append(foobar)

        def set_trace(self, frame):
            calls.append(frame.f_code.co_name)

    with hunter.trace(lambda event: event.locals.get('node') == 'Foobar',
                      module='test_hunter',
                      function='foo',
                      actions=[
                          CodePrinter,
                          VarsPrinter('a',
                                      'node',
                                      'foo',
                                      'test_debugger',
                                      stream=out),
                          Debugger(klass=FakePDB, foobar=2)
                      ]):

        def foo():
            a = 1
            node = 'Foobar'
            node += 'x'
            a += 2
            return a

        foo()
    print(out.getvalue())
    assert calls == [2, 'foo']
    lm = LineMatcher(out.getvalue().splitlines())
    pprint(lm.lines)
    lm.fnmatch_lines_random([
        "*      [[]test_debugger => <function test_debugger at *[]]",
        "*      [[]node => 'Foobar'[]]",
        "*      [[]a => 1[]]",
    ])