test: add debug adapter tests
Add basic debug adapter tests to check that basic programs can
run using the vscode-debugadapter-testsupport package.
Updates golang/vscode-go#137
Change-Id: Ida60da545058f229253a27dcc4d66e94f558d113
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/259206
Trust: Suzy Mueller <suzmue@golang.org>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Suzy Mueller <suzmue@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/package-lock.json b/package-lock.json
index 93079f4..f142358 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4711,6 +4711,21 @@
"vscode-debugprotocol": "1.41.0"
}
},
+ "vscode-debugadapter-testsupport": {
+ "version": "1.42.0",
+ "resolved": "https://registry.npmjs.org/vscode-debugadapter-testsupport/-/vscode-debugadapter-testsupport-1.42.0.tgz",
+ "integrity": "sha512-5miGnlsT1VLeXcu04AR+LvD4lwTRlEMAj0nyLgVlMdHzH4RDbX2M2/nXSpRbcsdEHcXoRQlfkAXhM4ZQQ4BUBw==",
+ "requires": {
+ "vscode-debugprotocol": "^1.42.0"
+ },
+ "dependencies": {
+ "vscode-debugprotocol": {
+ "version": "1.42.0",
+ "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.42.0.tgz",
+ "integrity": "sha512-nVsfVCat9FZlOso5SYB1LQQiFGifTyOALpkpJdudDlRXGTpI3mSFiDYXWaoFm7UcfqTOzn1SC7Hqw4d89btT0w=="
+ }
+ }
+ },
"vscode-debugprotocol": {
"version": "1.41.0",
"resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.41.0.tgz",
diff --git a/package.json b/package.json
index 81f380f..d4cc1eb 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
"semver": "^7.3.2",
"tree-kill": "file:third_party/tree-kill",
"vscode-debugadapter": "^1.40.0",
+ "vscode-debugadapter-testsupport": "^1.42.0",
"vscode-debugprotocol": "^1.40.0",
"vscode-languageclient": "^6.1.3",
"web-request": "^1.0.7"
diff --git a/test/fixtures/panic/go.mod b/test/fixtures/panic/go.mod
new file mode 100644
index 0000000..c8c9086
--- /dev/null
+++ b/test/fixtures/panic/go.mod
@@ -0,0 +1 @@
+module github.com/microsoft/vscode-go/gofixtures/panic
diff --git a/test/fixtures/panic/panic.go b/test/fixtures/panic/panic.go
new file mode 100644
index 0000000..6996fb8
--- /dev/null
+++ b/test/fixtures/panic/panic.go
@@ -0,0 +1,5 @@
+package main
+
+func main() {
+ panic("BOOM")
+}
diff --git a/test/integration/goDebug.test.ts b/test/integration/goDebug.test.ts
index 618087f..3b9a7d1 100644
--- a/test/integration/goDebug.test.ts
+++ b/test/integration/goDebug.test.ts
@@ -2,6 +2,8 @@
import * as fs from 'fs';
import * as path from 'path';
import * as sinon from 'sinon';
+import {DebugClient} from 'vscode-debugadapter-testsupport';
+import {DebugProtocol} from 'vscode-debugprotocol';
import {
Delve,
escapeGoModPath,
@@ -9,6 +11,7 @@
PackageBuildInfo,
RemoteSourcesAndPackages,
} from '../../src/debugAdapter/goDebug';
+import { GoDebugConfigurationProvider } from '../../src/goDebugConfiguration';
suite('Path Manipulation Tests', () => {
test('escapeGoModPath works', () => {
@@ -267,3 +270,160 @@
assert.deepEqual(remoteSourcesAndPackages.remotePackagesBuildInfo, [helloPackage, testPackage]);
});
});
+
+// Test suite adapted from:
+// https://github.com/microsoft/vscode-mock-debug/blob/master/src/tests/adapter.test.ts
+suite('Go Debug Adapter', function () {
+ this.timeout(10000);
+
+ const debugConfigProvider = new GoDebugConfigurationProvider();
+
+ const DEBUG_ADAPTER = './dist/debugAdapter.js';
+
+ const PROJECT_ROOT = path.join(__dirname, '../../../');
+ const DATA_ROOT = path.join(PROJECT_ROOT, 'test/fixtures/');
+
+ let dc: DebugClient;
+
+ setup( () => {
+ dc = new DebugClient('node', path.join(PROJECT_ROOT, DEBUG_ADAPTER), 'go');
+ return dc.start();
+ });
+
+ suite('basic', () => {
+
+ test('unknown request should produce error', (done) => {
+ dc.send('illegal_request').then(() => {
+ done(new Error('does not report error on unknown request'));
+ }).catch(() => {
+ done();
+ });
+ });
+ });
+
+ suite('initialize', () => {
+
+ test('should return supported features', () => {
+ return dc.initializeRequest().then((response) => {
+ response.body = response.body || {};
+ assert.strictEqual(response.body.supportsConfigurationDoneRequest, true);
+ });
+ });
+
+ test('should produce error for invalid \'pathFormat\'', (done) => {
+ dc.initializeRequest({
+ adapterID: 'mock',
+ linesStartAt1: true,
+ columnsStartAt1: true,
+ pathFormat: 'url'
+ }).then((response) => {
+ done(new Error('does not report error on invalid \'pathFormat\' attribute'));
+ }).catch((err) => {
+ // error expected
+ done();
+ });
+ });
+ });
+
+ suite('launch', () => {
+ test('should run program to the end', () => {
+
+ const PROGRAM = path.join(DATA_ROOT, 'baseTest');
+
+ const config = {
+ name: 'Launch',
+ type: 'go',
+ request: 'launch',
+ mode: 'auto',
+ program: PROGRAM,
+ };
+ const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config);
+
+ return Promise.all([
+ dc.configurationSequence(),
+ dc.launch(debugConfig),
+ dc.waitForEvent('terminated')
+ ]);
+ });
+
+ test('should stop on entry', () => {
+ const PROGRAM = path.join(DATA_ROOT, 'baseTest');
+ const config = {
+ name: 'Launch',
+ type: 'go',
+ request: 'launch',
+ mode: 'auto',
+ program: PROGRAM,
+ stopOnEntry: true
+ };
+ const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config);
+
+ return Promise.all([
+ dc.configurationSequence(),
+ dc.launch(debugConfig),
+ // The debug adapter does not support a stack trace request
+ // when there are no goroutines running. Which is true when it is stopped
+ // on entry. Therefore we would need another method from dc.assertStoppedLocation
+ // to check the debugger is stopped on entry.
+ dc.waitForEvent('stopped').then((event) => {
+ const stevent = event as DebugProtocol.StoppedEvent;
+ assert.strictEqual(stevent.body.reason, 'entry');
+ })
+ ]);
+ });
+ });
+
+ suite('setBreakpoints', () => {
+
+ test('should stop on a breakpoint', () => {
+
+ const PROGRAM = path.join(DATA_ROOT, 'baseTest');
+ const FILE = path.join(DATA_ROOT, 'baseTest/test.go');
+
+ const BREAKPOINT_LINE = 11;
+
+ const config = {
+ name: 'Launch',
+ type: 'go',
+ request: 'launch',
+ mode: 'auto',
+ program: PROGRAM,
+ };
+ const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config);
+
+ return dc.hitBreakpoint(debugConfig, { path: FILE, line: BREAKPOINT_LINE } );
+ });
+ });
+
+ suite('setExceptionBreakpoints', () => {
+
+ test('should stop on an exception', () => {
+
+ const PROGRAM_WITH_EXCEPTION = path.join(DATA_ROOT, 'panic');
+
+ const config = {
+ name: 'Launch',
+ type: 'go',
+ request: 'launch',
+ mode: 'auto',
+ program: PROGRAM_WITH_EXCEPTION,
+ };
+ const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config);
+
+ return Promise.all([
+
+ dc.waitForEvent('initialized').then(() => {
+ return dc.setExceptionBreakpointsRequest({
+ filters: [ 'all' ]
+ });
+ }).then(() => {
+ return dc.configurationDoneRequest();
+ }),
+
+ dc.launch(debugConfig),
+
+ dc.assertStoppedLocation('panic', {} )
+ ]);
+ });
+ });
+});