Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: CTest Test Suite Delimiter prevents running all tests (#4092) #4154

Merged
merged 5 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Improvements:

Bug Fixes:

- Fix issue where setting test suite delimiter prevent execution of all tests. [#4092](https://github.com/microsoft/vscode-cmake-tools/issues/4092)
- Fix our setting of `isUserPreset` for presets, only set it to `true` if it's defined in a user presets file. [#4059](https://github.com/microsoft/vscode-cmake-tools/issues/4059)
- Fix issue where duplicate presets are being listed in dropdown. [#4104](https://github.com/microsoft/vscode-cmake-tools/issues/4104)
- Fix various GCC compiler errors and GCC linker errors not showing up in Problems View [#2864](https://github.com/microsoft/vscode-cmake-tools/issues/2864)
Expand Down
71 changes: 49 additions & 22 deletions src/ctest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ interface SiteAttributes {}

type TestStatus = ('failed' | 'notrun' | 'passed');

type DriverMapT = Map<string, { driver: CMakeDriver; ctestPath: string; ctestArgs: string[]; tests: vscode.TestItem[] }>;

export interface TestMeasurement {
type: string;
name: string;
Expand Down Expand Up @@ -395,9 +397,34 @@ export class CTestDriver implements vscode.Disposable {
run.failed(test, message, duration);
}

private async runCTestHelper(tests: vscode.TestItem[], run: vscode.TestRun, cancellation: vscode.CancellationToken, driver?: CMakeDriver, ctestPath?: string, ctestArgs?: string[], customizedTask: boolean = false, consumer?: proc.OutputConsumer, entryPoint: RunCTestHelperEntryPoint = RunCTestHelperEntryPoint.RunTests): Promise<number> {
let returnCode: number = 0;
const driverMap = new Map<string, { driver: CMakeDriver; ctestPath: string; ctestArgs: string[]; tests: vscode.TestItem[]}>();
/**
* Retrieve the driver from the test in argument
*
* @param test : test to retrieve the driver from
* @returns : the driver
*/
private async getProjectDriver(test: vscode.TestItem): Promise<CMakeDriver> {
const folder = this.getTestRootFolder(test);
const project = await this.projectController?.getProjectForFolder(folder);
if (!project) {
throw new Error(localize('no.project.found', 'No project found for folder {0}', folder));
}
const _driver = await project.getCMakeDriverInstance();
if (!_driver) {
throw new Error(localize('no.driver.found', 'No driver found for folder {0}', folder));
}
return _driver;
}

/**
* Recursively collect all tests informations among all the test suite tree and store them in the driverMap
*
*/
private async fillDriverMap(tests: vscode.TestItem[], run: vscode.TestRun, cancellation: vscode.CancellationToken, driverMap?: DriverMapT, driver?: CMakeDriver, ctestPath?: string, ctestArgs?: string[], customizedTask: boolean = false): Promise<void> {
let _driverMap = new Map<string, { driver: CMakeDriver; ctestPath: string; ctestArgs: string[]; tests: vscode.TestItem[] }>();
if (driverMap) {
_driverMap = driverMap;
}

/**
* Loop through the tests and get the driver, ctestPath, ctestArgs for each test. Construct a map for each soure directory, mapping drivers to tests.
Expand All @@ -407,15 +434,10 @@ export class CTestDriver implements vscode.Disposable {
if (driver) {
_driver = driver;
} else {
const folder = this.getTestRootFolder(test);
const project = await this.projectController?.getProjectForFolder(folder);
if (!project) {
this.ctestErrored(test, run, { message: localize('no.project.found', 'No project found for folder {0}', folder) });
continue;
}
_driver = await project.getCMakeDriverInstance();
if (!_driver) {
this.ctestErrored(test, run, { message: localize('no.driver.found', 'No driver found for folder {0}', folder) });
try {
_driver = await this.getProjectDriver(test);
} catch (err: any) {
this.ctestErrored(test, run, { message: err.message });
continue;
}
}
Expand Down Expand Up @@ -444,21 +466,26 @@ export class CTestDriver implements vscode.Disposable {
}

if (test.children.size > 0) {
// Shouldn't reach here now, but not hard to write so keeping it in case we want to have more complicated test hierarchies
// If test has children then it is a suite, so we need to recursively call this function
const children = this.testItemCollectionToArray(test.children);
if (await this.runCTestHelper(children, run, cancellation, _driver, _ctestPath, _ctestArgs, customizedTask, consumer, entryPoint)) {
returnCode = -1;
}
return returnCode;
await this.fillDriverMap(children, run, cancellation, _driverMap, _driver, _ctestPath, _ctestArgs, customizedTask);
} else {
if (!driverMap.has(_driver.sourceDir)) {
driverMap.set(_driver.sourceDir, { driver: _driver, ctestPath: _ctestPath, ctestArgs: _ctestArgs, tests: [test] });
// If test has no children, it is a leaf of the test suite hierarchy so add its characteristics to the driver map
if (!_driverMap.has(_driver.sourceDir)) {
_driverMap.set(_driver.sourceDir, { driver: _driver, ctestPath: _ctestPath, ctestArgs: _ctestArgs, tests: [test] });
} else {
const d = driverMap.get(_driver.sourceDir);
driverMap.set(_driver.sourceDir, { driver: d!.driver, ctestPath: d!.ctestPath, ctestArgs: d!.ctestArgs, tests: d!.tests.concat(test) });
const d = _driverMap.get(_driver.sourceDir);
_driverMap.set(_driver.sourceDir, { driver: d!.driver, ctestPath: d!.ctestPath, ctestArgs: d!.ctestArgs, tests: d!.tests.concat(test) });
}
}
}
};

private async runCTestHelper(tests: vscode.TestItem[], run: vscode.TestRun, cancellation: vscode.CancellationToken, driver?: CMakeDriver, ctestPath?: string, ctestArgs?: string[], customizedTask: boolean = false, consumer?: proc.OutputConsumer, entryPoint: RunCTestHelperEntryPoint = RunCTestHelperEntryPoint.RunTests): Promise<number> {
let returnCode: number = 0;
const driverMap = new Map<string, { driver: CMakeDriver; ctestPath: string; ctestArgs: string[]; tests: vscode.TestItem[] }>();

await this.fillDriverMap(tests, run, cancellation, driverMap, driver, ctestPath, ctestArgs, customizedTask);

if (!this.ws.config.ctestAllowParallelJobs) {
for (const driver of driverMap.values()) {
Expand Down Expand Up @@ -777,7 +804,7 @@ export class CTestDriver implements vscode.Disposable {
}
}

const testAndParentSuite = this.createTestItemAndSuiteTree(test.name, testExplorerRoot, initializedTestExplorer, testDefFile ? vscode.Uri.file(testDefFile) : undefined);
const testAndParentSuite = this.createTestItemAndSuiteTree(test.name, testExplorerRoot, initializedTestExplorer, testDefFile ? vscode.Uri.file(testDefFile) : undefined);
const testItem = testAndParentSuite.test;
const parentSuiteItem = testAndParentSuite.parentSuite;

Expand Down
Loading