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

Test Explorer - Part 1 #3032

Merged
merged 7 commits into from
Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from 6 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
30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,24 @@
"when": "cmake:enableFullFeatureSet",
"category": "CMake"
},
{
"command": "cmake.revealTestExplorer",
"title": "%cmake-tools.command.cmake.revealTestExplorer.title%",
"when": "cmake:enableFullFeatureSet",
"category": "CMake"
},
{
"command": "cmake.refreshTests",
"title": "%cmake-tools.command.cmake.refreshTests.title%",
"when": "cmake:enableFullFeatureSet",
"category": "CMake"
},
{
"command": "cmake.refreshTestsAll",
"title": "%cmake-tools.command.cmake.refreshTestsAll.title%",
"when": "cmake:enableFullFeatureSet",
"category": "CMake"
},
{
"command": "cmake.editCache",
"title": "%cmake-tools.command.cmake.editCache.title%",
Expand Down Expand Up @@ -676,6 +694,18 @@
"command": "cmake.ctestAll",
"when": "cmake:multiProject && cmake:enableFullFeatureSet"
},
{
"command": "cmake.revealTestExplorer",
"when": "cmake:enableFullFeatureSet"
},
{
"command": "cmake.refreshTests",
"when": "cmake:enableFullFeatureSet"
},
{
"command": "cmake.refreshTestsAll",
"when": "cmake:enableFullFeatureSet"
},
{
"when": "cmake:enableFullFeatureSet",
"command": "cmake.editCache"
Expand Down
3 changes: 3 additions & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
"cmake-tools.command.cmake.cleanRebuildAll.title": "Clean Rebuild All Projects",
"cmake-tools.command.cmake.ctest.title": "Run Tests",
"cmake-tools.command.cmake.ctestAll.title": "Run Tests for All Projects",
"cmake-tools.command.cmake.revealTestExplorer.title": "Reveal Test Explorer",
"cmake-tools.command.cmake.refreshTests.title": "Refresh Tests",
"cmake-tools.command.cmake.refreshTestsAll.title": "Refresh Tests for All Projects",
"cmake-tools.command.cmake.editCache.title": "Edit CMake Cache",
"cmake-tools.command.cmake.quickStart.title": "Quick Start",
"cmake-tools.command.cmake.debugTarget.title": "Debug",
Expand Down
68 changes: 41 additions & 27 deletions src/cmakeProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
ExecutableTarget,
NoGeneratorError
} from '@cmt/drivers/drivers';
import { CTestDriver, BasicTestResults } from './ctest';
import { CTestDriver } from './ctest';
import { CMakeBuildConsumer } from './diagnostics/build';
import { CMakeOutputConsumer } from './diagnostics/cmake';
import { FileDiagnostic, populateCollection } from './diagnostics/util';
Expand All @@ -45,6 +45,7 @@ import { Environment, EnvironmentUtils } from './environmentVariables';
import { KitsController } from './kitsController';
import { PresetsController } from './presetsController';
import paths from './paths';
import { ProjectController } from './projectController';

nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
Expand Down Expand Up @@ -119,18 +120,21 @@ export class CMakeProject {
private wasUsingCMakePresets: boolean | undefined;
private onDidOpenTextDocumentListener: vscode.Disposable | undefined;
private disposables: vscode.Disposable[] = [];
private readonly cTestController: CTestDriver;
private readonly onUseCMakePresetsChangedEmitter = new vscode.EventEmitter<boolean>();
public kitsController!: KitsController;
public presetsController!: PresetsController;

/**
* Construct a new instance. The instance isn't ready, and must be initalized.
* @param projectController Required for test explorer to work properly. Setting as optional to avoid breaking tests.
*
* This is private. You must call `create` to get an instance.
*/
private constructor(readonly workspaceContext: DirectoryContext, readonly isMultiProjectFolder: boolean = false) {
private constructor(readonly workspaceContext: DirectoryContext, projectController?: ProjectController, readonly isMultiProjectFolder: boolean = false) {
// Handle the active kit changing. We want to do some updates and teardown
log.debug(localize('constructing.cmakeproject', 'Constructing new CMakeProject instance'));
this.cTestController = new CTestDriver(workspaceContext, projectController);
this.onCodeModelChanged(FireLate, (_) => this._codeModelChangedApiEventEmitter.fire());
}

Expand Down Expand Up @@ -482,17 +486,6 @@ export class CMakeProject {
}
private readonly _ctestEnabled = new Property<boolean>(false);

/**
* The current CTest results
*/
get testResults() {
return this._testResults.value;
}
get onTestResultsChanged() {
return this._testResults.changeEvent;
}
private readonly _testResults = new Property<BasicTestResults | null>(null);

/**
* Whether the backend is busy running some task
*/
Expand Down Expand Up @@ -591,7 +584,7 @@ export class CMakeProject {
if (drv) {
await drv.asyncDispose();
}
for (const disp of [this.statusMessage, this.targetName, this.activeVariant, this._ctestEnabled, this._testResults, this.isBusy, this.variantManager, this.cTestController]) {
for (const disp of [this.statusMessage, this.targetName, this.activeVariant, this._ctestEnabled, this.isBusy, this.variantManager, this.cTestController]) {
disp.dispose();
}
}
Expand Down Expand Up @@ -824,7 +817,7 @@ export class CMakeProject {

await drv.setVariant(this.variantManager.activeVariantOptions, this.variantManager.activeKeywordSetting);
this.targetName.set(this.defaultBuildTarget || (this.useCMakePresets ? this.targetsInPresetName : drv.allTargetName));
await this.cTestController.reloadTests(drv);
await this.cTestController.refreshTests(drv);

// All set up. Fulfill the driver promise.
return drv;
Expand Down Expand Up @@ -913,7 +906,6 @@ export class CMakeProject {
});
});
this.cTestController.onTestingEnabledChanged(enabled => this._ctestEnabled.set(enabled));
this.cTestController.onResultsChanged(res => this._testResults.set(res));

this.statusMessage.set(localize('ready.status', 'Ready'));

Expand Down Expand Up @@ -1147,13 +1139,14 @@ export class CMakeProject {
/**
* Create an instance asynchronously
* @param extensionContext The extension context
* @param projectController Required for test explorer to work properly. Setting as optional to avoid breaking tests.
*
* The purpose of making this the only way to create an instance is to prevent
* us from creating uninitialized instances of the CMake Tools extension.
*/
static async create(workspaceContext: DirectoryContext, sourceDirectory: string, isMultiProjectFolder?: boolean): Promise<CMakeProject> {
static async create(workspaceContext: DirectoryContext, sourceDirectory: string, projectController?: ProjectController, isMultiProjectFolder?: boolean): Promise<CMakeProject> {
log.debug(localize('safely.constructing.cmakeproject', 'Safe constructing new CMakeProject instance'));
const inst = new CMakeProject(workspaceContext, isMultiProjectFolder);
const inst = new CMakeProject(workspaceContext, projectController, isMultiProjectFolder);
await inst.init(sourceDirectory);
log.debug(localize('initialization.complete', 'CMakeProject instance initialization complete.'));
return inst;
Expand Down Expand Up @@ -1272,7 +1265,7 @@ export class CMakeProject {
if (result === 0) {
await this.refreshCompileDatabase(drv.expansionOptions);
}
await this.cTestController.reloadTests(drv);
await this.cTestController.refreshTests(drv);
this.onReconfiguredEmitter.fire();
return result;
}
Expand Down Expand Up @@ -1340,7 +1333,7 @@ export class CMakeProject {
await this.refreshCompileDatabase(drv.expansionOptions);
}

await this.cTestController.reloadTests(drv);
await this.cTestController.refreshTests(drv);
this.onReconfiguredEmitter.fire();
return result;
} finally {
Expand Down Expand Up @@ -1821,25 +1814,46 @@ export class CMakeProject {
return this.build();
}

private readonly cTestController = new CTestDriver(this.workspaceContext);

public async runCTestCustomized(driver: CMakeDriver, testPreset?: preset.TestPreset, consumer?: proc.OutputConsumer) {
return this.cTestController.runCTest(driver, true, testPreset, consumer);
}

async ctest(): Promise<number> {

private async preTest(): Promise<CMakeDriver> {
const buildResult = await this.build(undefined, false, false);
if (buildResult !== 0) {
this.cTestController.markAllCurrentTestsAsNotRun();
return buildResult;
throw new Error(localize('build.failed', 'Build failed.'));
}

const drv = await this.getCMakeDriverInstance();
if (!drv) {
throw new Error(localize('driver.died.after.build.succeeded', 'CMake driver died immediately after build succeeded.'));
}
return await this.cTestController.runCTest(drv) || -1;
return drv;
}

async ctest(): Promise<number> {
const drv = await this.preTest();
return (await this.cTestController.runCTest(drv)) ? 0 : -1;
}

async revealTestExplorer() {
if (!await this.cTestController.revealTestExplorer()) {
await this.refreshTests();
return this.cTestController.revealTestExplorer();
}
}

async refreshTests(): Promise<number> {
const drv = await this.preTest();
return this.cTestController.refreshTests(drv);
}

addTestExplorerRoot(folder: string) {
return this.cTestController.addTestExplorerRoot(folder);
}

removeTestExplorerRoot(folder: string) {
return this.cTestController.removeTestExplorerRoot(folder);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/cmakeTaskProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,13 +518,13 @@ export class CustomBuildTaskTerminal implements vscode.Pseudoterminal, proc.Outp
return;
}
}
const result: number | null | undefined = cmakeDriver ? await project?.runCTestCustomized(cmakeDriver, testPreset, this) : undefined;
if (result === undefined || result === null) {
const result: number | undefined = cmakeDriver ? await project?.runCTestCustomized(cmakeDriver, testPreset, this) : undefined;
if (result === undefined) {
this.writeEmitter.fire(localize('ctest.run.terminated', 'CTest run was terminated') + endOfLine);
this.closeEmitter.fire(-1);
} else {
this.writeEmitter.fire(localize('ctest.finished.with.code', 'CTest finished with return code {0}', result) + endOfLine);
benmcmorran marked this conversation as resolved.
Show resolved Hide resolved
this.closeEmitter.fire(result);
this.writeEmitter.fire(localize('ctest.finished', 'CTest finished') + endOfLine);
this.closeEmitter.fire(0);
}
} else {
log.debug(localize("cmake.driver.not.found", 'CMake driver not found.'));
Expand Down
Loading