test/integration: refactor installation tests, add slow tests
Refactored the tool installation tests to follow the Mocha framework a
bit better, with setup, teardown, etc. I also added a test that should
only run in CI, when a special environment variable is set. This test
will be slow, as it download tools from the Internet. However, I think
it's worth it to have this so that we get notified earlier on about
breakages upstream.
Updates golang/vscode-go#42
Change-Id: I65edb83bf7e5b1f9374d8a9edbc8af93c6a9c660
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/236058
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index db14834..1a8a449 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -76,6 +76,7 @@
run: npm run test
env:
CODE_VERSION: 'insiders'
+ VSCODEGO_BEFORE_RELEASE_TESTS: true
- name: Publish
if: github.ref == 'refs/heads/master' && github.repository == 'golang/vscode-go'
diff --git a/src/goTools.ts b/src/goTools.ts
index 99ed0ac..eaa2b87 100644
--- a/src/goTools.ts
+++ b/src/goTools.ts
@@ -176,7 +176,7 @@
return tools;
}
-const allToolsInformation: { [key: string]: Tool } = {
+export const allToolsInformation: { [key: string]: Tool } = {
'gocode': {
name: 'gocode',
importPath: 'github.com/mdempsky/gocode',
diff --git a/test/integration/index.ts b/test/integration/index.ts
index 12e0292..2d964a1 100644
--- a/test/integration/index.ts
+++ b/test/integration/index.ts
@@ -6,7 +6,6 @@
import * as Mocha from 'mocha';
import * as path from 'path';
export function run(): Promise<void> {
- // Create the mocha test
const mocha = new Mocha({
ui: 'tdd',
});
diff --git a/test/integration/install.test.ts b/test/integration/install.test.ts
index f2de7f7..2c663f5 100644
--- a/test/integration/install.test.ts
+++ b/test/integration/install.test.ts
@@ -12,31 +12,55 @@
import sinon = require('sinon');
import util = require('util');
import vscode = require('vscode');
+import { toolInstallationEnvironment } from '../../src/goEnv';
import { installTools } from '../../src/goInstallTools';
-import { getTool, getToolAtVersion } from '../../src/goTools';
+import { allToolsInformation, getTool, getToolAtVersion } from '../../src/goTools';
import { getBinPath, getGoVersion, rmdirRecursive } from '../../src/util';
suite('Installation Tests', function () {
- this.timeout(10000);
+ // Disable timeout when we are running slow tests.
+ let timeout = 10000;
+ if (shouldRunSlowTests()) {
+ timeout = 0;
+ }
+ this.timeout(timeout);
- test('install tools', async () => {
- const goVersion = await getGoVersion();
- const testCases: string[][] = [
- ['gopls'],
- ['gopls', 'guru'],
- ];
- const proxyDir = buildFakeProxy([].concat(...testCases));
+ let tmpToolsGopath: string;
+ let sandbox: sinon.SinonSandbox;
+ let toolsGopathStub: sinon.SinonStub;
- for (const missing of testCases) {
- // Create a temporary directory in which to install tools.
- const tmpToolsGopath = fs.mkdtempSync(path.join(os.tmpdir(), 'install-test'));
- fs.mkdirSync(path.join(tmpToolsGopath, 'bin'));
- fs.mkdirSync(path.join(tmpToolsGopath, 'src'));
+ setup(() => {
+ // Create a temporary directory in which to install tools.
+ tmpToolsGopath = fs.mkdtempSync(path.join(os.tmpdir(), 'install-test'));
+ fs.mkdirSync(path.join(tmpToolsGopath, 'bin'));
+ fs.mkdirSync(path.join(tmpToolsGopath, 'src'));
- const sandbox = sinon.createSandbox();
- const utils = require('../../src/util');
+ sandbox = sinon.createSandbox();
+ const utils = require('../../src/util');
+ toolsGopathStub = sandbox.stub(utils, 'getToolsGopath').returns(tmpToolsGopath);
+ });
- const toolsGopathStub = sandbox.stub(utils, 'getToolsGopath').returns(tmpToolsGopath);
+ teardown(async () => {
+ sandbox.restore();
+
+ // Clean up the temporary GOPATH. To delete the module cache, run `go clean -modcache`.
+ const goRuntimePath = getBinPath('go');
+ const envForTest = Object.assign({}, process.env);
+ envForTest['GOPATH'] = tmpToolsGopath;
+ const execFile = util.promisify(cp.execFile);
+ await execFile(goRuntimePath, ['clean', '-modcache'], {
+ env: envForTest,
+ });
+ rmdirRecursive(tmpToolsGopath);
+ });
+
+ // runTest actually executes the logic of the test.
+ // If withLocalProxy is true, the test does not require internet.
+ async function runTest(testCases: string[], withLocalProxy?: boolean) {
+ let proxyDir: string;
+ let configStub: sinon.SinonStub;
+ if (withLocalProxy) {
+ proxyDir = buildFakeProxy([].concat(...testCases));
const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
toolsEnvVars: {
value: {
@@ -45,34 +69,57 @@
}
},
});
- const configStub = sandbox.stub(vscode.workspace, 'getConfiguration').returns(goConfig);
- // TODO(rstambler): Test with versions as well.
- const missingTools = missing.map((tool) => getToolAtVersion(tool));
- await installTools(missingTools, goVersion);
-
- sinon.assert.calledWith(toolsGopathStub);
- sinon.assert.calledWith(configStub);
- sandbox.restore();
-
- // Read the $GOPATH/bin to confirm that the expected tools were
- // installed.
- const readdir = util.promisify(fs.readdir);
- const files = await readdir(path.join(tmpToolsGopath, 'bin'));
- assert.deepEqual(files, missing, `tool installation failed for ${missing}`);
-
- // Clean up the temporary GOPATH. To delete the module cache, run `go clean -modcache`.
- const goRuntimePath = getBinPath('go');
- const envForTest = Object.assign({}, process.env);
- envForTest['GOPATH'] = tmpToolsGopath;
- const execFile = util.promisify(cp.execFile);
- await execFile(goRuntimePath, ['clean', '-modcache'], {
- env: envForTest,
- });
- rmdirRecursive(tmpToolsGopath);
+ configStub = sandbox.stub(vscode.workspace, 'getConfiguration').returns(goConfig);
+ } else {
+ const env = toolInstallationEnvironment();
+ console.log(`Installing tools using GOPROXY=${env['GOPROXY']}`);
}
- rmdirRecursive(proxyDir);
+ // TODO(rstambler): Test with versions as well.
+ const missingTools = testCases.map((tool) => getToolAtVersion(tool));
+ const goVersion = await getGoVersion();
+ await installTools(missingTools, goVersion);
+
+ // Confirm that each expected tool has been installed.
+ const checks: Promise<void>[] = [];
+ const exists = util.promisify(fs.exists);
+ for (const tool of testCases) {
+ checks.push(new Promise<void>(async (resolve) => {
+ // Check that the expect tool has been installed to $GOPATH/bin.
+ const ok = await exists(path.join(tmpToolsGopath, 'bin', tool));
+ if (!ok) {
+ assert.fail(`expected ${tmpToolsGopath}/bin/${tool}, not found`);
+ }
+ return resolve();
+ }));
+ }
+ await Promise.all(checks);
+
+ sandbox.assert.calledWith(toolsGopathStub);
+
+ if (withLocalProxy) {
+ sandbox.assert.calledWith(configStub);
+ rmdirRecursive(proxyDir);
+ }
+ }
+
+ test('Install one tool with a local proxy', async () => {
+ await runTest(['gopls'], true);
});
+
+ test('Install multiple tools with a local proxy', async () => {
+ await runTest(['gopls', 'guru'], true);
+ });
+
+ test('Install all tools via GOPROXY', async () => {
+ // Only run this test if we are in CI before a Nightly release.
+ if (!shouldRunSlowTests()) {
+ return;
+ }
+ const tools = Object.keys(allToolsInformation);
+ await runTest(tools);
+ });
+
});
// buildFakeProxy creates a fake file-based proxy used for testing. The code is
@@ -103,3 +150,10 @@
}
return proxyDir;
}
+
+// Check if VSCODEGO_BEFORE_RELEASE_TESTS is set to true. This environment
+// variable is set by the CI system that releases the Nightly extension,
+// allowing us to opt-in to more rigorous testing only before releases.
+function shouldRunSlowTests(): boolean {
+ return !!process.env['VSCODEGO_BEFORE_RELEASE_TESTS'];
+}