eyeling 1.28.6 → 1.28.7
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/package.json +1 -1
- package/test/api.test.js +13 -29
- package/test/builtins.test.js +8 -21
- package/test/examples.test.js +27 -42
- package/test/extra.test.js +9 -25
- package/test/manifest.test.js +23 -28
- package/test/package.test.js +17 -24
- package/test/packlist.test.js +5 -14
- package/test/playground.test.js +6 -22
- package/test/rdf12.test.js +15 -54
- package/test/report.js +67 -0
- package/test/stream_messages.test.js +11 -25
package/package.json
CHANGED
package/test/api.test.js
CHANGED
|
@@ -66,29 +66,12 @@ function reasonQuiet(opt, input) {
|
|
|
66
66
|
throw err;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const
|
|
70
|
-
const C = TTY
|
|
71
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
72
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
73
|
-
|
|
74
|
-
function ok(msg) {
|
|
75
|
-
console.log(`${C.g}OK ${C.n} ${msg}`);
|
|
76
|
-
}
|
|
77
|
-
function info(msg) {
|
|
78
|
-
console.log(`${C.y}==${C.n} ${msg}`);
|
|
79
|
-
}
|
|
80
|
-
function fail(msg) {
|
|
81
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
82
|
-
}
|
|
69
|
+
const { detail, failResult, info, pass } = require('./report');
|
|
83
70
|
|
|
84
71
|
function unnumberedName(name) {
|
|
85
72
|
return String(name).replace(/^\d+[a-z]*\s+/i, '');
|
|
86
73
|
}
|
|
87
74
|
|
|
88
|
-
function numberedName(index, name) {
|
|
89
|
-
return `${String(index + 1).padStart(3, '0')} ${unnumberedName(name)}`;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
75
|
function msNow() {
|
|
93
76
|
return Date.now();
|
|
94
77
|
}
|
|
@@ -3172,7 +3155,8 @@ let failed = 0;
|
|
|
3172
3155
|
info(`Running ${cases.length} API tests (independent of examples/)`);
|
|
3173
3156
|
|
|
3174
3157
|
for (const [index, tc] of cases.entries()) {
|
|
3175
|
-
const
|
|
3158
|
+
const testNr = index + 1;
|
|
3159
|
+
const testName = unnumberedName(tc.name);
|
|
3176
3160
|
const start = msNow();
|
|
3177
3161
|
try {
|
|
3178
3162
|
const out = typeof tc.run === 'function' ? await tc.run() : reasonQuiet(tc.opt, tc.input);
|
|
@@ -3187,19 +3171,19 @@ let failed = 0;
|
|
|
3187
3171
|
if (typeof tc.check === 'function') tc.check(out, tc);
|
|
3188
3172
|
|
|
3189
3173
|
const dur = msNow() - start;
|
|
3190
|
-
|
|
3174
|
+
pass(testNr, testName, dur);
|
|
3191
3175
|
passed++;
|
|
3192
3176
|
} catch (e) {
|
|
3193
3177
|
const dur = msNow() - start;
|
|
3194
3178
|
|
|
3195
3179
|
if (tc.expectErrorCode != null) {
|
|
3196
3180
|
if (e && typeof e === 'object' && 'code' in e && e.code === tc.expectErrorCode) {
|
|
3197
|
-
|
|
3181
|
+
pass(testNr, `${testName} (expected exit ${tc.expectErrorCode})`, dur);
|
|
3198
3182
|
passed++;
|
|
3199
3183
|
continue;
|
|
3200
3184
|
}
|
|
3201
|
-
|
|
3202
|
-
|
|
3185
|
+
failResult(testNr, testName, dur);
|
|
3186
|
+
detail(
|
|
3203
3187
|
`Expected exit code ${tc.expectErrorCode}, got: ${e && e.code != null ? e.code : 'unknown'}\n${
|
|
3204
3188
|
e && e.stderr ? e.stderr : e && e.stack ? e.stack : String(e)
|
|
3205
3189
|
}`,
|
|
@@ -3209,26 +3193,26 @@ let failed = 0;
|
|
|
3209
3193
|
}
|
|
3210
3194
|
|
|
3211
3195
|
if (tc.expectError) {
|
|
3212
|
-
|
|
3196
|
+
pass(testNr, `${testName} (expected error)`, dur);
|
|
3213
3197
|
passed++;
|
|
3214
3198
|
continue;
|
|
3215
3199
|
}
|
|
3216
3200
|
|
|
3217
|
-
|
|
3218
|
-
|
|
3201
|
+
failResult(testNr, testName, dur);
|
|
3202
|
+
detail(e && e.stack ? e.stack : String(e));
|
|
3219
3203
|
failed++;
|
|
3220
3204
|
}
|
|
3221
3205
|
}
|
|
3222
3206
|
|
|
3223
3207
|
console.log('');
|
|
3224
3208
|
const suiteMs = Date.now() - suiteStart;
|
|
3225
|
-
|
|
3209
|
+
info(`Total elapsed: ${suiteMs} ms (${(suiteMs / 1000).toFixed(2)} s)`);
|
|
3226
3210
|
|
|
3227
3211
|
if (failed === 0) {
|
|
3228
|
-
|
|
3212
|
+
info(`All API tests passed (${passed}/${cases.length})`);
|
|
3229
3213
|
process.exit(0);
|
|
3230
3214
|
} else {
|
|
3231
|
-
|
|
3215
|
+
info(`Some API tests failed (${passed}/${cases.length})`);
|
|
3232
3216
|
process.exit(1);
|
|
3233
3217
|
}
|
|
3234
3218
|
})();
|
package/test/builtins.test.js
CHANGED
|
@@ -2,20 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const assert = require('node:assert/strict');
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const C = TTY
|
|
7
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
8
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
9
|
-
|
|
10
|
-
function ok(msg) {
|
|
11
|
-
console.log(`${C.g}OK ${C.n} ${msg}`);
|
|
12
|
-
}
|
|
13
|
-
function info(msg) {
|
|
14
|
-
console.log(`${C.y}==${C.n} ${msg}`);
|
|
15
|
-
}
|
|
16
|
-
function fail(msg) {
|
|
17
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
18
|
-
}
|
|
5
|
+
const { detail, failResult, info, pass } = require('./report');
|
|
19
6
|
|
|
20
7
|
const builtins = require('../lib/builtins');
|
|
21
8
|
require('../lib/engine');
|
|
@@ -226,25 +213,25 @@ let failed = 0;
|
|
|
226
213
|
const suiteStart = Date.now();
|
|
227
214
|
info(`Running ${cases.length} builtin contract tests`);
|
|
228
215
|
|
|
229
|
-
for (const tc of cases) {
|
|
216
|
+
for (const [index, tc] of cases.entries()) {
|
|
230
217
|
const start = Date.now();
|
|
231
218
|
try {
|
|
232
219
|
tc.run();
|
|
233
|
-
|
|
220
|
+
pass(index + 1, tc.name, Date.now() - start);
|
|
234
221
|
passed++;
|
|
235
222
|
} catch (e) {
|
|
236
|
-
|
|
237
|
-
|
|
223
|
+
failResult(index + 1, tc.name, Date.now() - start);
|
|
224
|
+
detail(e && e.stack ? e.stack : String(e));
|
|
238
225
|
failed++;
|
|
239
226
|
}
|
|
240
227
|
}
|
|
241
228
|
|
|
242
229
|
console.log('');
|
|
243
|
-
|
|
230
|
+
info(`Total elapsed: ${Date.now() - suiteStart} ms`);
|
|
244
231
|
if (failed === 0) {
|
|
245
|
-
|
|
232
|
+
info(`All builtin contract tests passed (${passed}/${cases.length})`);
|
|
246
233
|
process.exit(0);
|
|
247
234
|
}
|
|
248
|
-
|
|
235
|
+
info(`Some builtin contract tests failed (${passed}/${cases.length})`);
|
|
249
236
|
process.exit(1);
|
|
250
237
|
})();
|
package/test/examples.test.js
CHANGED
|
@@ -6,21 +6,7 @@ const os = require('node:os');
|
|
|
6
6
|
const path = require('node:path');
|
|
7
7
|
const cp = require('node:child_process');
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
const C = TTY
|
|
11
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
12
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
13
|
-
const msTag = (ms) => `${C.dim}(${ms} ms)${C.n}`;
|
|
14
|
-
|
|
15
|
-
function ok(msg) {
|
|
16
|
-
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
17
|
-
}
|
|
18
|
-
function fail(msg) {
|
|
19
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
20
|
-
}
|
|
21
|
-
function info(msg) {
|
|
22
|
-
console.log(`${C.y}==${C.n} ${msg}`);
|
|
23
|
-
}
|
|
9
|
+
const { C, detail, failResult, info, pass } = require('./report');
|
|
24
10
|
|
|
25
11
|
function run(cmd, args, opts = {}) {
|
|
26
12
|
return cp.spawnSync(cmd, args, {
|
|
@@ -224,11 +210,11 @@ function main() {
|
|
|
224
210
|
const nodePath = process.execPath;
|
|
225
211
|
|
|
226
212
|
if (!fs.existsSync(examplesDir)) {
|
|
227
|
-
|
|
213
|
+
failResult(1, `Cannot find examples directory: ${examplesDir}`, 0);
|
|
228
214
|
process.exit(1);
|
|
229
215
|
}
|
|
230
216
|
if (!fs.existsSync(eyelingJsPath)) {
|
|
231
|
-
|
|
217
|
+
failResult(1, `Cannot find eyeling.js: ${eyelingJsPath}`, 0);
|
|
232
218
|
process.exit(1);
|
|
233
219
|
}
|
|
234
220
|
|
|
@@ -252,21 +238,19 @@ function main() {
|
|
|
252
238
|
console.log(`${C.dim}${getEyelingVersion(nodePath, eyelingJsPath, root)}; node ${process.version}${C.n}`);
|
|
253
239
|
|
|
254
240
|
if (totalTests === 0) {
|
|
255
|
-
|
|
241
|
+
info(proofOnly ? 'No proof goldens found in examples/proof/' : 'No .n3 files found in examples/');
|
|
256
242
|
process.exit(0);
|
|
257
243
|
}
|
|
258
244
|
|
|
259
245
|
let passed = 0;
|
|
260
246
|
let failed = 0;
|
|
261
247
|
|
|
262
|
-
|
|
263
|
-
const idxWidth = String(files.length).length;
|
|
264
|
-
const proofIdxWidth = String(Math.max(proofFiles.length, 1)).length;
|
|
265
|
-
const proofLabel = proofOnly ? '' : 'proof ';
|
|
248
|
+
let sequence = 0;
|
|
266
249
|
|
|
267
250
|
for (let i = 0; i < files.length; i++) {
|
|
268
|
-
const
|
|
251
|
+
const testNr = ++sequence;
|
|
269
252
|
const file = files[i];
|
|
253
|
+
const testName = file;
|
|
270
254
|
|
|
271
255
|
const start = Date.now();
|
|
272
256
|
|
|
@@ -278,8 +262,8 @@ function main() {
|
|
|
278
262
|
n3Text = fs.readFileSync(filePath, 'utf8');
|
|
279
263
|
} catch (e) {
|
|
280
264
|
const ms = Date.now() - start;
|
|
281
|
-
|
|
282
|
-
|
|
265
|
+
failResult(testNr, testName, ms);
|
|
266
|
+
detail(`Cannot read input: ${e.message}`);
|
|
283
267
|
failed++;
|
|
284
268
|
continue;
|
|
285
269
|
}
|
|
@@ -291,8 +275,8 @@ function main() {
|
|
|
291
275
|
// comparable across environments.
|
|
292
276
|
if (!fs.existsSync(expectedPath)) {
|
|
293
277
|
const ms = Date.now() - start;
|
|
294
|
-
|
|
295
|
-
|
|
278
|
+
failResult(testNr, testName, ms);
|
|
279
|
+
detail(`Missing expected output for ${path.basename(file, path.extname(file))}.*`);
|
|
296
280
|
failed++;
|
|
297
281
|
continue;
|
|
298
282
|
}
|
|
@@ -324,18 +308,18 @@ function main() {
|
|
|
324
308
|
|
|
325
309
|
if (diffOk && rcOk) {
|
|
326
310
|
if (expectedRc === 0) {
|
|
327
|
-
|
|
311
|
+
pass(testNr, testName, ms);
|
|
328
312
|
} else {
|
|
329
|
-
|
|
313
|
+
pass(testNr, `${testName} (expected exit ${expectedRc})`, ms);
|
|
330
314
|
}
|
|
331
315
|
passed++;
|
|
332
316
|
} else {
|
|
333
|
-
|
|
317
|
+
failResult(testNr, testName, ms);
|
|
334
318
|
if (!rcOk) {
|
|
335
|
-
|
|
319
|
+
detail(`Exit code ${rc}, expected ${expectedRc}`);
|
|
336
320
|
}
|
|
337
321
|
if (!diffOk) {
|
|
338
|
-
|
|
322
|
+
detail('Output differs');
|
|
339
323
|
}
|
|
340
324
|
|
|
341
325
|
// Show diffs, because this is a test runner
|
|
@@ -353,8 +337,9 @@ function main() {
|
|
|
353
337
|
|
|
354
338
|
|
|
355
339
|
for (let i = 0; i < proofFiles.length; i++) {
|
|
356
|
-
const
|
|
340
|
+
const testNr = ++sequence;
|
|
357
341
|
const file = proofFiles[i];
|
|
342
|
+
const testName = proofOnly ? file : `proof ${file}`;
|
|
358
343
|
const start = Date.now();
|
|
359
344
|
const filePath = path.join(examplesDir, file);
|
|
360
345
|
const expectedPath = path.join(proofDir, file);
|
|
@@ -364,8 +349,8 @@ function main() {
|
|
|
364
349
|
n3Text = fs.readFileSync(filePath, 'utf8');
|
|
365
350
|
} catch (e) {
|
|
366
351
|
const ms = Date.now() - start;
|
|
367
|
-
|
|
368
|
-
|
|
352
|
+
failResult(testNr, testName, ms);
|
|
353
|
+
detail(`Cannot read proof input: ${e.message}`);
|
|
369
354
|
failed++;
|
|
370
355
|
continue;
|
|
371
356
|
}
|
|
@@ -388,18 +373,18 @@ function main() {
|
|
|
388
373
|
|
|
389
374
|
if (diffOk && rcOk) {
|
|
390
375
|
if (expectedRc === 0) {
|
|
391
|
-
|
|
376
|
+
pass(testNr, testName, ms);
|
|
392
377
|
} else {
|
|
393
|
-
|
|
378
|
+
pass(testNr, `${testName} (expected exit ${expectedRc})`, ms);
|
|
394
379
|
}
|
|
395
380
|
passed++;
|
|
396
381
|
} else {
|
|
397
|
-
|
|
382
|
+
failResult(testNr, testName, ms);
|
|
398
383
|
if (!rcOk) {
|
|
399
|
-
|
|
384
|
+
detail(`Exit code ${rc}, expected ${expectedRc}`);
|
|
400
385
|
}
|
|
401
386
|
if (!diffOk) {
|
|
402
|
-
|
|
387
|
+
detail('Proof output differs');
|
|
403
388
|
}
|
|
404
389
|
showDiff({
|
|
405
390
|
examplesDir,
|
|
@@ -417,12 +402,12 @@ function main() {
|
|
|
417
402
|
info(`Total elapsed: ${suiteMs} ms (${(suiteMs / 1000).toFixed(2)} s)`);
|
|
418
403
|
|
|
419
404
|
if (failed === 0) {
|
|
420
|
-
|
|
405
|
+
info(proofOnly
|
|
421
406
|
? `All proof golden tests passed (${passed}/${totalTests})`
|
|
422
407
|
: `All examples tests passed (${passed}/${totalTests})`);
|
|
423
408
|
process.exit(0);
|
|
424
409
|
} else {
|
|
425
|
-
|
|
410
|
+
info(proofOnly
|
|
426
411
|
? `Some proof golden tests failed (${passed}/${totalTests})`
|
|
427
412
|
: `Some examples tests failed (${passed}/${totalTests})`);
|
|
428
413
|
// keep exit code 2 (matches historical behavior of examples/test)
|
package/test/extra.test.js
CHANGED
|
@@ -5,21 +5,7 @@ const fs = require('node:fs');
|
|
|
5
5
|
const path = require('node:path');
|
|
6
6
|
const cp = require('node:child_process');
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
const C = TTY
|
|
10
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
11
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
12
|
-
const msTag = (ms) => `${C.dim}(${ms} ms)${C.n}`;
|
|
13
|
-
|
|
14
|
-
function ok(msg) {
|
|
15
|
-
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
16
|
-
}
|
|
17
|
-
function fail(msg) {
|
|
18
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
19
|
-
}
|
|
20
|
-
function info(msg) {
|
|
21
|
-
console.log(`${C.y}==${C.n} ${msg}`);
|
|
22
|
-
}
|
|
8
|
+
const { C, detail, failResult, info, pass } = require('./report');
|
|
23
9
|
|
|
24
10
|
function main() {
|
|
25
11
|
const suiteStart = Date.now();
|
|
@@ -29,7 +15,7 @@ function main() {
|
|
|
29
15
|
const nodePath = process.execPath;
|
|
30
16
|
|
|
31
17
|
if (!fs.existsSync(extraDir)) {
|
|
32
|
-
|
|
18
|
+
failResult(1, `Cannot find examples/extra directory: ${extraDir}`, 0);
|
|
33
19
|
process.exit(1);
|
|
34
20
|
}
|
|
35
21
|
|
|
@@ -44,16 +30,14 @@ function main() {
|
|
|
44
30
|
console.log(`${C.dim}node ${process.version}${C.n}`);
|
|
45
31
|
|
|
46
32
|
if (files.length === 0) {
|
|
47
|
-
|
|
33
|
+
info('No .js files found in examples/extra/');
|
|
48
34
|
process.exit(0);
|
|
49
35
|
}
|
|
50
36
|
|
|
51
37
|
let passed = 0;
|
|
52
38
|
let failed = 0;
|
|
53
|
-
const idxWidth = String(files.length).length;
|
|
54
|
-
|
|
55
39
|
for (let i = 0; i < files.length; i += 1) {
|
|
56
|
-
const
|
|
40
|
+
const testNr = i + 1;
|
|
57
41
|
const file = files[i];
|
|
58
42
|
const start = Date.now();
|
|
59
43
|
|
|
@@ -74,11 +58,11 @@ function main() {
|
|
|
74
58
|
const ms = Date.now() - start;
|
|
75
59
|
|
|
76
60
|
if (rc === 0) {
|
|
77
|
-
|
|
61
|
+
pass(testNr, `${file} -> output/${path.basename(outputPath)}`, ms);
|
|
78
62
|
passed += 1;
|
|
79
63
|
} else {
|
|
80
|
-
|
|
81
|
-
|
|
64
|
+
failResult(testNr, file, ms);
|
|
65
|
+
detail(`Exit code ${rc}`);
|
|
82
66
|
if (r.stderr) process.stderr.write(r.stderr);
|
|
83
67
|
failed += 1;
|
|
84
68
|
}
|
|
@@ -89,11 +73,11 @@ function main() {
|
|
|
89
73
|
info(`Total elapsed: ${suiteMs} ms (${(suiteMs / 1000).toFixed(2)} s)`);
|
|
90
74
|
|
|
91
75
|
if (failed === 0) {
|
|
92
|
-
|
|
76
|
+
info(`All extra examples passed (${passed}/${files.length})`);
|
|
93
77
|
process.exit(0);
|
|
94
78
|
}
|
|
95
79
|
|
|
96
|
-
|
|
80
|
+
info(`Some extra examples failed (${passed}/${files.length})`);
|
|
97
81
|
process.exit(2);
|
|
98
82
|
}
|
|
99
83
|
|
package/test/manifest.test.js
CHANGED
|
@@ -25,21 +25,7 @@ const cp = require('node:child_process');
|
|
|
25
25
|
|
|
26
26
|
const ROOT = path.resolve(__dirname, '..');
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
const C = TTY
|
|
30
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
31
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
32
|
-
|
|
33
|
-
function ok(msg) {
|
|
34
|
-
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
35
|
-
}
|
|
36
|
-
function warn(msg) {
|
|
37
|
-
console.log(`${C.y}SKIP${C.n} ${msg}`);
|
|
38
|
-
}
|
|
39
|
-
function fail(msg) {
|
|
40
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
41
|
-
process.exitCode = 1;
|
|
42
|
-
}
|
|
28
|
+
const { C, failResult, pass, warn } = require('./report');
|
|
43
29
|
|
|
44
30
|
function run(cmd, args, opts = {}) {
|
|
45
31
|
const t0 = Date.now();
|
|
@@ -70,17 +56,20 @@ function rmrf(p) {
|
|
|
70
56
|
}
|
|
71
57
|
|
|
72
58
|
(async function main() {
|
|
59
|
+
let sequence = 0;
|
|
73
60
|
if (process.env.CI && process.env.EYELING_RUN_NOTATION3TESTS !== '1') {
|
|
74
61
|
warn('CI detected; set EYELING_RUN_NOTATION3TESTS=1 to run Notation3 tests');
|
|
75
62
|
return;
|
|
76
63
|
}
|
|
77
64
|
|
|
78
65
|
if (!has('git')) {
|
|
79
|
-
|
|
66
|
+
failResult(++sequence, 'git not found in PATH', 0);
|
|
67
|
+
process.exitCode = 1;
|
|
80
68
|
return;
|
|
81
69
|
}
|
|
82
70
|
if (!has('npm')) {
|
|
83
|
-
|
|
71
|
+
failResult(++sequence, 'npm not found in PATH', 0);
|
|
72
|
+
process.exitCode = 1;
|
|
84
73
|
return;
|
|
85
74
|
}
|
|
86
75
|
|
|
@@ -94,11 +83,12 @@ function rmrf(p) {
|
|
|
94
83
|
// 1) Clone suite
|
|
95
84
|
let r = run('git', ['clone', '--depth', '1', 'https://codeberg.org/phochste/notation3tests', suiteDir]);
|
|
96
85
|
if (r.status !== 0) {
|
|
97
|
-
|
|
86
|
+
failResult(++sequence, `git clone failed (exit ${r.status})`, r.ms);
|
|
87
|
+
process.exitCode = 1;
|
|
98
88
|
rmrf(workDir);
|
|
99
89
|
return;
|
|
100
90
|
}
|
|
101
|
-
|
|
91
|
+
pass(++sequence, 'cloned notation3tests', r.ms);
|
|
102
92
|
|
|
103
93
|
// 2) Install suite dependencies
|
|
104
94
|
// Notation3tests can carry vulnerabilities in its transient dependency tree.
|
|
@@ -106,11 +96,12 @@ function rmrf(p) {
|
|
|
106
96
|
// Disable audit/funding output for this integration test install.
|
|
107
97
|
r = run('npm', ['ci', '--audit=false', '--fund=false'], { cwd: suiteDir });
|
|
108
98
|
if (r.status !== 0) {
|
|
109
|
-
|
|
99
|
+
failResult(++sequence, `npm ci failed (exit ${r.status})`, r.ms);
|
|
100
|
+
process.exitCode = 1;
|
|
110
101
|
rmrf(workDir);
|
|
111
102
|
return;
|
|
112
103
|
}
|
|
113
|
-
|
|
104
|
+
pass(++sequence, 'npm ci', r.ms);
|
|
114
105
|
|
|
115
106
|
// 3) Pack local Eyeling
|
|
116
107
|
const pack = runCapture('npm', ['pack', '--silent'], {
|
|
@@ -120,29 +111,32 @@ function rmrf(p) {
|
|
|
120
111
|
});
|
|
121
112
|
if (pack.status !== 0) {
|
|
122
113
|
console.error(pack.stderr || '');
|
|
123
|
-
|
|
114
|
+
failResult(++sequence, `npm pack failed (exit ${pack.status})`, pack.ms);
|
|
115
|
+
process.exitCode = 1;
|
|
124
116
|
rmrf(workDir);
|
|
125
117
|
return;
|
|
126
118
|
}
|
|
127
119
|
const tgzName = String(pack.stdout).trim().split(/\r?\n/).pop();
|
|
128
120
|
const tgzPath = path.join(ROOT, tgzName);
|
|
129
121
|
if (!fs.existsSync(tgzPath)) {
|
|
130
|
-
|
|
122
|
+
failResult(++sequence, `npm pack did not produce expected tarball: ${tgzPath}`, pack.ms);
|
|
123
|
+
process.exitCode = 1;
|
|
131
124
|
rmrf(workDir);
|
|
132
125
|
return;
|
|
133
126
|
}
|
|
134
|
-
|
|
127
|
+
pass(++sequence, `packed ${tgzName}`, pack.ms);
|
|
135
128
|
|
|
136
129
|
// 4) Install local tarball into suite
|
|
137
130
|
// Keep the install output focused on the actual test run.
|
|
138
131
|
r = run('npm', ['install', '--no-save', '--audit=false', '--fund=false', tgzPath], { cwd: suiteDir });
|
|
139
132
|
if (r.status !== 0) {
|
|
140
|
-
|
|
133
|
+
failResult(++sequence, `npm install eyeling tarball failed (exit ${r.status})`, r.ms);
|
|
134
|
+
process.exitCode = 1;
|
|
141
135
|
rmrf(tgzPath);
|
|
142
136
|
rmrf(workDir);
|
|
143
137
|
return;
|
|
144
138
|
}
|
|
145
|
-
|
|
139
|
+
pass(++sequence, 'installed local eyeling', r.ms);
|
|
146
140
|
|
|
147
141
|
// 5) Run suite test target
|
|
148
142
|
const t0 = Date.now();
|
|
@@ -153,7 +147,7 @@ function rmrf(p) {
|
|
|
153
147
|
rmrf(tgzPath);
|
|
154
148
|
|
|
155
149
|
if (r.status === 0) {
|
|
156
|
-
|
|
150
|
+
pass(++sequence, 'notation3tests:eyeling passed', totalMs);
|
|
157
151
|
if (process.env.EYELING_KEEP_NOTATION3TESTS === '1') {
|
|
158
152
|
console.log(`${C.dim}Keeping workdir (EYELING_KEEP_NOTATION3TESTS=1):${C.n} ${workDir}`);
|
|
159
153
|
} else {
|
|
@@ -162,7 +156,8 @@ function rmrf(p) {
|
|
|
162
156
|
return;
|
|
163
157
|
}
|
|
164
158
|
|
|
165
|
-
|
|
159
|
+
failResult(++sequence, `notation3tests:eyeling failed (exit ${r.status})`, totalMs);
|
|
160
|
+
process.exitCode = 1;
|
|
166
161
|
if (process.env.EYELING_KEEP_NOTATION3TESTS === '1') {
|
|
167
162
|
console.log(`${C.dim}Keeping workdir (EYELING_KEEP_NOTATION3TESTS=1):${C.n} ${workDir}`);
|
|
168
163
|
} else {
|
package/test/package.test.js
CHANGED
|
@@ -6,20 +6,7 @@ const os = require('node:os');
|
|
|
6
6
|
const path = require('node:path');
|
|
7
7
|
const cp = require('node:child_process');
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
const C = TTY
|
|
11
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
12
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
13
|
-
|
|
14
|
-
function info(msg) {
|
|
15
|
-
console.log(`${C.y}==${C.n} ${msg}`);
|
|
16
|
-
}
|
|
17
|
-
function ok(msg) {
|
|
18
|
-
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
19
|
-
}
|
|
20
|
-
function fail(msg) {
|
|
21
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
22
|
-
}
|
|
9
|
+
const { C, detail, failResult, info, pass } = require('./report');
|
|
23
10
|
|
|
24
11
|
function isWin() {
|
|
25
12
|
return process.platform === 'win32';
|
|
@@ -158,6 +145,7 @@ function packTarball(root) {
|
|
|
158
145
|
|
|
159
146
|
function main() {
|
|
160
147
|
const suiteStart = Date.now();
|
|
148
|
+
let sequence = 0;
|
|
161
149
|
const root = path.resolve(__dirname, '..');
|
|
162
150
|
|
|
163
151
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'eyeling-smoke-'));
|
|
@@ -167,15 +155,19 @@ function main() {
|
|
|
167
155
|
|
|
168
156
|
try {
|
|
169
157
|
info('Building tarball (npm pack)');
|
|
158
|
+
let stepStart = Date.now();
|
|
170
159
|
tgzInRoot = packTarball(root);
|
|
171
160
|
const srcTgz = path.join(root, tgzInRoot);
|
|
172
161
|
const dstTgz = path.join(tmp, tgzInRoot);
|
|
173
162
|
|
|
174
163
|
fs.renameSync(srcTgz, dstTgz);
|
|
164
|
+
pass(++sequence, `packed ${tgzInRoot}`, Date.now() - stepStart);
|
|
175
165
|
|
|
176
166
|
info('Creating temp project + installing tarball');
|
|
167
|
+
stepStart = Date.now();
|
|
177
168
|
runChecked(npmCmd(), ['init', '-y'], { cwd: tmp, stdio: 'ignore' });
|
|
178
169
|
runChecked(npmCmd(), ['install', `./${tgzInRoot}`, '--no-audit', '--no-fund'], { cwd: tmp, stdio: 'inherit' });
|
|
170
|
+
pass(++sequence, 'created temp project and installed tarball', Date.now() - stepStart);
|
|
179
171
|
|
|
180
172
|
info('API smoke test');
|
|
181
173
|
// Run a tiny API check via node -e
|
|
@@ -193,17 +185,18 @@ function main() {
|
|
|
193
185
|
console.error('Unexpected output:\\n' + out);
|
|
194
186
|
process.exit(1);
|
|
195
187
|
}
|
|
196
|
-
console.log('OK: API works');
|
|
197
188
|
`;
|
|
189
|
+
stepStart = Date.now();
|
|
198
190
|
runChecked(process.execPath, ['-e', apiCode], { cwd: tmp, stdio: 'inherit' });
|
|
199
|
-
|
|
191
|
+
pass(++sequence, 'API works', Date.now() - stepStart);
|
|
200
192
|
|
|
201
193
|
info('CLI smoke test');
|
|
202
194
|
const bin = isWin()
|
|
203
195
|
? path.join(tmp, 'node_modules', '.bin', 'eyeling.cmd')
|
|
204
196
|
: path.join(tmp, 'node_modules', '.bin', 'eyeling');
|
|
197
|
+
stepStart = Date.now();
|
|
205
198
|
runChecked(bin, ['-v'], { cwd: tmp, stdio: 'inherit' });
|
|
206
|
-
|
|
199
|
+
pass(++sequence, 'CLI works', Date.now() - stepStart);
|
|
207
200
|
|
|
208
201
|
info('Examples smoke test (installed package)');
|
|
209
202
|
const pkgRoot = path.join(tmp, 'node_modules', 'eyeling');
|
|
@@ -220,11 +213,10 @@ function main() {
|
|
|
220
213
|
const SMOKE_EXAMPLES = ['age.n3', 'basic-monadic.n3', 'family-cousins.n3', 'backward.n3', 'context-association.n3'];
|
|
221
214
|
|
|
222
215
|
const tmpExamplesOut = fs.mkdtempSync(path.join(os.tmpdir(), 'eyeling-pkg-examples-'));
|
|
223
|
-
|
|
224
|
-
const smokePad2 = (n) => String(n).padStart(2, '0');
|
|
225
|
-
const smokeOk = (n, msg) => console.log(`${C.g}OK${C.n} ${smokePad2(n)} ${msg}`);
|
|
216
|
+
stepStart = Date.now();
|
|
226
217
|
try {
|
|
227
218
|
for (const file of SMOKE_EXAMPLES) {
|
|
219
|
+
const smokeStart = Date.now();
|
|
228
220
|
const inputPath = path.join(examplesDir, file);
|
|
229
221
|
const expectedPath = resolveExpectedPath(outputDir, file);
|
|
230
222
|
|
|
@@ -275,20 +267,21 @@ Output differs for ${file}:`);
|
|
|
275
267
|
throw new Error(`Example ${file}: output differs from golden`);
|
|
276
268
|
}
|
|
277
269
|
|
|
278
|
-
|
|
270
|
+
pass(++sequence, `Example smoke: ${file}`, Date.now() - smokeStart);
|
|
279
271
|
}
|
|
280
272
|
} finally {
|
|
281
273
|
rmrf(tmpExamplesOut);
|
|
282
274
|
}
|
|
283
|
-
|
|
275
|
+
pass(++sequence, 'Installed examples smoke test passed', Date.now() - stepStart);
|
|
284
276
|
|
|
285
277
|
const suiteMs = Date.now() - suiteStart;
|
|
286
278
|
console.log('');
|
|
287
|
-
|
|
279
|
+
info(`Packaged install smoke test passed (${suiteMs} ms, ${(suiteMs / 1000).toFixed(2)} s)`);
|
|
288
280
|
process.exit(0);
|
|
289
281
|
} catch (e) {
|
|
290
282
|
console.log('');
|
|
291
|
-
|
|
283
|
+
failResult(++sequence, 'packaged install smoke test failed', Date.now() - suiteStart);
|
|
284
|
+
detail(e && e.stack ? e.stack : String(e));
|
|
292
285
|
process.exit(1);
|
|
293
286
|
} finally {
|
|
294
287
|
// If rename failed and the tarball still exists in root, try to delete it
|
package/test/packlist.test.js
CHANGED
|
@@ -4,19 +4,9 @@ const assert = require('node:assert/strict');
|
|
|
4
4
|
const cp = require('node:child_process');
|
|
5
5
|
const fs = require('node:fs');
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const C = TTY ? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', n: '\x1b[0m' } : { g: '', r: '', y: '', n: '' };
|
|
9
|
-
|
|
10
|
-
function ok(msg) {
|
|
11
|
-
console.log(`${C.g}OK ${C.n} ${msg}`);
|
|
12
|
-
}
|
|
13
|
-
function info(msg) {
|
|
14
|
-
console.log(`${C.y}${msg}${C.n}`);
|
|
15
|
-
}
|
|
16
|
-
function fail(msg) {
|
|
17
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
18
|
-
}
|
|
7
|
+
const { detail, failResult, info, pass } = require('./report');
|
|
19
8
|
|
|
9
|
+
const start = Date.now();
|
|
20
10
|
try {
|
|
21
11
|
info('Checking packlist + metadata…');
|
|
22
12
|
|
|
@@ -65,8 +55,9 @@ try {
|
|
|
65
55
|
'missing from npm pack: examples/output/*',
|
|
66
56
|
);
|
|
67
57
|
|
|
68
|
-
|
|
58
|
+
pass(1, 'packlist + metadata sanity checks passed', Date.now() - start);
|
|
69
59
|
} catch (e) {
|
|
70
|
-
|
|
60
|
+
failResult(1, 'packlist + metadata sanity checks failed', Date.now() - start);
|
|
61
|
+
detail(e && e.stack ? e.stack : String(e));
|
|
71
62
|
process.exit(1);
|
|
72
63
|
}
|
package/test/playground.test.js
CHANGED
|
@@ -18,45 +18,29 @@ const { setTimeout: sleep } = require('node:timers/promises');
|
|
|
18
18
|
|
|
19
19
|
const ROOT = path.resolve(__dirname, '..');
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
const C = TTY
|
|
23
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
24
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
25
|
-
const msTag = (ms) => `${C.dim}(${ms} ms)${C.n}`;
|
|
21
|
+
const { detail, failResult, info, pass } = require('./report');
|
|
26
22
|
|
|
27
23
|
const TOTAL_TESTS = (fs.readFileSync(__filename, 'utf8').match(/^\s*beginTest\(/gm) || []).length;
|
|
28
|
-
const idxWidth = String(Math.max(1, TOTAL_TESTS)).length;
|
|
29
24
|
let passed = 0;
|
|
30
25
|
let failed = 0;
|
|
31
26
|
let currentTest = null;
|
|
32
27
|
let nonTestFailure = false;
|
|
33
28
|
const suiteStart = Date.now();
|
|
34
29
|
|
|
35
|
-
function ok(msg) {
|
|
36
|
-
console.log(`${C.g}OK${C.n} ${msg}`);
|
|
37
|
-
}
|
|
38
|
-
function info(msg) {
|
|
39
|
-
console.log(`${C.y}==${C.n} ${msg}`);
|
|
40
|
-
}
|
|
41
|
-
function fail(msg) {
|
|
42
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
43
|
-
}
|
|
44
30
|
function beginTest(msg) {
|
|
45
31
|
currentTest = { msg, start: Date.now() };
|
|
46
32
|
}
|
|
47
33
|
function endTest() {
|
|
48
34
|
const tc = currentTest;
|
|
49
35
|
if (!tc) return;
|
|
50
|
-
|
|
51
|
-
ok(`${idx} ${tc.msg} ${msTag(Date.now() - tc.start)}`);
|
|
36
|
+
pass(passed + failed + 1, tc.msg, Date.now() - tc.start);
|
|
52
37
|
passed += 1;
|
|
53
38
|
currentTest = null;
|
|
54
39
|
}
|
|
55
40
|
function recordCurrentFailure() {
|
|
56
41
|
const tc = currentTest;
|
|
57
42
|
if (!tc) return false;
|
|
58
|
-
|
|
59
|
-
fail(`${idx} ${tc.msg} ${msTag(Date.now() - tc.start)}`);
|
|
43
|
+
failResult(passed + failed + 1, tc.msg, Date.now() - tc.start);
|
|
60
44
|
failed += 1;
|
|
61
45
|
currentTest = null;
|
|
62
46
|
return true;
|
|
@@ -66,9 +50,9 @@ function printSummary() {
|
|
|
66
50
|
const suiteMs = Date.now() - suiteStart;
|
|
67
51
|
info(`Total elapsed: ${suiteMs} ms (${(suiteMs / 1000).toFixed(2)} s)`);
|
|
68
52
|
if (failed === 0 && !nonTestFailure) {
|
|
69
|
-
|
|
53
|
+
info(`All playground tests passed (${passed}/${TOTAL_TESTS})`);
|
|
70
54
|
} else {
|
|
71
|
-
|
|
55
|
+
info(`Some playground tests failed (${passed}/${TOTAL_TESTS})`);
|
|
72
56
|
}
|
|
73
57
|
}
|
|
74
58
|
|
|
@@ -1269,6 +1253,6 @@ ${JSON.stringify(last, null, 2)}`);
|
|
|
1269
1253
|
main().catch((e) => {
|
|
1270
1254
|
if (!recordCurrentFailure()) nonTestFailure = true;
|
|
1271
1255
|
printSummary();
|
|
1272
|
-
|
|
1256
|
+
detail(e && e.stack ? e.stack : String(e));
|
|
1273
1257
|
process.exit(1);
|
|
1274
1258
|
});
|
package/test/rdf12.test.js
CHANGED
|
@@ -3,44 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
const cp = require('node:child_process');
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
process.stdout.isTTY ||
|
|
8
|
-
(process.env.FORCE_COLOR && process.env.FORCE_COLOR !== '0')
|
|
9
|
-
);
|
|
10
|
-
const C = USE_COLOR
|
|
11
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', gray: '\x1b[90m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
12
|
-
: { g: '', r: '', y: '', gray: '', dim: '', n: '' };
|
|
13
|
-
|
|
14
|
-
function formatDuration(ms) {
|
|
15
|
-
if (!Number.isFinite(ms) || ms < 0) return '0 ms';
|
|
16
|
-
if (ms < 1000) return `${Math.round(ms)} ms`;
|
|
17
|
-
if (ms < 10000) return `${(ms / 1000).toFixed(2)} s`;
|
|
18
|
-
if (ms < 60000) return `${(ms / 1000).toFixed(1)} s`;
|
|
19
|
-
|
|
20
|
-
const minutes = Math.floor(ms / 60000);
|
|
21
|
-
const seconds = ((ms % 60000) / 1000).toFixed(1).padStart(4, '0');
|
|
22
|
-
return `${minutes}m ${seconds}s`;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function durationSuffix(ms) {
|
|
26
|
-
return ms == null ? '' : ` ${C.gray}${formatDuration(ms)}${C.n}`;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function ok(msg, ms) {
|
|
30
|
-
console.log(`${C.g}OK${C.n} ${msg}${durationSuffix(ms)}`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function fail(msg, ms) {
|
|
34
|
-
console.error(`${C.r}FAIL${C.n} ${msg}${durationSuffix(ms)}`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function info(msg, ms) {
|
|
38
|
-
console.log(`${C.y}==${C.n} ${msg}${durationSuffix(ms)}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function detail(msg) {
|
|
42
|
-
console.log(`${C.dim}${msg}${C.n}`);
|
|
43
|
-
}
|
|
6
|
+
const { C, detail, failResult, formatDuration, info, pass } = require('./report');
|
|
44
7
|
|
|
45
8
|
function nowMs() {
|
|
46
9
|
return Number(process.hrtime.bigint()) / 1e6;
|
|
@@ -143,9 +106,6 @@ function resolveSuiteKeys(args) {
|
|
|
143
106
|
return keys;
|
|
144
107
|
}
|
|
145
108
|
|
|
146
|
-
function sequenceLabel(n) {
|
|
147
|
-
return String(n).padStart(3, '0');
|
|
148
|
-
}
|
|
149
109
|
|
|
150
110
|
function createLineReader(onLine) {
|
|
151
111
|
let buffer = '';
|
|
@@ -177,12 +137,12 @@ function printEvent(suiteResult, event, totals) {
|
|
|
177
137
|
const caseElapsedMs = now - suiteResult.lastCaseAt;
|
|
178
138
|
suiteResult.lastCaseAt = now;
|
|
179
139
|
|
|
180
|
-
const message = `${
|
|
140
|
+
const message = `${suiteResult.suite.label}: ${event.message}`;
|
|
181
141
|
if (event.kind === 'ok') {
|
|
182
|
-
|
|
142
|
+
pass(totals.sequence, message, caseElapsedMs);
|
|
183
143
|
totals.passed++;
|
|
184
144
|
} else {
|
|
185
|
-
|
|
145
|
+
failResult(totals.sequence, message, caseElapsedMs);
|
|
186
146
|
totals.failed++;
|
|
187
147
|
suiteResult.failedCount++;
|
|
188
148
|
}
|
|
@@ -236,11 +196,11 @@ function runSuite(key, totals) {
|
|
|
236
196
|
suiteResult.error = e;
|
|
237
197
|
if (!sawCase) {
|
|
238
198
|
totals.sequence++;
|
|
239
|
-
|
|
199
|
+
failResult(totals.sequence, `${suite.label}: rdf-test-suite could not start: ${e.message || String(e)}`, elapsedMs);
|
|
240
200
|
totals.failed++;
|
|
241
201
|
suiteResult.caseCount++;
|
|
242
202
|
}
|
|
243
|
-
console.log(`${C.
|
|
203
|
+
console.log(`${C.dim}Suite elapsed ${formatDuration(elapsedMs)}${C.n}`);
|
|
244
204
|
console.log('');
|
|
245
205
|
resolve({ ...suiteResult, status: 1, elapsedMs });
|
|
246
206
|
return;
|
|
@@ -273,21 +233,21 @@ function runSuite(key, totals) {
|
|
|
273
233
|
: `${suite.label}: rdf-test-suite exited with ${suiteResult.status === 0 ? 'success' : exitText}`;
|
|
274
234
|
|
|
275
235
|
if (suiteResult.status === 0) {
|
|
276
|
-
|
|
236
|
+
pass(totals.sequence, message, elapsedMs);
|
|
277
237
|
totals.passed++;
|
|
278
238
|
} else {
|
|
279
|
-
|
|
239
|
+
failResult(totals.sequence, message, elapsedMs);
|
|
280
240
|
totals.failed++;
|
|
281
241
|
}
|
|
282
242
|
suiteResult.caseCount++;
|
|
283
243
|
} else if (suiteResult.status !== 0 && suiteResult.failedCount === 0) {
|
|
284
244
|
totals.sequence++;
|
|
285
|
-
|
|
245
|
+
failResult(totals.sequence, `${suite.label}: rdf-test-suite exited with status ${suiteResult.status}`, elapsedMs);
|
|
286
246
|
totals.failed++;
|
|
287
247
|
suiteResult.caseCount++;
|
|
288
248
|
}
|
|
289
249
|
|
|
290
|
-
console.log(`${C.
|
|
250
|
+
console.log(`${C.dim}Suite elapsed ${formatDuration(elapsedMs)}${C.n}`);
|
|
291
251
|
console.log('');
|
|
292
252
|
resolve(suiteResult);
|
|
293
253
|
});
|
|
@@ -299,7 +259,7 @@ async function main() {
|
|
|
299
259
|
try {
|
|
300
260
|
keys = resolveSuiteKeys(process.argv.slice(2));
|
|
301
261
|
} catch (e) {
|
|
302
|
-
|
|
262
|
+
failResult(1, e && e.message ? e.message : String(e), 0);
|
|
303
263
|
process.exit(1);
|
|
304
264
|
return;
|
|
305
265
|
}
|
|
@@ -322,16 +282,17 @@ async function main() {
|
|
|
322
282
|
info(`Grand total: ${totals.passed} OK, ${totals.failed} FAIL, ${totals.sequence} RDF 1.2 tests`, grandElapsedMs);
|
|
323
283
|
|
|
324
284
|
if (totals.failed === 0 && results.every((suiteResult) => suiteResult.status === 0)) {
|
|
325
|
-
|
|
285
|
+
info(`All RDF 1.2 syntax tests passed (${totals.passed}/${totals.sequence})`);
|
|
326
286
|
process.exit(0);
|
|
327
287
|
return;
|
|
328
288
|
}
|
|
329
289
|
|
|
330
|
-
|
|
290
|
+
info(`Some RDF 1.2 syntax tests failed (${totals.passed}/${totals.sequence})`);
|
|
331
291
|
process.exit(1);
|
|
332
292
|
}
|
|
333
293
|
|
|
334
294
|
main().catch((e) => {
|
|
335
|
-
|
|
295
|
+
failResult(1, 'RDF 1.2 syntax test runner failed', 0);
|
|
296
|
+
detail(e && e.stack ? e.stack : String(e));
|
|
336
297
|
process.exit(1);
|
|
337
298
|
});
|
package/test/report.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const USE_COLOR = !process.env.NO_COLOR && (
|
|
4
|
+
process.stdout.isTTY ||
|
|
5
|
+
(process.env.FORCE_COLOR && process.env.FORCE_COLOR !== '0')
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
const C = USE_COLOR
|
|
9
|
+
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
10
|
+
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
11
|
+
|
|
12
|
+
function formatDuration(ms) {
|
|
13
|
+
if (!Number.isFinite(ms) || ms < 0) return '0 ms';
|
|
14
|
+
if (ms < 1000) return `${Math.round(ms)} ms`;
|
|
15
|
+
if (ms < 10000) return `${(ms / 1000).toFixed(2)} s`;
|
|
16
|
+
if (ms < 60000) return `${(ms / 1000).toFixed(1)} s`;
|
|
17
|
+
|
|
18
|
+
const minutes = Math.floor(ms / 60000);
|
|
19
|
+
const seconds = ((ms % 60000) / 1000).toFixed(1).padStart(4, '0');
|
|
20
|
+
return `${minutes}m ${seconds}s`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function durationSuffix(ms) {
|
|
24
|
+
return ms == null ? '' : ` ${C.dim}(${formatDuration(ms)})${C.n}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function sequenceLabel(n) {
|
|
28
|
+
return String(n).padStart(3, '0');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function result(status, n, description, ms) {
|
|
32
|
+
const color = status === 'OK' ? C.g : C.r;
|
|
33
|
+
const stream = status === 'OK' ? console.log : console.error;
|
|
34
|
+
stream(`${color}${status}${C.n} ${sequenceLabel(n)} ${description}${durationSuffix(ms)}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function pass(n, description, ms) {
|
|
38
|
+
result('OK', n, description, ms);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function failResult(n, description, ms) {
|
|
42
|
+
result('FAIL', n, description, ms);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function info(msg, ms) {
|
|
46
|
+
console.log(`${C.y}==${C.n} ${msg}${durationSuffix(ms)}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function warn(msg) {
|
|
50
|
+
console.log(`${C.y}SKIP${C.n} ${msg}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function detail(msg) {
|
|
54
|
+
console.log(`${C.dim}${msg}${C.n}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = {
|
|
58
|
+
C,
|
|
59
|
+
detail,
|
|
60
|
+
durationSuffix,
|
|
61
|
+
failResult,
|
|
62
|
+
formatDuration,
|
|
63
|
+
info,
|
|
64
|
+
pass,
|
|
65
|
+
sequenceLabel,
|
|
66
|
+
warn,
|
|
67
|
+
};
|
|
@@ -9,23 +9,7 @@ const path = require('node:path');
|
|
|
9
9
|
const root = path.resolve(__dirname, '..');
|
|
10
10
|
const eyelingJsPath = path.join(root, 'eyeling.js');
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
const C = TTY
|
|
14
|
-
? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
|
|
15
|
-
: { g: '', r: '', y: '', dim: '', n: '' };
|
|
16
|
-
|
|
17
|
-
function ok(msg) {
|
|
18
|
-
console.log(`${C.g}OK ${C.n} ${msg}`);
|
|
19
|
-
}
|
|
20
|
-
function info(msg) {
|
|
21
|
-
console.log(`${C.y}==${C.n} ${msg}`);
|
|
22
|
-
}
|
|
23
|
-
function fail(msg) {
|
|
24
|
-
console.error(`${C.r}FAIL${C.n} ${msg}`);
|
|
25
|
-
}
|
|
26
|
-
function numberedName(index, name) {
|
|
27
|
-
return `${String(index + 1).padStart(3, '0')} ${name}`;
|
|
28
|
-
}
|
|
12
|
+
const { detail, failResult, info, pass } = require('./report');
|
|
29
13
|
function msNow() {
|
|
30
14
|
return Date.now();
|
|
31
15
|
}
|
|
@@ -354,15 +338,16 @@ const cases = [
|
|
|
354
338
|
let failed = 0;
|
|
355
339
|
for (const [index, tc] of cases.entries()) {
|
|
356
340
|
const tmp = mkTmpDir();
|
|
357
|
-
const
|
|
341
|
+
const testNr = index + 1;
|
|
342
|
+
const testName = tc.name;
|
|
358
343
|
const start = msNow();
|
|
359
344
|
try {
|
|
360
345
|
await tc.run(tmp);
|
|
361
|
-
|
|
346
|
+
pass(testNr, testName, msNow() - start);
|
|
362
347
|
passed++;
|
|
363
348
|
} catch (e) {
|
|
364
|
-
|
|
365
|
-
|
|
349
|
+
failResult(testNr, testName, msNow() - start);
|
|
350
|
+
detail(e && e.stack ? e.stack : String(e));
|
|
366
351
|
failed++;
|
|
367
352
|
} finally {
|
|
368
353
|
rmrf(tmp);
|
|
@@ -370,14 +355,15 @@ const cases = [
|
|
|
370
355
|
}
|
|
371
356
|
console.log('');
|
|
372
357
|
const suiteMs = msNow() - suiteStart;
|
|
373
|
-
|
|
358
|
+
info(`Total elapsed: ${suiteMs} ms (${(suiteMs / 1000).toFixed(2)} s)`);
|
|
374
359
|
if (failed === 0) {
|
|
375
|
-
|
|
360
|
+
info(`All stream-message tests passed (${passed}/${cases.length})`);
|
|
376
361
|
process.exit(0);
|
|
377
362
|
}
|
|
378
|
-
|
|
363
|
+
info(`Some stream-message tests failed (${passed}/${cases.length})`);
|
|
379
364
|
process.exit(1);
|
|
380
365
|
})().catch((e) => {
|
|
381
|
-
|
|
366
|
+
failResult(1, 'stream-message test runner failed', 0);
|
|
367
|
+
detail(e && e.stack ? e.stack : String(e));
|
|
382
368
|
process.exit(1);
|
|
383
369
|
});
|