示例#1
0
def test_attaching_by_pid(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        # import_and_enable_debugger()
        import time

        def do_something(i):
            time.sleep(0.1)
            print(i)

        for i in range(100):
            do_something(i)

    bp_line = 5
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )
        session.set_breakpoints(code_to_debug, [bp_line])
        session.start_debugging()
        hit = session.wait_for_thread_stopped()
        frames = hit.stacktrace.body['stackFrames']
        assert bp_line == frames[0]['line']

        # remove breakpoint and continue
        session.set_breakpoints(code_to_debug, [])
        session.send_request('continue').wait_for_response(freeze=False)
        session.wait_for_next(
            Event('output', ANY.dict_with({'category': 'stdout'})))
        session.wait_for_exit()
示例#2
0
def test_with_tab_in_output(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        a = '\t'.join(('Hello', 'World'))
        print(a)
        # Break here so we are sure to get the output event.
        a = 1  # @bp1

    line_numbers = get_marked_line_numbers(code_to_debug)
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )

        session.set_breakpoints(code_to_debug, [line_numbers['bp1']])
        session.start_debugging()

        # Breakpoint at the end just to make sure we get all output events.
        session.wait_for_thread_stopped()
        session.send_request('continue').wait_for_response(freeze=False)
        session.wait_for_exit()

        output = session.all_occurrences_of(
            Event('output', ANY.dict_with({'category': 'stdout'})))
        output_str = ''.join(o.body['output'] for o in output)
        assert output_str.startswith('Hello\tWorld')
示例#3
0
def _initialize_flask_session_no_multiproc(session, start_method):
    env = {
        'FLASK_APP': 'app.py',
        'FLASK_ENV': 'development',
        'FLASK_DEBUG': '0',
    }
    if platform.system() != 'Windows':
        locale = 'en_US.utf8' if platform.system(
        ) == 'Linux' else 'en_US.UTF-8'
        env.update({
            'LC_ALL': locale,
            'LANG': locale,
        })

    session.initialize(
        start_method=start_method,
        target=('module', 'flask'),
        program_args=[
            'run', '--no-debugger', '--no-reload', '--with-threads', '--port',
            str(FLASK_PORT)
        ],
        ignore_unobserved=[Event('stopped'),
                           Event('continued')],
        debug_options=['Jinja'],
        cwd=FLASK1_ROOT,
        env=env,
        expected_returncode=ANY.int,  # No clean way to kill Flask server
    )
示例#4
0
def test_continue_on_disconnect_for_attach(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        import backchannel
        backchannel.write_json('continued')

    bp_line = 4
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('exited'),
                               Event('terminated')],
            use_backchannel=True,
        )
        session.set_breakpoints(code_to_debug, [bp_line])
        session.start_debugging()
        hit = session.wait_for_thread_stopped('breakpoint')
        frames = hit.stacktrace.body['stackFrames']
        assert frames[0]['line'] == bp_line
        session.send_request('disconnect').wait_for_response()
        session.wait_for_disconnect()
        assert 'continued' == session.read_json()
示例#5
0
def test_completions_scope(pyfile, bp_line, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        class SomeClass():
            def __init__(self, someVar):
                self.some_var = someVar
            def do_someting(self):
                someVariable = self.some_var
                return someVariable
        def someFunction(someVar):
            someVariable = someVar
            return SomeClass(someVariable).do_someting()
        someFunction('value')
        print('done')

    expected = expected_at_line[bp_line]

    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('stopped'), Event('continued')],
        )
        session.set_breakpoints(code_to_debug, [bp_line])
        session.start_debugging()

        thread_stopped = session.wait_for_next(Event('stopped', ANY.dict_with({'reason': 'breakpoint'})))
        assert thread_stopped.body['threadId'] is not None
        tid = thread_stopped.body['threadId']

        resp_stacktrace = session.send_request('stackTrace', arguments={
            'threadId': tid,
        }).wait_for_response()
        assert resp_stacktrace.body['totalFrames'] > 0
        frames = resp_stacktrace.body['stackFrames']
        assert len(frames) > 0

        fid = frames[0]['id']
        resp_completions = session.send_request('completions', arguments={
            'text': 'some',
            'frameId': fid,
            'column': 5,
        }).wait_for_response()
        targets = resp_completions.body['targets']

        session.send_request('continue').wait_for_response(freeze=False)

        targets.sort(key=lambda t: t['label'])
        expected.sort(key=lambda t: t['label'])
        assert targets == expected

        session.wait_for_exit()
