diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2020-03-03 18:22:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-03 18:22:53 +0100 |
commit | ee452ad883c1c711839655a307b39e8eea5bf410 (patch) | |
tree | 2812a5201beb2b52c92d6e3c958f2288b0253b68 /cli/tests/workers_test.ts | |
parent | 4dc004f0a24fdc81026ec03326b9943a95f1a31d (diff) |
add assertOps sanitizer in cli/js/ unit tests (#4209)
* add "assertOps" test assertion which makes sure test case
is not "leaking" ops - ie. after test finishes there are no
pending async ops
* apply "assertOps" to all tests in "cli/js/"
* fix numerous tests leaking ops
* document problem with edge case in "clearInterval"
and "clearTimeout" implementation where they
may leak async ops
* move "cli/js/worker_test.ts" to "cli/tests/worker_test.ts" and
run as integration test; workers leak ops because of missing
"terminate" implementation
Diffstat (limited to 'cli/tests/workers_test.ts')
-rw-r--r-- | cli/tests/workers_test.ts | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/cli/tests/workers_test.ts b/cli/tests/workers_test.ts new file mode 100644 index 000000000..44e7a1776 --- /dev/null +++ b/cli/tests/workers_test.ts @@ -0,0 +1,115 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +// 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"; + +export interface ResolvableMethods<T> { + resolve: (value?: T | PromiseLike<T>) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + reject: (reason?: any) => void; +} + +export type Resolvable<T> = Promise<T> & ResolvableMethods<T>; + +export function createResolvable<T>(): Resolvable<T> { + let methods: ResolvableMethods<T>; + const promise = new Promise<T>((resolve, reject): void => { + methods = { resolve, reject }; + }); + // TypeScript doesn't know that the Promise callback occurs synchronously + // therefore use of not null assertion (`!`) + return Object.assign(promise, methods!) as Resolvable<T>; +} + +Deno.test(async function workersBasic(): Promise<void> { + const promise = createResolvable(); + const jsWorker = new Worker("../tests/subdir/test_worker.js", { + type: "module", + name: "jsWorker" + }); + const tsWorker = new Worker("../tests/subdir/test_worker.ts", { + type: "module", + name: "tsWorker" + }); + + tsWorker.onmessage = (e): void => { + assertEquals(e.data, "Hello World"); + promise.resolve(); + }; + + jsWorker.onmessage = (e): void => { + assertEquals(e.data, "Hello World"); + tsWorker.postMessage("Hello World"); + }; + + jsWorker.onerror = (e: Event): void => { + e.preventDefault(); + jsWorker.postMessage("Hello World"); + }; + + jsWorker.postMessage("Hello World"); + await promise; +}); + +Deno.test(async function nestedWorker(): Promise<void> { + const promise = createResolvable(); + + const nestedWorker = new Worker("../tests/subdir/nested_worker.js", { + type: "module", + name: "nested" + }); + + nestedWorker.onmessage = (e): void => { + assert(e.data.type !== "error"); + promise.resolve(); + }; + + nestedWorker.postMessage("Hello World"); + await promise; +}); + +Deno.test(async function workerThrowsWhenExecuting(): Promise<void> { + const promise = createResolvable(); + const throwingWorker = new Worker("../tests/subdir/throwing_worker.js", { + type: "module" + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + throwingWorker.onerror = (e: any): void => { + e.preventDefault(); + assert(/Uncaught Error: Thrown error/.test(e.message)); + promise.resolve(); + }; + + await promise; +}); + +Deno.test(async function workerCanUseFetch(): Promise<void> { + const promise = createResolvable(); + + const fetchingWorker = new Worker("../tests/subdir/fetching_worker.js", { + type: "module" + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + fetchingWorker.onerror = (e: any): void => { + e.preventDefault(); + promise.reject(e.message); + }; + + // Defer promise.resolve() to allow worker to shut down + fetchingWorker.onmessage = (e): void => { + assert(e.data === "Done!"); + promise.resolve(); + }; + + await promise; +}); + +await Deno.runTests(); |