import { expect as expect_ } from "bun:test"; // @ts-ignore import { gcTick } from "gc"; import assertNode from "node:assert"; type DoneCb = (err?: Error) => any; function noop() {} const expect = (actual) => { gcTick(); const ret = expect_(actual); gcTick(); return ret; }; // Assert export const strictEqual = ( ...args: Parameters ) => { assertNode.strictEqual.apply(this, args); expect(true).toBe(true); }; export const notStrictEqual = ( ...args: Parameters ) => { assertNode.notStrictEqual.apply(this, args); expect(true).toBe(true); }; export const deepStrictEqual = ( ...args: Parameters ) => { assertNode.deepStrictEqual.apply(this, args); expect(true).toBe(true); }; export const throws = (...args: Parameters) => { assertNode.throws.apply(this, args); expect(true).toBe(true); }; export const ok = (...args: Parameters) => { assertNode.ok.apply(this, args); expect(true).toBe(true); }; export const ifError = (...args: Parameters) => { assertNode.ifError.apply(this, args); expect(true).toBe(true); }; export const match = (...args: Parameters) => { assertNode.match.apply(this, args); expect(true).toBe(true); }; export const 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); } 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 if (typeof fn === "function") return fn.apply(this, 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) => { // @ts-ignore const result = fn.apply(this, args); actual++; if (actual >= expected) { done(); } return result; }; // 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, }; }; 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; }