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()
def test_exception_stack(pyfile, run_as, start_method, max_frames): @pyfile def code_to_debug(): from dbgimporter import import_and_enable_debugger import_and_enable_debugger() def do_something(n): if n <= 0: raise ArithmeticError('bad code') # @unhandled do_something2(n - 1) def do_something2(n): do_something(n - 1) do_something(100) if max_frames == 'all': # trace back compresses repeated text min_expected_lines = 100 max_expected_lines = 220 args = {'maxExceptionStackFrames': 0} elif max_frames == 'default': # default is all frames min_expected_lines = 100 max_expected_lines = 220 args = {} else: min_expected_lines = 10 max_expected_lines = 21 args = {'maxExceptionStackFrames': 10} 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')], expected_returncode=ANY.int, args=args, ) session.send_request('setExceptionBreakpoints', { 'filters': ['uncaught'] }).wait_for_response() session.start_debugging() hit = session.wait_for_thread_stopped(reason='exception') frames = hit.stacktrace.body['stackFrames'] assert frames[0]['line'] == line_numbers['unhandled'] resp_exc_info = session.send_request('exceptionInfo', { 'threadId': hit.thread_id }).wait_for_response() expected = ANY.dict_with({ 'exceptionId': Regex('ArithmeticError'), 'description': 'bad code', 'breakMode': 'unhandled', 'details': ANY.dict_with({ 'typeName': Regex('ArithmeticError'), 'message': 'bad code', 'source': Path(code_to_debug), }), }) assert resp_exc_info.body == expected stack_str = resp_exc_info.body['details']['stackTrace'] stack_line_count = len(stack_str.split('\n')) assert min_expected_lines <= stack_line_count <= max_expected_lines session.send_request('continue').wait_for_response(freeze=False) session.wait_for_exit()