From a98c92d2eff55037b011a37dffb069c009419df5 Mon Sep 17 00:00:00 2001 From: snehara99 Date: Mon, 31 Jul 2023 15:07:19 -0700 Subject: [PATCH] allowed a way to run jobs in parallel --- CHANGELOG.md | 1 + package.json | 6 ++++ package.nls.json | 6 +++- src/config.ts | 9 ++++-- src/ctest.ts | 50 +++++++++++++++++++++++++++++++++- test/unit-tests/config.test.ts | 4 ++- 6 files changed, 71 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb905c36d..75da1bd51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Bug Fixes: - IntelliSense resolves headers coming from MacOS frameworks. CMake 3.27 or later is required. [#2324](https://github.com/microsoft/vscode-cmake-tools/issues/2324) - Don't ignore empty cache string variables when configuring from presets. [#1842](https://github.com/microsoft/vscode-cmake-tools/issues/1842) - Fix active build configuration warning coming from CppTools. [#2353](https://github.com/microsoft/vscode-cmake-tools/issues/2353) +- Allow a way to run ctests in parallel by setting `cmake.ctest.allowParallelJobs` to `true`. []() Improvements: - Decreased the number of cases where we reconfigure erroneously upon usage of `cmake.getLaunchTargetPath`. [#2878](https://github.com/microsoft/vscode-cmake-tools/issues/2878) diff --git a/package.json b/package.json index 5565219f5..576878089 100644 --- a/package.json +++ b/package.json @@ -1656,6 +1656,12 @@ "description": "%cmake-tools.configuration.cmake.ctest.parallelJobs.description%", "scope": "resource" }, + "cmake.ctest.allowParallelJobs": { + "type": "boolean", + "default": false, + "description": "%cmake-tools.configuration.cmake.ctest.allowParallelJobs.description%", + "scope": "window" + }, "cmake.parseBuildDiagnostics": { "type": "boolean", "default": true, diff --git a/package.nls.json b/package.nls.json index 009741f8a..4a64d7a89 100644 --- a/package.nls.json +++ b/package.nls.json @@ -86,7 +86,11 @@ "cmake-tools.configuration.cmake.buildToolArgs.description": "Additional arguments to pass to the underlying build tool when building.", "cmake-tools.configuration.cmake.parallelJobs.description": "The number of parallel build jobs. Use zero to automatically detect the number of CPUs. Setting this to 1 will omit the parallelism flag (-j) from the underlying build command, which has a generator-dependent effect on build parallelism.", "cmake-tools.configuration.cmake.ctestPath.description": "Path to CTest executable. If null, will be inferred from cmake.cmakePath (recommended to leave null).", - "cmake-tools.configuration.cmake.ctest.parallelJobs.description": "The number of parallel test jobs. Use zero to use the value of cmake.parallelJobs.", + "cmake-tools.configuration.cmake.ctest.parallelJobs.description": { + "message": "The number of parallel test jobs. Use zero to use the value of cmake.parallelJobs. This only works when `#cmake.ctest.allowParallelJobs` is set to `true`.", + "comment": "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." + }, + "cmake-tools.configuration.cmake.ctest.allowParallelJobs.description": "Allows ctests to be run in parallel, however the result output may be garbled as a result.", "cmake-tools.configuration.cmake.parseBuildDiagnostics.description": "Parse compiler output for warnings and errors.", "cmake-tools.configuration.cmake.enabledOutputParsers.description": { "message": "Output parsers to use. Supported parsers `cmake`, `gcc`, `gnuld` for GNULD-style linker output, `msvc` for Microsoft Visual C++, `ghs` for the Green Hills compiler with --no_wrap_diagnostics --brief_diagnostics, and `diab` for the Wind River Diab compiler.", diff --git a/src/config.ts b/src/config.ts index 0b9676cf3..bf7420382 100644 --- a/src/config.ts +++ b/src/config.ts @@ -107,8 +107,9 @@ export interface ExtensionConfigurationSettings { buildArgs: string[]; buildToolArgs: string[]; parallelJobs: number | undefined; + allowParallelJobs: boolean; ctestPath: string; - ctest: { parallelJobs: number }; + ctest: { parallelJobs: number; allowParallelJobs: boolean }; parseBuildDiagnostics: boolean; enabledOutputParsers: string[]; debugConfig: CppDebugConfiguration; @@ -301,6 +302,9 @@ export class ConfigurationReader implements vscode.Disposable { get ctestParallelJobs(): number | null { return this.configData.ctest.parallelJobs; } + get ctestAllowParallelJobs(): boolean { + return this.configData.ctest.allowParallelJobs; + } get parseBuildDiagnostics(): boolean { return !!this.configData.parseBuildDiagnostics; } @@ -483,8 +487,9 @@ export class ConfigurationReader implements vscode.Disposable { buildArgs: new vscode.EventEmitter(), buildToolArgs: new vscode.EventEmitter(), parallelJobs: new vscode.EventEmitter(), + allowParallelJobs: new vscode.EventEmitter(), ctestPath: new vscode.EventEmitter(), - ctest: new vscode.EventEmitter<{ parallelJobs: number }>(), + ctest: new vscode.EventEmitter<{ parallelJobs: number; allowParallelJobs: boolean }>(), parseBuildDiagnostics: new vscode.EventEmitter(), enabledOutputParsers: new vscode.EventEmitter(), debugConfig: new vscode.EventEmitter(), diff --git a/src/ctest.ts b/src/ctest.ts index 5089d5b5f..6b28c31d8 100644 --- a/src/ctest.ts +++ b/src/ctest.ts @@ -285,13 +285,61 @@ export class CTestDriver implements vscode.Disposable { if (!testExplorer) { log.info(localize('no.tests.found', 'No tests found')); return -1; - } else { + } else if (!this.ws.config.ctestAllowParallelJobs) { const tests = this.testItemCollectionToArray(testExplorer.items); const run = testExplorer.createTestRun(new vscode.TestRunRequest()); const ctestArgs = await this.getCTestArgs(driver, customizedTask, testPreset); const returnCode = await this.runCTestHelper(tests, run, driver, undefined, ctestArgs, undefined, customizedTask, consumer); run.end(); return returnCode; + } else { + // below code taken from #3032 PR (before changes in how tests are run) + const ctestpath = await this.ws.getCTestPath(driver.cmakePathFromPreset); + if (ctestpath === null) { + log.info(localize('ctest.path.not.set', 'CTest path is not set')); + return -2; + } + + let ctestArgs: string[]; + if (customizedTask && testPreset) { + ctestArgs = ['-T', 'test'].concat(testArgs(testPreset)); + } else if (!customizedTask && driver.useCMakePresets) { + if (!driver.testPreset) { + log.error(localize('test.preset.not.set', 'Test preset is not set')); + return -3; + } + // Add a few more args so we can show the result in status bar + ctestArgs = ['-T', 'test'].concat(testArgs(driver.testPreset)); + } else { + const configuration = driver.currentBuildType; + const opts = driver.expansionOptions; + const jobs = await expandString(this.ws.config.numCTestJobs, opts); + const defaultArgs = []; + for (const value of this.ws.config.ctestDefaultArgs) { + defaultArgs.push(await expandString(value, opts)); + } + const args = []; + for (const value of this.ws.config.ctestArgs) { + args.push(await expandString(value, opts)); + } + ctestArgs = [`-j${jobs}`, '-C', configuration].concat(defaultArgs, args); + } + + const child = driver.executeCommand( + ctestpath, + ctestArgs, + ((customizedTask && consumer) ? consumer : new CTestOutputLogger()), + { environment: await driver.getCTestCommandEnvironment(), cwd: driver.binaryDir }); + const res = await child.result; + // not sure if direct comparison can be made to replace reloadTests with refreshTests + await this.refreshTests(driver); + if (res.retc === null) { + log.info(localize('ctest.run.terminated', 'CTest run was terminated')); + return -1; + } else { + log.info(localize('ctest.finished.with.code', 'CTest finished with return code {0}', res.retc)); + } + return res.retc; } } diff --git a/test/unit-tests/config.test.ts b/test/unit-tests/config.test.ts index 0b0211e71..0858e7bae 100644 --- a/test/unit-tests/config.test.ts +++ b/test/unit-tests/config.test.ts @@ -21,9 +21,11 @@ function createConfig(conf: Partial): Configurat buildArgs: [], buildToolArgs: [], parallelJobs: 0, + allowParallelJobs: false, ctestPath: '', ctest: { - parallelJobs: 0 + parallelJobs: 0, + allowParallelJobs: false }, parseBuildDiagnostics: true, enabledOutputParsers: [],