示例#6
0
def test_set_variable(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        import backchannel
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        import ptvsd
        a = 1
        ptvsd.break_into_debugger()
        backchannel.write_json(a)

    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
            use_backchannel=True,
        )
        session.start_debugging()
        hit = session.wait_for_thread_stopped()

        resp_scopes = session.send_request('scopes',
                                           arguments={
                                               'frameId': hit.frame_id
                                           }).wait_for_response()
        scopes = resp_scopes.body['scopes']
        assert len(scopes) > 0

        resp_variables = session.send_request(
            'variables',
            arguments={
                'variablesReference': scopes[0]['variablesReference']
            }).wait_for_response()
        variables = list(v for v in resp_variables.body['variables']
                         if v['name'] == 'a')
        assert len(variables) == 1
        assert variables[0] == {
            'type': 'int',
            'value': '1',
            'name': 'a',
            'evaluateName': "a"
        }

        resp_set_variable = session.send_request(
            'setVariable',
            arguments={
                'variablesReference': scopes[0]['variablesReference'],
                'name': 'a',
                'value': '1000'
            }).wait_for_response()
        assert resp_set_variable.body == ANY.dict_with({
            'type': 'int',
            'value': '1000'
        })

        session.send_request('continue').wait_for_response(freeze=False)

        assert session.read_json() == 1000

        session.wait_for_exit()
示例#7
0
def test_redirect_output(pyfile, run_as, start_method, redirect):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()

        for i in [111, 222, 333, 444]:
            print(i)

        print()  # @bp1

    line_numbers = get_marked_line_numbers(code_to_debug)
    with DebugSession() as session:
        # By default 'RedirectOutput' is always set. So using this way
        #  to override the default in session.
        session.debug_options = [redirect] if bool(redirect) else []
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
        )

        session.set_breakpoints(code_to_debug, [line_numbers['bp1']])
        session.start_debugging()

        # Breakpoint at the end just to make sure we get all output events.
        session.wait_for_thread_stopped()
        session.send_request('continue').wait_for_response(freeze=False)
        session.wait_for_exit()

        output = session.all_occurrences_of(
            Event('output', ANY.dict_with({'category': 'stdout'})))
        expected = ['111', '222', '333', '444'] if bool(redirect) else []
        assert expected == list(o.body['output'] for o in output
                                if len(o.body['output']) == 3)
示例#8
0
def test_break_on_entry(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        import backchannel
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        backchannel.write_json('done')

    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            debug_options=['StopOnEntry'],
            ignore_unobserved=[Event('continued')],
            use_backchannel=True,
        )
        session.start_debugging()

        thread_stopped, resp_stacktrace, tid, _ = session.wait_for_thread_stopped(
        )
        frames = resp_stacktrace.body['stackFrames']
        assert frames[0]['line'] == 1

        session.send_request('continue').wait_for_response(freeze=False)
        session.wait_for_termination()

        assert session.read_json() == 'done'

        session.wait_for_exit()
示例#9
0
def test_attaching_by_pid_no_threading(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        # import_and_enable_debugger
        import time

        wait = True
        i = 0
        while wait:
            i += 1
            print('in loop')
            time.sleep(0.1)
            if i > 100:
                raise AssertionError(
                    'Debugger did not change wait to False as expected within the timeout.'
                )

    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
        )
        session.start_debugging()
        # Wait for the first print to make sure we're in the proper state to pause.
        session.wait_for_next(
            Event('output',
                  ANY.dict_with({
                      'category': 'stdout',
                      'output': 'in loop'
                  })))
        _change_wait_to_false_and_exit(session)
