Files
bun.sh/test/js/web/fetch/fetch-leak-test-fixture-5.js
2025-11-07 05:28:33 -08:00

123 lines
2.8 KiB
JavaScript
Generated

import { heapStats } from "bun:jsc";
import { expect } from "bun:test";
function getHeapStats() {
return heapStats().objectTypeCounts;
}
const server = process.argv[2];
const batch = 10;
const iterations = 50;
const threshold = batch * 2 + batch / 2;
const BODY_SIZE = parseInt(process.argv[3], 10);
if (!Number.isSafeInteger(BODY_SIZE)) {
console.error("BODY_SIZE must be a safe integer", BODY_SIZE, process.argv);
process.exit(1);
}
function getFormData() {
const formData = new FormData();
formData.set("file", getBlob());
return formData;
}
let cachedBlobBuffer;
function getBlob() {
if (!cachedBlobBuffer) {
const buf = new Uint8Array(BODY_SIZE);
buf.fill(42);
for (let i = 0; i < 256; i++) {
buf[i] = i;
}
cachedBlobBuffer = buf;
}
return new Blob([cachedBlobBuffer], { type: "application/octet-stream" });
}
function getBuffer() {
return Buffer.alloc(BODY_SIZE, "abcdefghijklmnopqrstuvwxyz");
}
function getString() {
return getBuffer().toString();
}
function getURLSearchParams() {
const urlSearchParams = new URLSearchParams();
urlSearchParams.set("file", getString());
return urlSearchParams;
}
const type = process.argv[4];
// Cache only buffer/string since those aren't reference counted the same way.
let cachedBody;
function getBody() {
let body;
switch (type.toLowerCase()) {
case "blob":
body = getBlob();
break;
case "buffer":
body = cachedBody ??= getBuffer();
break;
case "string":
body = cachedBody ??= getString();
break;
case "formdata":
body = getFormData();
break;
case "urlsearchparams":
body = getURLSearchParams();
break;
case "iterator":
body = async function* iter() {
yield (cachedBody ??= getString());
};
break;
case "stream":
body = new ReadableStream({
async pull(c) {
await Bun.sleep(10);
c.enqueue((cachedBody ??= getBuffer()));
c.close();
},
});
break;
default:
throw new Error(`Invalid type: ${type}`);
}
return body;
}
async function iterate() {
const promises = [];
for (let j = 0; j < batch; j++) {
promises.push(fetch(server, { method: "POST", body: getBody() }));
}
await Promise.all(promises);
}
try {
for (let i = 0; i < iterations; i++) {
await iterate();
{
Bun.gc(true);
await Bun.sleep(100);
Bun.gc(true);
const stats = getHeapStats();
expect(stats.Response || 0).toBeLessThanOrEqual(threshold);
expect(stats.Promise || 0).toBeLessThanOrEqual(threshold);
process.send({
rss: process.memoryUsage.rss(),
});
}
}
process.send({
rss: process.memoryUsage.rss(),
});
await Bun.sleep(10);
process.exit(0);
} catch (e) {
console.error(e);
process.exit(1);
}