Skip to content
This repository was archived by the owner on Apr 19, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
57 changes: 57 additions & 0 deletions src/cmake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,62 @@ export class CMakeTests {
let test = new CMakeTest();
test.command = testJSON.command;
test.cwd = testJSON.cwd;

// Extract environment information if present in ctest JSON.
// ctest may expose environment as `environment` (string or array),
// or embed it into `properties` either as an object or array.
try {
let envArr: string[] | undefined = undefined;

if (testJSON.environment) {
envArr = Array.isArray(testJSON.environment)
? testJSON.environment
: [testJSON.environment];
}

if (!envArr && testJSON.properties) {
const props = testJSON.properties;

// properties might be an object with ENVIRONMENT key or an array of {name,value} entries
if (!Array.isArray(props) && props.ENVIRONMENT) {
const val = props.ENVIRONMENT;
if (typeof val === "string") {
envArr = [val];
} else if (Array.isArray(val)) {
envArr = val;
}
} else if (Array.isArray(props)) {
for (const p of props) {
if (!p || !p.name) {
continue;
}
if (p.name === "ENVIRONMENT" || p.name === "Environment") {
const v = p.value;
if (typeof v === "string") {
envArr = [v];
} else if (Array.isArray(v)) {
envArr = v;
}
break;
}
}
}
}

if (envArr) {
test.environment = envArr;
}
} catch (e) {
try {
logMessage(
"ctest: failed to parse environment for test: " +
JSON.stringify(testJSON) +
" error: " +
e,
);
} catch (_) {}
}

return test;
});

Expand Down Expand Up @@ -270,6 +326,7 @@ export class CMakeTests {
export class CMakeTest {
public command: string[] = [];
public cwd: string = "";
public environment: string[] = [];

public id(): string {
return this.command.join(",");
Expand Down
28 changes: 26 additions & 2 deletions src/qttest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export class QtTest {
/// The list of individual runnable test slots
slots: QtTestSlot[] | null = null;

/// Environment variables coming from CTest (array of "VAR=VALUE")
environment: string[] = [];

/// Set after running
lastExitCode: number = 0;

Expand Down Expand Up @@ -77,6 +80,19 @@ export class QtTest {
return result;
}

private buildSpawnEnv(): NodeJS.ProcessEnv {
const env: NodeJS.ProcessEnv = Object.assign({}, process.env);
if (this.environment && Array.isArray(this.environment)) {
for (const kv of this.environment) {
const idx = kv.indexOf("=");
if (idx > -1) {
env[kv.substring(0, idx)] = kv.substring(idx + 1);
}
}
}
return env;
}

/**
* Calls "./yourqttest -functions" and stores the results in the slots property.
*/
Expand All @@ -93,6 +109,7 @@ export class QtTest {

const child = spawn(this.filename, ["-functions"], {
cwd: this.buildDirPath,
env: this.buildSpawnEnv(),
});

child.stdout.on("data", (chunk) => {
Expand Down Expand Up @@ -184,7 +201,9 @@ export class QtTest {
/// Note that if this is not a QtTest it might not run help and instead execute the test itself
public async isQtTestViaHelp(): Promise<boolean | undefined> {
return await new Promise((resolve, reject) => {
const child = spawn(this.filename, ["-help"]);
const child = spawn(this.filename, ["-help"], {
env: this.buildSpawnEnv(),
});
let output = "";
let result = false;
child.stdout.on("data", (chunk) => {
Expand Down Expand Up @@ -244,7 +263,10 @@ export class QtTest {
" with cwd=" +
cwdDir,
);
const child = spawn(this.filename, args, { cwd: cwdDir });
const child = spawn(this.filename, args, {
cwd: cwdDir,
env: this.buildSpawnEnv(),
});

if (this.outputFunc) {
// Callers wants the process output:
Expand Down Expand Up @@ -448,6 +470,8 @@ export class QtTests {
if (ctests) {
for (let ctest of ctests) {
let qtest = new QtTest(ctest.executablePath(), buildDirPath);
// Propagate environment from CTest metadata
qtest.environment = ctest.environment;
this.qtTestExecutables.push(qtest);
}
} else {
Expand Down
16 changes: 16 additions & 0 deletions src/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ async function runTests(buildDirPath: string) {
let qt = new QtTests();
await qt.discoverViaCMake(buildDirPath);

// Verify that environment properties from CTest were discovered for test1
const test1Exe = qt.qtTestExecutables.find((e) =>
e.filenameWithoutExtension().endsWith("test1"),
);
if (!test1Exe) {
console.error("Expected to find test1 executable after discovery");
process.exit(1);
}
if (!test1Exe.environment || !test1Exe.environment.includes("MY_ENV=VALUE")) {
console.error(
"Expected test1 to have environment MY_ENV=VALUE, got: " +
JSON.stringify(test1Exe.environment),
);
process.exit(1);
}

let expectedExecutables = [
"test/qt_test/build-dev/test1",
"test/qt_test/build-dev/test2",
Expand Down
1 change: 1 addition & 0 deletions test/qt_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ target_link_libraries(test3 Qt${QT_VERSION}::Test)

enable_testing()
add_test(NAME test1 COMMAND test1)
set_tests_properties(test1 PROPERTIES ENVIRONMENT "MY_ENV=VALUE")
add_test(NAME test2 COMMAND test2)
add_test(NAME test3 COMMAND test3)
add_test(NAME non_qttest COMMAND non_qttest)
Expand Down
2 changes: 1 addition & 1 deletion test/qt_test/test1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ private Q_SLOTS:
void testA() {
QBENCHMARK { int a = 1; }
}
void testB() {}
void testB() { QCOMPARE(qgetenv("MY_ENV"), QByteArray("VALUE")); }
void testC() { qDebug() << "MyTest::testC()"; }
void testXFAIL() {
QEXPECT_FAIL("", "To be fixed", Continue);
Expand Down
Loading