示例#10
0
def test_success_exitcodes(pyfile, run_as, start_method, exit_code):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        import sys
        exit_code = eval(sys.argv[1])
        print('sys.exit(%r)' % (exit_code, ))
        sys.exit(exit_code)

    with DebugSession() as session:
        session.program_args = [repr(exit_code)]
        session.success_exitcodes = [3]
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
            expected_returncode=exit_code,
        )
        session.send_request('setExceptionBreakpoints', {
            'filters': ['uncaught']
        }).wait_for_response()
        session.start_debugging()

        if exit_code == 0:
            session.wait_for_thread_stopped(reason='exception')
            session.send_request('continue').wait_for_response(freeze=False)

        session.wait_for_exit()
示例#11
0
def test_wait_on_normal_exit_enabled(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        import backchannel
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        import ptvsd
        ptvsd.break_into_debugger()
        backchannel.write_json('done')

    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            debug_options=['WaitOnNormalExit'],
            ignore_unobserved=[Event('continued')],
            use_backchannel=True,
        )
        session.start_debugging()

        session.wait_for_thread_stopped()
        session.send_request('continue').wait_for_response(freeze=False)

        session.expected_returncode = ANY.int
        assert session.read_json() == 'done'

        session.process.stdin.write(b' \r\n')
        session.wait_for_exit()

        decoded = u'\n'.join((x.decode('utf-8') if isinstance(x, bytes) else x)
                             for x in session.output_data['OUT'])

        assert u'Press' in decoded
示例#12
0
def test_nodebug(pyfile, run_as):
    @pyfile
    def code_to_debug():
        # import_and_enable_debugger
        import backchannel
        backchannel.read_json()
        print('ok')

    with DebugSession() as session:
        session.no_debug = True
        session.initialize(target=(run_as, code_to_debug),
                           start_method='launch',
                           use_backchannel=True)
        session.set_breakpoints(code_to_debug, [3])
        session.start_debugging()

        session.write_json(None)

        # Breakpoint shouldn't be hit.
        session.wait_for_exit()

        session.expect_realized(
            Event('output',
                  ANY.dict_with({
                      'category': 'stdout',
                      'output': 'ok',
                  })))
示例#13
0
def test_exit_normally_with_wait_on_abnormal_exit_enabled(
        pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        import backchannel
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        import ptvsd
        ptvsd.break_into_debugger()
        backchannel.write_json('done')

    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            debug_options=['WaitOnAbnormalExit'],
            ignore_unobserved=[Event('continued')],
            use_backchannel=True,
        )
        session.start_debugging()

        session.wait_for_thread_stopped()
        session.send_request('continue').wait_for_response(freeze=False)

        session.wait_for_termination()

        assert session.read_json() == 'done'

        session.wait_for_exit()
示例#14
0
def test_exit_on_disconnect_for_launch(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        import os.path
        fp = os.join(os.path.dirname(os.path.abspath(__file__)), 'here.txt')
        # should not execute this
        with open(fp, 'w') as f:
            print('Should not continue after disconnect on launch', file=f)

    bp_line = 4
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
            use_backchannel=True,
            expected_returncode=ANY.int,
        )
        session.set_breakpoints(code_to_debug, [bp_line])
        session.start_debugging()
        hit = session.wait_for_thread_stopped('breakpoint')
        frames = hit.stacktrace.body['stackFrames']
        assert frames[0]['line'] == bp_line
        session.send_request('disconnect').wait_for_response()
        session.wait_for_exit()
        fp = os.join(os.path.dirname(os.path.abspath(code_to_debug)),
                     'here.txt')
        assert not os.path.exists(fp)
