Skip to content

Commit

Permalink
Categorise test cases into test suite(s)
Browse files Browse the repository at this point in the history
Meson test cases may belong to test suite(s). If so, in VSCode's
"Testing" feature from the Activity Bar, add the test suite(s) as a
parent item and add the test cases as children.

The user has the choice to run all tests belonging to a test suite.
Will pass the test suite to the meson test command --suite. The option
--suite is needed to run test cases that the meson config purposely
excludes (for example, test suite "flaky").

Fixes mesonbuild#245

Quote the "test case" in the meson command, so can run test cases with a
space in the name. The quotes are needed because `cp.ExecFileOptions`
sets `shell=true`.

Fixes mesonbuild#256
  • Loading branch information
cskeogh committed Jun 30, 2024
1 parent f59c628 commit bf2e8f9
Showing 1 changed file with 76 additions and 10 deletions.
86 changes: 76 additions & 10 deletions src/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,73 @@ import { Tests, DebugEnvironmentConfiguration } from "./types";
import { getMesonTests, getMesonTargets } from "./introspection";
import { workspaceState } from "./extension";

export async function rebuildTests(controller: vscode.TestController) {
let tests = await getMesonTests(workspaceState.get<string>("mesonbuild.buildDir")!);
function addMesonTestsToController(
controller: vscode.TestController,
tests: Tests,
): WeakMap<vscode.TestItem, boolean> | null {
/* returns a WeakMap (value True) for TestItems with corresponding Meson
* tests. If a TestItem is not in the WeakMap, then the TestItem is outdated.
* If 0 existing TestItems, then there is nothing outdated, returns null.
*/
const testsVisited = new WeakMap<vscode.TestItem, boolean>();
const emptyController = controller.items.size == 0;
for (const test of tests) {
if (test.suite == undefined || test.suite.length == 0) {
const testItem = controller.createTestItem(test.name, test.name);
controller.items.add(testItem);
if (!emptyController) {
testsVisited.set(testItem, true);
}
} else {
/* if test suite(s) are defined, create TestItems as children */
for (const suiteLabel of test.suite) {
let suite = controller.items.get(suiteLabel);
if (suite == undefined) {
suite = controller.createTestItem(suiteLabel, suiteLabel);
controller.items.add(suite);
}
if (!emptyController) {
testsVisited.set(suite, true);
}
let testItem = suite.children.get(test.name);
if (testItem == undefined) {
testItem = controller.createTestItem(test.name, test.name);
suite.children.add(testItem);
}
if (!emptyController) {
testsVisited.set(testItem, true);
}
}
}
}
return emptyController ? null : testsVisited;
}

controller.items.forEach((item) => {
if (!tests.some((test) => item.id == test.name)) {
controller.items.delete(item.id);
function deleteTestsFromControllerNotVisited(
controller: vscode.TestController,
testsVisited: WeakMap<vscode.TestItem, boolean>,
) {
for (const [test_id, test] of controller.items) {
if (testsVisited.get(test) == undefined) {
for (const [child_id] of test.children) {
test.children.delete(child_id);
}
controller.items.delete(test_id);
} else {
for (const [child_id, child] of test.children) {
if (testsVisited.get(child) == undefined) {
test.children.delete(child_id);
}
}
}
});
}
}

for (let testDescr of tests) {
let testItem = controller.createTestItem(testDescr.name, testDescr.name);
controller.items.add(testItem);
export async function rebuildTests(controller: vscode.TestController) {
let tests = await getMesonTests(workspaceState.get<string>("mesonbuild.buildDir")!);
const testsVisited = addMesonTestsToController(controller, tests);
if (testsVisited != null) {
deleteTestsFromControllerNotVisited(controller, testsVisited);
}
}

Expand All @@ -38,10 +93,21 @@ export async function testRunHandler(
for (let test of queue) {
run.started(test);
let starttime = Date.now();
let suite = "";
let testcase = "";
if (test.children.size > 0) {
suite = `--suite="${test.id}"`;
} else if (test.parent != undefined) {
suite = `--suite="${test.parent.id}"`;
testcase = `"${test.id}"`;
} else {
testcase = `"${test.id}"`;
}

try {
await exec(
extensionConfiguration("mesonPath"),
["test", "-C", buildDir, "--print-errorlog", test.id],
["test", "-C", buildDir, "--print-errorlog", suite, testcase],
extensionConfiguration("testEnvironment"),
);
let duration = Date.now() - starttime;
Expand Down

0 comments on commit bf2e8f9

Please sign in to comment.