diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/cli/run/run-process-env.test.ts | 5 | ||||
-rw-r--r-- | test/js/bun/websocket/websocket-server.test.ts | 3 | ||||
-rw-r--r-- | test/js/first_party/ws/ws.test.ts | 12 | ||||
-rw-r--r-- | test/js/web/workers/example.txt | 1 | ||||
-rw-r--r-- | test/js/web/workers/structured-clone.test.ts | 248 |
5 files changed, 259 insertions, 10 deletions
diff --git a/test/cli/run/run-process-env.test.ts b/test/cli/run/run-process-env.test.ts index 1d7cb2c56..8303fe19c 100644 --- a/test/cli/run/run-process-env.test.ts +++ b/test/cli/run/run-process-env.test.ts @@ -15,16 +15,15 @@ describe("process.env", () => { }); // https://github.com/oven-sh/bun/issues/3589 - test('npm_lifecycle_event should have the value of the last call', () => { + test("npm_lifecycle_event should have the value of the last call", () => { const dir = tempDirWithFiles("processenv_ls_call", { "package.json": `{"scripts": { "first": "${bunExe()} run --cwd lsc second" } }`, "lsc": { "package.json": `{"scripts": { "second": "${bunExe()} run index.ts" } }`, "index.ts": "console.log(process.env.npm_lifecycle_event);", - } + }, }); - const { stdout } = bunRunAsScript(dir, "first"); expect(stdout).toBe("second"); }); diff --git a/test/js/bun/websocket/websocket-server.test.ts b/test/js/bun/websocket/websocket-server.test.ts index eb9b773a3..7a31fa396 100644 --- a/test/js/bun/websocket/websocket-server.test.ts +++ b/test/js/bun/websocket/websocket-server.test.ts @@ -107,7 +107,8 @@ describe("Server", () => { const data = new Uint8Array(1 * 1024 * 1024); // send data until backpressure is triggered for (let i = 0; i < 10; i++) { - if (ws.send(data) < 1) { // backpressure or dropped + if (ws.send(data) < 1) { + // backpressure or dropped break; } } diff --git a/test/js/first_party/ws/ws.test.ts b/test/js/first_party/ws/ws.test.ts index c0b56a200..fc8e63f5f 100644 --- a/test/js/first_party/ws/ws.test.ts +++ b/test/js/first_party/ws/ws.test.ts @@ -110,11 +110,11 @@ describe("WebSocket", () => { expect(isBinary).toBeTrue(); ws.ping(); }); - ws.on("ping", (data) => { + ws.on("ping", data => { expect(data).toBeInstanceOf(type); ws.pong(); }); - ws.on("pong", (data) => { + ws.on("pong", data => { expect(data).toBeInstanceOf(type); done(); }); @@ -145,7 +145,7 @@ describe("WebSocket", () => { ws.on("open", () => { ws.ping(); }); - ws.on("ping", (data) => { + ws.on("ping", data => { expect(data).toBeInstanceOf(Buffer); done(); }); @@ -155,7 +155,7 @@ describe("WebSocket", () => { ws.on("open", () => { ws.ping(message); }); - ws.on("ping", (data) => { + ws.on("ping", data => { expect(data).toEqual(Buffer.from(bytes)); done(); }); @@ -167,7 +167,7 @@ describe("WebSocket", () => { ws.on("open", () => { ws.pong(); }); - ws.on("pong", (data) => { + ws.on("pong", data => { expect(data).toBeInstanceOf(Buffer); done(); }); @@ -177,7 +177,7 @@ describe("WebSocket", () => { ws.on("open", () => { ws.pong(message); }); - ws.on("pong", (data) => { + ws.on("pong", data => { expect(data).toEqual(Buffer.from(bytes)); done(); }); diff --git a/test/js/web/workers/example.txt b/test/js/web/workers/example.txt new file mode 100644 index 000000000..96236f815 --- /dev/null +++ b/test/js/web/workers/example.txt @@ -0,0 +1 @@ +example
\ No newline at end of file diff --git a/test/js/web/workers/structured-clone.test.ts b/test/js/web/workers/structured-clone.test.ts new file mode 100644 index 000000000..61a0c1320 --- /dev/null +++ b/test/js/web/workers/structured-clone.test.ts @@ -0,0 +1,248 @@ +import { join } from "path"; +import { openSync } from "fs"; + +describe("structured clone", () => { + let primitives_tests = [ + { description: "primitive undefined", value: undefined }, + { description: "primitive null", value: null }, + { description: "primitive true", value: true }, + { description: "primitive false", value: false }, + { description: "primitive string, empty string", value: "" }, + { description: "primitive string, lone high surrogate", value: "\uD800" }, + { description: "primitive string, lone low surrogate", value: "\uDC00" }, + { description: "primitive string, NUL", value: "\u0000" }, + { description: "primitive string, astral character", value: "\uDBFF\uDFFD" }, + { description: "primitive number, 0.2", value: 0.2 }, + { description: "primitive number, 0", value: 0 }, + { description: "primitive number, -0", value: -0 }, + { description: "primitive number, NaN", value: NaN }, + { description: "primitive number, Infinity", value: Infinity }, + { description: "primitive number, -Infinity", value: -Infinity }, + { description: "primitive number, 9007199254740992", value: 9007199254740992 }, + { description: "primitive number, -9007199254740992", value: -9007199254740992 }, + { description: "primitive number, 9007199254740994", value: 9007199254740994 }, + { description: "primitive number, -9007199254740994", value: -9007199254740994 }, + { description: "primitive BigInt, 0n", value: 0n }, + { description: "primitive BigInt, -0n", value: -0n }, + { description: "primitive BigInt, -9007199254740994000n", value: -9007199254740994000n }, + { + description: "primitive BigInt, -9007199254740994000900719925474099400090071992547409940009007199254740994000n", + value: -9007199254740994000900719925474099400090071992547409940009007199254740994000n, + }, + ]; + for (let { description, value } of primitives_tests) { + test(description, () => { + var cloned = structuredClone(value); + expect(cloned).toBe(value); + }); + } + + test("Array with primitives", () => { + var input = [ + undefined, + null, + true, + false, + "", + "\uD800", + "\uDC00", + "\u0000", + "\uDBFF\uDFFD", + 0.2, + 0, + -0, + NaN, + Infinity, + -Infinity, + 9007199254740992, + -9007199254740992, + 9007199254740994, + -9007199254740994, + -12n, + -0n, + 0n, + ]; + var cloned = structuredClone(input); + expect(cloned).toBeInstanceOf(Array); + expect(cloned).not.toBe(input); + expect(cloned.length).toEqual(input.length); + for (const x in input) { + expect(cloned[x]).toBe(input[x]); + } + }); + test("Object with primitives", () => { + var input: any = { + undefined: undefined, + null: null, + true: true, + false: false, + empty: "", + "high surrogate": "\uD800", + "low surrogate": "\uDC00", + nul: "\u0000", + astral: "\uDBFF\uDFFD", + "0.2": 0.2, + "0": 0, + "-0": -0, + NaN: NaN, + Infinity: Infinity, + "-Infinity": -Infinity, + "9007199254740992": 9007199254740992, + "-9007199254740992": -9007199254740992, + "9007199254740994": 9007199254740994, + "-9007199254740994": -9007199254740994, + "-12n": -12n, + "-0n": -0n, + "0n": 0n, + }; + var cloned = structuredClone(input); + expect(cloned).toBeInstanceOf(Object); + expect(cloned).not.toBeInstanceOf(Array); + expect(cloned).not.toBe(input); + for (const x in input) { + expect(cloned[x]).toBe(input[x]); + } + }); + + test("map", () => { + var input = new Map(); + input.set("a", 1); + input.set("b", 2); + input.set("c", 3); + var cloned = structuredClone(input); + expect(cloned).toBeInstanceOf(Map); + expect(cloned).not.toBe(input); + expect(cloned.size).toEqual(input.size); + for (const [key, value] of input) { + expect(cloned.get(key)).toBe(value); + } + }); + + test("set", () => { + var input = new Set(); + input.add("a"); + input.add("b"); + input.add("c"); + var cloned = structuredClone(input); + expect(cloned).toBeInstanceOf(Set); + expect(cloned).not.toBe(input); + expect(cloned.size).toEqual(input.size); + for (const value of input) { + expect(cloned.has(value)).toBe(true); + } + }); + + describe("bun blobs work", () => { + test("simple", async () => { + const blob = new Blob(["hello"], { type: "application/octet-stream" }); + const cloned = structuredClone(blob); + await compareBlobs(blob, cloned); + }); + test("empty", async () => { + const emptyBlob = new Blob([], { type: "" }); + const clonedEmpty = structuredClone(emptyBlob); + await compareBlobs(emptyBlob, clonedEmpty); + }); + test("empty with type", async () => { + const emptyBlob = new Blob([], { type: "application/octet-stream" }); + const clonedEmpty = structuredClone(emptyBlob); + await compareBlobs(emptyBlob, clonedEmpty); + }); + test("unknown type", async () => { + const blob = new Blob(["hello type"], { type: "this is type" }); + const cloned = structuredClone(blob); + await compareBlobs(blob, cloned); + }); + test("file from path", async () => { + const blob = Bun.file(join(import.meta.dir, "example.txt")); + const cloned = structuredClone(blob); + expect(cloned.lastModified).toBe(blob.lastModified); + expect(cloned.name).toBe(blob.name); + }); + test("file from fd", async () => { + const fd = openSync(join(import.meta.dir, "example.txt"), "r"); + const blob = Bun.file(fd); + const cloned = structuredClone(blob); + expect(cloned.lastModified).toBe(blob.lastModified); + expect(cloned.name).toBe(blob.name); + }); + test("unpaired high surrogate (invalid utf-8)", async () => { + const blob = createBlob(encode_cesu8([0xd800])); + const cloned = structuredClone(blob); + await compareBlobs(blob, cloned); + }); + test("unpaired low surrogate (invalid utf-8)", async () => { + const blob = createBlob(encode_cesu8([0xdc00])); + const cloned = structuredClone(blob); + await compareBlobs(blob, cloned); + }); + test("paired surrogates (invalid utf-8)", async () => { + const blob = createBlob(encode_cesu8([0xd800, 0xdc00])); + const cloned = structuredClone(blob); + await compareBlobs(blob, cloned); + }); + }); + + describe("transferrables", () => { + test("ArrayBuffer", () => { + const buffer = Uint8Array.from([1]).buffer; + const cloned = structuredClone(buffer, { transfer: [buffer] }); + expect(buffer.byteLength).toBe(0); + expect(cloned.byteLength).toBe(1); + }); + test("A detached ArrayBuffer cannot be transferred", () => { + const buffer = new ArrayBuffer(2); + const cloned = structuredClone(buffer, { transfer: [buffer] }); + expect(() => { + structuredClone(buffer, { transfer: [buffer] }); + }).toThrow(DOMException); + }); + test("Transferring a non-transferable platform object fails", () => { + const blob = new Blob(); + expect(() => { + structuredClone(blob, { transfer: [blob] }); + }).toThrow(DOMException); + }); + }); +}); + +async function compareBlobs(original: Blob, cloned: Blob) { + expect(cloned).toBeInstanceOf(Blob); + expect(cloned).not.toBe(original); + expect(cloned.size).toBe(original.size); + expect(cloned.type).toBe(original.type); + const ab1 = await new Response(cloned).arrayBuffer(); + const ab2 = await new Response(original).arrayBuffer(); + expect(ab1.byteLength).toBe(ab2.byteLength); + const ta1 = new Uint8Array(ab1); + const ta2 = new Uint8Array(ab2); + for (let i = 0; i < ta1.length; i++) { + expect(ta1[i]).toBe(ta2[i]); + } +} + +function encode_cesu8(codeunits: number[]): number[] { + // http://www.unicode.org/reports/tr26/ section 2.2 + // only the 3-byte form is supported + const rv: number[] = []; + codeunits.forEach(function (codeunit) { + rv.push(b("11100000") + ((codeunit & b("1111000000000000")) >> 12)); + rv.push(b("10000000") + ((codeunit & b("0000111111000000")) >> 6)); + rv.push(b("10000000") + (codeunit & b("0000000000111111"))); + }); + return rv; +} + +function b(s: string): number { + return parseInt(s, 2); +} + +function createBlob(arr: number[]): Blob { + const buffer = new ArrayBuffer(arr.length); + const view = new DataView(buffer); + for (let i = 0; i < arr.length; i++) { + view.setUint8(i, arr[i]); + } + + return new Blob([view]); +} |