Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ npm-debug.log
coverage/
.vscode-test/**
.venv
pythonFiles/experimental/ptvsd/**
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ before_install: |
export TRAVIS_PYTHON_PATH=`which python`
install:
- pip install --upgrade -r requirements.txt
- pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/
- yarn

script:
Expand All @@ -33,6 +34,7 @@ script:
- if [ $TRAVIS_UPLOAD_COVERAGE == "true" ]; then
bash <(curl -s https://codecov.io/bash);
fi
- rm -rf ./pythonFiles/experimental/ptvsd
- yarn run clean
- yarn run vscode:prepublish
- yarn run cover:enable
Expand Down
1 change: 1 addition & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ install:
- yarn
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- pip install -U pip
- pip install -t ./pythonFiles/experimental/ptvsd git+https://github.com/Microsoft/ptvsd/
- python --version
- python -m easy_install -U setuptools
- "%PYTHON%/Scripts/pip.exe install --upgrade -r requirements.txt"
Expand Down
1 change: 1 addition & 0 deletions news/3 Code Health/742.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enable unit testing of the experimental debugger on CI servers
4 changes: 3 additions & 1 deletion src/client/common/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

import * as path from 'path';
export const PythonLanguage = { language: 'python' };

export namespace Commands {
Expand Down Expand Up @@ -69,3 +69,5 @@ export function isTestExecution(): boolean {
// tslint:disable-next-line:interface-name no-string-literal
return process.env['VSC_PYTHON_CI_TEST'] === '1';
}

export const EXTENSION_ROOT_DIR = path.join(__dirname, '..', '..', '..');
9 changes: 8 additions & 1 deletion src/client/debugger/DebugClients/LocalDebugClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ChildProcess } from 'child_process';
import * as path from 'path';
import { DebugSession, OutputEvent } from 'vscode-debugadapter';
import { DebugProtocol } from 'vscode-debugprotocol';
import { EXTENSION_ROOT_DIR } from '../../common/constants';
import { open } from '../../common/open';
import { PathUtils } from '../../common/platform/pathUtils';
import { CurrentProcess } from '../../common/process/currentProcess';
Expand Down Expand Up @@ -82,8 +83,14 @@ export class LocalDebugClient extends DebugClient<LaunchRequestArguments> {
public async LaunchApplicationToDebug(dbgServer: IDebugServer): Promise<any> {
const pathUtils = new PathUtils(IS_WINDOWS);
const currentProcess = new CurrentProcess();
const helper = new DebugClientHelper(new EnvironmentVariablesService(pathUtils), pathUtils, currentProcess);
const environmentVariablesService = new EnvironmentVariablesService(pathUtils);
const helper = new DebugClientHelper(environmentVariablesService, pathUtils, currentProcess);
const environmentVariables = await helper.getEnvironmentVariables(this.args);
if (this.args.type === 'pythonExperimental') {
// Import the PTVSD debugger, allowing users to use their own latest copies.
const experimentalPTVSDPath = path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'experimental', 'ptvsd');
environmentVariablesService.appendPythonPath(environmentVariables, experimentalPTVSDPath);
}
// tslint:disable-next-line:max-func-body-length cyclomatic-complexity no-any
return new Promise<any>((resolve, reject) => {
const fileDir = this.args && this.args.program ? path.dirname(this.args.program) : '';
Expand Down
70 changes: 38 additions & 32 deletions src/test/debugger/misc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import * as path from 'path';
import { ThreadEvent } from 'vscode-debugadapter';
import { DebugClient } from 'vscode-debugadapter-testsupport';
import { DebugProtocol } from 'vscode-debugprotocol';
import { noop } from '../../client/common/core.utils';
import { LaunchRequestArguments } from '../../client/debugger/Common/Contracts';
import { sleep } from '../common';
import { IS_CI_SERVER, IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize';
import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize';

const isProcessRunning = require('is-running') as (number) => boolean;

Expand All @@ -34,10 +35,6 @@ const THREAD_TIMEOUT = 10000;
if (!IS_MULTI_ROOT_TEST || !TEST_DEBUGGER) {
this.skip();
}
// Temporary, untill new version of PTVSD is bundled we cannot run tests
if (debuggerType !== 'python' && IS_CI_SERVER) {
return this.skip();
}
await new Promise(resolve => setTimeout(resolve, 1000));
debugClient = new DebugClient('node', testAdapterFilePath, debuggerType);
await debugClient.start();
Expand All @@ -46,26 +43,20 @@ const THREAD_TIMEOUT = 10000;
// Wait for a second before starting another test (sometimes, sockets take a while to get closed).
await sleep(1000);
try {
// tslint:disable-next-line:no-empty
await debugClient.stop().catch(() => { });
await debugClient.stop().catch(noop);
// tslint:disable-next-line:no-empty
} catch (ex) { }
await sleep(1000);
});

function buildLauncArgs(pythonFile: string, stopOnEntry: boolean = false): LaunchRequestArguments {
// Temporary, untill new version of PTVSD is bundled we cannot run tests.
// For now lets run test locally.
const pythonPath = debuggerType === 'python' ? 'python' : '/Users/donjayamanne/Desktop/Development/PythonStuff/IssueRepos/debuggerTests/.envp36/bin/python';
const env = debuggerType === 'python' ? {} : { PYTHONPATH: '/Users/donjayamanne/Desktop/Development/PythonStuff/IssueRepos/expPTVSD/ptvsd' };
return {
program: path.join(debugFilesPath, pythonFile),
cwd: debugFilesPath,
stopOnEntry,
debugOptions: ['RedirectOutput'],
pythonPath,
pythonPath: 'python',
args: [],
env,
env: {},
envFile: '',
logToFile: false,
type: debuggerType
Expand Down Expand Up @@ -325,17 +316,23 @@ const THREAD_TIMEOUT = 10000;
const threadId = ((await threadIdPromise) as ThreadEvent).body.threadId;
await debugClient.assertStoppedLocation('breakpoint', breakpointLocation);

await debugClient.nextRequest({ threadId });
const functionLocation = { path: path.join(debugFilesPath, 'sample2.py'), column: 1, line: 7 };
await debugClient.assertStoppedLocation('step', functionLocation);
await Promise.all([
debugClient.nextRequest({ threadId }),
debugClient.assertStoppedLocation('step', functionLocation)
]);

await debugClient.nextRequest({ threadId });
const functionInvocationLocation = { path: path.join(debugFilesPath, 'sample2.py'), column: 1, line: 11 };
await debugClient.assertStoppedLocation('step', functionInvocationLocation);
await Promise.all([
debugClient.nextRequest({ threadId }),
debugClient.assertStoppedLocation('step', functionInvocationLocation)
]);

await debugClient.nextRequest({ threadId });
const printLocation = { path: path.join(debugFilesPath, 'sample2.py'), column: 1, line: 13 };
await debugClient.assertStoppedLocation('step', printLocation);
await Promise.all([
debugClient.nextRequest({ threadId }),
debugClient.assertStoppedLocation('step', printLocation)
]);
});
test('Test stepin and stepout', async () => {
const threadIdPromise = debugClient.waitForEvent('thread', THREAD_TIMEOUT);
Expand All @@ -357,28 +354,37 @@ const THREAD_TIMEOUT = 10000;
await debugClient.assertStoppedLocation('breakpoint', breakpointLocation);
const threadId = ((await threadIdPromise) as ThreadEvent).body.threadId;

await debugClient.nextRequest({ threadId });
const functionLocation = { path: path.join(debugFilesPath, 'sample2.py'), column: 1, line: 7 };
await debugClient.assertStoppedLocation('step', functionLocation);
await Promise.all([
debugClient.nextRequest({ threadId }),
debugClient.assertStoppedLocation('step', functionLocation)
]);

await debugClient.nextRequest({ threadId });
const functionInvocationLocation = { path: path.join(debugFilesPath, 'sample2.py'), column: 1, line: 11 };
await debugClient.assertStoppedLocation('step', functionInvocationLocation);
await Promise.all([
debugClient.nextRequest({ threadId }),
debugClient.assertStoppedLocation('step', functionInvocationLocation)
]);

await debugClient.stepInRequest({ threadId });
const loopPrintLocation = { path: path.join(debugFilesPath, 'sample2.py'), column: 1, line: 8 };
await debugClient.assertStoppedLocation('step', loopPrintLocation);
await Promise.all([
debugClient.stepInRequest({ threadId }),
debugClient.assertStoppedLocation('step', loopPrintLocation)
]);

await debugClient.stepOutRequest({ threadId });
await debugClient.assertStoppedLocation('step', functionInvocationLocation);
await Promise.all([
debugClient.stepOutRequest({ threadId }),
debugClient.assertStoppedLocation('step', functionInvocationLocation)
]);

await debugClient.nextRequest({ threadId });
const printLocation = { path: path.join(debugFilesPath, 'sample2.py'), column: 1, line: 13 };
await debugClient.assertStoppedLocation('step', printLocation);
await Promise.all([
debugClient.nextRequest({ threadId }),
debugClient.assertStoppedLocation('step', printLocation)
]);
});
test('Test pausing', async function () {
// TODO: re-enable for new debugger once it's running on CI
if (debuggerType !== 'pythonExperimental' || IS_CI_SERVER) {
if (debuggerType !== 'pythonExperimental') {
return this.skip();
}

Expand Down
12 changes: 3 additions & 9 deletions src/test/debugger/portAndHost.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as getFreePort from 'get-port';
import * as net from 'net';
import * as path from 'path';
import { DebugClient } from 'vscode-debugadapter-testsupport';
import { noop } from '../../client/common/core.utils';
import { LaunchRequestArguments } from '../../client/debugger/Common/Contracts';
import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize';

Expand All @@ -28,10 +29,6 @@ const EXPERIMENTAL_DEBUG_ADAPTER = path.join(__dirname, '..', '..', 'client', 'd
// tslint:disable-next-line:no-invalid-this
this.skip();
}
if (debuggerType !== 'python') {
// tslint:disable-next-line:no-invalid-this
return this.skip();
}
await new Promise(resolve => setTimeout(resolve, 1000));
debugClient = new DebugClient('node', testAdapterFilePath, debuggerType);
await debugClient.start();
Expand All @@ -40,14 +37,12 @@ const EXPERIMENTAL_DEBUG_ADAPTER = path.join(__dirname, '..', '..', 'client', 'd
// Wait for a second before starting another test (sometimes, sockets take a while to get closed).
await new Promise(resolve => setTimeout(resolve, 1000));
try {
// tslint:disable-next-line:no-empty
debugClient.stop().catch(() => { });
debugClient.stop().catch(noop);
// tslint:disable-next-line:no-empty
} catch (ex) { }
});

function buildLauncArgs(pythonFile: string, stopOnEntry: boolean = false, port?: number, host?: string): LaunchRequestArguments {
// pythonPath: '/Users/donjayamanne/anaconda3/envs/py36/bin/python',
return {
program: path.join(debugFilesPath, pythonFile),
cwd: debugFilesPath,
Expand Down Expand Up @@ -103,8 +98,7 @@ const EXPERIMENTAL_DEBUG_ADAPTER = path.join(__dirname, '..', '..', 'client', 'd
expect(exception!.message).contains('ENOTFOUND', 'Debugging failed for some other reason');
});
test('Confirm debuggig fails when provided port is in use', async () => {
// tslint:disable-next-line:no-empty
const server = net.createServer((s) => { });
const server = net.createServer(noop);
const port = await new Promise<number>((resolve, reject) => server.listen({ host: 'localhost', port: 0 }, () => resolve(server.address().port)));
let exception: Error | undefined;
try {
Expand Down