Files
vscode-codeql/extensions/ql-vscode/src/vscode-tests/run-integration-tests.ts
Andrew Eisenberg 351db4efc8 Fix cli-integration tests
The main problem this commit fixes is with vscode 1.67.0, an error is
thrown when inside of integration tests and a dialog box is opened. We
were opening the telemetry dialog box. Now, an env variable is set
during cli-integration tests that prevents the dialog from being
opened.

There are also other cleanups and improvements with cli-integration
tests that assist with running locally:

- `vscode-test` dependency has been renamed to `@vscode/test-electron`,
  so use that instead and make the small API changes to support it.
- Commit the codeql-pack.lock.yml file so it isn't recreated on each
  test run.
- Ensure all databases are removed before _and after_ each test run
  that manipulates the set of installed databases
- Similarly, for quick query files, delete them before and after each
  test.
- Change some async `forEach` blocks to for loops in order to support
  sequential operations more easily.
2022-05-09 13:50:28 -07:00

161 lines
5.2 KiB
TypeScript

import * as path from 'path';
import * as os from 'os';
import * as cp from 'child_process';
import {
runTests,
downloadAndUnzipVSCode,
resolveCliPathFromVSCodeExecutablePath
} from '@vscode/test-electron';
import { assertNever } from '../pure/helpers-pure';
import * as tmp from 'tmp-promise';
// For some reason, the following are not exported directly from `@vscode/test-electron`,
// but we can be tricky and import directly from the out file.
import { TestOptions } from '@vscode/test-electron/out/runTest';
import { systemDefaultPlatform } from '@vscode/test-electron/out/util';
// For CI purposes we want to leave this at 'stable' to catch any bugs
// that might show up with new vscode versions released, even though
// this makes testing not-quite-pure, but it can be changed for local
// testing against old versions if necessary.
const VSCODE_VERSION = 'stable';
// List if test dirs
// - no-workspace - Tests with no workspace selected upon launch.
// - minimal-workspace - Tests with a simple workspace selected upon launch.
// - cli-integration - Tests that require a cli to invoke actual commands
enum TestDir {
NoWorksspace = 'no-workspace',
MinimalWorksspace = 'minimal-workspace',
CliIntegration = 'cli-integration'
}
/**
* Run an integration test suite `suite`, retrying if it segfaults, at
* most `tries` times.
*/
async function runTestsWithRetryOnSegfault(suite: TestOptions, tries: number): Promise<void> {
for (let t = 0; t < tries; t++) {
try {
// Download and unzip VS Code if necessary, and run the integration test suite.
await runTests(suite);
return;
} catch (err) {
if (err === 'SIGSEGV') {
console.error('Test runner segfaulted.');
if (t < tries - 1)
console.error('Retrying...');
}
else if (os.platform() === 'win32') {
console.error(`Test runner caught exception (${err})`);
if (t < tries - 1)
console.error('Retrying...');
}
else {
throw err;
}
}
}
console.error(`Tried running suite ${tries} time(s), still failed, giving up.`);
process.exit(1);
}
const tmpDir = tmp.dirSync({ unsafeCleanup: true });
/**
* Integration test runner. Launches the VSCode Extension Development Host with this extension installed.
* See https://github.com/microsoft/vscode-test/blob/master/sample/test/runTest.ts
*/
async function main() {
try {
const extensionDevelopmentPath = path.resolve(__dirname, '../..');
const vscodeExecutablePath = await downloadAndUnzipVSCode(VSCODE_VERSION);
// Which tests to run. Use a comma-separated list of directories.
const testDirsString = process.argv[2];
const dirs = testDirsString.split(',').map(dir => dir.trim().toLocaleLowerCase());
const extensionTestsEnv: Record<string, string> = {};
if (dirs.includes(TestDir.CliIntegration)) {
console.log('Installing required extensions');
const cliPath = resolveCliPathFromVSCodeExecutablePath(vscodeExecutablePath, systemDefaultPlatform);
cp.spawnSync(
cliPath,
[
'--install-extension',
'hbenl.vscode-test-explorer',
'--install-extension',
'ms-vscode.test-adapter-converter',
],
{
encoding: 'utf-8',
stdio: 'inherit',
}
);
extensionTestsEnv.INTEGRATION_TEST_MODE = 'true';
}
console.log(`Running integration tests in these directories: ${dirs}`);
for (const dir of dirs) {
const launchArgs = getLaunchArgs(dir as TestDir);
console.log(`Next integration test dir: ${dir}`);
console.log(`Launch args: ${launchArgs}`);
await runTestsWithRetryOnSegfault({
version: VSCODE_VERSION,
vscodeExecutablePath,
extensionDevelopmentPath,
extensionTestsPath: path.resolve(__dirname, dir, 'index'),
extensionTestsEnv,
launchArgs
}, 3);
}
} catch (err) {
console.error(`Unexpected exception while running tests: ${err}`);
console.error((err as Error).stack);
process.exit(1);
}
}
void main();
function getLaunchArgs(dir: TestDir) {
switch (dir) {
case TestDir.NoWorksspace:
return [
'--disable-extensions',
'--disable-gpu',
'--user-data-dir=' + path.join(tmpDir.name, dir, 'user-data')
];
case TestDir.MinimalWorksspace:
return [
'--disable-extensions',
'--disable-gpu',
'--user-data-dir=' + path.join(tmpDir.name, dir, 'user-data'),
path.resolve(__dirname, '../../test/data')
];
case TestDir.CliIntegration:
// CLI integration tests requires a multi-root workspace so that the data and the QL sources are accessible.
return [
'--disable-gpu',
path.resolve(__dirname, '../../test/data'),
// explicitly disable extensions that are known to interfere with the CLI integration tests
'--disable-extension',
'eamodio.gitlens',
'--disable-extension',
'github.codespaces',
'--disable-extension',
'github.copilot',
'--user-data-dir=' + path.join(tmpDir.name, dir, 'user-data'),
].concat(process.env.TEST_CODEQL_PATH ? [process.env.TEST_CODEQL_PATH] : []);
default:
assertNever(dir);
}
return undefined;
}