@iamsergio/qttest-utils 2.3.0 → 2.6.0
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.md +296 -0
- package/out/cmake.d.ts +1 -0
- package/out/cmake.js +118 -59
- package/out/example.js +65 -62
- package/out/index.js +5 -1
- package/out/qttest.d.ts +2 -0
- package/out/qttest.js +284 -258
- package/out/test.js +220 -221
- package/out/utils.js +20 -8
- package/package.json +22 -7
- package/.release-please-manifest.json +0 -3
- package/CONTRIBUTING.md +0 -33
- package/Changelog +0 -229
- package/release-please-config.json +0 -16
- package/test.sh +0 -7
package/out/qttest.js
CHANGED
|
@@ -18,27 +18,29 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
18
18
|
}) : function(o, v) {
|
|
19
19
|
o["default"] = v;
|
|
20
20
|
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || function (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
37
38
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
38
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
39
40
|
};
|
|
40
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
-
exports.QtTests = exports.QtTestSlot = exports.QtTest =
|
|
42
|
+
exports.QtTests = exports.QtTestSlot = exports.QtTest = void 0;
|
|
43
|
+
exports.logMessage = logMessage;
|
|
42
44
|
const child_process_1 = require("child_process");
|
|
43
45
|
const path_1 = __importDefault(require("path"));
|
|
44
46
|
const fs = __importStar(require("fs"));
|
|
@@ -50,21 +52,26 @@ function logMessage(message) {
|
|
|
50
52
|
gLogFunction(message);
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
|
-
exports.logMessage = logMessage;
|
|
54
55
|
/**
|
|
55
56
|
* Represents a single QtTest executable.
|
|
56
57
|
* Supports listing the individual test slots
|
|
57
58
|
*/
|
|
58
59
|
class QtTest {
|
|
60
|
+
filename;
|
|
61
|
+
buildDirPath;
|
|
62
|
+
/// If true, will print more verbose output
|
|
63
|
+
verbose = false;
|
|
64
|
+
/// Allows vscode extensions to associate with a test item
|
|
65
|
+
vscodeTestItem;
|
|
66
|
+
/// The list of individual runnable test slots
|
|
67
|
+
slots = null;
|
|
68
|
+
/// Environment variables coming from CTest (array of "VAR=VALUE")
|
|
69
|
+
environment = [];
|
|
70
|
+
/// Set after running
|
|
71
|
+
lastExitCode = 0;
|
|
72
|
+
/// Allows the caller to receive the output of the test process
|
|
73
|
+
outputFunc = undefined;
|
|
59
74
|
constructor(filename, buildDirPath) {
|
|
60
|
-
/// If true, will print more verbose output
|
|
61
|
-
this.verbose = false;
|
|
62
|
-
/// The list of individual runnable test slots
|
|
63
|
-
this.slots = null;
|
|
64
|
-
/// Set after running
|
|
65
|
-
this.lastExitCode = 0;
|
|
66
|
-
/// Allows the caller to receive the output of the test process
|
|
67
|
-
this.outputFunc = undefined;
|
|
68
75
|
this.filename = filename;
|
|
69
76
|
this.buildDirPath = buildDirPath;
|
|
70
77
|
}
|
|
@@ -77,8 +84,9 @@ class QtTest {
|
|
|
77
84
|
relativeFilename() {
|
|
78
85
|
let result = path_1.default.relative(process.cwd(), this.filename);
|
|
79
86
|
// strip .exe, as we only use this for tests
|
|
80
|
-
if (result.endsWith(".exe"))
|
|
87
|
+
if (result.endsWith(".exe")) {
|
|
81
88
|
result = result.slice(0, -4);
|
|
89
|
+
}
|
|
82
90
|
// normalize slashes
|
|
83
91
|
result = result.replace(/\\/g, "/");
|
|
84
92
|
return result;
|
|
@@ -86,55 +94,67 @@ class QtTest {
|
|
|
86
94
|
/// returns filename without .exe extension
|
|
87
95
|
filenameWithoutExtension() {
|
|
88
96
|
let result = this.filename;
|
|
89
|
-
if (result.endsWith(".exe"))
|
|
97
|
+
if (result.endsWith(".exe")) {
|
|
90
98
|
result = result.slice(0, -4);
|
|
99
|
+
}
|
|
91
100
|
return result;
|
|
92
101
|
}
|
|
102
|
+
buildSpawnEnv() {
|
|
103
|
+
const env = Object.assign({}, process.env);
|
|
104
|
+
if (this.environment && Array.isArray(this.environment)) {
|
|
105
|
+
for (const kv of this.environment) {
|
|
106
|
+
const idx = kv.indexOf("=");
|
|
107
|
+
if (idx > -1) {
|
|
108
|
+
env[kv.substring(0, idx)] = kv.substring(idx + 1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return env;
|
|
113
|
+
}
|
|
93
114
|
/**
|
|
94
115
|
* Calls "./yourqttest -functions" and stores the results in the slots property.
|
|
95
116
|
*/
|
|
96
|
-
parseAvailableSlots() {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
117
|
+
async parseAvailableSlots() {
|
|
118
|
+
let slotNames = [];
|
|
119
|
+
let output = "";
|
|
120
|
+
let err = "";
|
|
121
|
+
await new Promise((resolve, reject) => {
|
|
122
|
+
if (!fs.existsSync(this.filename)) {
|
|
123
|
+
reject(new Error("qttest: File doesn't exit: " + this.filename));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const child = (0, child_process_1.spawn)(this.filename, ["-functions"], {
|
|
127
|
+
cwd: this.buildDirPath,
|
|
128
|
+
env: this.buildSpawnEnv(),
|
|
129
|
+
});
|
|
130
|
+
child.stdout.on("data", (chunk) => {
|
|
131
|
+
output += chunk.toString();
|
|
132
|
+
});
|
|
133
|
+
child.stderr.on("data", (chunk) => {
|
|
134
|
+
err += chunk.toString();
|
|
135
|
+
});
|
|
136
|
+
child.on("exit", (code) => {
|
|
137
|
+
if (code === 0) {
|
|
138
|
+
slotNames = slotNames.concat(output.split("\n"));
|
|
139
|
+
slotNames = slotNames.map((entry) => entry.trim().replace("()", ""));
|
|
140
|
+
slotNames = slotNames.filter((entry) => entry.length > 0);
|
|
141
|
+
if (slotNames.length > 0) {
|
|
142
|
+
this.slots = [];
|
|
143
|
+
for (var slotName of slotNames) {
|
|
144
|
+
var slot = new QtTestSlot(slotName, this);
|
|
145
|
+
this.slots.push(slot);
|
|
126
146
|
}
|
|
127
|
-
resolve(slotNames);
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
reject(new Error("qttest: Failed to run -functions, stdout=" +
|
|
131
|
-
output +
|
|
132
|
-
"; stderr=" +
|
|
133
|
-
err +
|
|
134
|
-
"; code=" +
|
|
135
|
-
code));
|
|
136
147
|
}
|
|
137
|
-
|
|
148
|
+
resolve(slotNames);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
reject(new Error("qttest: Failed to run -functions, stdout=" +
|
|
152
|
+
output +
|
|
153
|
+
"; stderr=" +
|
|
154
|
+
err +
|
|
155
|
+
"; code=" +
|
|
156
|
+
code));
|
|
157
|
+
}
|
|
138
158
|
});
|
|
139
159
|
});
|
|
140
160
|
}
|
|
@@ -151,8 +171,9 @@ class QtTest {
|
|
|
151
171
|
return undefined;
|
|
152
172
|
}
|
|
153
173
|
return new Promise((resolve, reject) => {
|
|
154
|
-
if (this.verbose)
|
|
174
|
+
if (this.verbose) {
|
|
155
175
|
logMessage("qttest: Running ldd on " + this.filename);
|
|
176
|
+
}
|
|
156
177
|
const child = (0, child_process_1.spawn)("ldd", [this.filename]);
|
|
157
178
|
let output = "";
|
|
158
179
|
let result = false;
|
|
@@ -163,8 +184,9 @@ class QtTest {
|
|
|
163
184
|
result = true;
|
|
164
185
|
}
|
|
165
186
|
}
|
|
166
|
-
if (this.verbose)
|
|
187
|
+
if (this.verbose) {
|
|
167
188
|
logMessage(chunk.toString());
|
|
189
|
+
}
|
|
168
190
|
});
|
|
169
191
|
child.on("exit", (code) => {
|
|
170
192
|
if (code === 0) {
|
|
@@ -178,98 +200,104 @@ class QtTest {
|
|
|
178
200
|
}
|
|
179
201
|
/// Returns whether this test is a QtTest by running it with -help and checking if the help text looks familiar
|
|
180
202
|
/// Note that if this is not a QtTest it might not run help and instead execute the test itself
|
|
181
|
-
isQtTestViaHelp() {
|
|
182
|
-
return
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
child.on("exit", (code) => {
|
|
195
|
-
if (code === 0) {
|
|
196
|
-
resolve(result);
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
resolve(false);
|
|
203
|
+
async isQtTestViaHelp() {
|
|
204
|
+
return await new Promise((resolve, reject) => {
|
|
205
|
+
const child = (0, child_process_1.spawn)(this.filename, ["-help"], {
|
|
206
|
+
env: this.buildSpawnEnv(),
|
|
207
|
+
});
|
|
208
|
+
let output = "";
|
|
209
|
+
let result = false;
|
|
210
|
+
child.stdout.on("data", (chunk) => {
|
|
211
|
+
if (!result) {
|
|
212
|
+
if (chunk.toString().includes("[testfunction[:testdata]]")) {
|
|
213
|
+
result = true;
|
|
200
214
|
}
|
|
201
|
-
}
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
child.on("exit", (code) => {
|
|
218
|
+
if (code === 0) {
|
|
219
|
+
resolve(result);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
resolve(false);
|
|
223
|
+
}
|
|
202
224
|
});
|
|
203
225
|
});
|
|
204
226
|
}
|
|
205
227
|
slotByName(name) {
|
|
206
|
-
if (!this.slots)
|
|
228
|
+
if (!this.slots) {
|
|
207
229
|
return undefined;
|
|
230
|
+
}
|
|
208
231
|
for (let slot of this.slots) {
|
|
209
|
-
if (slot.name
|
|
232
|
+
if (slot.name === name) {
|
|
210
233
|
return slot;
|
|
234
|
+
}
|
|
211
235
|
}
|
|
212
236
|
return undefined;
|
|
213
237
|
}
|
|
214
238
|
/// Runs this test
|
|
215
|
-
runTest(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
if (this.outputFunc)
|
|
246
|
-
this.outputFunc(chunk.toString());
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
child.on("exit", (code) => __awaiter(this, void 0, void 0, function* () {
|
|
250
|
-
/// Can code even be null ?
|
|
251
|
-
if (code == undefined)
|
|
252
|
-
code = -1;
|
|
253
|
-
if (!slot) {
|
|
254
|
-
this.lastExitCode = code;
|
|
239
|
+
async runTest(slot, cwd = "") {
|
|
240
|
+
let args = [];
|
|
241
|
+
if (slot) {
|
|
242
|
+
// Runs a single Qt test instead
|
|
243
|
+
args = args.concat(slot.name);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
this.clearSubTestStates();
|
|
247
|
+
}
|
|
248
|
+
// log to file and to stdout
|
|
249
|
+
args = args.concat("-o").concat(this.tapOutputFileName(slot) + ",tap");
|
|
250
|
+
args = args.concat("-o").concat(this.txtOutputFileName(slot) + ",txt");
|
|
251
|
+
args = args.concat("-o").concat("-,txt");
|
|
252
|
+
return await new Promise((resolve, reject) => {
|
|
253
|
+
let cwdDir = cwd.length > 0 ? cwd : this.buildDirPath;
|
|
254
|
+
logMessage("Running " +
|
|
255
|
+
this.filename +
|
|
256
|
+
" " +
|
|
257
|
+
args.join(" ") +
|
|
258
|
+
" with cwd=" +
|
|
259
|
+
cwdDir);
|
|
260
|
+
const child = (0, child_process_1.spawn)(this.filename, args, {
|
|
261
|
+
cwd: cwdDir,
|
|
262
|
+
env: this.buildSpawnEnv(),
|
|
263
|
+
});
|
|
264
|
+
if (this.outputFunc) {
|
|
265
|
+
// Callers wants the process output:
|
|
266
|
+
child.stdout.on("data", (chunk) => {
|
|
267
|
+
if (this.outputFunc) {
|
|
268
|
+
this.outputFunc(chunk.toString());
|
|
255
269
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
yield this.updateSubTestStates(cwdDir, slot);
|
|
261
|
-
}
|
|
262
|
-
catch (e) {
|
|
263
|
-
logMessage("Failed to update sub-test states: " + e);
|
|
264
|
-
}
|
|
270
|
+
});
|
|
271
|
+
child.stderr.on("data", (chunk) => {
|
|
272
|
+
if (this.outputFunc) {
|
|
273
|
+
this.outputFunc(chunk.toString());
|
|
265
274
|
}
|
|
266
|
-
|
|
267
|
-
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
child.on("exit", async (code) => {
|
|
278
|
+
/// Can code even be null ?
|
|
279
|
+
if (code === undefined || code === null) {
|
|
280
|
+
code = -1;
|
|
281
|
+
}
|
|
282
|
+
if (!slot) {
|
|
283
|
+
this.lastExitCode = code;
|
|
284
|
+
}
|
|
285
|
+
if (this.slots && this.slots.length > 0) {
|
|
286
|
+
/// When running a QtTest executable, let's check which sub-tests failed
|
|
287
|
+
/// (So VSCode can show some error icon for each fail)
|
|
288
|
+
try {
|
|
289
|
+
await this.updateSubTestStates(cwdDir, slot);
|
|
268
290
|
}
|
|
269
|
-
|
|
270
|
-
|
|
291
|
+
catch (e) {
|
|
292
|
+
logMessage("Failed to update sub-test states: " + e);
|
|
271
293
|
}
|
|
272
|
-
}
|
|
294
|
+
}
|
|
295
|
+
if (code === 0) {
|
|
296
|
+
resolve(true);
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
resolve(false);
|
|
300
|
+
}
|
|
273
301
|
});
|
|
274
302
|
});
|
|
275
303
|
}
|
|
@@ -293,76 +321,76 @@ class QtTest {
|
|
|
293
321
|
}
|
|
294
322
|
}
|
|
295
323
|
}
|
|
296
|
-
updateSubTestStates(cwdDir, slot) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
324
|
+
async updateSubTestStates(cwdDir, slot) {
|
|
325
|
+
let tapFileName = cwdDir + "/" + this.tapOutputFileName(slot);
|
|
326
|
+
var failures = await new Promise((resolve, reject) => {
|
|
327
|
+
fs.readFile(tapFileName, "utf8", (error, data) => {
|
|
328
|
+
if (error) {
|
|
329
|
+
logMessage("ERROR: Failed to read log file");
|
|
330
|
+
reject(error);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
let failedResults = [];
|
|
334
|
+
try {
|
|
335
|
+
const tapEvents = tap_parser_1.Parser.parse(data);
|
|
336
|
+
for (let event of tapEvents) {
|
|
337
|
+
try {
|
|
338
|
+
if (event.length < 2) {
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (event.at(0) !== "assert") {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
var obj = event.at(1);
|
|
345
|
+
let pass = obj["ok"] === true;
|
|
346
|
+
let xfail = !pass && obj["todo"] !== false;
|
|
347
|
+
if (xfail) {
|
|
348
|
+
// This is a QEXPECT_FAIL test, all good.
|
|
349
|
+
// QtTest outputs it as "todo"
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
// There's an QEXPECT_FAIL but test passed, not good.
|
|
353
|
+
let xpass = pass && obj["todo"].includes("returned TRUE unexpectedly");
|
|
354
|
+
if (!pass || xpass) {
|
|
355
|
+
// We found a failure
|
|
356
|
+
var name = obj["name"].replace(/\(.*\)/, "");
|
|
357
|
+
var filename = "";
|
|
358
|
+
var lineNumber = -1;
|
|
359
|
+
if (obj["diag"]) {
|
|
360
|
+
filename = obj["diag"]["file"];
|
|
361
|
+
lineNumber = obj["diag"]["line"];
|
|
322
362
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (!pass || xpass) {
|
|
326
|
-
// We found a failure
|
|
327
|
-
var name = obj["name"].replace(/\(.*\)/, "");
|
|
328
|
-
var filename = "";
|
|
329
|
-
var lineNumber = -1;
|
|
330
|
-
if (obj["diag"]) {
|
|
331
|
-
filename = obj["diag"]["file"];
|
|
332
|
-
lineNumber = obj["diag"]["line"];
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
// A XPASS for example misses file:line info. Nothing we can do, it's a Qt bug arguably.
|
|
336
|
-
}
|
|
337
|
-
failedResults.push({
|
|
338
|
-
name: name,
|
|
339
|
-
filePath: filename,
|
|
340
|
-
lineNumber: lineNumber,
|
|
341
|
-
});
|
|
363
|
+
else {
|
|
364
|
+
// A XPASS for example misses file:line info. Nothing we can do, it's a Qt bug arguably.
|
|
342
365
|
}
|
|
366
|
+
failedResults.push({
|
|
367
|
+
name: name,
|
|
368
|
+
filePath: filename,
|
|
369
|
+
lineNumber: lineNumber,
|
|
370
|
+
});
|
|
343
371
|
}
|
|
344
|
-
catch (e) { }
|
|
345
372
|
}
|
|
373
|
+
catch (e) { }
|
|
346
374
|
}
|
|
347
|
-
catch (e) { }
|
|
348
|
-
resolve(failedResults);
|
|
349
375
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
for (let failure of failures) {
|
|
353
|
-
if (slot && slot.name != failure.name) {
|
|
354
|
-
// We executed a single slot, ignore anything else
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
let failedSlot = this.slotByName(failure.name);
|
|
358
|
-
if (failedSlot) {
|
|
359
|
-
failedSlot.lastTestFailure = failure;
|
|
376
|
+
catch (e) { }
|
|
377
|
+
resolve(failedResults);
|
|
360
378
|
}
|
|
361
|
-
|
|
362
|
-
logMessage("ERROR: Failed to find slot with name " + failure.name);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
379
|
+
});
|
|
365
380
|
});
|
|
381
|
+
for (let failure of failures) {
|
|
382
|
+
if (slot && slot.name !== failure.name) {
|
|
383
|
+
// We executed a single slot, ignore anything else
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
let failedSlot = this.slotByName(failure.name);
|
|
387
|
+
if (failedSlot) {
|
|
388
|
+
failedSlot.lastTestFailure = failure;
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
logMessage("ERROR: Failed to find slot with name " + failure.name);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
366
394
|
}
|
|
367
395
|
}
|
|
368
396
|
exports.QtTest = QtTest;
|
|
@@ -370,6 +398,13 @@ exports.QtTest = QtTest;
|
|
|
370
398
|
* Represents a single Qt test slot
|
|
371
399
|
*/
|
|
372
400
|
class QtTestSlot {
|
|
401
|
+
name;
|
|
402
|
+
// The QTest executable this slot belongs to
|
|
403
|
+
parentQTest;
|
|
404
|
+
/// Allows vscode extensions to associate with a test item
|
|
405
|
+
vscodeTestItem;
|
|
406
|
+
/// Set after running
|
|
407
|
+
lastTestFailure;
|
|
373
408
|
constructor(name, parent) {
|
|
374
409
|
this.name = name;
|
|
375
410
|
this.parentQTest = parent;
|
|
@@ -380,10 +415,8 @@ class QtTestSlot {
|
|
|
380
415
|
get absoluteFilePath() {
|
|
381
416
|
return this.parentQTest.filename;
|
|
382
417
|
}
|
|
383
|
-
runTest() {
|
|
384
|
-
return
|
|
385
|
-
return this.parentQTest.runTest(this);
|
|
386
|
-
});
|
|
418
|
+
async runTest() {
|
|
419
|
+
return this.parentQTest.runTest(this);
|
|
387
420
|
}
|
|
388
421
|
command() {
|
|
389
422
|
return {
|
|
@@ -398,51 +431,45 @@ exports.QtTestSlot = QtTestSlot;
|
|
|
398
431
|
* Represents the list of all QtTest executables in your project
|
|
399
432
|
*/
|
|
400
433
|
class QtTests {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
this.qtTestExecutables.push(qtest);
|
|
412
|
-
}
|
|
434
|
+
qtTestExecutables = [];
|
|
435
|
+
async discoverViaCMake(buildDirPath) {
|
|
436
|
+
var cmake = new cmake_1.CMakeTests(buildDirPath);
|
|
437
|
+
let ctests = await cmake.tests();
|
|
438
|
+
if (ctests) {
|
|
439
|
+
for (let ctest of ctests) {
|
|
440
|
+
let qtest = new QtTest(ctest.executablePath(), buildDirPath);
|
|
441
|
+
// Propagate environment from CTest metadata
|
|
442
|
+
qtest.environment = ctest.environment;
|
|
443
|
+
this.qtTestExecutables.push(qtest);
|
|
413
444
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
logMessage("ERROR: Failed to retrieve ctests!");
|
|
448
|
+
}
|
|
418
449
|
}
|
|
419
450
|
/// Removes any executable (from the list) that doesn't link to libQtTest.so
|
|
420
451
|
/// This heuristic tries to filter-out doctest and other non-Qt tests
|
|
421
452
|
/// Only implemented for linux for now
|
|
422
|
-
removeNonLinking() {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
acceptedExecutables.push(ex);
|
|
434
|
-
}
|
|
435
|
-
this.qtTestExecutables = acceptedExecutables;
|
|
453
|
+
async removeNonLinking() {
|
|
454
|
+
let isLinux = process.platform === "linux";
|
|
455
|
+
if (!isLinux) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
let acceptedExecutables = [];
|
|
459
|
+
for (let ex of this.qtTestExecutables) {
|
|
460
|
+
let linksToQt = await ex.linksToQtTestLib();
|
|
461
|
+
// undefined or true is accepted
|
|
462
|
+
if (linksToQt !== false) {
|
|
463
|
+
acceptedExecutables.push(ex);
|
|
436
464
|
}
|
|
437
|
-
|
|
465
|
+
this.qtTestExecutables = acceptedExecutables;
|
|
466
|
+
}
|
|
438
467
|
}
|
|
439
468
|
setLogFunction(func) {
|
|
440
469
|
gLogFunction = func;
|
|
441
470
|
}
|
|
442
|
-
removeByRunningHelp() {
|
|
443
|
-
|
|
444
|
-
this.qtTestExecutables = this.qtTestExecutables.filter((ex) => __awaiter(this, void 0, void 0, function* () { return yield ex.isQtTestViaHelp(); }));
|
|
445
|
-
});
|
|
471
|
+
async removeByRunningHelp() {
|
|
472
|
+
this.qtTestExecutables = this.qtTestExecutables.filter(async (ex) => await ex.isQtTestViaHelp());
|
|
446
473
|
}
|
|
447
474
|
/// Removes any executable (from the list) that matches the specified regex
|
|
448
475
|
removeMatching(regex) {
|
|
@@ -457,19 +484,18 @@ class QtTests {
|
|
|
457
484
|
console.log(ex.filename);
|
|
458
485
|
}
|
|
459
486
|
}
|
|
460
|
-
dumpTestSlots() {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
487
|
+
async dumpTestSlots() {
|
|
488
|
+
for (var ex of this.qtTestExecutables) {
|
|
489
|
+
if (!ex.slots) {
|
|
490
|
+
await ex.parseAvailableSlots();
|
|
491
|
+
}
|
|
492
|
+
console.log(ex.filename);
|
|
493
|
+
if (ex.slots) {
|
|
494
|
+
for (let slot of ex.slots) {
|
|
495
|
+
console.log(" - " + slot.name);
|
|
470
496
|
}
|
|
471
497
|
}
|
|
472
|
-
}
|
|
498
|
+
}
|
|
473
499
|
}
|
|
474
500
|
/// Returns all executables that contain a Qt test slot with the specified name
|
|
475
501
|
executablesContainingSlot(slotName) {
|