def test_run_submodule(): cwd = get_test_root('testpkgs') with DebugSession() as session: session.initialize( target=('module', 'pkg1.sub'), start_method='launch', cwd=cwd, ) session.start_debugging() session.wait_for_next( Event('output', ANY.dict_with({ 'category': 'stdout', 'output': 'three' }))) session.wait_for_exit()
def test_attach(run_as, wait_for_attach, is_attached, break_into): testfile = os.path.join(get_test_root('attach'), 'attach1.py') with DebugSession() as session: env = { 'PTVSD_TEST_HOST': 'localhost', 'PTVSD_TEST_PORT': str(session.ptvsd_port), } if wait_for_attach == 'waitOn': env['PTVSD_WAIT_FOR_ATTACH'] = '1' if is_attached == 'attachCheckOn': env['PTVSD_IS_ATTACHED'] = '1' if break_into == 'break': env['PTVSD_BREAK_INTO_DBG'] = '1' session.initialize( target=(run_as, testfile), start_method='launch', ignore_unobserved=[Event('continued')], env=env, use_backchannel=True, ) session.start_debugging() if wait_for_attach == 'waitOn': assert session.read_json() == 'wait_for_attach' if is_attached == 'attachCheckOn': assert session.read_json() == 'is_attached' if break_into == 'break': assert session.read_json() == 'break_into_debugger' hit = session.wait_for_thread_stopped() frames = hit.stacktrace.body['stackFrames'] assert 32 == frames[0]['line'] else: # pause test session.write_json('pause_test') session.send_request('pause').wait_for_response(freeze=False) hit = session.wait_for_thread_stopped(reason='pause') frames = hit.stacktrace.body['stackFrames'] # Note: no longer asserting line as it can even stop on different files # (such as as backchannel.py). # assert frames[0]['line'] in [27, 28, 29] session.send_request('continue').wait_for_response(freeze=False) session.wait_for_exit()
def test_package_launch(): bp_line = 2 cwd = get_test_root('testpkgs') testfile = os.path.join(cwd, 'pkg1', '__main__.py') with DebugSession() as session: session.initialize( target=('module', 'pkg1'), start_method='launch', cwd=cwd, ) session.set_breakpoints(testfile, [bp_line]) session.start_debugging() hit = session.wait_for_thread_stopped() frames = hit.stacktrace.body['stackFrames'] assert bp_line == frames[0]['line'] session.send_request('continue').wait_for_response(freeze=False) session.wait_for_exit()
def test_exceptions_and_partial_exclude_rules(pyfile, run_as, start_method, scenario): @pyfile def code_to_debug(): from dbgimporter import import_and_enable_debugger import_and_enable_debugger() import backchannel import sys json = backchannel.read_json() call_me_back_dir = json['call_me_back_dir'] sys.path.append(call_me_back_dir) import call_me_back def call_func(): raise RuntimeError('unhandled error') # @raise_line call_me_back.call_me_back(call_func) # @call_me_back_line print('done') line_numbers = get_marked_line_numbers(code_to_debug) call_me_back_dir = get_test_root('call_me_back') if scenario == 'exclude_code_to_debug': rules = [{ 'path': '**/' + os.path.basename(code_to_debug), 'include': False }] elif scenario == 'exclude_callback_dir': rules = [{'path': call_me_back_dir, '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, use_backchannel=True, 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() if scenario == 'exclude_code_to_debug': breakpoints = session.set_breakpoints(code_to_debug, [1]) assert breakpoints == [{ 'verified': False, 'message': ('Breakpoint in file excluded by filters.\n' 'Note: may be excluded because of "justMyCode" option (default == true).' ), 'source': ANY.dict_with({'path': Path(code_to_debug)}), 'line': 1 }] session.start_debugging() session.write_json({'call_me_back_dir': call_me_back_dir}) if scenario == 'exclude_code_to_debug': # Stop at handled hit = session.wait_for_thread_stopped(reason='exception') frames = hit.stacktrace.body['stackFrames'] # We don't stop at the raise line but rather at the callback module which is # not excluded. assert len(frames) == 1 assert frames[0] == ANY.dict_with({ 'line': 2, 'source': ANY.dict_with({ 'path': Path(os.path.join(call_me_back_dir, 'call_me_back.py')) }) }) # assert frames[1] == ANY.dict_with({ -- filtered out # 'line': line_numbers['call_me_back_line'], # 'source': ANY.dict_with({ # 'path': Path(code_to_debug) # }) # }) # 'continue' should terminate the debuggee session.send_request('continue').wait_for_response(freeze=False) # Note: does not stop at unhandled exception because raise was in excluded file. elif scenario == 'exclude_callback_dir': # Stop at handled raise_line hit = session.wait_for_thread_stopped(reason='exception') frames = hit.stacktrace.body['stackFrames'] assert [(frame['name'], basename(frame['source']['path'])) for frame in frames] == [ ('call_func', 'code_to_debug.py'), # ('call_me_back', 'call_me_back.py'), -- filtered out ('<module>', 'code_to_debug.py'), ] assert frames[0] == ANY.dict_with({ 'line': line_numbers['raise_line'], 'source': ANY.dict_with({'path': Path(code_to_debug)}) }) session.send_request('continue').wait_for_response() # Stop at handled call_me_back_line hit = session.wait_for_thread_stopped(reason='exception') frames = hit.stacktrace.body['stackFrames'] assert [(frame['name'], basename(frame['source']['path'])) for frame in frames] == [ ('<module>', 'code_to_debug.py'), ] assert frames[0] == ANY.dict_with({ 'line': line_numbers['call_me_back_line'], 'source': ANY.dict_with({'path': Path(code_to_debug)}) }) session.send_request('continue').wait_for_response() # Stop at unhandled hit = session.wait_for_thread_stopped(reason='exception') frames = hit.stacktrace.body['stackFrames'] assert [(frame['name'], basename(frame['source']['path'])) for frame in frames] == [ ('call_func', 'code_to_debug.py'), # ('call_me_back', 'call_me_back.py'), -- filtered out ('<module>', 'code_to_debug.py'), ] assert frames[0] == ANY.dict_with({ 'line': line_numbers['raise_line'], 'source': ANY.dict_with({'path': Path(code_to_debug)}) }) session.send_request('continue').wait_for_response(freeze=False) else: raise AssertionError('Unexpected scenario: %s' % (scenario, )) session.wait_for_exit()
# Licensed under the MIT License. See LICENSE in the project root # for license information. from __future__ import print_function, with_statement, absolute_import import os.path import pytest import sys import re from tests.helpers.pathutils import get_test_root from tests.helpers.session import DebugSession from tests.helpers.timeline import Event from tests.helpers.pattern import ANY, Path BP_TEST_ROOT = get_test_root('bp') def test_path_with_ampersand(run_as, start_method): bp_line = 4 testfile = os.path.join(BP_TEST_ROOT, 'a&b', 'test.py') with DebugSession() as session: session.initialize( target=(run_as, testfile), start_method=start_method, ignore_unobserved=[Event('continued')], ) session.set_breakpoints(testfile, [bp_line]) session.start_debugging() hit = session.wait_for_thread_stopped('breakpoint')
def test_with_path_mappings(pyfile, tmpdir, run_as, start_method): @pyfile def code_to_debug(): from dbgimporter import import_and_enable_debugger import_and_enable_debugger() import os import sys import backchannel json = backchannel.read_json() call_me_back_dir = json['call_me_back_dir'] sys.path.append(call_me_back_dir) import call_me_back def call_func(): print('break here') backchannel.write_json(os.path.abspath(__file__)) call_me_back.call_me_back(call_func) print('done') bp_line = 13 path_local = tmpdir.mkdir('local').join('code_to_debug.py').strpath path_remote = tmpdir.mkdir('remote').join('code_to_debug.py').strpath dir_local = os.path.dirname(path_local) dir_remote = os.path.dirname(path_remote) copyfile(code_to_debug, path_local) copyfile(code_to_debug, path_remote) call_me_back_dir = get_test_root('call_me_back') with DebugSession() as session: session.initialize( target=(run_as, path_remote), start_method=start_method, use_backchannel=True, path_mappings=[{ 'localRoot': dir_local, 'remoteRoot': dir_remote, }], ) session.set_breakpoints(path_remote, [bp_line]) session.start_debugging() session.write_json({'call_me_back_dir': call_me_back_dir}) hit = session.wait_for_thread_stopped('breakpoint') frames = hit.stacktrace.body['stackFrames'] assert frames[0]['source']['path'] == Path(path_local) source_reference = frames[0]['source']['sourceReference'] assert source_reference == 0 # Mapped files should be found locally. assert frames[1]['source']['path'].endswith('call_me_back.py') source_reference = frames[1]['source']['sourceReference'] assert source_reference > 0 # Unmapped file should have a source reference. resp_variables = session.send_request('source', arguments={ 'sourceReference': source_reference }).wait_for_response() assert "def call_me_back(callback):" in ( resp_variables.body['content']) remote_code_path = session.read_json() assert path_remote == Path(remote_code_path) session.send_request('continue').wait_for_response(freeze=False) session.wait_for_exit()
from __future__ import print_function, with_statement, absolute_import import os.path import platform import pytest import sys import tests.helpers from tests.helpers.pattern import ANY, Path from tests.helpers.session import DebugSession from tests.helpers.timeline import Event from tests.helpers.webhelper import get_web_content, wait_for_connection from tests.helpers.pathutils import get_test_root FLASK1_ROOT = get_test_root('flask1') FLASK1_APP = os.path.join(FLASK1_ROOT, 'app.py') FLASK1_TEMPLATE = os.path.join(FLASK1_ROOT, 'templates', 'hello.html') FLASK1_BAD_TEMPLATE = os.path.join(FLASK1_ROOT, 'templates', 'bad.html') FLASK_PORT = tests.helpers.get_unique_port(5000) FLASK_LINK = 'http://127.0.0.1:{}/'.format(FLASK_PORT) 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(
# Licensed under the MIT License. See LICENSE in the project root # for license information. from __future__ import print_function, with_statement, absolute_import import os.path import pytest import tests.helpers from tests.helpers.pattern import ANY, Path from tests.helpers.session import DebugSession from tests.helpers.timeline import Event from tests.helpers.pathutils import get_test_root from tests.helpers.webhelper import get_url_from_str, get_web_content, wait_for_connection DJANGO1_ROOT = get_test_root('django1') DJANGO1_MANAGE = os.path.join(DJANGO1_ROOT, 'app.py') DJANGO1_TEMPLATE = os.path.join(DJANGO1_ROOT, 'templates', 'hello.html') DJANGO1_BAD_TEMPLATE = os.path.join(DJANGO1_ROOT, 'templates', 'bad.html') DJANGO_PORT = tests.helpers.get_unique_port(8000) DJANGO_LINK = 'http://127.0.0.1:{}/'.format(DJANGO_PORT) @pytest.mark.parametrize('bp_target', ['code', 'template']) @pytest.mark.parametrize('start_method', ['launch', 'attach_socket_cmdline']) @pytest.mark.timeout(60) def test_django_breakpoint_no_multiproc(bp_target, start_method): bp_file, bp_line, bp_name = { 'code': (DJANGO1_MANAGE, 40, 'home'), 'template': (DJANGO1_TEMPLATE, 8, 'Django Template'), }[bp_target]