summaryrefslogtreecommitdiff
path: root/cli/tests/workers_test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tests/workers_test.ts')
-rw-r--r--cli/tests/workers_test.ts280
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();
+});