示例#15
0
def test_log_point(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        a = 10
        for i in range(1, a):
            print('value: %d' % i)
        # Break at end too so that we're sure we get all output
        # events before the break.
        a = 10

    bp_line = 5
    end_bp_line = 8
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )
        session.send_request('setBreakpoints', arguments={
            'source': {'path': code_to_debug},
            'breakpoints': [{
                'line': bp_line,
                'logMessage': 'log: {a + i}'
            }, {'line': end_bp_line}],
        }).wait_for_response()
        session.start_debugging()

        # Breakpoint at the end just to make sure we get all output events.
        hit = session.wait_for_thread_stopped()
        frames = hit.stacktrace.body['stackFrames']
        assert end_bp_line == frames[0]['line']

        session.send_request('continue').wait_for_response(freeze=False)

        session.wait_for_exit()
        assert session.get_stderr_as_string() == b''

        output = session.all_occurrences_of(Event('output', ANY.dict_with({'category': 'stdout'})))
        output_str = ''.join(o.body['output'] for o in output)
        logged = sorted(int(i) for i in re.findall(r"log:\s([0-9]*)", output_str))
        values = sorted(int(i) for i in re.findall(r"value:\s([0-9]*)", output_str))

        assert logged == list(range(11, 20))
        assert values == list(range(1, 10))
示例#16
0
def test_run_submodule():
    cwd = get_test_root('testpkgs')
    with DebugSession() as session:
        session.initialize(
            target=('module', 'pkg1.sub'),
            start_method='launch',
            ignore_unobserved=[Event('continued')],
            cwd=cwd,
        )
        session.start_debugging()
        session.wait_for_next(
            Event('output',
                  ANY.dict_with({
                      'category': 'stdout',
                      'output': 'three'
                  })))
        session.wait_for_exit()
示例#17
0
def test_argv_quoting(pyfile, run_as, start_method):
    @pyfile
    def args():
        # import_and_enable_debugger
        args = [  # noqa
            r'regular',
            r'',
            r'with spaces'
            r'"quoted"',
            r'" quote at start',
            r'quote at end "',
            r'quote in " the middle',
            r'quotes "in the" middle',
            r'\path with\spaces',
            r'\path\with\terminal\backslash' + '\\',
            r'backslash \" before quote',
        ]

    @pyfile
    def parent():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()

        import sys
        import subprocess
        from args import args
        child = sys.argv[1]
        subprocess.check_call([sys.executable] + [child] + args)

    @pyfile
    def child():
        # import_and_enable_debugger
        import backchannel
        import sys

        from args import args as expected_args
        backchannel.write_json(expected_args)

        actual_args = sys.argv[1:]
        backchannel.write_json(actual_args)

    with DebugSession() as session:
        session.initialize(
            target=(run_as, parent),
            start_method=start_method,
            program_args=[child],
            use_backchannel=True,
            ignore_unobserved=[Event('continued')],
        )

        session.start_debugging()

        expected_args = session.read_json()
        actual_args = session.read_json()
        assert expected_args == actual_args

        session.wait_for_exit()
示例#18
0
def test_vsc_exception_options_raise_with_except(pyfile, run_as, start_method, raised, uncaught):

    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()

        def raise_with_except():
            try:
                raise ArithmeticError('bad code')  # @exception_line
            except Exception:
                pass

        raise_with_except()

    line_numbers = get_marked_line_numbers(code_to_debug)
    ex_line = line_numbers['exception_line']
    filters = []
    filters += ['raised'] if raised == 'raisedOn' else []
    filters += ['uncaught'] if uncaught == 'uncaughtOn' else []
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )
        session.send_request('setExceptionBreakpoints', {
            'filters': filters
        }).wait_for_response()
        session.start_debugging()

        expected = ANY.dict_with({
            'exceptionId': ANY.such_that(lambda s: s.endswith('ArithmeticError')),
            'description': 'bad code',
            'breakMode': 'always' if raised == 'raisedOn' else 'unhandled',
            'details': ANY.dict_with({
                'typeName': ANY.such_that(lambda s: s.endswith('ArithmeticError')),
                'message': 'bad code',
                'source': Path(code_to_debug),
            }),
        })

        if raised == 'raisedOn':
            hit = session.wait_for_thread_stopped(reason='exception')
            frames = hit.stacktrace.body['stackFrames']
            assert ex_line == frames[0]['line']

            resp_exc_info = session.send_request('exceptionInfo', {
                'threadId': hit.thread_id
            }).wait_for_response()

            assert resp_exc_info.body == expected
            session.send_request('continue').wait_for_response(freeze=False)

        # uncaught should not 'stop' matter since the exception is caught

        session.wait_for_exit()
