Skip to content

Commit be2ae45

Browse files
authored
Fix debugger adapter capabilities test (microsoft#2659)
For microsoft#2658 <!-- If an item below does not apply to you, then go ahead and check it off as "done" and strikethrough the text, e.g.: - [x] ~Has unit tests & system/integration tests~ --> - [x] Pull request represents a single change (i.e. not fixing disparate/unrelated things in a single PR) - [x] Title summarizes what is changing - [x] Has a [news entry](https://github.com/Microsoft/vscode-python/tree/master/news) file (remember to thank yourself!) - [x] Has unit tests & system/integration tests - [n/a] Any new/changed dependencies in [`package.json`](https://github.com/Microsoft/vscode-python/blob/master/package.json) are pinned (e.g. `"1.2.3"`, not `"^1.2.3"` for the specified version) - [n/a] [`package-lock.json`](https://github.com/Microsoft/vscode-python/blob/master/package-lock.json) has been regenerated by running `npm install` (if dependencies have changed)
1 parent bfcd225 commit be2ae45

4 files changed

Lines changed: 111 additions & 62 deletions

File tree

.vscode/launch.json

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.1.0",
44
"configurations": [
55
{
6-
"name": "Launch Extension",
6+
"name": "Extension",
77
"type": "extensionHost",
88
"request": "launch",
99
"runtimeExecutable": "${execPath}",
@@ -19,7 +19,7 @@
1919
"preLaunchTask": "Compile"
2020
},
2121
{
22-
"name": "Launch Debugger as debugServer", // https://code.visualstudio.com/docs/extensions/example-debuggers
22+
"name": "Debugger as debugServer",
2323
"type": "node",
2424
"request": "launch",
2525
"program": "${workspaceFolder}/out/client/debugger/mainV2.js",
@@ -36,40 +36,45 @@
3636
"preLaunchTask": "Compile"
3737
},
3838
{
39-
"name": "Launch Tests",
39+
"name": "Tests (Debugger, VS Code, *.test.ts)",
4040
"type": "extensionHost",
4141
"request": "launch",
4242
"runtimeExecutable": "${execPath}",
4343
"args": [
44-
"${workspaceFolder}/src/test",
44+
"${workspaceFolder}/src/testMultiRootWkspc/multi.code-workspace",
4545
"--extensionDevelopmentPath=${workspaceFolder}",
4646
"--extensionTestsPath=${workspaceFolder}/out/test"
4747
],
4848
"stopOnEntry": false,
4949
"sourceMaps": true,
50+
"smartStep": true,
5051
"outFiles": [
51-
"${workspaceFolder}/out/**/*.js"
52+
"${workspaceFolder}/out/**/*"
5253
],
53-
"preLaunchTask": "Compile"
54+
"preLaunchTask": "Compile",
55+
"env": {
56+
"IS_CI_SERVER_TEST_DEBUGGER": "1"
57+
}
5458
},
5559
{
56-
"name": "Debug Unit Tests",
57-
"type": "node",
60+
"name": "Tests (Sigle Workspace, VS Code, *.test.ts)",
61+
"type": "extensionHost",
5862
"request": "launch",
59-
"program": "${workspaceFolder}/out/test/unittests.js",
60-
"stopOnEntry": false,
61-
"sourceMaps": true,
63+
"runtimeExecutable": "${execPath}",
6264
"args": [
63-
"timeout=60000",
64-
"grep="
65+
"${workspaceFolder}/src/test",
66+
"--extensionDevelopmentPath=${workspaceFolder}",
67+
"--extensionTestsPath=${workspaceFolder}/out/test"
6568
],
69+
"stopOnEntry": false,
70+
"sourceMaps": true,
6671
"outFiles": [
6772
"${workspaceFolder}/out/**/*.js"
6873
],
6974
"preLaunchTask": "Compile"
7075
},
7176
{
72-
"name": "Launch Multiroot Tests",
77+
"name": "Tests (Multiroot, VS Code, *.test.ts)",
7378
"type": "extensionHost",
7479
"request": "launch",
7580
"runtimeExecutable": "${execPath}",
@@ -87,7 +92,7 @@
8792
"preLaunchTask": "Compile"
8893
},
8994
{
90-
"name": "Launch Language Server Tests",
95+
"name": "Tests (Language Server)",
9196
"type": "extensionHost",
9297
"request": "launch",
9398
"runtimeExecutable": "${execPath}",
@@ -107,7 +112,7 @@
107112
}
108113
},
109114
{
110-
"name": "Launch Tests (with code coverage)",
115+
"name": "Tests (VS Code, with code coverage, *.test.ts)",
111116
"type": "extensionHost",
112117
"request": "launch",
113118
"runtimeExecutable": "${execPath}",
@@ -122,15 +127,31 @@
122127
"outFiles": [
123128
"${workspaceFolder}/out/**/*.js"
124129
]
130+
},
131+
{
132+
"name": "Unit Tests (without VS Ccode, *.unit.test.ts)",
133+
"type": "node",
134+
"request": "launch",
135+
"program": "${workspaceFolder}/out/test/unittests.js",
136+
"stopOnEntry": false,
137+
"sourceMaps": true,
138+
"args": [
139+
"timeout=60000",
140+
"grep="
141+
],
142+
"outFiles": [
143+
"${workspaceFolder}/out/**/*.js"
144+
],
145+
"preLaunchTask": "Compile"
125146
}
126147
],
127148
"compounds": [
128149
{
129150
"name": "Extension + Debugger",
130151
"configurations": [
131-
"Launch Extension",
132-
"Launch Debugger as debugServer"
152+
"Extension",
153+
"Debugger as debugServer"
133154
]
134155
}
135156
]
136-
}
157+
}

