Skip to content

Commit 8176bfe

Browse files
committed
Copy extension binaries for CI tests
1 parent 08668bf commit 8176bfe

4 files changed

Lines changed: 84 additions & 34 deletions

File tree

Extension/.scripts/copyExtensionBinaries.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { cp, readdir, rm, stat } from 'node:fs/promises';
77
import { homedir } from 'node:os';
8-
import { join } from 'node:path';
8+
import { basename, join } from 'node:path';
99
import { verbose } from '../src/Utility/Text/streams';
1010
import { $args, $root, green, heading, note } from './common';
1111

@@ -125,7 +125,7 @@ async function findLatestInstalledExtension(providedPath?: string): Promise<stri
125125
return installed[0].path;
126126
}
127127

128-
export async function main(sourcePath = $args[0]) {
128+
export async function main(sourcePath = $args[0]): Promise<string | undefined> {
129129
console.log(heading('Copy installed extension binaries'));
130130

131131
const installedExtensionPath: string = await findLatestInstalledExtension(sourcePath);
@@ -141,4 +141,7 @@ export async function main(sourcePath = $args[0]) {
141141
}
142142

143143
note(`Copied installed binaries into ${$root}`);
144+
145+
const installedVersion = tryParseVersion(basename(installedExtensionPath));
146+
return installedVersion?.join('.');
144147
}

Extension/.scripts/installAndCopyBinaries.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
* ------------------------------------------------------------------------------------------ */
55

66
import { runVSCodeCommand } from '@vscode/test-electron';
7-
import { error, heading } from './common';
7+
import { writeFile } from 'node:fs/promises';
8+
import { join } from 'node:path';
9+
import { $root, error, heading, note } from './common';
810
import * as copy from './copyExtensionBinaries';
911
import { install, isolated, options } from "./vscode";
1012

@@ -13,13 +15,17 @@ export async function main() {
1315
const vscode = await install();
1416

1517
console.log(heading('Install latest C/C++ Extension'));
16-
const result = await runVSCodeCommand([...vscode?.args ?? [], '--install-extension', 'ms-vscode.cpptools@1.31.4', '--pre-release'], options);
18+
const result = await runVSCodeCommand([...vscode?.args ?? [], '--install-extension', 'ms-vscode.cpptools', '--pre-release'], options);
1719
if (result.stdout) {
1820
console.log(result.stdout.toString());
1921
}
2022
if (result.stderr) {
2123
error(result.stderr.toString());
2224
}
2325

24-
await copy.main(isolated);
26+
const binaryVersion = await copy.main(isolated);
27+
if (binaryVersion) {
28+
await writeFile(join($root, 'bin', 'binaryVersion.json'), JSON.stringify({ version: binaryVersion }));
29+
note(`Wrote binary version ${binaryVersion} to bin/binaryVersion.json`);
30+
}
2531
}

Extension/test/common/selectTests.ts

Lines changed: 67 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
* See 'LICENSE' in the project root for license information.
44
* ------------------------------------------------------------------------------------------ */
55

6-
import { readdir } from 'fs/promises';
7-
import { IOptions, glob as globSync } from 'glob';
8-
import Mocha from 'mocha';
6+
import { readdir, readFile } from 'fs/promises';
7+
import { glob as globSync, IOptions } from 'glob';
8+
import * as Mocha from 'mocha';
99
import { basename, dirname, resolve } from 'path';
1010
import { env } from 'process';
1111
import { promisify } from 'util';
@@ -73,6 +73,41 @@ export async function getTestInfo(...scenarioOptions: (string | undefined)[]) {
7373
return undefined;
7474
}
7575

76+
/**
77+
* When running tests on GitHub, this function determines if the tests should be skipped based on
78+
* whether the binary version copied for tests is compatible with the minimum required version.
79+
* The minimum required binary version is defined in the `binaryCompat.json` file and changes when
80+
* there are breaking changes in the communication protocol or messages.
81+
*
82+
* When running locally, the function will always return false since you're expected to have the
83+
* correct binaries available.
84+
* @returns A promise that resolves to a boolean indicating whether the tests should be skipped.
85+
*/
86+
async function shouldSkipTests(): Promise<boolean> {
87+
try {
88+
const binaryVersion = JSON.parse(await readFile(`${$root}/bin/binaryVersion.json`, 'utf-8')) as { version: string } | undefined;
89+
const binaryCompat = JSON.parse(await readFile(`${$root}/test/minBinaryVersion.json`, 'utf-8')) as { minBinaryVersion: string } | undefined;
90+
if (binaryCompat?.minBinaryVersion && binaryVersion?.version) {
91+
const minParts = binaryCompat.minBinaryVersion.split('.').map(Number);
92+
const actualParts = binaryVersion.version.split('.').map(Number);
93+
const maxLen = Math.max(minParts.length, actualParts.length);
94+
let tooOld = false;
95+
for (let i = 0; i < maxLen; i++) {
96+
const diff = (actualParts[i] ?? 0) - (minParts[i] ?? 0);
97+
if (diff < 0) { tooOld = true; break; }
98+
if (diff > 0) { break; }
99+
}
100+
if (tooOld) {
101+
console.warn(`\nBinary-dependent tests SKIPPED: installed binary version ${binaryVersion.version} is below the required minimum ${binaryCompat.minBinaryVersion}.`);
102+
console.warn(`Tests will re-enable automatically once binaries >= ${binaryCompat.minBinaryVersion} are installed.\n`);
103+
return true;
104+
}
105+
}
106+
} catch {
107+
}
108+
return false;
109+
}
110+
76111
export function run(testsRoot: string, cb: (error: any, failures?: number) => void): void {
77112
/**
78113
* This code runs in the extension host process, and not in the launch (main.ts) process.
@@ -89,32 +124,35 @@ export function run(testsRoot: string, cb: (error: any, failures?: number) => vo
89124
}
90125
const { name } = testInfo;
91126

92-
void glob(`${$root}/dist/test/scenarios/${name}/tests/**/**.test.js`).then((files) => {
93-
94-
try {
95-
if (!files.length) {
96-
throw new Error(`Unable to find unit tests for ${name} at '${$root}/dist/test/scenarios/${name}/tests/**/**.test.js'`);
97-
}
98-
const mocha = new Mocha({
99-
ui: 'tdd',
100-
timeout: 500000,
101-
require: ['source-map-support/register'],
102-
color: true
103-
});
104-
105-
// Add files to the test suite
106-
files.forEach(f => mocha.addFile(resolve(testsRoot, f)));
107-
108-
console.log('\n\n=============================================\n Test Output\n\n');
109-
// Run the mocha test
110-
mocha.run((failures: any) => {
111-
cb(null, failures);
112-
console.log('\n\n=============================================\n\n');
113-
});
114-
} catch (err) {
115-
console.error(err);
116-
cb(err);
127+
if (await shouldSkipTests()) {
128+
cb(null, 0);
129+
return;
130+
}
131+
132+
const files = await glob(`${$root}/dist/test/scenarios/${name}/tests/**/**.test.js`);
133+
try {
134+
if (!files.length) {
135+
throw new Error(`Unable to find unit tests for ${name} at '${$root}/dist/test/scenarios/${name}/tests/**/**.test.js'`);
117136
}
118-
});
137+
const mocha = new Mocha({
138+
ui: 'tdd',
139+
timeout: 500000,
140+
require: ['source-map-support/register'],
141+
color: true
142+
});
143+
144+
// Add files to the test suite
145+
files.forEach(f => mocha.addFile(resolve(testsRoot, f)));
146+
147+
console.log('\n\n=============================================\n Test Output\n\n');
148+
// Run the mocha test
149+
mocha.run((failures: any) => {
150+
cb(null, failures);
151+
console.log('\n\n=============================================\n\n');
152+
});
153+
} catch (err) {
154+
console.error(err);
155+
cb(err);
156+
}
119157
});
120158
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"minBinaryVersion": "1.33.0"
3+
}

0 commit comments

Comments
 (0)