diff options
Diffstat (limited to 'cli/tests/workers_test.ts')
-rw-r--r-- | cli/tests/workers_test.ts | 280 |
1 files changed, 258 insertions, 22 deletions
diff --git a/cli/tests/workers_test.ts b/cli/tests/workers_test.ts index 3bfe0181a..2dfc7e26b 100644 --- a/cli/tests/workers_test.ts +++ b/cli/tests/workers_test.ts @@ -2,12 +2,12 @@ // Requires to be run with `--allow-net` flag -// FIXME(bartlomieju): this file is an integration test only because -// workers are leaking ops at the moment - `worker.terminate()` is not -// yet implemented. Once it gets implemented this file should be -// again moved to `cli/js/` as an unit test file. - -import { assert, assertEquals } from "../../std/testing/asserts.ts"; +import { + assert, + assertEquals, + assertThrows, + fail, +} from "../../std/testing/asserts.ts"; import { deferred } from "../../std/async/deferred.ts"; Deno.test({ @@ -16,11 +16,11 @@ Deno.test({ const promise = deferred(); const jsWorker = new Worker( - new URL("subdir/test_worker.js", import.meta.url).href, + new URL("workers/test_worker.js", import.meta.url).href, { type: "module" }, ); const tsWorker = new Worker( - new URL("subdir/test_worker.ts", import.meta.url).href, + new URL("workers/test_worker.ts", import.meta.url).href, { type: "module", name: "tsWorker" }, ); @@ -73,7 +73,7 @@ Deno.test({ const promise = deferred(); const nestedWorker = new Worker( - new URL("subdir/nested_worker.js", import.meta.url).href, + new URL("workers/nested_worker.js", import.meta.url).href, { type: "module", name: "nested" }, ); @@ -93,7 +93,7 @@ Deno.test({ fn: async function (): Promise<void> { const promise = deferred(); const throwingWorker = new Worker( - new URL("subdir/throwing_worker.js", import.meta.url).href, + new URL("workers/throwing_worker.js", import.meta.url).href, { type: "module" }, ); @@ -114,7 +114,7 @@ Deno.test({ fn: async function (): Promise<void> { const promise = deferred(); const w = new Worker( - new URL("subdir/worker_globals.ts", import.meta.url).href, + new URL("workers/worker_globals.ts", import.meta.url).href, { type: "module" }, ); w.onmessage = (e): void => { @@ -133,7 +133,7 @@ Deno.test({ const promise = deferred(); const fetchingWorker = new Worker( - new URL("subdir/fetching_worker.js", import.meta.url).href, + new URL("workers/fetching_worker.js", import.meta.url).href, { type: "module" }, ); @@ -160,7 +160,7 @@ Deno.test({ const promise = deferred(); const busyWorker = new Worker( - new URL("subdir/busy_worker.js", import.meta.url).href, + new URL("workers/busy_worker.js", import.meta.url).href, { type: "module" }, ); @@ -193,7 +193,7 @@ Deno.test({ const promise = deferred(); const racyWorker = new Worker( - new URL("subdir/racy_worker.js", import.meta.url).href, + new URL("workers/racy_worker.js", import.meta.url).href, { type: "module" }, ); @@ -221,7 +221,7 @@ Deno.test({ const promise2 = deferred(); const worker = new Worker( - new URL("subdir/event_worker.js", import.meta.url).href, + new URL("workers/event_worker.js", import.meta.url).href, { type: "module" }, ); @@ -265,7 +265,7 @@ Deno.test({ const promise1 = deferred(); const worker = new Worker( - new URL("subdir/event_worker_scope.js", import.meta.url).href, + new URL("workers/event_worker_scope.js", import.meta.url).href, { type: "module" }, ); @@ -294,12 +294,18 @@ Deno.test({ const promise2 = deferred(); const regularWorker = new Worker( - new URL("subdir/non_deno_worker.js", import.meta.url).href, + new URL("workers/non_deno_worker.js", import.meta.url).href, { type: "module" }, ); const denoWorker = new Worker( - new URL("subdir/deno_worker.ts", import.meta.url).href, - { type: "module", deno: true }, + new URL("workers/deno_worker.ts", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: "inherit", + }, + }, ); regularWorker.onmessage = (e): void => { @@ -326,7 +332,7 @@ Deno.test({ fn: async function (): Promise<void> { const promise = deferred(); const w = new Worker( - new URL("subdir/worker_crypto.js", import.meta.url).href, + new URL("workers/worker_crypto.js", import.meta.url).href, { type: "module" }, ); w.onmessage = (e): void => { @@ -344,7 +350,7 @@ Deno.test({ fn: async function (): Promise<void> { const promise = deferred(); const w = new Worker( - new URL("subdir/test_worker.ts", import.meta.url).href, + new URL("workers/test_worker.ts", import.meta.url).href, { type: "module", name: "tsWorker" }, ); const arr: number[] = []; @@ -368,7 +374,7 @@ Deno.test({ fn: async function (): Promise<void> { const promise = deferred(); const w = new Worker( - new URL("./immediately_close_worker.js", import.meta.url).href, + new URL("./workers/immediately_close_worker.js", import.meta.url).href, { type: "module" }, ); setTimeout(() => { @@ -378,3 +384,233 @@ Deno.test({ w.terminate(); }, }); + +Deno.test("Worker inherits permissions", async function () { + const promise = deferred(); + const worker = new Worker( + new URL("./workers/read_check_worker.js", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: "inherit", + }, + }, + ); + + worker.onmessage = ({ data: hasPermission }) => { + assert(hasPermission); + promise.resolve(); + }; + + worker.postMessage(null); + + await promise; + worker.terminate(); +}); + +Deno.test("Worker limit children permissions", async function () { + const promise = deferred(); + const worker = new Worker( + new URL("./workers/read_check_worker.js", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: { + read: false, + }, + }, + }, + ); + + worker.onmessage = ({ data: hasPermission }) => { + assert(!hasPermission); + promise.resolve(); + }; + + worker.postMessage(null); + + await promise; + worker.terminate(); +}); + +Deno.test("Worker limit children permissions granularly", async function () { + const promise = deferred(); + const worker = new Worker( + new URL("./workers/read_check_granular_worker.js", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: { + read: [ + new URL("./workers/read_check_worker.js", import.meta.url), + ], + }, + }, + }, + ); + + //Routes are relative to the spawned worker location + const routes = [ + { permission: false, route: "read_check_granular_worker.js" }, + { permission: true, route: "read_check_worker.js" }, + ]; + + let checked = 0; + worker.onmessage = ({ data }) => { + checked++; + assertEquals(data.hasPermission, routes[data.index].permission); + routes.shift(); + if (checked === routes.length) { + promise.resolve(); + } + }; + + routes.forEach(({ route }, index) => + worker.postMessage({ + index, + route, + }) + ); + + await promise; + worker.terminate(); +}); + +Deno.test("Nested worker limit children permissions", async function () { + const promise = deferred(); + + /** This worker has read permissions but doesn't grant them to its children */ + const worker = new Worker( + new URL("./workers/parent_read_check_worker.js", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: "inherit", + }, + }, + ); + + worker.onmessage = ({ data }) => { + assert(data.parentHasPermission); + assert(!data.childHasPermission); + promise.resolve(); + }; + + worker.postMessage(null); + + await promise; + worker.terminate(); +}); + +Deno.test("Nested worker limit children permissions granularly", async function () { + const promise = deferred(); + + /** This worker has read permissions but doesn't grant them to its children */ + const worker = new Worker( + new URL("./workers/parent_read_check_granular_worker.js", import.meta.url) + .href, + { + type: "module", + deno: { + namespace: true, + permissions: { + read: [ + new URL("./workers/read_check_granular_worker.js", import.meta.url), + ], + }, + }, + }, + ); + + //Routes are relative to the spawned worker location + const routes = [ + { + childHasPermission: false, + parentHasPermission: true, + route: "read_check_granular_worker.js", + }, + { + childHasPermission: false, + parentHasPermission: false, + route: "read_check_worker.js", + }, + ]; + + let checked = 0; + worker.onmessage = ({ data }) => { + checked++; + assertEquals( + data.childHasPermission, + routes[data.index].childHasPermission, + ); + assertEquals( + data.parentHasPermission, + routes[data.index].parentHasPermission, + ); + if (checked === routes.length) { + promise.resolve(); + } + }; + + // Index needed cause requests will be handled asynchronously + routes.forEach(({ route }, index) => + worker.postMessage({ + index, + route, + }) + ); + + await promise; + worker.terminate(); +}); + +// This test relies on env permissions not being granted on main thread +Deno.test("Worker initialization throws on worker permissions greater than parent thread permissions", function () { + assertThrows( + () => { + const worker = new Worker( + new URL("./workers/deno_worker.ts", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: { + env: true, + }, + }, + }, + ); + worker.terminate(); + }, + Deno.errors.PermissionDenied, + "Can't escalate parent thread permissions", + ); +}); + +Deno.test("Worker with disabled permissions", async function () { + const promise = deferred(); + + const worker = new Worker( + new URL("./workers/no_permissions_worker.js", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: false, + }, + }, + ); + + worker.onmessage = ({ data: sandboxed }) => { + assert(sandboxed); + promise.resolve(); + }; + + worker.postMessage(null); + await promise; + worker.terminate(); +}); |