From fdbccef1108f233b483554dd0845d2483aea61e0 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sun, 26 May 2024 04:09:28 -0700 Subject: [PATCH] Speed up a couple tests (#11369) --- test/js/bun/http/serve-body-leak.test.ts | 10 +-- test/js/bun/http/serve-listen.test.ts | 24 ++++-- test/js/bun/udp/dgram.test.ts | 25 +++--- test/js/node/http/node-http.test.ts | 24 +++--- test/js/web/fetch/fetch.tls.test.ts | 104 ++++++++++++----------- 5 files changed, 105 insertions(+), 82 deletions(-) diff --git a/test/js/bun/http/serve-body-leak.test.ts b/test/js/bun/http/serve-body-leak.test.ts index f7228ab14711c3..057797a44c3568 100644 --- a/test/js/bun/http/serve-body-leak.test.ts +++ b/test/js/bun/http/serve-body-leak.test.ts @@ -123,11 +123,11 @@ async function calculateMemoryLeak(fn: () => Promise) { } for (const test_info of [ - ["#10265 should not leak memory when ignoring the body", callIgnore, false, 8], - ["should not leak memory when buffering the body", callBuffering, false, 24], - ["should not leak memory when streaming the body", callStreaming, false, 8], - ["should not leak memory when streaming the body incompletely", callIncompleteStreaming, false, 16], - ["should not leak memory when streaming the body and echoing it back", callStreamingEcho, false, 16], + ["#10265 should not leak memory when ignoring the body", callIgnore, false, 16], + ["should not leak memory when buffering the body", callBuffering, false, 48], + ["should not leak memory when streaming the body", callStreaming, false, 16], + ["should not leak memory when streaming the body incompletely", callIncompleteStreaming, false, 32], + ["should not leak memory when streaming the body and echoing it back", callStreamingEcho, false, 32], ] as const) { const [testName, fn, skip, maxMemoryGrowth] = test_info; it.todoIf(skip)( diff --git a/test/js/bun/http/serve-listen.test.ts b/test/js/bun/http/serve-listen.test.ts index b75c6c91ae6b4e..031496710d48c0 100644 --- a/test/js/bun/http/serve-listen.test.ts +++ b/test/js/bun/http/serve-listen.test.ts @@ -3,13 +3,13 @@ import { file, serve } from "bun"; import type { NetworkInterfaceInfo } from "node:os"; import { networkInterfaces } from "node:os"; import { join } from "node:path"; -import { tmpdirSync } from "harness"; +import { isWindows, tmpdirSync } from "harness"; const networks = Object.values(networkInterfaces()).flat() as NetworkInterfaceInfo[]; const hasIPv4 = networks.some(({ family }) => family === "IPv4"); const hasIPv6 = networks.some(({ family }) => family === "IPv6"); -const unix = join(tmpdirSync(), "unix.sock"); +const unix = join(tmpdirSync(), "unix.sock").replaceAll("\\", "/"); const tls = { cert: file(new URL("./fixtures/cert.pem", import.meta.url)), key: file(new URL("./fixtures/cert.key", import.meta.url)), @@ -109,14 +109,20 @@ describe.each([ }, }, { - if: process.platform !== "win32", options: { - unix, - }, - url: { - protocol: "unix:", - pathname: unix, - }, + unix: unix, + }, + url: isWindows + ? { + protocol: "unix:", + pathname: unix.substring(unix.indexOf(":") + 1), + hostname: unix.substring(0, unix.indexOf(":")), + port: "", + } + : { + protocol: "unix:", + pathname: unix, + }, }, ])("Bun.serve()", ({ if: enabled = true, options, hostname, url }) => { const title = Bun.inspect(options).replaceAll("\n", " "); diff --git a/test/js/bun/udp/dgram.test.ts b/test/js/bun/udp/dgram.test.ts index 44184bddcb02df..c6d486c3c66179 100644 --- a/test/js/bun/udp/dgram.test.ts +++ b/test/js/bun/udp/dgram.test.ts @@ -2,6 +2,7 @@ import { createSocket } from "dgram"; import { describe, test, expect, it } from "bun:test"; import { nodeDataCases } from "./testdata"; +import { disableAggressiveGCScope } from "harness"; describe("createSocket()", () => { test("connect", done => { @@ -39,8 +40,8 @@ describe("createSocket()", () => { }); socket.on("error", err => { - socket.close(done); expect(err).toBeNull(); + socket.close(done); }); socket.bind(0, "127.0.0.1"); @@ -62,21 +63,25 @@ describe("createSocket()", () => { }); socket.on("error", err => { - socket.close(done); expect(err).toBeNull(); + socket.close(done); }); socket.bind(0, localhost); }); const validateRecv = (server, data, rinfo, bytes) => { - expect(data).toHaveLength(bytes.length); - expect(data).toStrictEqual(Buffer.from(bytes)); - expect(rinfo.port).toBeInteger(); - expect(rinfo.port).toBeWithin(1, 65535 + 1); - expect(rinfo.address).toBeString(); - expect(rinfo.address).not.toBeEmpty(); - expect(rinfo.port).not.toBe(server.address().port); + using _ = disableAggressiveGCScope(); + try { + expect(rinfo.port).toBeInteger(); + expect(rinfo.port).toBeWithin(1, 65535 + 1); + expect(rinfo.address).toBeString(); + expect(rinfo.address).not.toBeEmpty(); + expect(rinfo.port).not.toBe(server.address().port); + } catch (e) { + console.error(e); + throw e; + } }; for (const { label, data, bytes } of nodeDataCases) { @@ -163,7 +168,7 @@ describe("createSocket()", () => { expect(err).toBeNull(); }); server.on("message", (data, rinfo) => { - validateRecv(server, data, rinfo, [bytes, bytes, bytes].flat()); + validateRecv(server, data, rinfo, Buffer.from([...bytes, ...bytes, ...bytes].flat())); server.close(); client.close(); diff --git a/test/js/node/http/node-http.test.ts b/test/js/node/http/node-http.test.ts index ffdbc45566a422..dc951a2e72c15a 100644 --- a/test/js/node/http/node-http.test.ts +++ b/test/js/node/http/node-http.test.ts @@ -25,7 +25,7 @@ import { unlinkSync } from "node:fs"; import { PassThrough } from "node:stream"; const { describe, expect, it, beforeAll, afterAll, createDoneDotAll, mock } = createTest(import.meta.path); import { bunExe } from "bun:harness"; -import { bunEnv, tmpdirSync } from "harness"; +import { bunEnv, disableAggressiveGCScope, tmpdirSync } from "harness"; import * as stream from "node:stream"; import * as zlib from "node:zlib"; @@ -1207,7 +1207,7 @@ describe("server.address should be valid IP", () => { test("ServerResponse instanceof OutgoingMessage", () => { expect(new ServerResponse({}) instanceof OutgoingMessage).toBe(true); }); - test("ServerResponse assign assignSocket", done => { + test("ServerResponse assign assignSocket", async done => { const createDone = createDoneDotAll(done); const doneRequest = createDone(); const waitSocket = createDone(); @@ -1223,13 +1223,13 @@ describe("server.address should be valid IP", () => { doneRequest(); }); res.assignSocket(socket); - setImmediate(() => { - expect(res.socket).toBe(socket); - expect(socket._httpMessage).toBe(res); - expect(() => res.assignSocket(socket)).toThrow("ServerResponse has an already assigned socket"); - socket.emit("close"); - doneSocket(); - }); + await Bun.sleep(10); + + expect(res.socket).toBe(socket); + expect(socket._httpMessage).toBe(res); + expect(() => res.assignSocket(socket)).toThrow("ServerResponse has an already assigned socket"); + socket.emit("close"); + doneSocket(); } catch (err) { doneRequest(err); } @@ -1785,7 +1785,7 @@ it("#10177 response.write with non-ascii latin1 should not cause duplicated char for (const char of chars) { for (let size = start_size; size <= end_size; size += increment_step) { - expected = char + "-".repeat(size) + "x"; + expected = char + Buffer.alloc(size, "-").toString("utf8") + "x"; try { const url = `http://${hostname}:${port}`; @@ -1798,6 +1798,7 @@ it("#10177 response.write with non-ascii latin1 should not cause duplicated char all.push(...(await Promise.all(batch))); } + using _ = disableAggressiveGCScope(); for (const result of all) { expect(result).toBe(expected); } @@ -1805,6 +1806,9 @@ it("#10177 response.write with non-ascii latin1 should not cause duplicated char return finish(err); } } + + // still always run GC at the end here. + Bun.gc(true); } finish(); }); diff --git a/test/js/web/fetch/fetch.tls.test.ts b/test/js/web/fetch/fetch.tls.test.ts index 916ccb18a941bd..246027977f6b7c 100644 --- a/test/js/web/fetch/fetch.tls.test.ts +++ b/test/js/web/fetch/fetch.tls.test.ts @@ -36,8 +36,8 @@ it("can handle multiple requests with non native checkServerIdentity", async () return tls.checkServerIdentity(hostname, cert); }, }, - }).then((res: Response) => res.text()); - expect(result?.length).toBeGreaterThan(0); + }).then((res: Response) => res.blob()); + expect(result?.size).toBeGreaterThan(0); expect(called).toBe(true); } const promises = []; @@ -48,35 +48,36 @@ it("can handle multiple requests with non native checkServerIdentity", async () }); it("fetch with valid tls should not throw", async () => { - const urls = ["https://bun.sh", "https://www.example.com"]; - for (const url of urls) { - const result = await fetch(url, { keepalive: false }).then((res: Response) => res.text()); - expect(result?.length).toBeGreaterThan(0); - } + const promises = [`https://bun.sh`, `https://www.example.com`].map(async url => { + const result = await fetch(url, { keepalive: false }).then((res: Response) => res.blob()); + expect(result?.size).toBeGreaterThan(0); + }); + + await Promise.all(promises); }); it("fetch with valid tls and non-native checkServerIdentity should work", async () => { - const urls = [`https://bun.sh`, `https://www.example.com`]; let count = 0; - for (const url of urls) { + const promises = [`https://bun.sh`, `https://www.example.com`].map(async url => { await fetch(url, { keepalive: false, tls: { checkServerIdentity(hostname: string, cert: tls.PeerCertificate) { count++; - expect(["bun.sh", "www.example.com"]).toContain(hostname); + expect(url).toContain(hostname); return tls.checkServerIdentity(hostname, cert); }, }, - }).then((res: Response) => res.text()); - } + }).then((res: Response) => res.blob()); + }); + await Promise.all(promises); expect(count).toBe(2); }); it("fetch with rejectUnauthorized: false should not call checkServerIdentity", async () => { let count = 0; - await fetch("https://bun.sh", { + await fetch("https://example.com", { keepalive: false, tls: { rejectUnauthorized: false, @@ -85,35 +86,38 @@ it("fetch with rejectUnauthorized: false should not call checkServerIdentity", a return tls.checkServerIdentity(hostname, cert); }, }, - }).then((res: Response) => res.text()); + }).then((res: Response) => res.blob()); expect(count).toBe(0); }); it("fetch with self-sign tls should throw", async () => { await createServer(CERT_LOCALHOST_IP, async port => { const urls = [`https://localhost:${port}`, `https://127.0.0.1:${port}`]; - for (const url of urls) { - try { - await fetch(url).then((res: Response) => res.text()); - expect.unreachable(); - } catch (e: any) { - expect(e.code).toBe("DEPTH_ZERO_SELF_SIGNED_CERT"); - } - } + await Promise.all( + urls.map(async url => { + try { + await fetch(url).then((res: Response) => res.blob()); + expect.unreachable(); + } catch (e: any) { + expect(e.code).toBe("DEPTH_ZERO_SELF_SIGNED_CERT"); + } + }), + ); }); }); it("fetch with invalid tls should throw", async () => { await createServer(CERT_EXPIRED, async port => { - const urls = [`https://localhost:${port}`, `https://127.0.0.1:${port}`]; - for (const url of urls) { - try { - await fetch(url).then((res: Response) => res.text()); - expect.unreachable(); - } catch (e: any) { - expect(e.code).toBe("CERT_HAS_EXPIRED"); - } - } + await Promise.all( + [`https://localhost:${port}`, `https://127.0.0.1:${port}`].map(async url => { + try { + await fetch(url).then((res: Response) => res.blob()); + expect.unreachable(); + } catch (e: any) { + expect(e.code).toBe("CERT_HAS_EXPIRED"); + } + }), + ); }); }); @@ -126,7 +130,7 @@ it("fetch with checkServerIdentity failing should throw", async () => { return new Error("CustomError"); }, }, - }).then((res: Response) => res.text()); + }).then((res: Response) => res.blob()); expect.unreachable(); } catch (e: any) { @@ -137,28 +141,32 @@ it("fetch with checkServerIdentity failing should throw", async () => { it("fetch with self-sign certificate tls + rejectUnauthorized: false should not throw", async () => { await createServer(CERT_LOCALHOST_IP, async port => { const urls = [`https://localhost:${port}`, `https://127.0.0.1:${port}`]; - for (const url of urls) { - try { - const result = await fetch(url, { tls: { rejectUnauthorized: false } }).then((res: Response) => res.text()); - expect(result).toBe("Hello World"); - } catch { - expect.unreachable(); - } - } + await Promise.all( + urls.map(async url => { + try { + const result = await fetch(url, { tls: { rejectUnauthorized: false } }).then((res: Response) => res.text()); + expect(result).toBe("Hello World"); + } catch { + expect.unreachable(); + } + }), + ); }); }); it("fetch with invalid tls + rejectUnauthorized: false should not throw", async () => { await createServer(CERT_EXPIRED, async port => { const urls = [`https://localhost:${port}`, `https://127.0.0.1:${port}`]; - for (const url of urls) { - try { - const result = await fetch(url, { tls: { rejectUnauthorized: false } }).then((res: Response) => res.text()); - expect(result).toBe("Hello World"); - } catch { - expect.unreachable(); - } - } + await Promise.all( + urls.map(async url => { + try { + const result = await fetch(url, { tls: { rejectUnauthorized: false } }).then((res: Response) => res.text()); + expect(result).toBe("Hello World"); + } catch { + expect.unreachable(); + } + }), + ); }); });