示例#19
0
def test_module_events(pyfile, run_as, start_method):
    @pyfile
    def module2():
        # import_and_enable_debugger()
        def do_more_things():
            print('done')

    @pyfile
    def module1():
        # import_and_enable_debugger()
        import module2

        def do_something():
            module2.do_more_things()

    @pyfile
    def test_code():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        from module1 import do_something
        do_something()

    bp_line = 3
    with DebugSession() as session:
        session.initialize(
            target=(run_as, test_code),
            start_method=start_method,
            ignore_unobserved=[Event('stopped')],
        )
        session.set_breakpoints(module2, [bp_line])
        session.start_debugging()

        session.wait_for_thread_stopped()
        modules = session.all_occurrences_of(Event('module'))
        modules = [(m.body['module']['name'], m.body['module']['path'])
                   for m in modules]
        assert modules[:3] == [
            ('module2', Path(module2)),
            ('module1', Path(module1)),
            ('__main__', Path(test_code)),
        ]

        session.send_request('continue').wait_for_response(freeze=False)
        session.wait_for_exit()
示例#20
0
def test_log_point(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        a = 10
        for i in range(1, a):
            print('value: %d' % i)

    bp_line = 5
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )
        session.send_request('setBreakpoints',
                             arguments={
                                 'source': {
                                     'path': code_to_debug
                                 },
                                 'breakpoints': [{
                                     'line': bp_line,
                                     'logMessage': 'log: {a + i}'
                                 }],
                             }).wait_for_response()
        session.start_debugging()

        session.wait_for_exit()
        assert session.get_stderr_as_string() == b''

        output = session.all_occurrences_of(
            Event('output', ANY.dict_with({'category': 'stdout'})))
        output_str = ''.join(o.body['output'] for o in output)
        logged = sorted(
            int(i) for i in re.findall(r"log:\s([0-9]*)", output_str))
        values = sorted(
            int(i) for i in re.findall(r"value:\s([0-9]*)", output_str))

        # NOTE: Due to https://github.com/Microsoft/ptvsd/issues/1028 we may not get
        # all output events. Once that is fixed we should check for the exact output
        # and log value
        assert len(logged) > 0
        assert len(values) > 0
示例#21
0
def test_conditional_breakpoint(pyfile, run_as, start_method, condition_key):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        for i in range(0, 10):
            print(i)

    expected = {
        'condition_var': ('condition', 'i==5', '5', 1),
        'hitCondition_#': ('hitCondition', '5', '4', 1),
        'hitCondition_eq': ('hitCondition', '==5', '4', 1),
        'hitCondition_gt': ('hitCondition', '>5', '5', 5),
        'hitCondition_ge': ('hitCondition', '>=5', '4', 6),
        'hitCondition_lt': ('hitCondition', '<5', '0', 4),
        'hitCondition_le': ('hitCondition', '<=5', '0', 5),
        'hitCondition_mod': ('hitCondition', '%3', '2', 3),
    }
    condition_type, condition, value, hits = expected[condition_key]

    bp_line = 4
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )
        session.send_request('setBreakpoints', arguments={
            'source': {'path': code_to_debug},
            'breakpoints': [{'line': bp_line, condition_type: condition}],
        }).wait_for_response()
        session.start_debugging()
        hit = session.wait_for_thread_stopped()
        frames = hit.stacktrace.body['stackFrames']
        assert bp_line == frames[0]['line']

        resp_scopes = session.send_request('scopes', arguments={
            'frameId': hit.frame_id
        }).wait_for_response()
        scopes = resp_scopes.body['scopes']
        assert len(scopes) > 0

        resp_variables = session.send_request('variables', arguments={
            'variablesReference': scopes[0]['variablesReference']
        }).wait_for_response()
        variables = list(v for v in resp_variables.body['variables']
                         if v['name'] == 'i')
        assert variables == [
            ANY.dict_with({'name': 'i', 'type': 'int', 'value': value, 'evaluateName': 'i'})
        ]

        session.send_request('continue').wait_for_response(freeze=False)
        for i in range(1, hits):
            session.wait_for_thread_stopped()
            session.send_request('continue').wait_for_response(freeze=False)
        session.wait_for_exit()
