From e81c30f78ceecbb699ea414c2b74430dc528732f Mon Sep 17 00:00:00 2001 From: Hana Date: Thu, 29 Oct 2020 19:12:37 -0400 Subject: [PATCH] test/gopls: change test environment setup to use single file edit When we wrote the first gopls integration test, gopls required vscode to open the workspace folder while vscode code does not support dynamic workspace folder registration in test mode. As a result, we ended up having a fixed workspace folder as a test fixture, starting the test code instance with the folder, and copying necessary files to the folder. There were so many moving parts and this created race conditions and caused slow test run. Since v0.4.x, gopls starts to support single file edit and automatically constructs an internal workspace by walking the directory tree around the open file. This CL utilizes this new capability. In each suite, we start testing by starting a new gopls, opening a single file, and waiting for the gopls to finish the initial package loading. This CL introduces Env.onPatternInTrace, which watches the fake trace output channel, and emits an event when a registered pattern is observed. This is a hack to wait for the gopls's internal state to reach to a desirable state - ideally, we want to intercept all the progress report messages like gopls' regression tests once it is supported from the language client middleware. https://github.com/microsoft/vscode-languageserver-node/issues/671 We also identified subtle issues in the existing test setup. Issue 1: when the code for testing starts (using `vscode-test`'s `runTests`) we pass the extension development path. It seems like the vscode instance uses the `main` program specified in `package.json` and activates it even without us asking. As a result, when we run tests and call 'activate' again, multiple hover/completion providers are registered, and vscode returns results from legacy and gopls-based providers. For example, the completion middleware test was observing entries from gopls, and goCompletionItemProvider that uses gocode. We address this issue here by introducing the VSCODE_GO_IN_TEST environment variable. If it is set, activate will return immediately. So, tests can control when to register what, and how. We need this setting in both `launch.json` and `runTest.ts` that's invoked in CI (`npm run test`) Issue 2: when the code for testing needs to call `activate`, we got the extension instance by using `vscode.extensions.getExtension` and called its `activate`. This was because there is no easy way to supply sufficiently complete vscode's ExtensionContext. It turned out, the extension instance vscode.extensions.getExtension returns is the one built with the `main` program specified in our `package.json` - that is the webpack'ed one in `dist/goMain.js`. On the other hand, our debugging depends on pre-webpack versions in `out/*`. This caused confusion and made debugging near impossible (breakpoints we set on pre-webpack versions will not be hit because we are running a different version of extension)! We don't know if there is a way to teach `vscode-test` to use pre-webpack version. Maybe this is our misconfiguration in our launch.json and package.json. For now, we work around this issue by not calling `activate`. Instead, in this gopls test, we call `buildLanguageClient` directly. This required some refactoring work in goLanguageServer.ts. Issue 3: sinon is cool, but stubbing vscode API for channel creation is too much. While we refactor buildLanguageClient, we made changes to let the caller supply the output channels. Issue 4: as `vscode-test` starts the test vscode instance, it also activates the registered snippets and it interferes with our gopls completion middleware tests. In test, now we explicitly filter out the snippet entries. Issue 5: for some reason, the first entry in the completion middleware test that expects 'Print' item, the filter text is not set. It can be a bug, or working as intended (the first item has label === filterText). Gopls is providing the expected entry. Workaround this issue by inspecting the label field too. Updates golang/vscode-go#655 Updates golang/vscode-go#832 Change-Id: Ic7088fd551329d1c8f78078ccb24a5f529eec72a Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/266418 Run-TryBot: Hyang-Ah Hana Kim TryBot-Result: kokoro Trust: Hyang-Ah Hana Kim Trust: Suzy Mueller Reviewed-by: Suzy Mueller Reviewed-by: Rebecca Stambler --- .vscode/launch.json | 9 +- src/goCheck.ts | 2 +- src/goInstallTools.ts | 6 +- src/goLanguageServer.ts | 58 ++++++---- src/goMain.ts | 3 + src/goStatus.ts | 6 +- test/gopls/extension.test.ts | 169 +++++++++++++---------------- test/integration/extension.test.ts | 4 +- test/runTest.ts | 11 +- 9 files changed, 140 insertions(+), 128 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 4f23b75e3d..3ec6c82573 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -64,10 +64,14 @@ "--timeout", "999999" ], + "env": { + "VSCODE_GO_IN_TEST": "1" // Disable code that shouldn't be used in test + }, "stopOnEntry": false, "sourceMaps": true, "smartStep": true, "outFiles": [ + "${workspaceFolder}/out/**/*.js", "${workspaceFolder}/out/test/**/*.js" ], "preLaunchTask": "npm: watch" @@ -83,11 +87,14 @@ "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out/test/gopls/index", "--timeout", "999999", - "${workspaceFolder}/test/gopls/testfixtures/src/workspace" // gopls requires a workspace to work with. ], + "env": { + "VSCODE_GO_IN_TEST": "1" // Disable code that shouldn't be used in test + }, "stopOnEntry": false, "sourceMaps": true, "outFiles": [ + "${workspaceFolder}/out/**/*.js", "${workspaceFolder}/out/test/**/*.js" ], "preLaunchTask": "npm: watch", diff --git a/src/goCheck.ts b/src/goCheck.ts index 597e018b11..327a5f8be1 100644 --- a/src/goCheck.ts +++ b/src/goCheck.ts @@ -59,7 +59,7 @@ export function check(fileUri: vscode.Uri, goConfig: vscode.WorkspaceConfigurati // If a user has enabled diagnostics via a language server, // then we disable running build or vet to avoid duplicate errors and warnings. - const lspConfig = buildLanguageServerConfig(); + const lspConfig = buildLanguageServerConfig(goConfig); const disableBuildAndVet = lspConfig.enabled && lspConfig.features.diagnostics; let testPromise: Thenable; diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts index 59974cf211..2e3a06aafa 100644 --- a/src/goInstallTools.ts +++ b/src/goInstallTools.ts @@ -466,6 +466,11 @@ export async function offerToInstallTools() { }); } + const goConfig = getGoConfig(); + if (!goConfig['useLanguageServer']) { + return; + } + const usingSourceGraph = getToolFromToolPath(getLanguageServerToolPath()) === 'go-langserver'; if (usingSourceGraph && goVersion.gt('1.10')) { const promptMsg = @@ -476,7 +481,6 @@ export async function offerToInstallTools() { if (selected === installLabel) { await installTools([getTool('gopls')], goVersion); } else if (selected === disableLabel) { - const goConfig = getGoConfig(); const inspectLanguageServerSetting = goConfig.inspect('useLanguageServer'); if (inspectLanguageServerSetting.globalValue === true) { goConfig.update('useLanguageServer', false, vscode.ConfigurationTarget.Global); diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts index 9d0dcf7b21..30256c967b 100644 --- a/src/goLanguageServer.ts +++ b/src/goLanguageServer.ts @@ -58,7 +58,7 @@ import { getFromGlobalState, updateGlobalState } from './stateUtils'; import { getBinPath, getCurrentGoPath, getGoConfig, getGoplsConfig, getWorkspaceFolderPath } from './util'; import { getToolFromToolPath } from './utils/pathUtils'; -interface LanguageServerConfig { +export interface LanguageServerConfig { serverName: string; path: string; version: string; @@ -102,7 +102,7 @@ let lastUserAction: Date = new Date(); // startLanguageServerWithFallback starts the language server, if enabled, // or falls back to the default language providers. export async function startLanguageServerWithFallback(ctx: vscode.ExtensionContext, activation: boolean) { - const cfg = buildLanguageServerConfig(); + const cfg = buildLanguageServerConfig(getGoConfig()); // If the language server is gopls, we enable a few additional features. // These include prompting for updates and surveys. @@ -134,7 +134,7 @@ function scheduleGoplsSuggestions(tool: Tool) { const update = async () => { setTimeout(update, timeDay); - const cfg = buildLanguageServerConfig(); + const cfg = buildLanguageServerConfig(getGoConfig()); if (!cfg.enabled) { return; } @@ -146,7 +146,7 @@ function scheduleGoplsSuggestions(tool: Tool) { const survey = async () => { setTimeout(survey, timeDay); - const cfg = buildLanguageServerConfig(); + const cfg = buildLanguageServerConfig(getGoConfig()); if (!goplsSurveyOn || !cfg.enabled) { return; } @@ -176,7 +176,7 @@ async function startLanguageServer(ctx: vscode.ExtensionContext, config: Languag // Track the latest config used to start the language server, // and rebuild the language client. latestConfig = config; - languageClient = await buildLanguageClient(config); + languageClient = await buildLanguageClient(buildLanguageClientOption(config)); crashCount = 0; } @@ -206,21 +206,38 @@ async function startLanguageServer(ctx: vscode.ExtensionContext, config: Languag return true; } -async function buildLanguageClient(cfg: LanguageServerConfig): Promise { - // Reuse the same output channel for each instance of the server. - if (cfg.enabled) { - if (!serverOutputChannel) { - serverOutputChannel = vscode.window.createOutputChannel(cfg.serverName + ' (server)'); - } - if (!serverTraceChannel) { - serverTraceChannel = vscode.window.createOutputChannel(cfg.serverName); +export interface BuildLanguageClientOption extends LanguageServerConfig { + outputChannel?: vscode.OutputChannel; + traceOutputChannel?: vscode.OutputChannel; +} + +// buildLanguageClientOption returns the default, extra configuration +// used in building a new LanguageClient instance. Options specified +// in LanguageServerConfig +function buildLanguageClientOption(cfg: LanguageServerConfig): BuildLanguageClientOption { + // Reuse the same output channel for each instance of the server. + if (cfg.enabled) { + if (!serverOutputChannel) { + serverOutputChannel = vscode.window.createOutputChannel(cfg.serverName + ' (server)'); + } + if (!serverTraceChannel) { + serverTraceChannel = vscode.window.createOutputChannel(cfg.serverName); + } } - } + return Object.assign({ + outputChannel: serverOutputChannel, + traceOutputChannel: serverTraceChannel + }, cfg); +} + +// buildLanguageClient returns a language client built using the given language server config. +// The returned language client need to be started before use. +export async function buildLanguageClient(cfg: BuildLanguageClientOption): Promise { let goplsWorkspaceConfig = getGoplsConfig(); goplsWorkspaceConfig = await adjustGoplsWorkspaceConfiguration(cfg, goplsWorkspaceConfig); const c = new LanguageClient( 'go', // id - cfg.serverName, // name + cfg.serverName, // name e.g. gopls { command: cfg.path, args: ['-mode=stdio', ...cfg.flags], @@ -235,8 +252,8 @@ async function buildLanguageClient(cfg: LanguageServerConfig): Promise vscode.Uri.parse(uri) }, - outputChannel: serverOutputChannel, - traceOutputChannel: serverTraceChannel, + outputChannel: cfg.outputChannel, + traceOutputChannel: cfg.traceOutputChannel, revealOutputChannelOn: RevealOutputChannelOn.Never, initializationFailedHandler: (error: WebRequest.ResponseError): boolean => { vscode.window.showErrorMessage( @@ -550,8 +567,8 @@ export function watchLanguageServerConfiguration(e: vscode.ConfigurationChangeEv } } -export function buildLanguageServerConfig(): LanguageServerConfig { - const goConfig = getGoConfig(); +export function buildLanguageServerConfig(goConfig: vscode.WorkspaceConfiguration): LanguageServerConfig { + const cfg: LanguageServerConfig = { serverName: '', path: '', @@ -604,9 +621,6 @@ Please try reinstalling it.`); */ export function getLanguageServerToolPath(): string { const goConfig = getGoConfig(); - if (!goConfig['useLanguageServer']) { - return; - } // Check that all workspace folders are configured with the same GOPATH. if (!allFoldersHaveSameGopath()) { vscode.window.showInformationMessage( diff --git a/src/goMain.ts b/src/goMain.ts index 78099aeed8..7c370c5e6c 100644 --- a/src/goMain.ts +++ b/src/goMain.ts @@ -83,6 +83,9 @@ export let vetDiagnosticCollection: vscode.DiagnosticCollection; export let restartLanguageServer = () => { return; }; export function activate(ctx: vscode.ExtensionContext) { + if (process.env['VSCODE_GO_IN_TEST'] === '1') { // Make sure this does not run when running in test. + return; + } const cfg = getGoConfig(); setLogConfig(cfg['logging']); diff --git a/src/goStatus.ts b/src/goStatus.ts index 08ec245501..bcd4bbb3fd 100644 --- a/src/goStatus.ts +++ b/src/goStatus.ts @@ -12,7 +12,7 @@ import { formatGoVersion, GoEnvironmentOption, terminalCreationListener } from ' import { buildLanguageServerConfig, getLocalGoplsVersion, serverOutputChannel } from './goLanguageServer'; import { isGoFile } from './goMode'; import { getModFolderPath, isModSupported } from './goModules'; -import { getGoVersion } from './util'; +import { getGoConfig, getGoVersion } from './util'; export let outputChannel = vscode.window.createOutputChannel('Go'); @@ -47,7 +47,7 @@ export async function expandGoStatusBar() { ]; // Get the gopls configuration - const cfg = buildLanguageServerConfig(); + const cfg = buildLanguageServerConfig(getGoConfig()); if (cfg.serverName === 'gopls') { const goplsVersion = await getLocalGoplsVersion(cfg); options.push({label: `${languageServerIcon}Open 'gopls' trace`, description: `${goplsVersion}`}); @@ -101,7 +101,7 @@ export async function initGoStatusBar() { // Add an icon to indicate that the 'gopls' server is running. // Assume if it is configured it is already running, since the // icon will be updated on an attempt to start. - const cfg = buildLanguageServerConfig(); + const cfg = buildLanguageServerConfig(getGoConfig()); updateLanguageServerIconGoStatusBar(true, cfg.serverName); showGoStatusBar(); diff --git a/test/gopls/extension.test.ts b/test/gopls/extension.test.ts index 4df045f7d1..7e82399576 100644 --- a/test/gopls/extension.test.ts +++ b/test/gopls/extension.test.ts @@ -4,11 +4,13 @@ *--------------------------------------------------------*/ import * as assert from 'assert'; import cp = require('child_process'); -import * as fs from 'fs-extra'; +import { EventEmitter } from 'events'; import * as path from 'path'; import sinon = require('sinon'); import * as vscode from 'vscode'; -import { extensionId } from '../../src/const'; +import { LanguageClient } from 'vscode-languageclient/node'; +import { buildLanguageClient, BuildLanguageClientOption, buildLanguageServerConfig } from '../../src/goLanguageServer'; +import { getGoConfig } from '../../src/util'; // FakeOutputChannel is a fake output channel used to buffer // the output of the tested language client in an in-memory @@ -21,6 +23,16 @@ class FakeOutputChannel implements vscode.OutputChannel { private buf = [] as string[]; + private eventEmitter = new EventEmitter(); + private registeredPatterns = new Set(); + public onPattern(msg: string, listener: () => void) { + this.registeredPatterns.add(msg); + this.eventEmitter.once(msg, () => { + this.registeredPatterns.delete(msg); + listener(); + }); + } + public append = (v: string) => this.enqueue(v); public appendLine = (v: string) => this.enqueue(v); public clear = () => { this.buf = []; }; @@ -29,98 +41,75 @@ class FakeOutputChannel implements vscode.OutputChannel { } private enqueue = (v: string) => { + this.registeredPatterns?.forEach((p) => { + if (v.includes(p)) { + this.eventEmitter.emit(p); + } + }); + if (this.buf.length > 1024) { this.buf.shift(); } this.buf.push(v.trim()); } } -// Env is a collection of test related variables -// that define the test environment such as vscode workspace. +// Env is a collection of test-related variables and lsp client. +// Currently, this works only in module-aware mode. class Env { - - // Currently gopls requires a workspace and does not work in a single-file mode. - // Code in test environment does not support dynamically adding folders. - // tslint:disable-next-line:max-line-length - // https://github.com/microsoft/vscode/blob/890f62dfd9f3e70198931f788c5c332b3e8b7ad7/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts#L281 - // - // So, when we start the gopls tests, we start the test extension host with a - // dummy workspace, ${projectDir}/test/gopls/testdata/src/workspace - // (see test/runTest.ts and launch.json). - // Then copy necessary files to the workspace using Env.reset() from the - // fixturesRoot directory. - public workspaceDir: string; - public fixturesRoot: string; - - public extension: vscode.Extension; - + public languageClient?: LanguageClient; private fakeOutputChannel: FakeOutputChannel; - - constructor(projectDir: string) { - if (!projectDir) { - assert.fail('project directory cannot be determined'); - } - this.workspaceDir = path.resolve(projectDir, 'test/gopls/testdata/src/workspace'); - this.fixturesRoot = path.resolve(projectDir, 'test/testdata'); - this.extension = vscode.extensions.getExtension(extensionId); - this.fakeOutputChannel = new FakeOutputChannel(); - - // Ensure the vscode extension host is configured as expected. - const workspaceFolder = path.resolve(vscode.workspace.workspaceFolders[0].uri.fsPath); - if (this.workspaceDir !== workspaceFolder) { - assert.fail(`specified workspaceDir: ${this.workspaceDir} does not match the workspace folder: ${workspaceFolder}`); - } - } + private disposables = [] as { dispose(): any }[]; public flushTrace(print: boolean) { if (print) { console.log(this.fakeOutputChannel.toString()); - this.fakeOutputChannel.clear(); } } - public async setup() { - // stub the language server's output channel to intercept the trace. - sinon.stub(vscode.window, 'createOutputChannel') - .callThrough().withArgs('gopls (server)').returns(this.fakeOutputChannel); - - await this.reset(); - await this.extension.activate(); - await sleep(2000); // allow the language server to start. - // TODO(hyangah): find a better way to check the language server's status. - // I thought I'd check the languageClient.onReady(), - // but couldn't make it working yet. + // This is a hack to check the progress of package loading. + // TODO(hyangah): use progress message middleware hook instead + // once it becomes available. + public onMessageInTrace(msg: string, timeoutMS: number): Promise { + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + this.flushTrace(true); + reject(`Timed out while waiting for '${msg}'`); + }, timeoutMS); + this.fakeOutputChannel.onPattern(msg, () => { + clearTimeout(timeout); + resolve(); + }); + }); } - public teardown() { - sinon.restore(); - } + public async setup(filePath: string) { // file path to open. + this.fakeOutputChannel = new FakeOutputChannel(); + const pkgLoadingDone = this.onMessageInTrace('Finished loading packages.', 60_000); - public async reset(fixtureDirName?: string) { // name of the fixtures subdirectory to use. - try { - // clean everything except the .gitignore file - // needed to keep the empty directory in vcs. - await fs.readdir(this.workspaceDir).then((files) => { - return Promise.all( - files.filter((filename) => filename !== '.gitignore' && filename !== '.vscode').map((file) => { - fs.remove(path.resolve(this.workspaceDir, file)); - })); - }); + // Start the language server with the fakeOutputChannel. + const goConfig = Object.create(getGoConfig(), { + useLanguageServer: { value: true }, + languageServerFlags: { value: ['-rpc.trace'] }, // enable rpc tracing to monitor progress reports + }); + const cfg: BuildLanguageClientOption = buildLanguageServerConfig(goConfig); + cfg.outputChannel = this.fakeOutputChannel; // inject our fake output channel. + this.languageClient = await buildLanguageClient(cfg); + this.disposables.push(this.languageClient.start()); + + await this.languageClient.onReady(); + await this.openDoc(filePath); + await pkgLoadingDone; + } - if (!fixtureDirName) { - return; - } - const src = path.resolve(this.fixturesRoot, fixtureDirName); - const dst = this.workspaceDir; - await fs.copy(src, dst, { recursive: true }); - } catch (err) { - assert.fail(err); + public async teardown() { + await this.languageClient?.stop(); + for (const d of this.disposables) { + d.dispose(); } + this.languageClient = undefined; } - // openDoc opens the file in the workspace with the given path (paths - // are the path elements of a file). public async openDoc(...paths: string[]) { - const uri = vscode.Uri.file(path.resolve(this.workspaceDir, ...paths)); + const uri = vscode.Uri.file(path.resolve(...paths)); const doc = await vscode.workspace.openTextDocument(uri); return { uri, doc }; } @@ -133,12 +122,11 @@ async function sleep(ms: number) { suite('Go Extension Tests With Gopls', function () { this.timeout(300000); const projectDir = path.join(__dirname, '..', '..', '..'); - const env = new Env(projectDir); + const testdataDir = path.join(projectDir, 'test', 'testdata'); + const env = new Env(); - suiteSetup(async () => { - await env.setup(); - }); - suiteTeardown(async () => { await env.reset(); }); + suiteSetup(async () => await env.setup(path.resolve(testdataDir, 'gogetdocTestData', 'test.go'))); + suiteTeardown(() => env.teardown()); this.afterEach(function () { // Note: this shouldn't use () => {...}. Arrow functions do not have 'this'. @@ -148,11 +136,7 @@ suite('Go Extension Tests With Gopls', function () { }); test('HoverProvider', async () => { - await env.reset('gogetdocTestData'); - const { uri, doc } = await env.openDoc('test.go'); - - // TODO(hyangah): find a way to wait for the language server to complete processing. - + const { uri } = await env.openDoc(testdataDir, 'gogetdocTestData', 'test.go'); const testCases: [string, vscode.Position, string | null, string | null][] = [ // [new vscode.Position(3,3), '/usr/local/go/src/fmt'], ['keyword', new vscode.Position(0, 3), null, null], // keyword @@ -186,8 +170,7 @@ suite('Go Extension Tests With Gopls', function () { }); test('Completion middleware', async () => { - await env.reset('gogetdocTestData'); - const { uri } = await env.openDoc('test.go'); + const { uri } = await env.openDoc(testdataDir, 'gogetdocTestData', 'test.go'); const testCases: [string, vscode.Position, string][] = [ ['fmt.P<>', new vscode.Position(19, 6), 'Print'], ]; @@ -213,14 +196,18 @@ suite('Go Extension Tests With Gopls', function () { if (!list.isIncomplete) { assert.fail(`gopls should provide an incomplete list by default`); } - // TODO(rstambler): For some reason, the filter text gets deleted - // from the first item. I can't reproduce this outside of the test - // suite. - for (let i = 1; i < list.items.length; i++) { - const item = list.items[i]; - assert.equal(item.filterText, wantFilterText, `${uri}:${name} failed, unexpected filter text (got ${item.filterText}, want ${wantFilterText})`); - } + + // vscode.executeCompletionItemProvider will return results from all + // registered completion item providers, not only gopls but also snippets. + // Alternative is to directly query the language client, but that will + // prevent us from detecting problems caused by issues between the language + // client library and the vscode. for (const item of list.items) { + if (item.kind === vscode.CompletionItemKind.Snippet) { continue; } // gopls does not supply Snippet yet. + assert.strictEqual(item.filterText ?? item.label, wantFilterText, + `${uri}:${name} failed, unexpected filter text ` + + `(got ${item.filterText ?? item.label}, want ${wantFilterText})\n` + + `${JSON.stringify(item, null, 2)}`); if (item.kind === vscode.CompletionItemKind.Method || item.kind === vscode.CompletionItemKind.Function) { assert.ok(item.command, `${uri}:${name}: expected command associated with ${item.label}, found none`); } diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts index b7ca7632f2..66dd9c365a 100644 --- a/test/integration/extension.test.ts +++ b/test/integration/extension.test.ts @@ -429,7 +429,7 @@ It returns the number of bytes written and any write error encountered. ]; // If a user has enabled diagnostics via a language server, // then we disable running build or vet to avoid duplicate errors and warnings. - const lspConfig = buildLanguageServerConfig(); + const lspConfig = buildLanguageServerConfig(getGoConfig()); const expectedBuildVetErrors = lspConfig.enabled ? [] : [{ line: 11, severity: 'error', msg: 'undefined: prin' }]; const expected = [...expectedLintErrors, ...expectedBuildVetErrors]; @@ -1370,7 +1370,7 @@ encountered. }); test('Build Tags checking', async () => { - const goplsConfig = buildLanguageServerConfig(); + const goplsConfig = buildLanguageServerConfig(getGoConfig()); if (goplsConfig.enabled) { // Skip this test if gopls is enabled. Build/Vet checks this test depend on are // disabled when the language server is enabled, and gopls is not handling tags yet. diff --git a/test/runTest.ts b/test/runTest.ts index 22dc780855..c0476913ea 100644 --- a/test/runTest.ts +++ b/test/runTest.ts @@ -2,6 +2,9 @@ import * as path from 'path'; import { runTests } from 'vscode-test'; async function main() { + // We are in test mode. + process.env['VSCODE_GO_IN_TEST'] = '1'; + // The folder containing the Extension Manifest package.json // Passed to `--extensionDevelopmentPath` const extensionDevelopmentPath = path.resolve(__dirname, '../../'); @@ -26,20 +29,14 @@ async function main() { // Integration tests using gopls. try { - // Currently gopls requires a workspace. Code in test environment does not support - // dynamically adding folders. + // Note: Code in test environment does not support dynamically adding folders. // tslint:disable-next-line:max-line-length // https://github.com/microsoft/vscode/blob/890f62dfd9f3e70198931f788c5c332b3e8b7ad7/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts#L281 - // So, we start the test extension host with a dummy workspace (test/gopls/testdata/src/workspace) - // and copy necessary files to the workspace. - const ws = path.resolve(extensionDevelopmentPath, 'test/gopls/testdata/src/workspace'); - await runTests({ extensionDevelopmentPath, extensionTestsPath: path.resolve(__dirname, './gopls/index'), launchArgs: [ '--disable-extensions', // disable all other extensions - ws // dummy workspace to start with ], }); } catch (err) {