summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
authorCasper Beyer <caspervonb@pm.me>2021-02-24 20:55:50 +0800
committerGitHub <noreply@github.com>2021-02-24 13:55:50 +0100
commit9cc7e32e37e6708980abc051f2cb71526c175d88 (patch)
tree42728035073e98745ebd022c6788ba4d4ba520fd /runtime
parentdc3683c7a433bf44656063c9eee87709fbe1e7d4 (diff)
feat: add exit sanitizer to Deno.test (#9529)
This adds an exit sanitizer to ensure that code being tested or dependencies of that code can't accidentally call "Deno.exit" leading to partial test runs and false results.
Diffstat (limited to 'runtime')
-rw-r--r--runtime/js/30_os.js14
-rw-r--r--runtime/js/40_testing.js28
2 files changed, 41 insertions, 1 deletions
diff --git a/runtime/js/30_os.js b/runtime/js/30_os.js
index 236131432..23c3d8de6 100644
--- a/runtime/js/30_os.js
+++ b/runtime/js/30_os.js
@@ -24,6 +24,13 @@
return core.jsonOpSync("op_system_cpu_info");
}
+ // This is an internal only method used by the test harness to override the
+ // behavior of exit when the exit sanitizer is enabled.
+ let exitHandler = null;
+ function setExitHandler(fn) {
+ exitHandler = fn;
+ }
+
function exit(code = 0) {
// Dispatches `unload` only when it's not dispatched yet.
if (!window[Symbol.for("isUnloadDispatched")]) {
@@ -31,6 +38,12 @@
// ref: https://github.com/denoland/deno/issues/3603
window.dispatchEvent(new Event("unload"));
}
+
+ if (exitHandler) {
+ exitHandler(code);
+ return;
+ }
+
core.jsonOpSync("op_exit", { code });
throw new Error("Code not reachable");
}
@@ -63,6 +76,7 @@
window.__bootstrap.os = {
env,
execPath,
+ setExitHandler,
exit,
osRelease,
systemMemoryInfo,
diff --git a/runtime/js/40_testing.js b/runtime/js/40_testing.js
index 2258dc7b6..eec75f133 100644
--- a/runtime/js/40_testing.js
+++ b/runtime/js/40_testing.js
@@ -4,7 +4,7 @@
((window) => {
const core = window.Deno.core;
const colors = window.__bootstrap.colors;
- const { exit } = window.__bootstrap.os;
+ const { setExitHandler, exit } = window.__bootstrap.os;
const { Console, inspectArgs } = window.__bootstrap.console;
const { stdout } = window.__bootstrap.files;
const { exposeForTest } = window.__bootstrap.internals;
@@ -86,6 +86,27 @@ finishing test case.`;
};
}
+ // Wrap test function in additional assertion that makes sure
+ // that the test case does not accidentally exit prematurely.
+ function assertExit(fn) {
+ return async function exitSanitizer() {
+ setExitHandler((exitCode) => {
+ assert(
+ false,
+ `Test case attempted to exit with exit code: ${exitCode}`,
+ );
+ });
+
+ try {
+ await fn();
+ } catch (err) {
+ throw err;
+ } finally {
+ setExitHandler(null);
+ }
+ };
+ }
+
const TEST_REGISTRY = [];
// Main test function provided by Deno, as you can see it merely
@@ -100,6 +121,7 @@ finishing test case.`;
only: false,
sanitizeOps: true,
sanitizeResources: true,
+ sanitizeExit: true,
};
if (typeof t === "string") {
@@ -128,6 +150,10 @@ finishing test case.`;
testDef.fn = assertResources(testDef.fn);
}
+ if (testDef.sanitizeExit) {
+ testDef.fn = assertExit(testDef.fn);
+ }
+
TEST_REGISTRY.push(testDef);
}