src/test/debugger/capabilities.test.ts

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33

44
'use strict';
55

6-
// tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any
6+
// tslint:disable:no-suspicious-comment max-func-body-length no-invalid-this no-var-requires no-require-imports no-any no-object-literal-type-assertion no-banned-terms
77

88
import { expect } from 'chai';
99
import { ChildProcess, spawn } from 'child_process';
1010
import * as getFreePort from 'get-port';
1111
import { Socket } from 'net';
1212
import * as path from 'path';
13-
import { PassThrough } from 'stream';
1413
import { Message } from 'vscode-debugadapter/lib/messages';
1514
import { DebugProtocol } from 'vscode-debugprotocol';
1615
import { EXTENSION_ROOT_DIR } from '../../client/common/constants';
@@ -19,71 +18,79 @@ import { ProtocolParser } from '../../client/debugger/Common/protocolParser';
1918
import { ProtocolMessageWriter } from '../../client/debugger/Common/protocolWriter';
2019
import { PythonDebugger } from '../../client/debugger/mainV2';
2120
import { createDeferred, sleep } from '../../utils/async';
21+
import { noop } from '../../utils/misc';
2222
import { PYTHON_PATH } from '../common';
2323
import { IS_MULTI_ROOT_TEST, TEST_DEBUGGER } from '../initialize';
2424

25-
class Request extends Message implements DebugProtocol.InitializeRequest {
26-
// tslint:disable-next-line:no-banned-terms
27-
public arguments: any;
28-
constructor(public command: string, args: any) {
29-
super('request');
30-
this.arguments = args;
31-
}
32-
}
33-
34-
const fileToDebug = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'remoteDebugger-start-with-ptvsd.py');
25+
const fileToDebug = path.join(EXTENSION_ROOT_DIR, 'src', 'testMultiRootWkspc', 'workspace5', 'remoteDebugger-start-with-ptvsd-nowait.py');
3526

