summaryrefslogtreecommitdiff
path: root/std/testing
diff options
context:
space:
mode:
authorCasper Beyer <caspervonb@pm.me>2021-02-02 19:05:46 +0800
committerGitHub <noreply@github.com>2021-02-02 12:05:46 +0100
commit6abf126c2a7a451cded8c6b5e6ddf1b69c84055d (patch)
treefd94c013a19fcb38954844085821ec1601c20e18 /std/testing
parenta2b5d44f1aa9d64f448a2a3cc2001272e2f60b98 (diff)
chore: remove std directory (#9361)
This removes the std folder from the tree. Various parts of the tests are pretty tightly dependent on std (47 direct imports and 75 indirect imports, not counting the cli tests that use them as fixtures) so I've added std as a submodule for now.
Diffstat (limited to 'std/testing')
-rw-r--r--std/testing/README.md248
-rw-r--r--std/testing/_diff.ts228
-rw-r--r--std/testing/_diff_test.ts111
-rw-r--r--std/testing/asserts.ts617
-rw-r--r--std/testing/asserts_test.ts927
-rw-r--r--std/testing/bench.ts363
-rw-r--r--std/testing/bench_example.ts32
-rw-r--r--std/testing/bench_test.ts379
8 files changed, 0 insertions, 2905 deletions
diff --git a/std/testing/README.md b/std/testing/README.md
deleted file mode 100644
index 2cff96a6d..000000000
--- a/std/testing/README.md
+++ /dev/null
@@ -1,248 +0,0 @@
-# Testing
-
-This module provides a few basic utilities to make testing easier and consistent
-in Deno.
-
-## Usage
-
-`testing/asserts.ts` module provides range of assertion helpers. If the
-assertion is false an `AssertionError` will be thrown which will result in
-pretty-printed diff of failing assertion.
-
-- `equal()` - Deep comparison function, where `actual` and `expected` are
- compared deeply, and if they vary, `equal` returns `false`.
-- `assert()` - Expects a boolean value, throws if the value is `false`.
-- `assertEquals()` - Uses the `equal` comparison and throws if the `actual` and
- `expected` are not equal.
-- `assertNotEquals()` - Uses the `equal` comparison and throws if the `actual`
- and `expected` are equal.
-- `assertStrictEquals()` - Compares `actual` and `expected` strictly, therefore
- for non-primitives the values must reference the same instance.
-- `assertStringIncludes()` - Make an assertion that `actual` includes
- `expected`.
-- `assertMatch()` - Make an assertion that `actual` match RegExp `expected`.
-- `assertNotMatch()` - Make an assertion that `actual` not match RegExp
- `expected`.
-- `assertArrayIncludes()` - Make an assertion that `actual` array includes the
- `expected` values.
-- `assertObjectMatch()` - Make an assertion that `actual` object match
- `expected` subset object
-- `assertThrows()` - Expects the passed `fn` to throw. If `fn` does not throw,
- this function does. Also compares any errors thrown to an optional expected
- `Error` class and checks that the error `.message` includes an optional
- string.
-- `assertThrowsAsync()` - Expects the passed `fn` to be async and throw (or
- return a `Promise` that rejects). If the `fn` does not throw or reject, this
- function will throw asynchronously. Also compares any errors thrown to an
- optional expected `Error` class and checks that the error `.message` includes
- an optional string.
-- `unimplemented()` - Use this to stub out methods that will throw when invoked.
-- `unreachable()` - Used to assert unreachable code.
-
-Basic usage:
-
-```ts
-import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
-
-Deno.test({
- name: "testing example",
- fn(): void {
- assertEquals("world", "world");
- assertEquals({ hello: "world" }, { hello: "world" });
- },
-});
-```
-
-Short syntax (named function instead of object):
-
-```ts
-Deno.test("example", function (): void {
- assertEquals("world", "world");
- assertEquals({ hello: "world" }, { hello: "world" });
-});
-```
-
-Using `assertStrictEquals()`:
-
-```ts
-Deno.test("isStrictlyEqual", function (): void {
- const a = {};
- const b = a;
- assertStrictEquals(a, b);
-});
-
-// This test fails
-Deno.test("isNotStrictlyEqual", function (): void {
- const a = {};
- const b = {};
- assertStrictEquals(a, b);
-});
-```
-
-Using `assertThrows()`:
-
-```ts
-Deno.test("doesThrow", function (): void {
- assertThrows((): void => {
- throw new TypeError("hello world!");
- });
- assertThrows((): void => {
- throw new TypeError("hello world!");
- }, TypeError);
- assertThrows(
- (): void => {
- throw new TypeError("hello world!");
- },
- TypeError,
- "hello",
- );
-});
-
-// This test will not pass.
-Deno.test("fails", function (): void {
- assertThrows((): void => {
- console.log("Hello world");
- });
-});
-```
-
-Using `assertThrowsAsync()`:
-
-```ts
-Deno.test("doesThrow", async function (): Promise<void> {
- await assertThrowsAsync(
- async (): Promise<void> => {
- throw new TypeError("hello world!");
- },
- );
- await assertThrowsAsync(async (): Promise<void> => {
- throw new TypeError("hello world!");
- }, TypeError);
- await assertThrowsAsync(
- async (): Promise<void> => {
- throw new TypeError("hello world!");
- },
- TypeError,
- "hello",
- );
- await assertThrowsAsync(
- async (): Promise<void> => {
- return Promise.reject(new Error());
- },
- );
-});
-
-// This test will not pass.
-Deno.test("fails", async function (): Promise<void> {
- await assertThrowsAsync(
- async (): Promise<void> => {
- console.log("Hello world");
- },
- );
-});
-```
-
-## Benching
-
-With this module you can benchmark your code and get information on how is it
-performing.
-
-### Basic usage:
-
-Benchmarks can be registered using the `bench` function, where you can define a
-code, that should be benchmarked. `b.start()` has to be called at the start of
-the part you want to benchmark and `b.stop()` at the end of it, otherwise an
-error will be thrown.
-
-After that simply calling `runBenchmarks()` will benchmark all registered
-benchmarks and log the results in the commandline.
-
-```ts
-import {
- bench,
- runBenchmarks,
-} from "https://deno.land/std@$STD_VERSION/testing/bench.ts";
-
-bench(function forIncrementX1e9(b): void {
- b.start();
- for (let i = 0; i < 1e9; i++);
- b.stop();
-});
-
-runBenchmarks();
-```
-
-Averaging execution time over multiple runs:
-
-```ts
-bench({
- name: "runs100ForIncrementX1e6",
- runs: 100,
- func(b): void {
- b.start();
- for (let i = 0; i < 1e6; i++);
- b.stop();
- },
-});
-```
-
-Running specific benchmarks using regular expressions:
-
-```ts
-runBenchmarks({ only: /desired/, skip: /exceptions/ });
-```
-
-### Processing benchmark results
-
-`runBenchmarks()` returns a `Promise<BenchmarkRunResult>`, so you can process
-the benchmarking results yourself. It contains detailed results of each
-benchmark's run as `BenchmarkResult` s.
-
-```ts
-runBenchmarks()
- .then((results: BenchmarkRunResult) => {
- console.log(results);
- })
- .catch((error: Error) => {
- // ... errors if benchmark was badly constructed.
- });
-```
-
-### Processing benchmarking progress
-
-`runBenchmarks()` accepts an optional progress handler callback function, so you
-can get information on the progress of the running benchmarking.
-
-Using `{ silent: true }` means you wont see the default progression logs in the
-commandline.
-
-```ts
-runBenchmarks({ silent: true }, (p: BenchmarkRunProgress) => {
- // initial progress data.
- if (p.state === ProgressState.BenchmarkingStart) {
- console.log(
- `Starting benchmarking. Queued: ${p.queued.length}, filtered: ${p.filtered}`,
- );
- }
- // ...
-});
-```
-
-#### Benching API
-
-##### `bench(benchmark: BenchmarkDefinition | BenchmarkFunction): void`
-
-Registers a benchmark that will be run once `runBenchmarks` is called.
-
-##### `runBenchmarks(opts?: BenchmarkRunOptions, progressCb?: (p: BenchmarkRunProgress) => void | Promise<void>): Promise<BenchmarkRunResult>`
-
-Runs all registered benchmarks serially. Filtering can be applied by setting
-`BenchmarkRunOptions.only` and/or `BenchmarkRunOptions.skip` to regular
-expressions matching benchmark names. Default progression logs can be turned off
-with the `BenchmarkRunOptions.silent` flag.
-
-##### `clearBenchmarks(opts?: BenchmarkClearOptions): void`
-
-Clears all registered benchmarks, so calling `runBenchmarks()` after it wont run
-them. Filtering can be applied by setting `BenchmarkRunOptions.only` and/or
-`BenchmarkRunOptions.skip` to regular expressions matching benchmark names.
diff --git a/std/testing/_diff.ts b/std/testing/_diff.ts
deleted file mode 100644
index 7d659acd2..000000000
--- a/std/testing/_diff.ts
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-// This module is browser compatible.
-
-interface FarthestPoint {
- y: number;
- id: number;
-}
-
-export enum DiffType {
- removed = "removed",
- common = "common",
- added = "added",
-}
-
-export interface DiffResult<T> {
- type: DiffType;
- value: T;
-}
-
-const REMOVED = 1;
-const COMMON = 2;
-const ADDED = 3;
-
-function createCommon<T>(A: T[], B: T[], reverse?: boolean): T[] {
- const common = [];
- if (A.length === 0 || B.length === 0) return [];
- for (let i = 0; i < Math.min(A.length, B.length); i += 1) {
- if (
- A[reverse ? A.length - i - 1 : i] === B[reverse ? B.length - i - 1 : i]
- ) {
- common.push(A[reverse ? A.length - i - 1 : i]);
- } else {
- return common;
- }
- }
- return common;
-}
-
-/**
- * Renders the differences between the actual and expected values
- * @param A Actual value
- * @param B Expected value
- */
-export function diff<T>(A: T[], B: T[]): Array<DiffResult<T>> {
- const prefixCommon = createCommon(A, B);
- const suffixCommon = createCommon(
- A.slice(prefixCommon.length),
- B.slice(prefixCommon.length),
- true,
- ).reverse();
- A = suffixCommon.length
- ? A.slice(prefixCommon.length, -suffixCommon.length)
- : A.slice(prefixCommon.length);
- B = suffixCommon.length
- ? B.slice(prefixCommon.length, -suffixCommon.length)
- : B.slice(prefixCommon.length);
- const swapped = B.length > A.length;
- [A, B] = swapped ? [B, A] : [A, B];
- const M = A.length;
- const N = B.length;
- if (!M && !N && !suffixCommon.length && !prefixCommon.length) return [];
- if (!N) {
- return [
- ...prefixCommon.map(
- (c): DiffResult<typeof c> => ({ type: DiffType.common, value: c }),
- ),
- ...A.map(
- (a): DiffResult<typeof a> => ({
- type: swapped ? DiffType.added : DiffType.removed,
- value: a,
- }),
- ),
- ...suffixCommon.map(
- (c): DiffResult<typeof c> => ({ type: DiffType.common, value: c }),
- ),
- ];
- }
- const offset = N;
- const delta = M - N;
- const size = M + N + 1;
- const fp = new Array(size).fill({ y: -1 });
- /**
- * INFO:
- * This buffer is used to save memory and improve performance.
- * The first half is used to save route and last half is used to save diff
- * type.
- * This is because, when I kept new uint8array area to save type,performance
- * worsened.
- */
- const routes = new Uint32Array((M * N + size + 1) * 2);
- const diffTypesPtrOffset = routes.length / 2;
- let ptr = 0;
- let p = -1;
-
- function backTrace<T>(
- A: T[],
- B: T[],
- current: FarthestPoint,
- swapped: boolean,
- ): Array<{
- type: DiffType;
- value: T;
- }> {
- const M = A.length;
- const N = B.length;
- const result = [];
- let a = M - 1;
- let b = N - 1;
- let j = routes[current.id];
- let type = routes[current.id + diffTypesPtrOffset];
- while (true) {
- if (!j && !type) break;
- const prev = j;
- if (type === REMOVED) {
- result.unshift({
- type: swapped ? DiffType.removed : DiffType.added,
- value: B[b],
- });
- b -= 1;
- } else if (type === ADDED) {
- result.unshift({
- type: swapped ? DiffType.added : DiffType.removed,
- value: A[a],
- });
- a -= 1;
- } else {
- result.unshift({ type: DiffType.common, value: A[a] });
- a -= 1;
- b -= 1;
- }
- j = routes[prev];
- type = routes[prev + diffTypesPtrOffset];
- }
- return result;
- }
-
- function createFP(
- slide: FarthestPoint,
- down: FarthestPoint,
- k: number,
- M: number,
- ): FarthestPoint {
- if (slide && slide.y === -1 && down && down.y === -1) {
- return { y: 0, id: 0 };
- }
- if (
- (down && down.y === -1) ||
- k === M ||
- (slide && slide.y) > (down && down.y) + 1
- ) {
- const prev = slide.id;
- ptr++;
- routes[ptr] = prev;
- routes[ptr + diffTypesPtrOffset] = ADDED;
- return { y: slide.y, id: ptr };
- } else {
- const prev = down.id;
- ptr++;
- routes[ptr] = prev;
- routes[ptr + diffTypesPtrOffset] = REMOVED;
- return { y: down.y + 1, id: ptr };
- }
- }
-
- function snake<T>(
- k: number,
- slide: FarthestPoint,
- down: FarthestPoint,
- _offset: number,
- A: T[],
- B: T[],
- ): FarthestPoint {
- const M = A.length;
- const N = B.length;
- if (k < -N || M < k) return { y: -1, id: -1 };
- const fp = createFP(slide, down, k, M);
- while (fp.y + k < M && fp.y < N && A[fp.y + k] === B[fp.y]) {
- const prev = fp.id;
- ptr++;
- fp.id = ptr;
- fp.y += 1;
- routes[ptr] = prev;
- routes[ptr + diffTypesPtrOffset] = COMMON;
- }
- return fp;
- }
-
- while (fp[delta + offset].y < N) {
- p = p + 1;
- for (let k = -p; k < delta; ++k) {
- fp[k + offset] = snake(
- k,
- fp[k - 1 + offset],
- fp[k + 1 + offset],
- offset,
- A,
- B,
- );
- }
- for (let k = delta + p; k > delta; --k) {
- fp[k + offset] = snake(
- k,
- fp[k - 1 + offset],
- fp[k + 1 + offset],
- offset,
- A,
- B,
- );
- }
- fp[delta + offset] = snake(
- delta,
- fp[delta - 1 + offset],
- fp[delta + 1 + offset],
- offset,
- A,
- B,
- );
- }
- return [
- ...prefixCommon.map(
- (c): DiffResult<typeof c> => ({ type: DiffType.common, value: c }),
- ),
- ...backTrace(A, B, fp[delta + offset], swapped),
- ...suffixCommon.map(
- (c): DiffResult<typeof c> => ({ type: DiffType.common, value: c }),
- ),
- ];
-}
diff --git a/std/testing/_diff_test.ts b/std/testing/_diff_test.ts
deleted file mode 100644
index ec40c191c..000000000
--- a/std/testing/_diff_test.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import { diff } from "./_diff.ts";
-import { assertEquals } from "../testing/asserts.ts";
-
-Deno.test({
- name: "empty",
- fn(): void {
- assertEquals(diff([], []), []);
- },
-});
-
-Deno.test({
- name: '"a" vs "b"',
- fn(): void {
- assertEquals(diff(["a"], ["b"]), [
- { type: "removed", value: "a" },
- { type: "added", value: "b" },
- ]);
- },
-});
-
-Deno.test({
- name: '"a" vs "a"',
- fn(): void {
- assertEquals(diff(["a"], ["a"]), [{ type: "common", value: "a" }]);
- },
-});
-
-Deno.test({
- name: '"a" vs ""',
- fn(): void {
- assertEquals(diff(["a"], []), [{ type: "removed", value: "a" }]);
- },
-});
-
-Deno.test({
- name: '"" vs "a"',
- fn(): void {
- assertEquals(diff([], ["a"]), [{ type: "added", value: "a" }]);
- },
-});
-
-Deno.test({
- name: '"a" vs "a, b"',
- fn(): void {
- assertEquals(diff(["a"], ["a", "b"]), [
- { type: "common", value: "a" },
- { type: "added", value: "b" },
- ]);
- },
-});
-
-Deno.test({
- name: '"strength" vs "string"',
- fn(): void {
- assertEquals(diff(Array.from("strength"), Array.from("string")), [
- { type: "common", value: "s" },
- { type: "common", value: "t" },
- { type: "common", value: "r" },
- { type: "removed", value: "e" },
- { type: "added", value: "i" },
- { type: "common", value: "n" },
- { type: "common", value: "g" },
- { type: "removed", value: "t" },
- { type: "removed", value: "h" },
- ]);
- },
-});
-
-Deno.test({
- name: '"strength" vs ""',
- fn(): void {
- assertEquals(diff(Array.from("strength"), Array.from("")), [
- { type: "removed", value: "s" },
- { type: "removed", value: "t" },
- { type: "removed", value: "r" },
- { type: "removed", value: "e" },
- { type: "removed", value: "n" },
- { type: "removed", value: "g" },
- { type: "removed", value: "t" },
- { type: "removed", value: "h" },
- ]);
- },
-});
-
-Deno.test({
- name: '"" vs "strength"',
- fn(): void {
- assertEquals(diff(Array.from(""), Array.from("strength")), [
- { type: "added", value: "s" },
- { type: "added", value: "t" },
- { type: "added", value: "r" },
- { type: "added", value: "e" },
- { type: "added", value: "n" },
- { type: "added", value: "g" },
- { type: "added", value: "t" },
- { type: "added", value: "h" },
- ]);
- },
-});
-
-Deno.test({
- name: '"abc", "c" vs "abc", "bcd", "c"',
- fn(): void {
- assertEquals(diff(["abc", "c"], ["abc", "bcd", "c"]), [
- { type: "common", value: "abc" },
- { type: "added", value: "bcd" },
- { type: "common", value: "c" },
- ]);
- },
-});
diff --git a/std/testing/asserts.ts b/std/testing/asserts.ts
deleted file mode 100644
index 3daf0d83f..000000000
--- a/std/testing/asserts.ts
+++ /dev/null
@@ -1,617 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-// This module is browser compatible. Do not rely on good formatting of values
-// for AssertionError messages in browsers.
-
-import { bold, gray, green, red, stripColor, white } from "../fmt/colors.ts";
-import { diff, DiffResult, DiffType } from "./_diff.ts";
-
-const CAN_NOT_DISPLAY = "[Cannot display]";
-
-interface Constructor {
- // deno-lint-ignore no-explicit-any
- new (...args: any[]): any;
-}
-
-export class AssertionError extends Error {
- constructor(message: string) {
- super(message);
- this.name = "AssertionError";
- }
-}
-
-/**
- * Converts the input into a string. Objects, Sets and Maps are sorted so as to
- * make tests less flaky
- * @param v Value to be formatted
- */
-export function _format(v: unknown): string {
- return globalThis.Deno
- ? Deno.inspect(v, {
- depth: Infinity,
- sorted: true,
- trailingComma: true,
- compact: false,
- iterableLimit: Infinity,
- })
- : `"${String(v).replace(/(?=["\\])/g, "\\")}"`;
-}
-
-/**
- * Colors the output of assertion diffs
- * @param diffType Difference type, either added or removed
- */
-function createColor(diffType: DiffType): (s: string) => string {
- switch (diffType) {
- case DiffType.added:
- return (s: string): string => green(bold(s));
- case DiffType.removed:
- return (s: string): string => red(bold(s));
- default:
- return white;
- }
-}
-
-/**
- * Prefixes `+` or `-` in diff output
- * @param diffType Difference type, either added or removed
- */
-function createSign(diffType: DiffType): string {
- switch (diffType) {
- case DiffType.added:
- return "+ ";
- case DiffType.removed:
- return "- ";
- default:
- return " ";
- }
-}
-
-function buildMessage(diffResult: ReadonlyArray<DiffResult<string>>): string[] {
- const messages: string[] = [];
- messages.push("");
- messages.push("");
- messages.push(
- ` ${gray(bold("[Diff]"))} ${red(bold("Actual"))} / ${
- green(bold("Expected"))
- }`,
- );
- messages.push("");
- messages.push("");
- diffResult.forEach((result: DiffResult<string>): void => {
- const c = createColor(result.type);
- messages.push(c(`${createSign(result.type)}${result.value}`));
- });
- messages.push("");
-
- return messages;
-}
-
-function isKeyedCollection(x: unknown): x is Set<unknown> {
- return [Symbol.iterator, "size"].every((k) => k in (x as Set<unknown>));
-}
-
-/**
- * Deep equality comparison used in assertions
- * @param c actual value
- * @param d expected value
- */
-export function equal(c: unknown, d: unknown): boolean {
- const seen = new Map();
- return (function compare(a: unknown, b: unknown): boolean {
- // Have to render RegExp & Date for string comparison
- // unless it's mistreated as object
- if (
- a &&
- b &&
- ((a instanceof RegExp && b instanceof RegExp) ||
- (a instanceof URL && b instanceof URL))
- ) {
- return String(a) === String(b);
- }
- if (a instanceof Date && b instanceof Date) {
- const aTime = a.getTime();
- const bTime = b.getTime();
- // Check for NaN equality manually since NaN is not
- // equal to itself.
- if (Number.isNaN(aTime) && Number.isNaN(bTime)) {
- return true;
- }
- return a.getTime() === b.getTime();
- }
- if (Object.is(a, b)) {
- return true;
- }
- if (a && typeof a === "object" && b && typeof b === "object") {
- if (seen.get(a) === b) {
- return true;
- }
- if (Object.keys(a || {}).length !== Object.keys(b || {}).length) {
- return false;
- }
- if (isKeyedCollection(a) && isKeyedCollection(b)) {
- if (a.size !== b.size) {
- return false;
- }
-
- let unmatchedEntries = a.size;
-
- for (const [aKey, aValue] of a.entries()) {
- for (const [bKey, bValue] of b.entries()) {
- /* Given that Map keys can be references, we need
- * to ensure that they are also deeply equal */
- if (
- (aKey === aValue && bKey === bValue && compare(aKey, bKey)) ||
- (compare(aKey, bKey) && compare(aValue, bValue))
- ) {
- unmatchedEntries--;
- }
- }
- }
-
- return unmatchedEntries === 0;
- }
- const merged = { ...a, ...b };
- for (const key in merged) {
- type Key = keyof typeof merged;
- if (!compare(a && a[key as Key], b && b[key as Key])) {
- return false;
- }
- }
- seen.set(a, b);
- return true;
- }
- return false;
- })(c, d);
-}
-
-/** Make an assertion, error will be thrown if `expr` does not have truthy value. */
-export function assert(expr: unknown, msg = ""): asserts expr {
- if (!expr) {
- throw new AssertionError(msg);
- }
-}
-
-/**
- * Make an assertion that `actual` and `expected` are equal, deeply. If not
- * deeply equal, then throw.
- *
- * Type parameter can be specified to ensure values under comparison have the same type.
- * For example:
- *```ts
- *assertEquals<number>(1, 2)
- *```
- */
-export function assertEquals(
- actual: unknown,
- expected: unknown,
- msg?: string,
-): void;
-export function assertEquals<T>(actual: T, expected: T, msg?: string): void;
-export function assertEquals(
- actual: unknown,
- expected: unknown,
- msg?: string,
-): void {
- if (equal(actual, expected)) {
- return;
- }
- let message = "";
- const actualString = _format(actual);
- const expectedString = _format(expected);
- try {
- const diffResult = diff(
- actualString.split("\n"),
- expectedString.split("\n"),
- );
- const diffMsg = buildMessage(diffResult).join("\n");
- message = `Values are not equal:\n${diffMsg}`;
- } catch (e) {
- message = `\n${red(CAN_NOT_DISPLAY)} + \n\n`;
- }
- if (msg) {
- message = msg;
- }
- throw new AssertionError(message);
-}
-
-/**
- * Make an assertion that `actual` and `expected` are not equal, deeply.
- * If not then throw.
- *
- * Type parameter can be specified to ensure values under comparison have the same type.
- * For example:
- *```ts
- *assertNotEquals<number>(1, 2)
- *```
- */
-export function assertNotEquals(
- actual: unknown,
- expected: unknown,
- msg?: string,
-): void;
-export function assertNotEquals<T>(actual: T, expected: T, msg?: string): void;
-export function assertNotEquals(
- actual: unknown,
- expected: unknown,
- msg?: string,
-): void {
- if (!equal(actual, expected)) {
- return;
- }
- let actualString: string;
- let expectedString: string;
- try {
- actualString = String(actual);
- } catch (e) {
- actualString = "[Cannot display]";
- }
- try {
- expectedString = String(expected);
- } catch (e) {
- expectedString = "[Cannot display]";
- }
- if (!msg) {
- msg = `actual: ${actualString} expected: ${expectedString}`;
- }
- throw new AssertionError(msg);
-}
-
-/**
- * Make an assertion that `actual` and `expected` are strictly equal. If
- * not then throw.
- * ```ts
- * assertStrictEquals(1, 2)
- * ```
- */
-export function assertStrictEquals(
- actual: unknown,
- expected: unknown,
- msg?: string,
-): void;
-export function assertStrictEquals<T>(
- actual: T,
- expected: T,
- msg?: string,
-): void;
-export function assertStrictEquals(
- actual: unknown,
- expected: unknown,
- msg?: string,
-): void {
- if (actual === expected) {
- return;
- }
-
- let message: string;
-
- if (msg) {
- message = msg;
- } else {
- const actualString = _format(actual);
- const expectedString = _format(expected);
-
- if (actualString === expectedString) {
- const withOffset = actualString
- .split("\n")
- .map((l) => ` ${l}`)
- .join("\n");
- message =
- `Values have the same structure but are not reference-equal:\n\n${
- red(withOffset)
- }\n`;
- } else {
- try {
- const diffResult = diff(
- actualString.split("\n"),
- expectedString.split("\n"),
- );
- const diffMsg = buildMessage(diffResult).join("\n");
- message = `Values are not strictly equal:\n${diffMsg}`;
- } catch (e) {
- message = `\n${red(CAN_NOT_DISPLAY)} + \n\n`;
- }
- }
- }
-
- throw new AssertionError(message);
-}
-
-/**
- * Make an assertion that `actual` and `expected` are not strictly equal.
- * If the values are strictly equal then throw.
- * ```ts
- * assertNotStrictEquals(1, 1)
- * ```
- */
-export function assertNotStrictEquals(
- actual: unknown,
- expected: unknown,
- msg?: string,
-): void;
-export function assertNotStrictEquals<T>(
- actual: T,
- expected: T,
- msg?: string,
-): void;
-export function assertNotStrictEquals(
- actual: unknown,
- expected: unknown,
- msg?: string,
-): void {
- if (actual !== expected) {
- return;
- }
-
- throw new AssertionError(
- msg ?? `Expected "actual" to be strictly unequal to: ${_format(actual)}\n`,
- );
-}
-
-/**
- * Make an assertion that actual is not null or undefined. If not
- * then thrown.
- */
-export function assertExists(
- actual: unknown,
- msg?: string,
-): void {
- if (actual === undefined || actual === null) {
- if (!msg) {
- msg =
- `actual: "${actual}" expected to match anything but null or undefined`;
- }
- throw new AssertionError(msg);
- }
-}
-
-/**
- * Make an assertion that actual includes expected. If not
- * then thrown.
- */
-export function assertStringIncludes(
- actual: string,
- expected: string,
- msg?: string,
-): void {
- if (!actual.includes(expected)) {
- if (!msg) {
- msg = `actual: "${actual}" expected to contain: "${expected}"`;
- }
- throw new AssertionError(msg);
- }
-}
-
-/**
- * Make an assertion that `actual` includes the `expected` values.
- * If not then an error will be thrown.
- *
- * Type parameter can be specified to ensure values under comparison have the same type.
- * For example:
- *```ts
- *assertArrayIncludes<number>([1, 2], [2])
- *```
- */
-export function assertArrayIncludes(
- actual: ArrayLike<unknown>,
- expected: ArrayLike<unknown>,
- msg?: string,
-): void;
-export function assertArrayIncludes<T>(
- actual: ArrayLike<T>,
- expected: ArrayLike<T>,
- msg?: string,
-): void;
-export function assertArrayIncludes(
- actual: ArrayLike<unknown>,
- expected: ArrayLike<unknown>,
- msg?: string,
-): void {
- const missing: unknown[] = [];
- for (let i = 0; i < expected.length; i++) {
- let found = false;
- for (let j = 0; j < actual.length; j++) {
- if (equal(expected[i], actual[j])) {
- found = true;
- break;
- }
- }
- if (!found) {
- missing.push(expected[i]);
- }
- }
- if (missing.length === 0) {
- return;
- }
- if (!msg) {
- msg = `actual: "${_format(actual)}" expected to include: "${
- _format(expected)
- }"\nmissing: ${_format(missing)}`;
- }
- throw new AssertionError(msg);
-}
-
-/**
- * Make an assertion that `actual` match RegExp `expected`. If not
- * then thrown
- */
-export function assertMatch(
- actual: string,
- expected: RegExp,
- msg?: string,
-): void {
- if (!expected.test(actual)) {
- if (!msg) {
- msg = `actual: "${actual}" expected to match: "${expected}"`;
- }
- throw new AssertionError(msg);
- }
-}
-
-/**
- * Make an assertion that `actual` not match RegExp `expected`. If match
- * then thrown
- */
-export function assertNotMatch(
- actual: string,
- expected: RegExp,
- msg?: string,
-): void {
- if (expected.test(actual)) {
- if (!msg) {
- msg = `actual: "${actual}" expected to not match: "${expected}"`;
- }
- throw new AssertionError(msg);
- }
-}
-
-/**
- * Make an assertion that `actual` object is a subset of `expected` object, deeply.
- * If not, then throw.
- */
-export function assertObjectMatch(
- actual: Record<PropertyKey, unknown>,
- expected: Record<PropertyKey, unknown>,
-): void {
- type loose = Record<PropertyKey, unknown>;
- const seen = new WeakMap();
- return assertEquals(
- (function filter(a: loose, b: loose): loose {
- // Prevent infinite loop with circular references with same filter
- if ((seen.has(a)) && (seen.get(a) === b)) {
- return a;
- }
- seen.set(a, b);
- // Filter keys and symbols which are present in both actual and expected
- const filtered = {} as loose;
- const entries = [
- ...Object.getOwnPropertyNames(a),
- ...Object.getOwnPropertySymbols(a),
- ]
- .filter((key) => key in b)
- .map((key) => [key, a[key as string]]) as Array<[string, unknown]>;
- // Build filtered object and filter recursively on nested objects references
- for (const [key, value] of entries) {
- if (typeof value === "object") {
- const subset = (b as loose)[key];
- if ((typeof subset === "object") && (subset)) {
- filtered[key] = filter(value as loose, subset as loose);
- continue;
- }
- }
- filtered[key] = value;
- }
- return filtered;
- })(actual, expected),
- expected,
- );
-}
-
-/**
- * Forcefully throws a failed assertion
- */
-export function fail(msg?: string): void {
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
- assert(false, `Failed assertion${msg ? `: ${msg}` : "."}`);
-}
-
-/**
- * Executes a function, expecting it to throw. If it does not, then it
- * throws. An error class and a string that should be included in the
- * error message can also be asserted.
- */
-export function assertThrows<T = void>(
- fn: () => T,
- ErrorClass?: Constructor,
- msgIncludes = "",
- msg?: string,
-): Error {
- let doesThrow = false;
- let error = null;
- try {
- fn();
- } catch (e) {
- if (e instanceof Error === false) {
- throw new AssertionError("A non-Error object was thrown.");
- }
- if (ErrorClass && !(e instanceof ErrorClass)) {
- msg =
- `Expected error to be instance of "${ErrorClass.name}", but was "${e.constructor.name}"${
- msg ? `: ${msg}` : "."
- }`;
- throw new AssertionError(msg);
- }
- if (
- msgIncludes &&
- !stripColor(e.message).includes(stripColor(msgIncludes))
- ) {
- msg =
- `Expected error message to include "${msgIncludes}", but got "${e.message}"${
- msg ? `: ${msg}` : "."
- }`;
- throw new AssertionError(msg);
- }
- doesThrow = true;
- error = e;
- }
- if (!doesThrow) {
- msg = `Expected function to throw${msg ? `: ${msg}` : "."}`;
- throw new AssertionError(msg);
- }
- return error;
-}
-
-/**
- * Executes a function which returns a promise, expecting it to throw or reject.
- * If it does not, then it throws. An error class and a string that should be
- * included in the error message can also be asserted.
- */
-export async function assertThrowsAsync<T = void>(
- fn: () => Promise<T>,
- ErrorClass?: Constructor,
- msgIncludes = "",
- msg?: string,
-): Promise<Error> {
- let doesThrow = false;
- let error = null;
- try {
- await fn();
- } catch (e) {
- if (e instanceof Error === false) {
- throw new AssertionError("A non-Error object was thrown or rejected.");
- }
- if (ErrorClass && !(e instanceof ErrorClass)) {
- msg =
- `Expected error to be instance of "${ErrorClass.name}", but got "${e.name}"${
- msg ? `: ${msg}` : "."
- }`;
- throw new AssertionError(msg);
- }
- if (
- msgIncludes &&
- !stripColor(e.message).includes(stripColor(msgIncludes))
- ) {
- msg =
- `Expected error message to include "${msgIncludes}", but got "${e.message}"${
- msg ? `: ${msg}` : "."
- }`;
- throw new AssertionError(msg);
- }
- doesThrow = true;
- error = e;
- }
- if (!doesThrow) {
- msg = `Expected function to throw${msg ? `: ${msg}` : "."}`;
- throw new AssertionError(msg);
- }
- return error;
-}
-
-/** Use this to stub out methods that will throw when invoked. */
-export function unimplemented(msg?: string): never {
- throw new AssertionError(msg || "unimplemented");
-}
-
-/** Use this to assert unreachable code. */
-export function unreachable(): never {
- throw new AssertionError("unreachable");
-}
diff --git a/std/testing/asserts_test.ts b/std/testing/asserts_test.ts
deleted file mode 100644
index 14ffd2962..000000000
--- a/std/testing/asserts_test.ts
+++ /dev/null
@@ -1,927 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import {
- _format,
- assert,
- assertArrayIncludes,
- assertEquals,
- assertExists,
- AssertionError,
- assertMatch,
- assertNotEquals,
- assertNotMatch,
- assertNotStrictEquals,
- assertObjectMatch,
- assertStrictEquals,
- assertStringIncludes,
- assertThrows,
- assertThrowsAsync,
- equal,
- fail,
- unimplemented,
- unreachable,
-} from "./asserts.ts";
-import { bold, gray, green, red, stripColor, yellow } from "../fmt/colors.ts";
-
-Deno.test("testingEqual", function (): void {
- assert(equal("world", "world"));
- assert(!equal("hello", "world"));
- assert(equal(5, 5));
- assert(!equal(5, 6));
- assert(equal(NaN, NaN));
- assert(equal({ hello: "world" }, { hello: "world" }));
- assert(!equal({ world: "hello" }, { hello: "world" }));
- assert(
- equal(
- { hello: "world", hi: { there: "everyone" } },
- { hello: "world", hi: { there: "everyone" } },
- ),
- );
- assert(
- !equal(
- { hello: "world", hi: { there: "everyone" } },
- { hello: "world", hi: { there: "everyone else" } },
- ),
- );
- assert(equal(/deno/, /deno/));
- assert(!equal(/deno/, /node/));
- assert(equal(new Date(2019, 0, 3), new Date(2019, 0, 3)));
- assert(!equal(new Date(2019, 0, 3), new Date(2019, 1, 3)));
- assert(
- !equal(
- new Date(2019, 0, 3, 4, 20, 1, 10),
- new Date(2019, 0, 3, 4, 20, 1, 20),
- ),
- );
- assert(equal(new Date("Invalid"), new Date("Invalid")));
- assert(!equal(new Date("Invalid"), new Date(2019, 0, 3)));
- assert(!equal(new Date("Invalid"), new Date(2019, 0, 3, 4, 20, 1, 10)));
- assert(equal(new Set([1]), new Set([1])));
- assert(!equal(new Set([1]), new Set([2])));
- assert(equal(new Set([1, 2, 3]), new Set([3, 2, 1])));
- assert(equal(new Set([1, new Set([2, 3])]), new Set([new Set([3, 2]), 1])));
- assert(!equal(new Set([1, 2]), new Set([3, 2, 1])));
- assert(!equal(new Set([1, 2, 3]), new Set([4, 5, 6])));
- assert(equal(new Set("denosaurus"), new Set("denosaurussss")));
- assert(equal(new Map(), new Map()));
- assert(
- equal(
- new Map([
- ["foo", "bar"],
- ["baz", "baz"],
- ]),
- new Map([
- ["foo", "bar"],
- ["baz", "baz"],
- ]),
- ),
- );
- assert(
- equal(
- new Map([["foo", new Map([["bar", "baz"]])]]),
- new Map([["foo", new Map([["bar", "baz"]])]]),
- ),
- );
- assert(
- equal(
- new Map([["foo", { bar: "baz" }]]),
- new Map([["foo", { bar: "baz" }]]),
- ),
- );
- assert(
- equal(
- new Map([
- ["foo", "bar"],
- ["baz", "qux"],
- ]),
- new Map([
- ["baz", "qux"],
- ["foo", "bar"],
- ]),
- ),
- );
- assert(equal(new Map([["foo", ["bar"]]]), new Map([["foo", ["bar"]]])));
- assert(!equal(new Map([["foo", "bar"]]), new Map([["bar", "baz"]])));
- assert(
- !equal(
- new Map([["foo", "bar"]]),
- new Map([
- ["foo", "bar"],
- ["bar", "baz"],
- ]),
- ),
- );
- assert(
- !equal(
- new Map([["foo", new Map([["bar", "baz"]])]]),
- new Map([["foo", new Map([["bar", "qux"]])]]),
- ),
- );
- assert(equal(new Map([[{ x: 1 }, true]]), new Map([[{ x: 1 }, true]])));
- assert(!equal(new Map([[{ x: 1 }, true]]), new Map([[{ x: 1 }, false]])));
- assert(!equal(new Map([[{ x: 1 }, true]]), new Map([[{ x: 2 }, true]])));
- assert(equal([1, 2, 3], [1, 2, 3]));
- assert(equal([1, [2, 3]], [1, [2, 3]]));
- assert(!equal([1, 2, 3, 4], [1, 2, 3]));
- assert(!equal([1, 2, 3, 4], [1, 2, 3]));
- assert(!equal([1, 2, 3, 4], [1, 4, 2, 3]));
- assert(equal(new Uint8Array([1, 2, 3, 4]), new Uint8Array([1, 2, 3, 4])));
- assert(!equal(new Uint8Array([1, 2, 3, 4]), new Uint8Array([2, 1, 4, 3])));
- assert(
- equal(new URL("https://example.test"), new URL("https://example.test")),
- );
- assert(
- !equal(
- new URL("https://example.test"),
- new URL("https://example.test/with-path"),
- ),
- );
-});
-
-Deno.test("testingNotEquals", function (): void {
- const a = { foo: "bar" };
- const b = { bar: "foo" };
- assertNotEquals(a, b);
- assertNotEquals("Denosaurus", "Tyrannosaurus");
- assertNotEquals(
- new Date(2019, 0, 3, 4, 20, 1, 10),
- new Date(2019, 0, 3, 4, 20, 1, 20),
- );
- assertNotEquals(
- new Date("invalid"),
- new Date(2019, 0, 3, 4, 20, 1, 20),
- );
- let didThrow;
- try {
- assertNotEquals("Raptor", "Raptor");
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
-});
-
-Deno.test("testingAssertExists", function (): void {
- assertExists("Denosaurus");
- assertExists(false);
- assertExists(0);
- assertExists("");
- assertExists(-0);
- assertExists(0);
- assertExists(NaN);
- let didThrow;
- try {
- assertExists(undefined);
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
- didThrow = false;
- try {
- assertExists(null);
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
-});
-
-Deno.test("testingAssertStringContains", function (): void {
- assertStringIncludes("Denosaurus", "saur");
- assertStringIncludes("Denosaurus", "Deno");
- assertStringIncludes("Denosaurus", "rus");
- let didThrow;
- try {
- assertStringIncludes("Denosaurus", "Raptor");
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
-});
-
-Deno.test("testingArrayContains", function (): void {
- const fixture = ["deno", "iz", "luv"];
- const fixtureObject = [{ deno: "luv" }, { deno: "Js" }];
- assertArrayIncludes(fixture, ["deno"]);
- assertArrayIncludes(fixtureObject, [{ deno: "luv" }]);
- assertArrayIncludes(
- Uint8Array.from([1, 2, 3, 4]),
- Uint8Array.from([1, 2, 3]),
- );
- assertThrows(
- (): void => assertArrayIncludes(fixtureObject, [{ deno: "node" }]),
- AssertionError,
- `actual: "[
- {
- deno: "luv",
- },
- {
- deno: "Js",
- },
-]" expected to include: "[
- {
- deno: "node",
- },
-]"
-missing: [
- {
- deno: "node",
- },
-]`,
- );
-});
-
-Deno.test("testingAssertStringContainsThrow", function (): void {
- let didThrow = false;
- try {
- assertStringIncludes("Denosaurus from Jurassic", "Raptor");
- } catch (e) {
- assert(
- e.message ===
- `actual: "Denosaurus from Jurassic" expected to contain: "Raptor"`,
- );
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assert(didThrow);
-});
-
-Deno.test("testingAssertStringMatching", function (): void {
- assertMatch("foobar@deno.com", RegExp(/[a-zA-Z]+@[a-zA-Z]+.com/));
-});
-
-Deno.test("testingAssertStringMatchingThrows", function (): void {
- let didThrow = false;
- try {
- assertMatch("Denosaurus from Jurassic", RegExp(/Raptor/));
- } catch (e) {
- assert(
- e.message ===
- `actual: "Denosaurus from Jurassic" expected to match: "/Raptor/"`,
- );
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assert(didThrow);
-});
-
-Deno.test("testingAssertStringNotMatching", function (): void {
- assertNotMatch("foobar.deno.com", RegExp(/[a-zA-Z]+@[a-zA-Z]+.com/));
-});
-
-Deno.test("testingAssertStringNotMatchingThrows", function (): void {
- let didThrow = false;
- try {
- assertNotMatch("Denosaurus from Jurassic", RegExp(/from/));
- } catch (e) {
- assert(
- e.message ===
- `actual: "Denosaurus from Jurassic" expected to not match: "/from/"`,
- );
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assert(didThrow);
-});
-
-Deno.test("testingAssertObjectMatching", function (): void {
- const sym = Symbol("foo");
- const a = { foo: true, bar: false };
- const b = { ...a, baz: a };
- const c = { ...b, qux: b };
- const d = { corge: c, grault: c };
- const e = { foo: true } as { [key: string]: unknown };
- e.bar = e;
- const f = { [sym]: true, bar: false };
- // Simple subset
- assertObjectMatch(a, {
- foo: true,
- });
- // Subset with another subset
- assertObjectMatch(b, {
- foo: true,
- baz: { bar: false },
- });
- // Subset with multiple subsets
- assertObjectMatch(c, {
- foo: true,
- baz: { bar: false },
- qux: {
- baz: { foo: true },
- },
- });
- // Subset with same object reference as subset
- assertObjectMatch(d, {
- corge: {
- foo: true,
- qux: { bar: false },
- },
- grault: {
- bar: false,
- qux: { foo: true },
- },
- });
- // Subset with circular reference
- assertObjectMatch(e, {
- foo: true,
- bar: {
- bar: {
- bar: {
- foo: true,
- },
- },
- },
- });
- // Subset with same symbol
- assertObjectMatch(f, {
- [sym]: true,
- });
- // Missing key
- {
- let didThrow;
- try {
- assertObjectMatch({
- foo: true,
- }, {
- foo: true,
- bar: false,
- });
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
- }
- // Simple subset
- {
- let didThrow;
- try {
- assertObjectMatch(a, {
- foo: false,
- });
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
- }
- // Subset with another subset
- {
- let didThrow;
- try {
- assertObjectMatch(b, {
- foo: true,
- baz: { bar: true },
- });
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
- }
- // Subset with multiple subsets
- {
- let didThrow;
- try {
- assertObjectMatch(c, {
- foo: true,
- baz: { bar: false },
- qux: {
- baz: { foo: false },
- },
- });
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
- }
- // Subset with same object reference as subset
- {
- let didThrow;
- try {
- assertObjectMatch(d, {
- corge: {
- foo: true,
- qux: { bar: true },
- },
- grault: {
- bar: false,
- qux: { foo: false },
- },
- });
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
- }
- // Subset with circular reference
- {
- let didThrow;
- try {
- assertObjectMatch(e, {
- foo: true,
- bar: {
- bar: {
- bar: {
- foo: false,
- },
- },
- },
- });
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
- }
- // Subset with symbol key but with string key subset
- {
- let didThrow;
- try {
- assertObjectMatch(f, {
- foo: true,
- });
- didThrow = false;
- } catch (e) {
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assertEquals(didThrow, true);
- }
-});
-
-Deno.test("testingAssertsUnimplemented", function (): void {
- let didThrow = false;
- try {
- unimplemented();
- } catch (e) {
- assert(e.message === "unimplemented");
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assert(didThrow);
-});
-
-Deno.test("testingAssertsUnreachable", function (): void {
- let didThrow = false;
- try {
- unreachable();
- } catch (e) {
- assert(e.message === "unreachable");
- assert(e instanceof AssertionError);
- didThrow = true;
- }
- assert(didThrow);
-});
-
-Deno.test("testingAssertFail", function (): void {
- assertThrows(fail, AssertionError, "Failed assertion.");
- assertThrows(
- (): void => {
- fail("foo");
- },
- AssertionError,
- "Failed assertion: foo",
- );
-});
-
-Deno.test("testingAssertFailWithWrongErrorClass", function (): void {
- assertThrows(
- (): void => {
- //This next assertThrows will throw an AssertionError due to the wrong
- //expected error class
- assertThrows(
- (): void => {
- fail("foo");
- },
- TypeError,
- "Failed assertion: foo",
- );
- },
- AssertionError,
- `Expected error to be instance of "TypeError", but was "AssertionError"`,
- );
-});
-
-Deno.test("testingAssertThrowsWithReturnType", () => {
- assertThrows(() => {
- throw new Error();
- });
-});
-
-Deno.test("testingAssertThrowsAsyncWithReturnType", () => {
- assertThrowsAsync(() => {
- throw new Error();
- });
-});
-
-const createHeader = (): string[] => [
- "",
- "",
- ` ${gray(bold("[Diff]"))} ${red(bold("Actual"))} / ${
- green(
- bold("Expected"),
- )
- }`,
- "",
- "",
-];
-
-const added: (s: string) => string = (s: string): string =>
- green(bold(stripColor(s)));
-const removed: (s: string) => string = (s: string): string =>
- red(bold(stripColor(s)));
-
-Deno.test({
- name: "pass case",
- fn(): void {
- assertEquals({ a: 10 }, { a: 10 });
- assertEquals(true, true);
- assertEquals(10, 10);
- assertEquals("abc", "abc");
- assertEquals({ a: 10, b: { c: "1" } }, { a: 10, b: { c: "1" } });
- assertEquals(new Date("invalid"), new Date("invalid"));
- },
-});
-
-Deno.test({
- name: "failed with number",
- fn(): void {
- assertThrows(
- (): void => assertEquals(1, 2),
- AssertionError,
- [
- "Values are not equal:",
- ...createHeader(),
- removed(`- ${yellow("1")}`),
- added(`+ ${yellow("2")}`),
- "",
- ].join("\n"),
- );
- },
-});
-
-Deno.test({
- name: "failed with number vs string",
- fn(): void {
- assertThrows(
- (): void => assertEquals(1, "1"),
- AssertionError,
- [
- "Values are not equal:",
- ...createHeader(),
- removed(`- ${yellow("1")}`),
- added(`+ "1"`),
- ].join("\n"),
- );
- },
-});
-
-Deno.test({
- name: "failed with array",
- fn(): void {
- assertThrows(
- (): void => assertEquals([1, "2", 3], ["1", "2", 3]),
- AssertionError,
- `
- [
-- 1,
-+ "1",
- "2",
- 3,
- ]`,
- );
- },
-});
-
-Deno.test({
- name: "failed with object",
- fn(): void {
- assertThrows(
- (): void => assertEquals({ a: 1, b: "2", c: 3 }, { a: 1, b: 2, c: [3] }),
- AssertionError,
- `
- {
- a: 1,
-+ b: 2,
-+ c: [
-+ 3,
-+ ],
-- b: "2",
-- c: 3,
- }`,
- );
- },
-});
-
-Deno.test({
- name: "failed with date",
- fn(): void {
- assertThrows(
- (): void =>
- assertEquals(
- new Date(2019, 0, 3, 4, 20, 1, 10),
- new Date(2019, 0, 3, 4, 20, 1, 20),
- ),
- AssertionError,
- [
- "Values are not equal:",
- ...createHeader(),
- removed(`- ${new Date(2019, 0, 3, 4, 20, 1, 10).toISOString()}`),
- added(`+ ${new Date(2019, 0, 3, 4, 20, 1, 20).toISOString()}`),
- "",
- ].join("\n"),
- );
- assertThrows(
- (): void =>
- assertEquals(
- new Date("invalid"),
- new Date(2019, 0, 3, 4, 20, 1, 20),
- ),
- AssertionError,
- [
- "Values are not equal:",
- ...createHeader(),
- removed(`- ${new Date("invalid")}`),
- added(`+ ${new Date(2019, 0, 3, 4, 20, 1, 20).toISOString()}`),
- "",
- ].join("\n"),
- );
- },
-});
-
-Deno.test({
- name: "strict pass case",
- fn(): void {
- assertStrictEquals(true, true);
- assertStrictEquals(10, 10);
- assertStrictEquals("abc", "abc");
-
- const xs = [1, false, "foo"];
- const ys = xs;
- assertStrictEquals(xs, ys);
-
- const x = { a: 1 };
- const y = x;
- assertStrictEquals(x, y);
- },
-});
-
-Deno.test({
- name: "strict failed with structure diff",
- fn(): void {
- assertThrows(
- (): void => assertStrictEquals({ a: 1, b: 2 }, { a: 1, c: [3] }),
- AssertionError,
- `
- {
- a: 1,
-+ c: [
-+ 3,
-+ ],
-- b: 2,
- }`,
- );
- },
-});
-
-Deno.test({
- name: "strict failed with reference diff",
- fn(): void {
- assertThrows(
- (): void => assertStrictEquals({ a: 1, b: 2 }, { a: 1, b: 2 }),
- AssertionError,
- `Values have the same structure but are not reference-equal:
-
- {
- a: 1,
- b: 2,
- }`,
- );
- },
-});
-
-Deno.test({
- name: "strictly unequal pass case",
- fn(): void {
- assertNotStrictEquals(true, false);
- assertNotStrictEquals(10, 11);
- assertNotStrictEquals("abc", "xyz");
- assertNotStrictEquals(1, "1");
-
- const xs = [1, false, "foo"];
- const ys = [1, true, "bar"];
- assertNotStrictEquals(xs, ys);
-
- const x = { a: 1 };
- const y = { a: 2 };
- assertNotStrictEquals(x, y);
- },
-});
-
-Deno.test({
- name: "strictly unequal fail case",
- fn(): void {
- assertThrows(() => assertNotStrictEquals(1, 1), AssertionError);
- },
-});
-
-Deno.test({
- name: "assert* functions with specified type parameter",
- fn(): void {
- assertEquals<string>("hello", "hello");
- assertNotEquals<number>(1, 2);
- assertArrayIncludes<boolean>([true, false], [true]);
- const value = { x: 1 };
- assertStrictEquals<typeof value>(value, value);
- // deno-lint-ignore ban-types
- assertNotStrictEquals<object>(value, { x: 1 });
- },
-});
-
-Deno.test("Assert Throws Non-Error Fail", () => {
- assertThrows(
- () => {
- assertThrows(
- () => {
- throw "Panic!";
- },
- String,
- "Panic!",
- );
- },
- AssertionError,
- "A non-Error object was thrown.",
- );
-
- assertThrows(
- () => {
- assertThrows(() => {
- throw null;
- });
- },
- AssertionError,
- "A non-Error object was thrown.",
- );
-
- assertThrows(
- () => {
- assertThrows(() => {
- throw undefined;
- });
- },
- AssertionError,
- "A non-Error object was thrown.",
- );
-});
-
-Deno.test("Assert Throws Async Non-Error Fail", () => {
- assertThrowsAsync(
- () => {
- return assertThrowsAsync(
- () => {
- return Promise.reject("Panic!");
- },
- String,
- "Panic!",
- );
- },
- AssertionError,
- "A non-Error object was thrown or rejected.",
- );
-
- assertThrowsAsync(
- () => {
- return assertThrowsAsync(() => {
- return Promise.reject(null);
- });
- },
- AssertionError,
- "A non-Error object was thrown or rejected.",
- );
-
- assertThrowsAsync(
- () => {
- return assertThrowsAsync(() => {
- return Promise.reject(undefined);
- });
- },
- AssertionError,
- "A non-Error object was thrown or rejected.",
- );
-
- assertThrowsAsync(
- () => {
- return assertThrowsAsync(() => {
- throw undefined;
- });
- },
- AssertionError,
- "A non-Error object was thrown or rejected.",
- );
-});
-
-Deno.test("assertEquals diff for differently ordered objects", () => {
- assertThrows(
- () => {
- assertEquals(
- {
- aaaaaaaaaaaaaaaaaaaaaaaa: 0,
- bbbbbbbbbbbbbbbbbbbbbbbb: 0,
- ccccccccccccccccccccccc: 0,
- },
- {
- ccccccccccccccccccccccc: 1,
- aaaaaaaaaaaaaaaaaaaaaaaa: 0,
- bbbbbbbbbbbbbbbbbbbbbbbb: 0,
- },
- );
- },
- AssertionError,
- `
- {
- aaaaaaaaaaaaaaaaaaaaaaaa: 0,
- bbbbbbbbbbbbbbbbbbbbbbbb: 0,
-- ccccccccccccccccccccccc: 0,
-+ ccccccccccccccccccccccc: 1,
- }`,
- );
-});
-
-// Check that the diff formatter overrides some default behaviours of
-// `Deno.inspect()` which are problematic for diffing.
-Deno.test("assert diff formatting", () => {
- // Wraps objects into multiple lines even when they are small. Prints trailing
- // commas.
- assertEquals(
- stripColor(_format({ a: 1, b: 2 })),
- `{
- a: 1,
- b: 2,
-}`,
- );
-
- // Same for nested small objects.
- assertEquals(
- stripColor(_format([{ x: { a: 1, b: 2 }, y: ["a", "b"] }])),
- `[
- {
- x: {
- a: 1,
- b: 2,
- },
- y: [
- "a",
- "b",
- ],
- },
-]`,
- );
-
- // Grouping is disabled.
- assertEquals(
- stripColor(_format(["i", "i", "i", "i", "i", "i", "i"])),
- `[
- "i",
- "i",
- "i",
- "i",
- "i",
- "i",
- "i",
-]`,
- );
-});
-
-Deno.test("Assert Throws Parent Error", () => {
- assertThrows(
- () => {
- throw new AssertionError("Fail!");
- },
- Error,
- "Fail!",
- );
-});
-
-Deno.test("Assert Throws Async Parent Error", () => {
- assertThrowsAsync(
- () => {
- throw new AssertionError("Fail!");
- },
- Error,
- "Fail!",
- );
-});
diff --git a/std/testing/bench.ts b/std/testing/bench.ts
deleted file mode 100644
index 159a70cf7..000000000
--- a/std/testing/bench.ts
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import { assert } from "../_util/assert.ts";
-import { deepAssign } from "../_util/deep_assign.ts";
-
-interface BenchmarkClock {
- start: number;
- stop: number;
- for?: string;
-}
-
-/** Provides methods for starting and stopping a benchmark clock. */
-export interface BenchmarkTimer {
- start: () => void;
- stop: () => void;
-}
-
-/** Defines a benchmark through a named function. */
-export interface BenchmarkFunction {
- (b: BenchmarkTimer): void | Promise<void>;
- name: string;
-}
-
-/** Defines a benchmark definition with configurable runs. */
-export interface BenchmarkDefinition {
- func: BenchmarkFunction;
- name: string;
- /** Defines how many times the provided `func` should be benchmarked in succession */
- runs?: number;
-}
-
-/** Defines runBenchmark's run constraints by matching benchmark names. */
-export interface BenchmarkRunOptions {
- /** Only benchmarks which name match this regexp will be run*/
- only?: RegExp;
- /** Benchmarks which name match this regexp will be skipped */
- skip?: RegExp;
- /** Setting it to true prevents default benchmarking progress logs to the commandline*/
- silent?: boolean;
-}
-
-/** Defines clearBenchmark's constraints by matching benchmark names. */
-export interface BenchmarkClearOptions {
- /** Only benchmarks which name match this regexp will be removed */
- only?: RegExp;
- /** Benchmarks which name match this regexp will be kept */
- skip?: RegExp;
-}
-
-/** Defines the result of a single benchmark */
-export interface BenchmarkResult {
- /** The name of the benchmark */
- name: string;
- /** The total time it took to run a given bechmark */
- totalMs: number;
- /** Times the benchmark was run in succession. */
- runsCount: number;
- /** The average time of running the benchmark in milliseconds. */
- measuredRunsAvgMs: number;
- /** The individual measurements in milliseconds it took to run the benchmark.*/
- measuredRunsMs: number[];
-}
-
-/** Defines the result of a `runBenchmarks` call */
-export interface BenchmarkRunResult {
- /** How many benchmark were ignored by the provided `only` and `skip` */
- filtered: number;
- /** The individual results for each benchmark that was run */
- results: BenchmarkResult[];
-}
-
-/** Defines the current progress during the run of `runBenchmarks` */
-export interface BenchmarkRunProgress extends BenchmarkRunResult {
- /** List of the queued benchmarks to run with their name and their run count */
- queued?: Array<{ name: string; runsCount: number }>;
- /** The currently running benchmark with its name, run count and the already finished measurements in milliseconds */
- running?: { name: string; runsCount: number; measuredRunsMs: number[] };
- /** Indicates in which state benchmarking currently is */
- state?: ProgressState;
-}
-
-/** Defines the states `BenchmarkRunProgress` can be in */
-export enum ProgressState {
- BenchmarkingStart = "benchmarking_start",
- BenchStart = "bench_start",
- BenchPartialResult = "bench_partial_result",
- BenchResult = "bench_result",
- BenchmarkingEnd = "benchmarking_end",
-}
-
-export class BenchmarkRunError extends Error {
- benchmarkName?: string;
- constructor(msg: string, benchmarkName?: string) {
- super(msg);
- this.name = "BenchmarkRunError";
- this.benchmarkName = benchmarkName;
- }
-}
-
-function red(text: string): string {
- return Deno.noColor ? text : `\x1b[31m${text}\x1b[0m`;
-}
-
-function blue(text: string): string {
- return Deno.noColor ? text : `\x1b[34m${text}\x1b[0m`;
-}
-
-function verifyOr1Run(runs?: number): number {
- return runs && runs >= 1 && runs !== Infinity ? Math.floor(runs) : 1;
-}
-
-function assertTiming(clock: BenchmarkClock): void {
- // NaN indicates that a benchmark has not been timed properly
- if (!clock.stop) {
- throw new BenchmarkRunError(
- `Running benchmarks FAILED during benchmark named [${clock.for}]. The benchmark timer's stop method must be called`,
- clock.for,
- );
- } else if (!clock.start) {
- throw new BenchmarkRunError(
- `Running benchmarks FAILED during benchmark named [${clock.for}]. The benchmark timer's start method must be called`,
- clock.for,
- );
- } else if (clock.start > clock.stop) {
- throw new BenchmarkRunError(
- `Running benchmarks FAILED during benchmark named [${clock.for}]. The benchmark timer's start method must be called before its stop method`,
- clock.for,
- );
- }
-}
-
-function createBenchmarkTimer(clock: BenchmarkClock): BenchmarkTimer {
- return {
- start(): void {
- clock.start = performance.now();
- },
- stop(): void {
- if (isNaN(clock.start)) {
- throw new BenchmarkRunError(
- `Running benchmarks FAILED during benchmark named [${clock.for}]. The benchmark timer's start method must be called before its stop method`,
- clock.for,
- );
- }
- clock.stop = performance.now();
- },
- };
-}
-
-const candidates: BenchmarkDefinition[] = [];
-
-/** Registers a benchmark as a candidate for the runBenchmarks executor. */
-export function bench(
- benchmark: BenchmarkDefinition | BenchmarkFunction,
-): void {
- if (!benchmark.name) {
- throw new Error("The benchmark function must not be anonymous");
- }
- if (typeof benchmark === "function") {
- candidates.push({ name: benchmark.name, runs: 1, func: benchmark });
- } else {
- candidates.push({
- name: benchmark.name,
- runs: verifyOr1Run(benchmark.runs),
- func: benchmark.func,
- });
- }
-}
-
-/** Clears benchmark candidates which name matches `only` and doesn't match `skip`.
- * Removes all candidates if options were not provided */
-export function clearBenchmarks({
- only = /[^\s]/,
- skip = /$^/,
-}: BenchmarkClearOptions = {}): void {
- const keep = candidates.filter(
- ({ name }): boolean => !only.test(name) || skip.test(name),
- );
- candidates.splice(0, candidates.length);
- candidates.push(...keep);
-}
-
-/**
- * Runs all registered and non-skipped benchmarks serially.
- *
- * @param [progressCb] provides the possibility to get updates of the current progress during the run of the benchmarking
- * @returns results of the benchmarking
- */
-export async function runBenchmarks(
- { only = /[^\s]/, skip = /^\s*$/, silent }: BenchmarkRunOptions = {},
- progressCb?: (progress: BenchmarkRunProgress) => void | Promise<void>,
-): Promise<BenchmarkRunResult> {
- // Filtering candidates by the "only" and "skip" constraint
- const benchmarks: BenchmarkDefinition[] = candidates.filter(
- ({ name }): boolean => only.test(name) && !skip.test(name),
- );
- // Init main counters and error flag
- const filtered = candidates.length - benchmarks.length;
- let failError: Error | undefined = undefined;
- // Setting up a shared benchmark clock and timer
- const clock: BenchmarkClock = { start: NaN, stop: NaN };
- const b = createBenchmarkTimer(clock);
-
- // Init progress data
- const progress: BenchmarkRunProgress = {
- // bench.run is already ensured with verifyOr1Run on register
- queued: benchmarks.map((bench) => ({
- name: bench.name,
- runsCount: bench.runs!,
- })),
- results: [],
- filtered,
- state: ProgressState.BenchmarkingStart,
- };
-
- // Publish initial progress data
- await publishProgress(progress, ProgressState.BenchmarkingStart, progressCb);
-
- if (!silent) {
- console.log(
- "running",
- benchmarks.length,
- `benchmark${benchmarks.length === 1 ? " ..." : "s ..."}`,
- );
- }
-
- // Iterating given benchmark definitions (await-in-loop)
- for (const { name, runs = 0, func } of benchmarks) {
- if (!silent) {
- // See https://github.com/denoland/deno/pull/1452 about groupCollapsed
- console.groupCollapsed(`benchmark ${name} ... `);
- }
-
- // Provide the benchmark name for clock assertions
- clock.for = name;
-
- // Remove benchmark from queued
- assert(progress.queued);
- const queueIndex = progress.queued.findIndex(
- (queued) => queued.name === name && queued.runsCount === runs,
- );
- if (queueIndex != -1) {
- progress.queued.splice(queueIndex, 1);
- }
- // Init the progress of the running benchmark
- progress.running = { name, runsCount: runs, measuredRunsMs: [] };
- // Publish starting of a benchmark
- await publishProgress(progress, ProgressState.BenchStart, progressCb);
-
- // Trying benchmark.func
- let result = "";
- try {
- // Averaging runs
- let pendingRuns = runs;
- let totalMs = 0;
-
- // Would be better 2 not run these serially
- while (true) {
- // b is a benchmark timer interfacing an unset (NaN) benchmark clock
- await func(b);
- // Making sure the benchmark was started/stopped properly
- assertTiming(clock);
-
- // Calculate length of run
- const measuredMs = clock.stop - clock.start;
-
- // Summing up
- totalMs += measuredMs;
- // Adding partial result
- progress.running.measuredRunsMs.push(measuredMs);
- // Publish partial benchmark results
- await publishProgress(
- progress,
- ProgressState.BenchPartialResult,
- progressCb,
- );
-
- // Resetting the benchmark clock
- clock.start = clock.stop = NaN;
- // Once all ran
- if (!--pendingRuns) {
- result = runs == 1
- ? `${totalMs}ms`
- : `${runs} runs avg: ${totalMs / runs}ms`;
- // Adding results
- progress.results.push({
- name,
- totalMs,
- runsCount: runs,
- measuredRunsAvgMs: totalMs / runs,
- measuredRunsMs: progress.running.measuredRunsMs,
- });
- // Clear currently running
- delete progress.running;
- // Publish results of the benchmark
- await publishProgress(
- progress,
- ProgressState.BenchResult,
- progressCb,
- );
- break;
- }
- }
- } catch (err) {
- failError = err;
-
- if (!silent) {
- console.groupEnd();
- console.error(red(err.stack));
- }
-
- break;
- }
-
- if (!silent) {
- // Reporting
- console.log(blue(result));
- console.groupEnd();
- }
-
- // Resetting the benchmark clock
- clock.start = clock.stop = NaN;
- delete clock.for;
- }
-
- // Indicate finished running
- delete progress.queued;
- // Publish final result in Cb too
- await publishProgress(progress, ProgressState.BenchmarkingEnd, progressCb);
-
- if (!silent) {
- // Closing results
- console.log(
- `benchmark result: ${failError ? red("FAIL") : blue("DONE")}. ` +
- `${progress.results.length} measured; ${filtered} filtered`,
- );
- }
-
- // Throw error if there was a failing benchmark
- if (failError) {
- throw failError;
- }
-
- const benchmarkRunResult = {
- filtered,
- results: progress.results,
- };
-
- return benchmarkRunResult;
-}
-
-async function publishProgress(
- progress: BenchmarkRunProgress,
- state: ProgressState,
- progressCb?: (progress: BenchmarkRunProgress) => void | Promise<void>,
-): Promise<void> {
- progressCb && (await progressCb(cloneProgressWithState(progress, state)));
-}
-
-function cloneProgressWithState(
- progress: BenchmarkRunProgress,
- state: ProgressState,
-): BenchmarkRunProgress {
- return deepAssign({}, progress, { state }) as BenchmarkRunProgress;
-}
diff --git a/std/testing/bench_example.ts b/std/testing/bench_example.ts
deleted file mode 100644
index 5af277f1c..000000000
--- a/std/testing/bench_example.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-// https://deno.land/std/testing/bench.ts
-import { bench, BenchmarkTimer, runBenchmarks } from "./bench.ts";
-
-// Basic
-bench(function forIncrementX1e9(b: BenchmarkTimer): void {
- b.start();
- for (let i = 0; i < 1e9; i++);
- b.stop();
-});
-
-// Reporting average measured time for $runs runs of func
-bench({
- name: "runs100ForIncrementX1e6",
- runs: 100,
- func(b): void {
- b.start();
- for (let i = 0; i < 1e6; i++);
- b.stop();
- },
-});
-
-// Itsabug
-bench(function throwing(b): void {
- b.start();
- // Throws bc the timer's stop method is never called
-});
-
-// Bench control
-if (import.meta.main) {
- runBenchmarks({ skip: /throw/ });
-}
diff --git a/std/testing/bench_test.ts b/std/testing/bench_test.ts
deleted file mode 100644
index 6ce7796ca..000000000
--- a/std/testing/bench_test.ts
+++ /dev/null
@@ -1,379 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import {
- bench,
- BenchmarkRunError,
- BenchmarkRunProgress,
- clearBenchmarks,
- ProgressState,
- runBenchmarks,
-} from "./bench.ts";
-import {
- assert,
- assertEquals,
- assertThrows,
- assertThrowsAsync,
-} from "./asserts.ts";
-
-Deno.test({
- name: "benching",
-
- fn: async function (): Promise<void> {
- bench(function forIncrementX1e3(b): void {
- b.start();
- for (let i = 0; i < 1e3; i++);
- b.stop();
- });
-
- bench(function forDecrementX1e3(b): void {
- b.start();
- for (let i = 1e3; i > 0; i--);
- b.stop();
- });
-
- bench(async function forAwaitFetchDenolandX10(b): Promise<void> {
- b.start();
- for (let i = 0; i < 10; i++) {
- const r = await fetch("https://deno.land/");
- await r.text();
- }
- b.stop();
- });
-
- bench(async function promiseAllFetchDenolandX10(b): Promise<void> {
- const urls = new Array(10).fill("https://deno.land/");
- b.start();
- await Promise.all(
- urls.map(
- async (denoland: string): Promise<void> => {
- const r = await fetch(denoland);
- await r.text();
- },
- ),
- );
- b.stop();
- });
-
- bench({
- name: "runs100ForIncrementX1e6",
- runs: 100,
- func(b): void {
- b.start();
- for (let i = 0; i < 1e6; i++);
- b.stop();
- },
- });
-
- bench(function throwing(b): void {
- b.start();
- // Throws bc the timer's stop method is never called
- });
-
- const benchResult = await runBenchmarks({ skip: /throw/ });
-
- assertEquals(benchResult.filtered, 1);
- assertEquals(benchResult.results.length, 5);
-
- const resultWithSingleRunsFiltered = benchResult.results.filter(
- ({ name }) => name === "forDecrementX1e3",
- );
- assertEquals(resultWithSingleRunsFiltered.length, 1);
-
- const resultWithSingleRuns = resultWithSingleRunsFiltered[0];
- assert(!!resultWithSingleRuns.runsCount);
- assert(!!resultWithSingleRuns.measuredRunsAvgMs);
- assert(!!resultWithSingleRuns.measuredRunsMs);
- assertEquals(resultWithSingleRuns.runsCount, 1);
- assertEquals(resultWithSingleRuns.measuredRunsMs.length, 1);
-
- const resultWithMultipleRunsFiltered = benchResult.results.filter(
- ({ name }) => name === "runs100ForIncrementX1e6",
- );
- assertEquals(resultWithMultipleRunsFiltered.length, 1);
-
- const resultWithMultipleRuns = resultWithMultipleRunsFiltered[0];
- assert(!!resultWithMultipleRuns.runsCount);
- assert(!!resultWithMultipleRuns.measuredRunsAvgMs);
- assert(!!resultWithMultipleRuns.measuredRunsMs);
- assertEquals(resultWithMultipleRuns.runsCount, 100);
- assertEquals(resultWithMultipleRuns.measuredRunsMs.length, 100);
-
- clearBenchmarks();
- },
-});
-
-Deno.test({
- name: "Bench without name should throw",
- fn() {
- assertThrows(
- (): void => {
- bench(() => {});
- },
- Error,
- "The benchmark function must not be anonymous",
- );
- },
-});
-
-Deno.test({
- name: "Bench without stop should throw",
- fn: async function (): Promise<void> {
- await assertThrowsAsync(
- async (): Promise<void> => {
- bench(function benchWithoutStop(b): void {
- b.start();
- // Throws bc the timer's stop method is never called
- });
- await runBenchmarks({ only: /benchWithoutStop/, silent: true });
- },
- BenchmarkRunError,
- "The benchmark timer's stop method must be called",
- );
- },
-});
-
-Deno.test({
- name: "Bench without start should throw",
- fn: async function (): Promise<void> {
- await assertThrowsAsync(
- async (): Promise<void> => {
- bench(function benchWithoutStart(b): void {
- b.stop();
- // Throws bc the timer's start method is never called
- });
- await runBenchmarks({ only: /benchWithoutStart/, silent: true });
- },
- BenchmarkRunError,
- "The benchmark timer's start method must be called",
- );
- },
-});
-
-Deno.test({
- name: "Bench with stop before start should throw",
- fn: async function (): Promise<void> {
- await assertThrowsAsync(
- async (): Promise<void> => {
- bench(function benchStopBeforeStart(b): void {
- b.stop();
- b.start();
- // Throws bc the timer's stop is called before start
- });
- await runBenchmarks({ only: /benchStopBeforeStart/, silent: true });
- },
- BenchmarkRunError,
- "The benchmark timer's start method must be called before its stop method",
- );
- },
-});
-
-Deno.test({
- name: "clearBenchmarks should clear all candidates",
- fn: async function (): Promise<void> {
- dummyBench("test");
-
- clearBenchmarks();
- const benchingResults = await runBenchmarks({ silent: true });
-
- assertEquals(benchingResults.filtered, 0);
- assertEquals(benchingResults.results.length, 0);
- },
-});
-
-Deno.test({
- name: "clearBenchmarks with only as option",
- fn: async function (): Promise<void> {
- // to reset candidates
- clearBenchmarks();
-
- dummyBench("test");
- dummyBench("onlyclear");
-
- clearBenchmarks({ only: /only/ });
- const benchingResults = await runBenchmarks({ silent: true });
-
- assertEquals(benchingResults.filtered, 0);
- assertEquals(benchingResults.results.length, 1);
- assertEquals(benchingResults.results[0].name, "test");
- },
-});
-
-Deno.test({
- name: "clearBenchmarks with skip as option",
- fn: async function (): Promise<void> {
- // to reset candidates
- clearBenchmarks();
-
- dummyBench("test");
- dummyBench("skipclear");
-
- clearBenchmarks({ skip: /skip/ });
- const benchingResults = await runBenchmarks({ silent: true });
-
- assertEquals(benchingResults.filtered, 0);
- assertEquals(benchingResults.results.length, 1);
- assertEquals(benchingResults.results[0].name, "skipclear");
- },
-});
-
-Deno.test({
- name: "clearBenchmarks with only and skip as option",
- fn: async function (): Promise<void> {
- // to reset candidates
- clearBenchmarks();
-
- dummyBench("test");
- dummyBench("clearonly");
- dummyBench("clearskip");
- dummyBench("clearonly");
-
- clearBenchmarks({ only: /clear/, skip: /skip/ });
- const benchingResults = await runBenchmarks({ silent: true });
-
- assertEquals(benchingResults.filtered, 0);
- assertEquals(benchingResults.results.length, 2);
- assert(!!benchingResults.results.find(({ name }) => name === "test"));
- assert(!!benchingResults.results.find(({ name }) => name === "clearskip"));
- },
-});
-
-Deno.test({
- name: "progressCallback of runBenchmarks",
- fn: async function (): Promise<void> {
- clearBenchmarks();
- dummyBench("skip");
- dummyBench("single");
- dummyBench("multiple", 2);
-
- const progressCallbacks: BenchmarkRunProgress[] = [];
-
- const benchingResults = await runBenchmarks(
- { skip: /skip/, silent: true },
- (progress) => {
- progressCallbacks.push(progress);
- },
- );
-
- let pc = 0;
- // Assert initial progress before running
- let progress = progressCallbacks[pc++];
- assert(progress.queued);
- assertEquals(progress.state, ProgressState.BenchmarkingStart);
- assertEquals(progress.filtered, 1);
- assertEquals(progress.queued.length, 2);
- assertEquals(progress.running, undefined);
- assertEquals(progress.results, []);
-
- // Assert start of bench "single"
- progress = progressCallbacks[pc++];
- assertEquals(progress.state, ProgressState.BenchStart);
- assertEquals(progress.filtered, 1);
- assert(progress.queued);
- assertEquals(progress.queued.length, 1);
- assert(!!progress.queued.find(({ name }) => name == "multiple"));
- assertEquals(progress.running, {
- name: "single",
- runsCount: 1,
- measuredRunsMs: [],
- });
- assertEquals(progress.results, []);
-
- // Assert running result of bench "single"
- progress = progressCallbacks[pc++];
- assertEquals(progress.state, ProgressState.BenchPartialResult);
- assert(progress.queued);
- assertEquals(progress.queued.length, 1);
- assertEquals(progress.running!.measuredRunsMs.length, 1);
- assertEquals(progress.results.length, 0);
-
- // Assert result of bench "single"
- progress = progressCallbacks[pc++];
- assertEquals(progress.state, ProgressState.BenchResult);
- assert(progress.queued);
- assertEquals(progress.queued.length, 1);
- assertEquals(progress.running, undefined);
- assertEquals(progress.results.length, 1);
- assert(!!progress.results.find(({ name }) => name == "single"));
-
- // Assert start of bench "multiple"
- progress = progressCallbacks[pc++];
- assertEquals(progress.state, ProgressState.BenchStart);
- assert(progress.queued);
- assertEquals(progress.queued.length, 0);
- assertEquals(progress.running, {
- name: "multiple",
- runsCount: 2,
- measuredRunsMs: [],
- });
- assertEquals(progress.results.length, 1);
-
- // Assert first result of bench "multiple"
- progress = progressCallbacks[pc++];
- assertEquals(progress.state, ProgressState.BenchPartialResult);
- assert(progress.queued);
- assertEquals(progress.queued.length, 0);
- assertEquals(progress.running!.measuredRunsMs.length, 1);
- assertEquals(progress.results.length, 1);
-
- // Assert second result of bench "multiple"
- progress = progressCallbacks[pc++];
- assertEquals(progress.state, ProgressState.BenchPartialResult);
- assert(progress.queued);
- assertEquals(progress.queued.length, 0);
- assertEquals(progress.running!.measuredRunsMs.length, 2);
- assertEquals(progress.results.length, 1);
-
- // Assert finish of bench "multiple"
- progress = progressCallbacks[pc++];
- assertEquals(progress.state, ProgressState.BenchResult);
- assert(progress.queued);
- assertEquals(progress.queued.length, 0);
- assertEquals(progress.running, undefined);
- assertEquals(progress.results.length, 2);
- assert(!!progress.results.find(({ name }) => name == "single"));
- const resultOfMultiple = progress.results.filter(
- ({ name }) => name == "multiple",
- );
- assertEquals(resultOfMultiple.length, 1);
- assert(!!resultOfMultiple[0].measuredRunsMs);
- assert(!isNaN(resultOfMultiple[0].measuredRunsAvgMs));
- assertEquals(resultOfMultiple[0].measuredRunsMs.length, 2);
-
- // The last progress should equal the final result from promise except the state property
- progress = progressCallbacks[pc++];
- assertEquals(progress.state, ProgressState.BenchmarkingEnd);
- delete progress.state;
- assertEquals(progress, benchingResults);
- },
-});
-
-Deno.test({
- name: "async progressCallback",
- fn: async function (): Promise<void> {
- clearBenchmarks();
- dummyBench("single");
-
- const asyncCallbacks = [];
-
- await runBenchmarks({ silent: true }, (progress) => {
- return new Promise((resolve) => {
- queueMicrotask(() => {
- asyncCallbacks.push(progress);
- resolve();
- });
- });
- });
-
- assertEquals(asyncCallbacks.length, 5);
- },
-});
-
-function dummyBench(name: string, runs = 1): void {
- bench({
- name,
- runs,
- func(b) {
- b.start();
- b.stop();
- },
- });
-}