Skip to content

Commit 250452b

Browse files
authored
DX Improvements (#16)
* fix bug with test262Dir not truly being customizable * fix bug with sourcemaps not having filesystem-resolvable paths * maxFailures setting * fullPath setting for displaying full filesystem paths in console * updateExpectedFailureFiles will remove test files that no longer exist. even when OFF, will warn about missing files * make missing-test-removal CLI text more understandable * fix typos
1 parent 6386a11 commit 250452b

File tree

1 file changed

+86
-10
lines changed

1 file changed

+86
-10
lines changed

index.mjs

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ const UTF8 = { encoding: 'utf-8' };
7474
* fix test failures, removing tests that were expected to fail but now pass
7575
* from the expected-failure files. This option does not add newly failing
7676
* tests to the expected-failure files - this must be done manually.
77+
* @property {number=} maxFailures Whether to stop executing test files after a
78+
* certain number of failures have been reached. Useful for preventing your
79+
* console from becoming overwhelmed.
80+
* @property {boolean=} fullPath Whether to print out the absolute file paths
81+
* of test files in reports.
7782
*
7883
* @param {Options} options Object with the following properties:
7984
* - `polyfillCodeFile: string` - Filename of the Temporal polyfill. Must be a
@@ -107,10 +112,23 @@ const UTF8 = { encoding: 'utf-8' };
107112
* fix test failures, removing tests that were expected to fail but now pass
108113
* from the expected-failure files. This option does not add newly failing
109114
* tests to the expected-failure files - this must be done manually.
115+
* - `maxFailures?: number` - Whether to stop executing test files after a
116+
* certain number of failures have been reached. Useful for preventing your
117+
* console from becoming overwhelmed.
118+
* - `fullPath?: boolean` - Whether to print out the absolute file paths
119+
* of test files in reports.
110120
* @returns {boolean} `true` if all tests completed as expected, `false` if not.
111121
*/
112-
export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, expectedFailureFiles, timeoutMsecs, updateExpectedFailureFiles }) {
113-
122+
export default function runTest262({
123+
test262Dir,
124+
testGlobs,
125+
polyfillCodeFile,
126+
expectedFailureFiles,
127+
timeoutMsecs,
128+
updateExpectedFailureFiles,
129+
maxFailures,
130+
fullPath
131+
}) {
114132
// Default timeout is 2 seconds. Set a longer timeout for running tests under
115133
// a debugger.
116134
timeoutMsecs = parseInt(timeoutMsecs);
@@ -177,7 +195,7 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
177195
function getHelperScript(includeName) {
178196
if (helpersCache.has(includeName)) return helpersCache.get(includeName);
179197

180-
const includeFile = `test262/harness/${includeName}`;
198+
const includeFile = path.join(test262Dir, 'harness', includeName);
181199
const includeCode = fs.readFileSync(includeFile, UTF8);
182200
const include = new vm.Script(includeCode, {filename: path.resolve(includeFile)});
183201

@@ -265,9 +283,16 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
265283
let passCount = 0;
266284
let expectedFailCount = 0;
267285
let unexpectedPassCount = 0;
286+
let skippedCount = 0;
268287

269288
// === The test loop ===
270289
for (const testFile of testFiles) {
290+
// Skip test if over the max-failure limit
291+
if (maxFailures && failures.length >= maxFailures) {
292+
skippedCount++;
293+
continue;
294+
}
295+
271296
// Set up the VM context with the polyfill first, as if it were built-in
272297
const testContext = {};
273298
vm.createContext(testContext);
@@ -285,7 +310,7 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
285310

286311
// Include a sourceURL so that when tests are run in a debugger they can be
287312
// found using the names listed in the expected-failures-style files.
288-
testCode += `\n//# sourceURL=${testRelPath}`;
313+
testCode += `\n//# sourceURL=file://${testFile}`;
289314

290315
const frontmatterString = frontmatterMatcher.exec(testCode)?.[1] ?? '';
291316
const frontmatter = yaml.load(frontmatterString);
@@ -319,7 +344,9 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
319344
// what it's supposed to be. This is so that you don't have to wait until the
320345
// end to see if your test failed.
321346
try {
322-
vm.runInContext(testCode, testContext, { timeout: timeoutMsecs });
347+
const testScript = new vm.Script(testCode, { filename: testFile });
348+
testScript.runInContext(testContext, { timeout: timeoutMsecs });
349+
323350
if (!expectedFailureLists) {
324351
passCount++;
325352
} else {
@@ -336,7 +363,7 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
336363
if (expectedFailureLists) {
337364
expectedFailCount++;
338365
} else {
339-
failures.push({ file: testRelPath, error: e });
366+
failures.push({ file: fullPath ? path.resolve(testFile) : testRelPath, error: e });
340367
progress.interrupt(`FAIL: ${testDisplayName}`);
341368
}
342369
}
@@ -350,6 +377,32 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
350377
progress.tick(1, { test: progressDisplayName });
351378
}
352379

380+
// === Detect expected-failure entries with missing files ===
381+
382+
const missingTestsMap = new Map();
383+
let missingTestsCnt = 0;
384+
385+
if (testGlobs.length === 0) {
386+
const testRelPathSet = new Set(
387+
[...testFiles].map((testFile) => path.relative(testSubdirectory, testFile))
388+
);
389+
390+
for (const [expectedFailureFile, expectedFailureTestsSet] of expectedFailureLists) {
391+
const missingTestsSet = new Set();
392+
393+
for (const expectedFailureTest of expectedFailureTestsSet) {
394+
if (!testRelPathSet.has(expectedFailureTest)) {
395+
missingTestsSet.add(expectedFailureTest);
396+
missingTestsCnt++;
397+
}
398+
}
399+
400+
if (missingTestsSet.size) {
401+
missingTestsMap.set(expectedFailureFile, missingTestsSet);
402+
}
403+
}
404+
}
405+
353406
// === Print results ===
354407

355408
const finish = process.hrtime.bigint();
@@ -378,9 +431,24 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
378431
}
379432
for (const [expectedFailureFile, unexpectedPassesSet] of unexpectedPasses) {
380433
if (updateExpectedFailureFiles) updateExpectedFailureFile(expectedFailureFile, unexpectedPassesSet);
381-
print(` \u2022 ${expectedFailureFile}:`);
434+
print(` \u2022 ${expectedFailureFile}:`);
382435
for (const unexpectedPass of unexpectedPassesSet) {
383-
print(`${unexpectedPass}`);
436+
print(` \u2022 ${unexpectedPass}`);
437+
}
438+
}
439+
}
440+
441+
if (missingTestsMap.size > 0) {
442+
if (updateExpectedFailureFiles) {
443+
print(`\n${color.yellow.bold('WARNING:')} Tests not found; references have been removed from the following expected-failure files:`);
444+
} else {
445+
print(`\n${color.yellow.bold('WARNING:')} Tests not found; remove references from the following expected-failure files?`);
446+
}
447+
for (const [expectedFailureFile, missingTestsSet] of missingTestsMap) {
448+
if (updateExpectedFailureFiles) updateExpectedFailureFile(expectedFailureFile, missingTestsSet);
449+
print(` \u2022 ${expectedFailureFile}:`);
450+
for (const missingTest of missingTestsSet) {
451+
print(` \u2022 ${missingTest}`);
384452
}
385453
}
386454
}
@@ -397,16 +465,24 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
397465
print(color.green(` ${passCount} passed`));
398466
print(color.red(` ${failures.length} failed`));
399467
print(color.red(` ${unexpectedPassCount} passed unexpectedly`));
468+
400469
if (expectedFailCount > 0) {
401470
print(color.cyan(` ${expectedFailCount} expected failures`));
402471
}
472+
if (missingTestsCnt > 0) {
473+
print(color.cyan(` ${missingTestsCnt} missing tests`));
474+
}
475+
if (skippedCount > 0) {
476+
print(color.grey(` ${skippedCount} skipped`));
477+
}
478+
403479
return !hasFailures;
404480
}
405481

406-
function updateExpectedFailureFile(fileName, expectedFailuresInFile) {
482+
function updateExpectedFailureFile(fileName, linesForRemoval) {
407483
const linesOnDisk = fs
408484
.readFileSync(fileName, UTF8)
409485
.split(/\r?\n/g);
410-
const output = linesOnDisk.filter(l => !expectedFailuresInFile.has(l));
486+
const output = linesOnDisk.filter(l => !linesForRemoval.has(l));
411487
fs.writeFileSync(fileName, output.join('\n'), UTF8);
412488
}

0 commit comments

Comments
 (0)