diff options
author | 2023-03-14 15:59:55 -0700 | |
---|---|---|
committer | 2023-03-14 15:59:55 -0700 | |
commit | e1921ff8c5996f325c152368e6f1ebb8226c28af (patch) | |
tree | 39a2c969314d41ec476c2a056eb8c637e78a7d41 | |
parent | 2b5139aa46663241302175b5560332da55f57bb3 (diff) | |
download | bun-e1921ff8c5996f325c152368e6f1ebb8226c28af.tar.gz bun-e1921ff8c5996f325c152368e6f1ebb8226c28af.tar.zst bun-e1921ff8c5996f325c152368e6f1ebb8226c28af.zip |
Fix node test harness
-rw-r--r-- | test/harness.ts | 9 | ||||
-rw-r--r-- | test/js/node/harness.ts | 395 | ||||
-rw-r--r-- | test/js/node/net/node-net-server.test.ts | 9 | ||||
-rw-r--r-- | test/js/node/readline/readline.node.test.ts | 4 | ||||
-rw-r--r-- | test/js/node/readline/readline_promises.node.test.ts | 4 |
5 files changed, 232 insertions, 189 deletions
diff --git a/test/harness.ts b/test/harness.ts index 486381cf2..9c4ce8e56 100644 --- a/test/harness.ts +++ b/test/harness.ts @@ -35,3 +35,12 @@ export function withoutAggressiveGC(block: () => unknown) { Bun.unsafe.gcAggressionLevel(origGC); } } + +export function hideFromStackTrace(block: CallableFunction) { + Object.defineProperty(block, "name", { + value: "::bunternal::", + configurable: true, + enumerable: true, + writable: true, + }); +} diff --git a/test/js/node/harness.ts b/test/js/node/harness.ts index 227009a64..a3a7a43e5 100644 --- a/test/js/node/harness.ts +++ b/test/js/node/harness.ts @@ -1,201 +1,232 @@ -import { expect as expect_ } from "bun:test"; -import { gcTick } from "harness"; +import { gcTick, hideFromStackTrace } from "harness"; import assertNode from "node:assert"; type DoneCb = (err?: Error) => any; function noop() {} +export function createTest(path: string) { + const { expect, test, it, describe, beforeAll, afterAll, beforeEach, afterEach } = Bun.jest(path); -const expect = actual => { - gcTick(); - const ret = expect_(actual); - gcTick(); - return ret; -}; - -// Assert -export const strictEqual = (...args: Parameters<typeof assertNode.strictEqual>) => { - assertNode.strictEqual.apply(this, args); - expect(true).toBe(true); -}; - -export const notStrictEqual = (...args: Parameters<typeof assertNode.notStrictEqual>) => { - assertNode.notStrictEqual.apply(this, args); - expect(true).toBe(true); -}; - -export const deepStrictEqual = (...args: Parameters<typeof assertNode.deepStrictEqual>) => { - assertNode.deepStrictEqual.apply(this, args); - expect(true).toBe(true); -}; - -export const throws = (...args: Parameters<typeof assertNode.throws>) => { - assertNode.throws.apply(this, args); - expect(true).toBe(true); -}; - -export const ok = (...args: Parameters<typeof assertNode.ok>) => { - assertNode.ok.apply(this, args); - expect(true).toBe(true); -}; - -export const ifError = (...args: Parameters<typeof assertNode.ifError>) => { - assertNode.ifError.apply(this, args); - expect(true).toBe(true); -}; - -export const match = (...args: Parameters<typeof assertNode.match>) => { - assertNode.match.apply(this, args); - expect(true).toBe(true); -}; - -export const assert = function (...args: any[]) { - // @ts-ignore - assertNode(...args); -}; - -Object.assign(assert, { - strictEqual, - deepStrictEqual, - notStrictEqual, - throws, - ok, - ifError, - match, -}); - -// End assert - -export const createCallCheckCtx = (done: DoneCb) => { - const createDone = createDoneDotAll(done); - - // const mustCallChecks = []; - - // failed.forEach(function (context) { - // console.log( - // "Mismatched %s function calls. Expected %s, actual %d.", - // context.name, - // context.messageSegment, - // context.actual - // ); - // console.log(context.stack.split("\n").slice(2).join("\n")); - // }); - - // TODO: Implement this to be exact only - function mustCall(fn?: (...args) => any, exact?: number) { - return mustCallAtLeast(fn, exact); - } + hideFromStackTrace(expect); - function mustNotCall(reason: string = "function should not have been called") { - const localDone = createDone(); - setTimeout(() => localDone(), 200); - return () => { - done(new Error(reason)); - }; - } + // Assert + const strictEqual = (...args: Parameters<typeof assertNode.strictEqual>) => { + assertNode.strictEqual(...args); + expect(true).toBe(true); + }; - function mustSucceed(fn: () => any, exact?: number) { - return mustCall(function (err, ...args) { - ifError(err); - // @ts-ignore - if (typeof fn === "function") return fn.apply(this, args as []); - }, exact); - } + const notStrictEqual = (...args: Parameters<typeof assertNode.notStrictEqual>) => { + assertNode.notStrictEqual(...args); + expect(true).toBe(true); + }; - function mustCallAtLeast(fn, minimum) { - return _mustCallInner(fn, minimum, "minimum"); - } + const deepStrictEqual = (...args: Parameters<typeof assertNode.deepStrictEqual>) => { + assertNode.deepStrictEqual(...args); + expect(true).toBe(true); + }; - function _mustCallInner(fn, criteria = 1, field) { - if (process._exiting) throw new Error("Cannot use common.mustCall*() in process exit handler"); - if (typeof fn === "number") { - criteria = fn; - fn = noop; - } else if (fn === undefined) { - fn = noop; - } + const throws = (...args: Parameters<typeof assertNode.throws>) => { + assertNode.throws(...args); + expect(true).toBe(true); + }; + + const ok = (...args: Parameters<typeof assertNode.ok>) => { + assertNode.ok(...args); + expect(true).toBe(true); + }; + + const ifError = (...args: Parameters<typeof assertNode.ifError>) => { + assertNode.ifError(...args); + expect(true).toBe(true); + }; - if (typeof criteria !== "number") throw new TypeError(`Invalid ${field} value: ${criteria}`); + const match = (...args: Parameters<typeof assertNode.match>) => { + assertNode.match(...args); + expect(true).toBe(true); + }; - let actual = 0; - let expected = criteria; + const assert = function (...args: any[]) { + // @ts-ignore + assertNode(...args); + }; - // mustCallChecks.push(context); - const done = createDone(); - const _return = (...args) => { - try { + hideFromStackTrace(strictEqual); + hideFromStackTrace(notStrictEqual); + hideFromStackTrace(deepStrictEqual); + hideFromStackTrace(throws); + hideFromStackTrace(ok); + hideFromStackTrace(ifError); + hideFromStackTrace(match); + hideFromStackTrace(assert); + + Object.assign(assert, { + strictEqual, + deepStrictEqual, + notStrictEqual, + throws, + ok, + ifError, + match, + }); + + // End assert + + const createCallCheckCtx = (done: DoneCb) => { + const createDone = createDoneDotAll(done); + + // const mustCallChecks = []; + + // failed.forEach(function (context) { + // console.log( + // "Mismatched %s function calls. Expected %s, actual %d.", + // context.name, + // context.messageSegment, + // context.actual + // ); + // console.log(context.stack.split("\n").slice(2).join("\n")); + // }); + + // TODO: Implement this to be exact only + function mustCall(fn?: (...args) => any, exact?: number) { + return mustCallAtLeast(fn, exact); + } + + function mustNotCall(reason: string = "function should not have been called") { + const localDone = createDone(); + setTimeout(() => localDone(), 200); + return () => { + done(new Error(reason)); + }; + } + + function mustSucceed(fn: () => any, exact?: number) { + return mustCall(function (err, ...args) { + ifError(err); // @ts-ignore - const result = fn.apply(this, args); - actual++; - if (actual >= expected) { - done(); - } - return result; - } catch (err) { - if (err instanceof Error) done(err); - else if (err?.toString) done(new Error(err?.toString())); - else { - console.error("Unknown error", err); - done(new Error("Unknown error")); - } + if (typeof fn === "function") return fn(...(args as [])); + }, exact); + } + + function mustCallAtLeast(fn, minimum) { + return _mustCallInner(fn, minimum, "minimum"); + } + + function _mustCallInner(fn, criteria = 1, field) { + if (process._exiting) throw new Error("Cannot use common.mustCall*() in process exit handler"); + if (typeof fn === "number") { + criteria = fn; + fn = noop; + } else if (fn === undefined) { + fn = noop; } + + if (typeof criteria !== "number") throw new TypeError(`Invalid ${field} value: ${criteria}`); + + let actual = 0; + let expected = criteria; + + // mustCallChecks.push(context); + const done = createDone(); + const _return = (...args) => { + try { + // @ts-ignore + const result = fn(...args); + actual++; + if (actual >= expected) { + done(); + } + return result; + } catch (err) { + if (err instanceof Error) done(err); + else if (err?.toString) done(new Error(err?.toString())); + else { + console.error("Unknown error", err); + done(new Error("Unknown error")); + } + } + }; + // Function instances have own properties that may be relevant. + // Let's replicate those properties to the returned function. + // Refs: https://tc39.es/ecma262/#sec-function-instances + Object.defineProperties(_return, { + name: { + value: fn.name, + writable: false, + enumerable: false, + configurable: true, + }, + length: { + value: fn.length, + writable: false, + enumerable: false, + configurable: true, + }, + }); + return _return; + } + return { + mustSucceed, + mustCall, + mustCallAtLeast, + mustNotCall, }; - // Function instances have own properties that may be relevant. - // Let's replicate those properties to the returned function. - // Refs: https://tc39.es/ecma262/#sec-function-instances - Object.defineProperties(_return, { - name: { - value: fn.name, - writable: false, - enumerable: false, - configurable: true, - }, - length: { - value: fn.length, - writable: false, - enumerable: false, - configurable: true, - }, - }); - return _return; + }; + + function createDoneDotAll(done: DoneCb, globalTimeout?: number) { + let toComplete = 0; + let completed = 0; + const globalTimer = globalTimeout + ? setTimeout(() => { + console.log("Global Timeout"); + done(new Error("Timed out!")); + }, globalTimeout) + : undefined; + function createDoneCb(timeout?: number) { + toComplete += 1; + const timer = + timeout !== undefined + ? setTimeout(() => { + console.log("Timeout"); + done(new Error("Timed out!")); + }, timeout) + : timeout; + return (result?: Error) => { + if (timer) clearTimeout(timer); + if (globalTimer) clearTimeout(globalTimer); + if (result instanceof Error) { + done(result); + return; + } + completed += 1; + if (completed === toComplete) { + done(); + } + }; + } + return createDoneCb; } + return { - mustSucceed, - mustCall, - mustCallAtLeast, - mustNotCall, + expect, + test, + it, + describe, + beforeAll, + afterAll, + beforeEach, + afterEach, + createDoneDotAll, + strictEqual, + notStrictEqual, + deepStrictEqual, + throws, + ok, + ifError, + createCallCheckCtx, + match, + assert, }; -}; - -export function createDoneDotAll(done: DoneCb, globalTimeout?: number) { - let toComplete = 0; - let completed = 0; - const globalTimer = globalTimeout - ? setTimeout(() => { - console.log("Global Timeout"); - done(new Error("Timed out!")); - }, globalTimeout) - : undefined; - function createDoneCb(timeout?: number) { - toComplete += 1; - const timer = - timeout !== undefined - ? setTimeout(() => { - console.log("Timeout"); - done(new Error("Timed out!")); - }, timeout) - : timeout; - return (result?: Error) => { - if (timer) clearTimeout(timer); - if (globalTimer) clearTimeout(globalTimer); - if (result instanceof Error) { - done(result); - return; - } - completed += 1; - if (completed === toComplete) { - done(); - } - }; - } - return createDoneCb; +} + +declare namespace Bun { + function jest(path: string): typeof import("bun:test"); } diff --git a/test/js/node/net/node-net-server.test.ts b/test/js/node/net/node-net-server.test.ts index bdaf289a7..063a822d5 100644 --- a/test/js/node/net/node-net-server.test.ts +++ b/test/js/node/net/node-net-server.test.ts @@ -1,9 +1,12 @@ -import { describe, expect, it } from "bun:test"; -import { createServer } from "net"; -import { createCallCheckCtx } from "node-harness"; +const { createServer } = require("net"); import { realpathSync } from "fs"; import { tmpdir } from "os"; import { join } from "path"; +import { createTest } from "node-harness"; + +const { throws, assert, createDoneDotAll, beforeAll, describe, expect, it, createCallCheckCtx } = createTest( + import.meta.path, +); const socket_domain = join(realpathSync(tmpdir()), "node-net-server.sock"); diff --git a/test/js/node/readline/readline.node.test.ts b/test/js/node/readline/readline.node.test.ts index 7dfa51ac8..a1077a799 100644 --- a/test/js/node/readline/readline.node.test.ts +++ b/test/js/node/readline/readline.node.test.ts @@ -1,8 +1,8 @@ -import { beforeEach, describe, it } from "bun:test"; import readline from "node:readline"; import { Writable, PassThrough } from "node:stream"; import { EventEmitter } from "node:events"; -import { createDoneDotAll, createCallCheckCtx, assert } from "node-harness"; +import { createTest } from "node-harness"; +const { beforeEach, describe, it, createDoneDotAll, createCallCheckCtx, assert } = createTest(import.meta.path); var { CSI, diff --git a/test/js/node/readline/readline_promises.node.test.ts b/test/js/node/readline/readline_promises.node.test.ts index c75d254ca..8a4ac014f 100644 --- a/test/js/node/readline/readline_promises.node.test.ts +++ b/test/js/node/readline/readline_promises.node.test.ts @@ -1,7 +1,7 @@ -import { describe, it } from "bun:test"; import readlinePromises from "node:readline/promises"; import { EventEmitter } from "node:events"; -import { createDoneDotAll, createCallCheckCtx, assert } from "node-harness"; +import { createTest } from "node-harness"; +const { describe, it, createDoneDotAll, createCallCheckCtx, assert } = createTest(import.meta.path); // ---------------------------------------------------------------------------- // Helpers |