@iamsergio/qttest-utils 2.1.1 โ 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog +28 -0
- package/out/cmake.d.ts +3 -2
- package/out/cmake.js +33 -18
- package/out/qttest.js +32 -13
- package/out/test.js +62 -4
- package/package.json +1 -1
package/Changelog
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
## [2.2.1] - 2024-05-02
|
|
6
|
+
|
|
7
|
+
### ๐ Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Fix running non-Qt tests
|
|
10
|
+
- Harden code against exception when reading .tap file
|
|
11
|
+
|
|
12
|
+
### ๐งช Testing
|
|
13
|
+
|
|
14
|
+
- Try fixing tests on macOS/Windows
|
|
15
|
+
- Try harder to fix macOS/Windows tests
|
|
16
|
+
|
|
17
|
+
### โ๏ธ Miscellaneous Tasks
|
|
18
|
+
|
|
19
|
+
- Ran code format on tests
|
|
20
|
+
- Run codeformat on qttest.ts
|
|
21
|
+
|
|
22
|
+
## [2.2.0] - 2024-04-25
|
|
23
|
+
|
|
24
|
+
### ๐ Features
|
|
25
|
+
|
|
26
|
+
- Allow to workaround microsoft/vscode-cmake-tools-api/issues/7
|
|
27
|
+
|
|
28
|
+
### โ๏ธ Miscellaneous Tasks
|
|
29
|
+
|
|
30
|
+
- Bump version
|
|
31
|
+
|
|
5
32
|
## [2.1.1] - 2024-04-25
|
|
6
33
|
|
|
7
34
|
### ๐ Bug Fixes
|
|
@@ -11,6 +38,7 @@
|
|
|
11
38
|
### โ๏ธ Miscellaneous Tasks
|
|
12
39
|
|
|
13
40
|
- Improve CONTRIBUTING.md
|
|
41
|
+
- Bump version
|
|
14
42
|
|
|
15
43
|
## [2.1.0] - 2024-04-25
|
|
16
44
|
|
package/out/cmake.d.ts
CHANGED
|
@@ -13,8 +13,9 @@ export declare class CMakeTests {
|
|
|
13
13
|
*/
|
|
14
14
|
tests(): Promise<CMakeTest[] | undefined>;
|
|
15
15
|
private ctestJsonToList;
|
|
16
|
-
targetNameForExecutable(executable: string, codemodel: any): string | undefined;
|
|
17
|
-
|
|
16
|
+
targetNameForExecutable(executable: string, codemodel: any, workaround?: boolean): string | undefined;
|
|
17
|
+
filenamesAreEqual(file1: string, file2: string, workaround?: boolean): boolean;
|
|
18
|
+
cppFilesForExecutable(executable: string, codemodel: any, workaround?: boolean): string[];
|
|
18
19
|
}
|
|
19
20
|
export declare class CMakeTest {
|
|
20
21
|
command: string[];
|
package/out/cmake.js
CHANGED
|
@@ -74,13 +74,7 @@ class CMakeTests {
|
|
|
74
74
|
}
|
|
75
75
|
/// Returns the cmake target name for the specified executable
|
|
76
76
|
/// codemodel should have a "projects" key at root.
|
|
77
|
-
targetNameForExecutable(executable, codemodel) {
|
|
78
|
-
// simplify:
|
|
79
|
-
if (executable.endsWith(".exe")) {
|
|
80
|
-
executable = executable.substring(0, executable.length - 4);
|
|
81
|
-
}
|
|
82
|
-
// replace backslashes with forward slashes
|
|
83
|
-
executable = executable.replace(/\\/g, "/");
|
|
77
|
+
targetNameForExecutable(executable, codemodel, workaround = false) {
|
|
84
78
|
let projects = codemodel["projects"];
|
|
85
79
|
if (!projects)
|
|
86
80
|
return undefined;
|
|
@@ -96,9 +90,7 @@ class CMakeTests {
|
|
|
96
90
|
if (artifact.endsWith(".exe")) {
|
|
97
91
|
artifact = artifact.substring(0, artifact.length - 4);
|
|
98
92
|
}
|
|
99
|
-
|
|
100
|
-
artifact = artifact.replace(/\\/g, "/");
|
|
101
|
-
if (artifact == executable) {
|
|
93
|
+
if (this.filenamesAreEqual(executable, artifact, workaround)) {
|
|
102
94
|
let name = target["name"];
|
|
103
95
|
if (name) {
|
|
104
96
|
// We found the target name
|
|
@@ -110,16 +102,39 @@ class CMakeTests {
|
|
|
110
102
|
}
|
|
111
103
|
return undefined;
|
|
112
104
|
}
|
|
105
|
+
/// Returns whether the two filenames are equal
|
|
106
|
+
/// If workaround is true, then we workaround microsoft/vscode-cmake-tools-api/issues/7 where
|
|
107
|
+
/// the basename is correct but the path is bogus, and we only compare the basenames
|
|
108
|
+
filenamesAreEqual(file1, file2, workaround = false) {
|
|
109
|
+
if (file1.endsWith(".exe"))
|
|
110
|
+
file1 = file1.substring(0, file1.length - 4);
|
|
111
|
+
if (file2.endsWith(".exe"))
|
|
112
|
+
file2 = file2.substring(0, file2.length - 4);
|
|
113
|
+
file1 = file1.replace(/\\/g, "/");
|
|
114
|
+
file2 = file2.replace(/\\/g, "/");
|
|
115
|
+
if (process.platform === "win32") {
|
|
116
|
+
file1 = file1.toLowerCase();
|
|
117
|
+
file2 = file2.toLowerCase();
|
|
118
|
+
}
|
|
119
|
+
if (file1 == file2)
|
|
120
|
+
return true;
|
|
121
|
+
if (!workaround) {
|
|
122
|
+
// files aren't equal!
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
const fs = require('fs');
|
|
126
|
+
if (fs.existsSync(file2)) {
|
|
127
|
+
// It's a real file, not bogus.
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
/// Compare only basename, since path is bogus
|
|
131
|
+
return path_1.default.basename(file1, ".exe") == path_1.default.basename(file2, ".exe");
|
|
132
|
+
}
|
|
113
133
|
/// Returns the list of .cpp files for the specified executable
|
|
114
134
|
/// codemodel is the CMake codemodel JSON object
|
|
115
135
|
/// codemodel should have a "projects" key at root.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (executable.endsWith(".exe")) {
|
|
119
|
-
executable = executable.substring(0, executable.length - 4);
|
|
120
|
-
}
|
|
121
|
-
// replace backslashes with forward slashes
|
|
122
|
-
executable = executable.replace(/\\/g, "/");
|
|
136
|
+
/// @param workaround If true, worksaround https://github.com/microsoft/vscode-cmake-tools-api/issues/7
|
|
137
|
+
cppFilesForExecutable(executable, codemodel, workaround = false) {
|
|
123
138
|
let projects = codemodel["projects"];
|
|
124
139
|
if (!projects)
|
|
125
140
|
return [];
|
|
@@ -141,7 +156,7 @@ class CMakeTests {
|
|
|
141
156
|
}
|
|
142
157
|
// replace backslashes with forward slashes
|
|
143
158
|
artifact = artifact.replace(/\\/g, "/");
|
|
144
|
-
if (artifact
|
|
159
|
+
if (this.filenamesAreEqual(executable, artifact, workaround)) {
|
|
145
160
|
let fileGroups = target["fileGroups"];
|
|
146
161
|
if (!fileGroups)
|
|
147
162
|
continue;
|
package/out/qttest.js
CHANGED
|
@@ -102,7 +102,9 @@ class QtTest {
|
|
|
102
102
|
reject(new Error("qttest: File doesn't exit: " + this.filename));
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
|
-
const child = (0, child_process_1.spawn)(this.filename, ["-functions"], {
|
|
105
|
+
const child = (0, child_process_1.spawn)(this.filename, ["-functions"], {
|
|
106
|
+
cwd: this.buildDirPath,
|
|
107
|
+
});
|
|
106
108
|
child.stdout.on("data", (chunk) => {
|
|
107
109
|
output += chunk.toString();
|
|
108
110
|
});
|
|
@@ -112,8 +114,8 @@ class QtTest {
|
|
|
112
114
|
child.on("exit", (code) => {
|
|
113
115
|
if (code === 0) {
|
|
114
116
|
slotNames = slotNames.concat(output.split("\n"));
|
|
115
|
-
slotNames = slotNames.map(entry => entry.trim().replace("()", ""));
|
|
116
|
-
slotNames = slotNames.filter(entry => entry.length > 0);
|
|
117
|
+
slotNames = slotNames.map((entry) => entry.trim().replace("()", ""));
|
|
118
|
+
slotNames = slotNames.filter((entry) => entry.length > 0);
|
|
117
119
|
if (slotNames.length > 0) {
|
|
118
120
|
this.slots = [];
|
|
119
121
|
for (var slotName of slotNames) {
|
|
@@ -124,7 +126,12 @@ class QtTest {
|
|
|
124
126
|
resolve(slotNames);
|
|
125
127
|
}
|
|
126
128
|
else {
|
|
127
|
-
reject(new Error("qttest: Failed to run -functions, stdout=" +
|
|
129
|
+
reject(new Error("qttest: Failed to run -functions, stdout=" +
|
|
130
|
+
output +
|
|
131
|
+
"; stderr=" +
|
|
132
|
+
err +
|
|
133
|
+
"; code=" +
|
|
134
|
+
code));
|
|
128
135
|
}
|
|
129
136
|
});
|
|
130
137
|
});
|
|
@@ -150,7 +157,8 @@ class QtTest {
|
|
|
150
157
|
let result = false;
|
|
151
158
|
child.stdout.on("data", (chunk) => {
|
|
152
159
|
if (!result) {
|
|
153
|
-
if (chunk.toString().includes("libQt5Test.so") ||
|
|
160
|
+
if (chunk.toString().includes("libQt5Test.so") ||
|
|
161
|
+
chunk.toString().includes("libQt6Test.so")) {
|
|
154
162
|
result = true;
|
|
155
163
|
}
|
|
156
164
|
}
|
|
@@ -219,7 +227,12 @@ class QtTest {
|
|
|
219
227
|
args = args.concat("-o").concat("-,txt");
|
|
220
228
|
return yield new Promise((resolve, reject) => {
|
|
221
229
|
let cwdDir = cwd.length > 0 ? cwd : this.buildDirPath;
|
|
222
|
-
logMessage("Running " +
|
|
230
|
+
logMessage("Running " +
|
|
231
|
+
this.filename +
|
|
232
|
+
" " +
|
|
233
|
+
args.join(" ") +
|
|
234
|
+
" with cwd=" +
|
|
235
|
+
cwdDir);
|
|
223
236
|
const child = (0, child_process_1.spawn)(this.filename, args, { cwd: cwdDir });
|
|
224
237
|
if (this.outputFunc) {
|
|
225
238
|
// Callers wants the process output:
|
|
@@ -239,9 +252,11 @@ class QtTest {
|
|
|
239
252
|
if (!slot) {
|
|
240
253
|
this.lastExitCode = code;
|
|
241
254
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
255
|
+
if (this.slots && this.slots.length > 0) {
|
|
256
|
+
/// When running a QtTest executable, let's check which sub-tests failed
|
|
257
|
+
/// (So VSCode can show some error icon for each fail)
|
|
258
|
+
yield this.updateSubTestStates(cwdDir, slot);
|
|
259
|
+
}
|
|
245
260
|
if (code === 0) {
|
|
246
261
|
resolve(true);
|
|
247
262
|
}
|
|
@@ -255,11 +270,11 @@ class QtTest {
|
|
|
255
270
|
/// Using .tap so we don't have to use a separate XML library
|
|
256
271
|
/// .tap is plain text and a single regexp can catch the failing tests and line number
|
|
257
272
|
tapOutputFileName(slot) {
|
|
258
|
-
let slotName = slot ?
|
|
273
|
+
let slotName = slot ? "_" + slot.name : "";
|
|
259
274
|
return this.label + slotName + ".tap";
|
|
260
275
|
}
|
|
261
276
|
txtOutputFileName(slot) {
|
|
262
|
-
let slotName = slot ?
|
|
277
|
+
let slotName = slot ? "_" + slot.name : "";
|
|
263
278
|
return this.label + slotName + ".txt";
|
|
264
279
|
}
|
|
265
280
|
command() {
|
|
@@ -286,7 +301,7 @@ class QtTest {
|
|
|
286
301
|
// at: MyTest::testF() (/some/path/qttest-utils/test/qt_test/test2.cpp:13)
|
|
287
302
|
const pattern = /at:\s+(.+?)::(.+?)\(\)\s+\((.+?):(\d+)\)/gm;
|
|
288
303
|
const matches = Array.from(data.matchAll(pattern));
|
|
289
|
-
const failedResults = matches.map(match => ({
|
|
304
|
+
const failedResults = matches.map((match) => ({
|
|
290
305
|
name: match[2],
|
|
291
306
|
filePath: match[3],
|
|
292
307
|
lineNumber: parseInt(match[4]),
|
|
@@ -332,7 +347,11 @@ class QtTestSlot {
|
|
|
332
347
|
});
|
|
333
348
|
}
|
|
334
349
|
command() {
|
|
335
|
-
return {
|
|
350
|
+
return {
|
|
351
|
+
label: this.name,
|
|
352
|
+
executablePath: this.absoluteFilePath,
|
|
353
|
+
args: [this.name],
|
|
354
|
+
};
|
|
336
355
|
}
|
|
337
356
|
}
|
|
338
357
|
exports.QtTestSlot = QtTestSlot;
|
package/out/test.js
CHANGED
|
@@ -23,19 +23,33 @@ function runTests(buildDirPath) {
|
|
|
23
23
|
let expected_executables = [
|
|
24
24
|
"test/qt_test/build-dev/test1",
|
|
25
25
|
"test/qt_test/build-dev/test2",
|
|
26
|
-
"test/qt_test/build-dev/test3"
|
|
26
|
+
"test/qt_test/build-dev/test3",
|
|
27
|
+
"test/qt_test/build-dev/non_qttest",
|
|
27
28
|
];
|
|
28
29
|
if (qt.qtTestExecutables.length != expected_executables.length) {
|
|
29
30
|
console.error("Expected 3 executables, got " + qt.qtTestExecutables.length);
|
|
30
31
|
process.exit(1);
|
|
31
32
|
}
|
|
32
33
|
yield qt.removeNonLinking();
|
|
34
|
+
/// On macOS and Windows we don't have ldd or equivalent, so we can't check if the test links to QtTest
|
|
35
|
+
/// Use the help way instead
|
|
36
|
+
yield qt.removeByRunningHelp();
|
|
37
|
+
/// Remove the non-qttest executable from qt.qtTestExecutables
|
|
38
|
+
qt.qtTestExecutables = qt.qtTestExecutables.filter((e) => !e.filenameWithoutExtension().endsWith("non_qttest"));
|
|
39
|
+
if (qt.qtTestExecutables.length != 3) {
|
|
40
|
+
console.error("Expected 3 executables, at this point got " +
|
|
41
|
+
qt.qtTestExecutables.length);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
33
44
|
// 1. Test that the executable test names are correct:
|
|
34
45
|
var i = 0;
|
|
35
46
|
for (var executable of qt.qtTestExecutables) {
|
|
36
47
|
let expected = expected_executables[i];
|
|
37
48
|
if (executable.relativeFilename() != expected) {
|
|
38
|
-
console.error("Expected executable " +
|
|
49
|
+
console.error("Expected executable " +
|
|
50
|
+
expected +
|
|
51
|
+
", got " +
|
|
52
|
+
executable.relativeFilename());
|
|
39
53
|
process.exit(1);
|
|
40
54
|
}
|
|
41
55
|
i++;
|
|
@@ -112,8 +126,8 @@ function runTests(buildDirPath) {
|
|
|
112
126
|
}
|
|
113
127
|
function runCodeModelTests(codeModelFile) {
|
|
114
128
|
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
-
const fs = require(
|
|
116
|
-
let codemodelStr = fs.readFileSync(codeModelFile,
|
|
129
|
+
const fs = require("fs");
|
|
130
|
+
let codemodelStr = fs.readFileSync(codeModelFile, "utf8");
|
|
117
131
|
let codemodelJson = JSON.parse(codemodelStr);
|
|
118
132
|
let cmake = new cmake_1.CMakeTests("random");
|
|
119
133
|
let files = cmake.cppFilesForExecutable("/vscode-qttest/test/qt_test/build-dev/test1", codemodelJson);
|
|
@@ -143,7 +157,51 @@ function runCodeModelTests(codeModelFile) {
|
|
|
143
157
|
console.error("Expected test2, got " + targetName);
|
|
144
158
|
process.exit(1);
|
|
145
159
|
}
|
|
160
|
+
// test workaround for microsoft/vscode-cmake-tools-api/issues/7
|
|
161
|
+
files = cmake.cppFilesForExecutable("/vscode-qttest/test/qt_test/build-dev/test3", codemodelJson,
|
|
162
|
+
/*workaround=*/ false);
|
|
163
|
+
if (files.length !== 0) {
|
|
164
|
+
console.error("Expected 0 files, got " + files.length);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
files = cmake.cppFilesForExecutable("/vscode-qttest/test/qt_test/build-dev/test3", codemodelJson,
|
|
168
|
+
/*workaround=*/ true);
|
|
169
|
+
if (files.length !== 1) {
|
|
170
|
+
console.error("Expected 0 files, got " + files.length);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
targetName = cmake.targetNameForExecutable("/vscode-qttest/test/qt_test/build-dev/test3", codemodelJson,
|
|
174
|
+
/*workaround=*/ false);
|
|
175
|
+
if (targetName) {
|
|
176
|
+
console.error("Expected null, got " + targetName);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
targetName = cmake.targetNameForExecutable("/vscode-qttest/test/qt_test/build-dev/test3", codemodelJson,
|
|
180
|
+
/*workaround=*/ true);
|
|
181
|
+
if (targetName != "test3") {
|
|
182
|
+
console.error("Expected null, got " + targetName);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function runNonQtTest(buildDirPath) {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
let qt = new qttest_1.QtTests();
|
|
190
|
+
yield qt.discoverViaCMake(buildDirPath);
|
|
191
|
+
var nonQtExecutable = undefined;
|
|
192
|
+
for (let executable of qt.qtTestExecutables) {
|
|
193
|
+
if (executable.filenameWithoutExtension().endsWith("non_qttest")) {
|
|
194
|
+
nonQtExecutable = executable;
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (nonQtExecutable === undefined) {
|
|
199
|
+
console.error("Expected to find non-Qt test executable");
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
yield nonQtExecutable.runTest();
|
|
146
203
|
});
|
|
147
204
|
}
|
|
148
205
|
runTests("test/qt_test/build-dev/");
|
|
206
|
+
runNonQtTest("test/qt_test/build-dev/");
|
|
149
207
|
runCodeModelTests("test/test_cmake_codemodel.json");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iamsergio/qttest-utils",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "API for listing QtTest executables from a build directory and which individual test slots each executable contains. Useful for a Text Explorer VSCode extension.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|