Skip to content

Commit 4be4b3d

Browse files
committed
Add timeout option to catch infinite-loop tests
Adds a `timeoutMsecs` option to allow tests to run before they'll be terminated. This ensures that infinite-loop (or super-long) tests won't prevent others from completing. Default is 2000 msecs (2 seconds) which should be fine even for slow CI systems. But when running tests in a debugger, set the timeout to much longer (like 1 hour) so that you'll have time to debug tests. If a string is provided, it'll be parsed into a number before evaluation, which makes it easier for callers to pass environment variables as-is. NaN values will silently be assigned the default value. FYI, this option was added to support using this Test262 runner package with https://github.com/fullcalendar/temporal.
1 parent 4b5610f commit 4be4b3d

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,12 @@ process.exit(result ? 0 : 1);
6565
built-ins/Temporal/Duration/compare/argument-string-negative-fractional-units.js
6666
built-ins/Temporal/Duration/from/argument-string-negative-fractional-units.js
6767
```
68+
* `timeoutMsecs?: number|string` - Optional number of milliseconds to allow
69+
tests to run before they'll be terminated. This ensures that infinite-loop (or
70+
super-long) tests won't prevent others from completing. Default is 2000 msecs
71+
(2 seconds) which should be fine even for slow CI systems. But when running
72+
tests in a debugger, set the timeout to much longer (like 1 hour) so that
73+
you'll have time to debug tests. If a string is provided, it'll be parsed into
74+
a number before evaluation, which makes it easier for callers to pass
75+
environment variables as-is. NaN values will silently be assigned the default
76+
value.

index.mjs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ import yaml from 'js-yaml';
5757
* built-ins/Temporal/Duration/compare/argument-string-negative-fractional-units.js
5858
* built-ins/Temporal/Duration/from/argument-string-negative-fractional-units.js
5959
* ```
60+
* @property {number|string=2000} timeoutMsecs Optional number of milliseconds
61+
* to allow tests to run before they'll be terminated. This ensures that
62+
* infinite-loop (or super-long) tests won't prevent others from completing.
63+
* Default is 2000 msecs (2 seconds) which should be fine even for slow CI
64+
* systems. But when running tests in a debugger, set the timeout to much
65+
* longer (like 1 hour) so that you'll have time to debug tests. If a string
66+
* is provided, it'll be parsed into a number before evaluation, which makes
67+
* it easier for callers to pass environment variables as-is. NaN values will
68+
* silently be assigned the default value.
6069
*
6170
* @param {Options} options Object with the following properties:
6271
* - `polyfillCodeFile: string` - Filename of the Temporal polyfill. Must be a
@@ -76,9 +85,24 @@ import yaml from 'js-yaml';
7685
* `test262Dir`) that are expected to fail. Lines starting with `#` and
7786
* blank lines are ignored. Lines from multiple files will be concatenated
7887
* and de-duped.
88+
* - `timeoutMsecs?: number|string` - Optional number of milliseconds to allow
89+
* tests to run before they'll be terminated. This ensures that
90+
* infinite-loop (or super-long) tests won't prevent others from completing.
91+
* Default is 2000 msecs (2 seconds) which should be fine even for slow CI
92+
* systems. But when running tests in a debugger, set the timeout to much
93+
* longer (like 1 hour) so that you'll have time to debug tests. If a string
94+
* is provided, it'll be parsed into a number before evaluation, which makes
95+
* it easier for callers to pass environment variables as-is. NaN values
96+
* will silently be assigned the default value.
7997
* @returns {boolean} `true` if all tests completed as expected, `false` if not.
8098
*/
81-
export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, expectedFailureFiles }) {
99+
export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, expectedFailureFiles, timeoutMsecs }) {
100+
101+
// Default timeout is 2 seconds. Set a longer timeout for running tests under
102+
// a debugger.
103+
timeoutMsecs = parseInt(timeoutMsecs);
104+
if (typeof timeoutMsecs === 'undefined' || isNaN(timeoutMsecs)) timeoutMsecs = 2000;
105+
82106
// In the test262 repo, the actual tests are contained in a /test directory
83107
const testSubdirectory = path.resolve(test262Dir, 'test');
84108

@@ -280,7 +304,7 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
280304
// what it's supposed to be. This is so that you don't have to wait until the
281305
// end to see if your test failed.
282306
try {
283-
vm.runInContext(testCode, testContext);
307+
vm.runInContext(testCode, testContext, { timeout: timeoutMsecs });
284308
if (!expectedFailureLists) {
285309
passCount++;
286310
} else {
@@ -344,7 +368,8 @@ export default function runTest262({ test262Dir, testGlobs, polyfillCodeFile, ex
344368
if (longTests.length > 0) {
345369
print('\nThe following tests took a long time:');
346370
longTests.forEach(({ file, ns }) => {
347-
print(` ${color.yellow(Math.round(Number(ns) / 1_000_000))} ms: ${file}`);
371+
const ms = Math.round(Number(ns) / 1_000_000);
372+
print(` ${color.yellow(ms)} ms${ms >= timeoutMsecs ? ' (timeout)' : ''}: ${file}`);
348373
});
349374
}
350375

0 commit comments

Comments
 (0)