示例#22
0
def test_add_and_remove_breakpoint(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        for i in range(0, 10):
            print(i)
        import backchannel
        backchannel.read_json()

    bp_line = 4
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            use_backchannel=True,
        )
        session.set_breakpoints(code_to_debug, [bp_line])
        session.start_debugging()

        hit = session.wait_for_thread_stopped()
        frames = hit.stacktrace.body['stackFrames']
        assert bp_line == frames[0]['line']

        # remove breakpoints in file
        session.set_breakpoints(code_to_debug, [])
        session.send_request('continue').wait_for_response(freeze=False)

        session.wait_for_next(
            Event('output', ANY.dict_with({
                'category': 'stdout',
                'output': '9'
            })))
        session.write_json('done')
        session.wait_for_exit()

        output = session.all_occurrences_of(
            Event('output', ANY.dict_with({'category': 'stdout'})))
        output = sorted(
            int(o.body['output'].strip()) for o in output
            if len(o.body['output'].strip()) > 0)
        assert list(range(0, 10)) == output
示例#23
0
def test_debug_this_thread(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()

        import platform
        import ptvsd
        import threading

        def foo(x):
            ptvsd.debug_this_thread()
            event.set()  #@bp
            return 0

        event = threading.Event()

        if platform.system() == 'Windows':
            from ctypes import CFUNCTYPE, c_void_p, c_size_t, c_uint32, windll
            thread_func_p = CFUNCTYPE(c_uint32, c_void_p)
            thread_func = thread_func_p(
                foo)  # must hold a reference to wrapper during the call
            assert windll.kernel32.CreateThread(c_void_p(0), c_size_t(0),
                                                thread_func, c_void_p(0),
                                                c_uint32(0), c_void_p(0))
        elif platform.system() == 'Linux' or platform.system() == 'Darwin':
            from ctypes import CDLL, CFUNCTYPE, byref, c_void_p, c_ulong
            from ctypes.util import find_library
            libpthread = CDLL(find_library('libpthread'))
            thread_func_p = CFUNCTYPE(c_void_p, c_void_p)
            thread_func = thread_func_p(
                foo)  # must hold a reference to wrapper during the call
            assert not libpthread.pthread_create(byref(
                c_ulong(0)), c_void_p(0), thread_func, c_void_p(0))
        else:
            assert False

        event.wait()

    line_numbers = get_marked_line_numbers(code_to_debug)

    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )
        session.set_breakpoints(code_to_debug, [line_numbers['bp']])
        session.start_debugging()

        session.wait_for_thread_stopped()
        session.send_request('continue').wait_for_response()
        session.wait_for_exit()