36-
suite('Debugging - Capabilities', () => {
27+
suite('Debugging - Capabilities', function () {
28+
this.timeout(30000);
3729
let disposables: { dispose?: Function; destroy?: Function }[];
3830
let proc: ChildProcess;
39-
setup(async function () {
40-
this.skip();
41-
return;
42-
31+
setup(function () {
32+
return this.skip();
4333
if (!IS_MULTI_ROOT_TEST || !TEST_DEBUGGER) {
4434
this.skip();
4535
}
46-
this.timeout(30000);
4736
disposables = [];
4837
});
4938
teardown(() => {
5039
disposables.forEach(disposable => {
5140
try {
5241
disposable.dispose!();
53-
// tslint:disable-next-line:no-empty
54-
} catch { }
42+
} catch {
43+
noop();
44+
}
5545
try {
5646
disposable.destroy!();
57-
// tslint:disable-next-line:no-empty
58-
} catch { }
47+
} catch {
48+
noop();
49+
}
5950
});
6051
try {
6152
proc.kill();
62-
// tslint:disable-next-line:no-empty
63-
} catch { }
53+
} catch {
54+
noop();
55+
}
6456
});
65-
test('Compare capabilities', async () => {
66-
const protocolWriter = new ProtocolMessageWriter();
67-
const initializeRequest: DebugProtocol.InitializeRequest = new Request('initialize', { pathFormat: 'path' });
57+
function createRequest(cmd: string, requestArgs: any) {
58+
return new class extends Message implements DebugProtocol.InitializeRequest {
59+
public arguments: any;
60+
constructor(public command: string, args: any) {
61+
super('request');
62+
this.arguments = args;
63+
}
64+
}(cmd, requestArgs);
65+
}
66+
function createDebugSession() {
67+
return new class extends PythonDebugger {
68+
constructor() {
69+
super({} as any);
70+
}
6871

69-
const debugClient = new PythonDebugger(undefined as any);
70-
const inStream = new PassThrough();
71-
const outStream = new PassThrough();
72-
disposables.push(inStream);
73-
disposables.push(outStream);
74-
debugClient.start(inStream, outStream);
75-
const debugClientProtocolParser = new ProtocolParser();
76-
debugClientProtocolParser.connect(outStream);
77-
disposables.push(debugClientProtocolParser);
78-
const expectedResponsePromise = new Promise<DebugProtocol.InitializeResponse>(resolve => debugClientProtocolParser.once('response_initialize', resolve));
79-
protocolWriter.write(inStream, initializeRequest);
80-
const expectedResponse = await expectedResponsePromise;
72+
public getInitializeResponseFromDebugAdapter() {
73+
let initializeResponse = {
74+
body: {}
75+
} as DebugProtocol.InitializeResponse;
76+
this.sendResponse = resp => initializeResponse = resp;
8177

78+
this.initializeRequest(initializeResponse, { supportsRunInTerminalRequest: true, adapterID: '' });
79+
return initializeResponse;
80+
}
81+
}();
82+
}
83+
test('Compare capabilities', async () => {
84+
const customDebugger = createDebugSession();
85+
const expectedResponse = customDebugger.getInitializeResponseFromDebugAdapter();
86+
87+
const protocolWriter = new ProtocolMessageWriter();
88+
const initializeRequest: DebugProtocol.InitializeRequest = createRequest('initialize', { pathFormat: 'path' });
8289
const host = 'localhost';
8390
const port = await getFreePort({ host, port: 3000 });
8491
const env = { ...process.env };
8592
env.PYTHONPATH = PTVSD_PATH;
86-
proc = spawn(PYTHON_PATH, ['-m', 'ptvsd', '--server', '--port', `${port}`, '--file', fileToDebug], { cwd: path.dirname(fileToDebug), env });
93+
proc = spawn(PYTHON_PATH, ['-m', 'ptvsd', '--server', '--wait', '--port', `${port}`, '--file', fileToDebug], { cwd: path.dirname(fileToDebug), env });
8794
await sleep(3000);
8895

8996
const connected = createDeferred();
@@ -95,9 +102,29 @@ suite('Debugging - Capabilities', () => {
95102
protocolParser.connect(socket!);
96103
disposables.push(protocolParser);
97104
const actualResponsePromise = new Promise<DebugProtocol.InitializeResponse>(resolve => protocolParser.once('response_initialize', resolve));
98-
protocolWriter.write(socket!, initializeRequest);
105+
protocolWriter.write(socket, initializeRequest);
99106
const actualResponse = await actualResponsePromise;
100107

108+
const attachRequest: DebugProtocol.AttachRequest = createRequest('attach', {
109+
name: 'attach',
110+
request: 'attach',
111+
type: 'python',
112+
port: port,
113+
host: 'localhost',
114+
logToFile: false,
115+
debugOptions: []
116+
});
117+
const attached = new Promise(resolve => protocolParser.once('response_attach', resolve));
118+
protocolWriter.write(socket, attachRequest);
119+
await attached;
120+
121+
const configRequest: DebugProtocol.ConfigurationDoneRequest = createRequest('configurationDone', {});
122+
const configured = new Promise(resolve => protocolParser.once('response_configurationDone', resolve));
123+
protocolWriter.write(socket, configRequest);
124+
await configured;
125+
126+
protocolParser.dispose();
127+
101128
// supportsDebuggerProperties is not documented, most probably a VS specific item.
102129
const body: any = actualResponse.body;
103130
delete body.supportsDebuggerProperties;

src/test/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ if ((Reflect as any).metadata === undefined) {
55
}
66

77
import {
8-
IS_CI_SERVER, IS_CI_SERVER_TEST_DEBUGGER,
8+
IS_CI_SERVER_TEST_DEBUGGER,
99
IS_VSTS, MOCHA_CI_PROPERTIES, MOCHA_CI_REPORTER_ID,
1010
MOCHA_CI_REPORTFILE, MOCHA_REPORTER_JUNIT
1111
} from './ciConstants';
@@ -18,7 +18,7 @@ process.env.IS_MULTI_ROOT_TEST = IS_MULTI_ROOT_TEST.toString();
1818
// If running on CI server and we're running the debugger tests, then ensure we only run debug tests.
1919
// We do this to ensure we only run debugger test, as debugger tests are very flaky on CI.
2020
// So the solution is to run them separately and first on CI.
21-
const grep = IS_CI_SERVER && IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : undefined;
21+
const grep = IS_CI_SERVER_TEST_DEBUGGER ? 'Debug' : undefined;
2222
const testFilesSuffix = process.env.TEST_FILES_SUFFIX;
2323

2424
// You can directly control Mocha options by uncommenting the following lines.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print('hello world')

0 commit comments

Comments
 (0)