Files
2026-08-27 21:09:14 +00:00

103 lines
3.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test } from "bun:test";
import { bunEnv, bunExe, isWindows, tempDir } from "harness";
import { join } from "node:path";
// @datadog/[email protected] ships node-gyp-build prebuilds for linux-{x64,arm64}
// (glibc + musl), darwin-{x64,arm64} and win32-x64 at ABI 147, matching Bun's
// process.versions.modules. win32-arm64 has no prebuild — skip there rather
// than fall through to a node-gyp source build.
const hasPrebuild = !(isWindows && process.arch === "arm64");
describe.skipIf(!hasPrebuild)("@datadog/pprof", () => {
test("TimeProfiler start/stop returns a populated profile", async () => {
using dir = tempDir("datadog-pprof", {
"package.json": JSON.stringify({
name: "datadog-pprof-fixture",
version: "0.0.0",
dependencies: {
"@datadog/pprof": "5.17.0",
},
trustedDependencies: ["@datadog/pprof"],
}),
"index.js": /* js */ `
const { time } = require("@datadog/pprof");
function hotLoop() {
// Busy-spin long enough for the 1ms wall sampler to capture real
// samples on slow debug/ASAN builds; this is CPU work, not a sleep.
const start = Date.now();
let acc = 0;
while (Date.now() - start < 300) {
for (let i = 0; i < 1000; i++) acc += Math.sqrt(i);
}
return acc;
}
time.start({ intervalMicros: 1000, durationMillis: 60000 });
hotLoop();
const profile = time.stop();
const strings = profile.stringTable.strings;
const summary = {
sampleCount: profile.sample.length,
locationCount: profile.location.length,
functionCount: profile.function.length,
stringCount: strings.length,
hasHotLoop: strings.includes("hotLoop"),
period: Number(profile.period),
};
process.stdout.write(JSON.stringify(summary) + "\\n");
`,
});
{
await using install = Bun.spawn({
cmd: [bunExe(), "install"],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([
install.stdout.text(),
install.stderr.text(),
install.exited,
]);
if (exitCode !== 0) {
throw new Error(`bun install failed (exit ${exitCode})\nstdout:\n${stdout}\nstderr:\n${stderr}`);
}
}
await using proc = Bun.spawn({
cmd: [bunExe(), join(String(dir), "index.js")],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
const summary = JSON.parse(stdout.trim());
expect(summary).toEqual({
sampleCount: expect.any(Number),
locationCount: expect.any(Number),
functionCount: expect.any(Number),
stringCount: expect.any(Number),
hasHotLoop: true,
period: expect.any(Number),
});
expect(summary.sampleCount).toBeGreaterThan(0);
expect(summary.locationCount).toBeGreaterThan(0);
expect(summary.functionCount).toBeGreaterThan(0);
expect(summary.stringCount).toBeGreaterThan(0);
// serializeTimeProfile recomputes intervalMicros from wall-clock/hit-count,
// clamps it to [intervalMicros, 2*intervalMicros], then ×1000 → nanoseconds.
expect(summary.period).toBeGreaterThanOrEqual(1_000_000);
expect(summary.period).toBeLessThanOrEqual(2_000_000);
expect(exitCode).toBe(0);
}, 120_000);
});