示例#24
0
def test_run(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        import os
        import sys
        import backchannel
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()

        print('begin')
        assert backchannel.read_json() == 'continue'
        backchannel.write_json(os.path.abspath(sys.modules['ptvsd'].__file__))
        print('end')

    with DebugSession() as session:
        session.initialize(target=(run_as, code_to_debug),
                           start_method=start_method,
                           use_backchannel=True)
        session.start_debugging()
        assert session.timeline.is_frozen

        process_event, = session.all_occurrences_of(Event('process'))
        assert process_event == Event(
            'process',
            ANY.dict_with({
                'name':
                ANY if run_as == 'code' else ANY.such_that(lambda name: (
                    # There can be a difference in file extension (.py/.pyc/.pyo) on clean runs.
                    name == code_to_debug or name == code_to_debug + 'c' or
                    name == code_to_debug + 'o')),
            }))

        session.write_json('continue')
        ptvsd_path = session.read_json()
        expected_ptvsd_path = os.path.abspath(ptvsd.__file__)
        assert (ptvsd_path == expected_ptvsd_path
                or ptvsd_path == expected_ptvsd_path + 'c'
                or ptvsd_path == expected_ptvsd_path + 'o')

        session.wait_for_exit()
示例#25
0
def test_completions_cases(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        a = 1
        b = {"one": 1, "two": 2}
        c = 3
        print([a, b, c])

    bp_line = 6
    bp_file = code_to_debug

    with DebugSession() as session:
        session.initialize(
            target=(run_as, bp_file),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )
        session.set_breakpoints(bp_file, [bp_line])
        session.start_debugging()
        hit = session.wait_for_thread_stopped()

        response = session.send_request('completions', arguments={
            'frameId': hit.frame_id,
            'text': 'b.',
            'column': 3,
        }).wait_for_response()

        labels = set(target['label'] for target in response.body['targets'])
        assert labels.issuperset(['get', 'items', 'keys', 'setdefault', 'update', 'values'])

        response = session.send_request('completions', arguments={
            'frameId': hit.frame_id,
            'text': 'x = b.setdefault',
            'column': 13,
        }).wait_for_response()

        assert response.body['targets'] == [
            {'label': 'setdefault', 'length': 6, 'start': 6, 'type': 'function'}]

        response = session.send_request('completions', arguments={
            'frameId': hit.frame_id,
            'text': 'not_there',
            'column': 10,
        }).wait_for_response()

        assert not response.body['targets']

        session.send_request('continue').wait_for_response(freeze=False)
        session.wait_for_exit()
示例#26
0
def test_justmycode_frames(pyfile, run_as, start_method, jmc):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        print('break here')  #@bp

    line_numbers = get_marked_line_numbers(code_to_debug)
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
            debug_options=[] if jmc == 'jmcOn' else ['DebugStdLib'])

        bp_line = line_numbers['bp']

        actual_bps = session.set_breakpoints(code_to_debug, [bp_line])
        actual_bps = [bp['line'] for bp in actual_bps]
        session.start_debugging()

        hit = session.wait_for_thread_stopped()
        frames = hit.stacktrace.body['stackFrames']
        assert frames[0] == ANY.dict_with({
            'line':
            bp_line,
            'source':
            ANY.dict_with({'path': Path(code_to_debug)})
        })

        if jmc == 'jmcOn':
            assert len(frames) == 1
            session.send_request('stepIn', {
                'threadId': hit.thread_id
            }).wait_for_response()
            # 'step' should terminate the debuggee
        else:
            assert len(frames) >= 1
            session.send_request('stepIn', {
                'threadId': hit.thread_id
            }).wait_for_response()

            # 'step' should enter stdlib
            hit2 = session.wait_for_thread_stopped()
            frames2 = hit2.stacktrace.body['stackFrames']
            assert frames2[0]['source']['path'] != Path(code_to_debug)

            # 'continue' should terminate the debuggee
            session.send_request('continue').wait_for_response(freeze=False)

        session.wait_for_exit()
示例#27
0
def test_stack_format(pyfile, run_as, start_method, module, line):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()
        from test_module import do_something
        do_something()

    @pyfile
    def test_module():
        # import_and_enable_debugger()
        def do_something():
            print('break here')

    bp_line = 3
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('stopped'), Event('continued')],
        )
        session.set_breakpoints(test_module, [bp_line])
        session.start_debugging()

        hit = session.wait_for_thread_stopped()
        resp_stacktrace = session.send_request('stackTrace', arguments={
            'threadId': hit.thread_id,
            'format': {'module': module, 'line': line},
        }).wait_for_response()
        assert resp_stacktrace.body['totalFrames'] > 0
        frames = resp_stacktrace.body['stackFrames']

        assert line == (frames[0]['name'].find(': ' + str(bp_line)) > -1)

        assert module == (frames[0]['name'].find('test_module') > -1)

        session.send_request('continue').wait_for_response(freeze=False)
        session.wait_for_exit()
示例#28
0
def test_run(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        import os
        import sys
        import backchannel
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()

        print('begin')
        assert backchannel.read_json() == 'continue'
        backchannel.write_json(os.path.abspath(sys.modules['ptvsd'].__file__))
        print('end')

    with DebugSession() as session:
        session.initialize(target=(run_as, code_to_debug),
                           start_method=start_method,
                           use_backchannel=True)
        session.start_debugging()
        assert session.timeline.is_frozen

        process_event, = session.all_occurrences_of(Event('process'))
        assert process_event == Event(
            'process',
            ANY.dict_with({
                'name':
                '-c' if run_as == 'code' else
                Regex(re.escape(code_to_debug) + r'(c|o)?$')
            }))

        session.write_json('continue')
        ptvsd_path = session.read_json()
        expected_ptvsd_path = os.path.abspath(ptvsd.__file__)
        assert re.match(
            re.escape(expected_ptvsd_path) + r'(c|o)?$', ptvsd_path)

        session.wait_for_exit()
示例#29
0
def test_exceptions_and_exclude_rules(pyfile, run_as, start_method, scenario, exception_type):

    if exception_type == 'RuntimeError':

        @pyfile
        def code_to_debug():
            from dbgimporter import import_and_enable_debugger
            import_and_enable_debugger()
            raise RuntimeError('unhandled error')  # @raise_line

    elif exception_type == 'SysExit':

        @pyfile
        def code_to_debug():
            from dbgimporter import import_and_enable_debugger
            import sys
            import_and_enable_debugger()
            sys.exit(1)  # @raise_line

    else:
        raise AssertionError('Unexpected exception_type: %s' % (exception_type,))

    if scenario == 'exclude_by_name':
        rules = [{'path': '**/' + os.path.basename(code_to_debug), 'include': False}]
    elif scenario == 'exclude_by_dir':
        rules = [{'path': os.path.dirname(code_to_debug), 'include': False}]
    else:
        raise AssertionError('Unexpected scenario: %s' % (scenario,))

    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
            rules=rules,
        )
        # TODO: The process returncode doesn't match the one returned from the DAP.
        # See: https://github.com/Microsoft/ptvsd/issues/1278
        session.expected_returncode = ANY.int
        filters = ['raised', 'uncaught']

        session.send_request('setExceptionBreakpoints', {
            'filters': filters
        }).wait_for_response()
        session.start_debugging()

        # No exceptions should be seen.
        session.wait_for_exit()
示例#30
0
def test_deep_stacks(pyfile, run_as, start_method):
    @pyfile
    def code_to_debug():
        from dbgimporter import import_and_enable_debugger
        import_and_enable_debugger()

        def deep_stack(level):
            if level <= 0:
                print('done')  #@bp
                return level
            deep_stack(level - 1)
        deep_stack(100)

    line_numbers = get_marked_line_numbers(code_to_debug)
    with DebugSession() as session:
        session.initialize(
            target=(run_as, code_to_debug),
            start_method=start_method,
            ignore_unobserved=[Event('continued')],
        )

        bp_line = line_numbers['bp']

        actual_bps = session.set_breakpoints(code_to_debug, [bp_line])
        actual_bps = [bp['line'] for bp in actual_bps]
        session.start_debugging()

        hit = session.wait_for_thread_stopped()
        full_frames = hit.stacktrace.body['stackFrames']
        assert len(full_frames) > 100

        # Construct stack from parts
        frames = []
        start = 0
        for _ in range(5):
            resp_stacktrace = session.send_request('stackTrace', arguments={
                'threadId': hit.thread_id,
                'startFrame': start,
                'levels': 25
            }).wait_for_response()
            assert resp_stacktrace.body['totalFrames'] > 0
            frames += resp_stacktrace.body['stackFrames']
            start = len(frames)

        assert full_frames == frames

        session.send_request('continue').wait_for_response()
        session.wait_for_exit()