返回 DeepSeek-Reasonix
app-memory-shards.test.mjs
根目录 / desktop / frontend / bench / app-memory-shards.test.mjs
1 import test from "node:test";
2 import assert from "node:assert/strict";
3 import { aggregateShards, completeShard, memoryProtocol, MEMORY_FIXTURES } from "./app-memory-shards.mjs";
4
5 const identity = { sourceSHA: "a".repeat(40), trackedDiffSHA256: "clean-diff", untrackedSourceSHA256: "clean-untracked", buildSHA256: "shared-build", node: "v24", platform: "linux", arch: "x64", sourceStatus: "" };
6
7 function fixture(profile = "full", executionId = "123:1") {
8 const protocol = memoryProtocol(profile);
9 const manifest = { identity, protocol, executionId };
10 const report = id => {
11 const sample = (phase, roundTrips) => ({ phase, roundTrips,
12 lifecycle: { liveRenderTokenIds: [1], liveRenderTokens: 1, activeOperations: 0, activeSubscriptions: 2, overflow: false, invariantViolations: 0 },
13 dom: { nodes: 10, jsEventListeners: 2 }, heap: { usedSize: 100 } });
14 const samples = [sample("baseline", 0)];
15 for (const phase of ["full", "windowed", "safety", "mixed"]) {
16 const count = phase === "mixed" ? protocol.mixedCycles : protocol.cycles;
17 for (let round = 32; round <= count; round += 32) samples.push(sample(phase, round));
18 }
19 samples.push(sample("settled", protocol.mixedCycles));
20 return { identity: structuredClone(identity), fixtures: structuredClone(MEMORY_FIXTURES), protocol: structuredClone(protocol),
21 shard: { id, total: protocol.shards, executionId }, cycles: protocol.cycles, mixedCycles: protocol.mixedCycles,
22 shardComplete: true, protocolComplete: false, verdict: "SHARD_PASS", processes: [{ process: id, browser: "chromium-fixed", samples,
23 snapshots: ["baseline", "full", "windowed", "safety", "mixed"].map(phase => ({ file: `${id}-${phase}.heapsnapshot`, summary: {} })),
24 checks: { evidenceIntegrity: true, instrumentedOperationsReleased: true, noPageErrors: true }, metrics: { pageErrors: [] } }] };
25 };
26 return { manifest, protocol, report, aggregate: reports => aggregateShards(reports, manifest, identity.sourceSHA) };
27 }
28
29 test("full screening preserves three independent complete shards", () => {
30 const { aggregate, report } = fixture("full");
31 const result = aggregate([report(3), report(1), report(2)]);
32 assert.equal(result.verdict, "PASS");
33 assert.equal(result.protocolComplete, true);
34 assert.equal(result.screeningLevel, "full");
35 assert.deepEqual(result.processes.map(run => run.process), [1, 2, 3]);
36 assert.ok(result.processes.every(run => run.attribution.reasons.includes("heap-retainer-and-control-evidence-required")));
37 });
38
39 test("short screening is one complete 32/128 shard and remains explicitly labeled", () => {
40 const { aggregate, report } = fixture("short");
41 assert.equal(completeShard(report(1)), true);
42 const result = aggregate([report(1)]);
43 assert.equal(result.verdict, "PASS");
44 assert.equal(result.screeningLevel, "short");
45 assert.equal(result.protocol.shards, 1);
46 assert.equal(result.processes.length, 1);
47 });
48
49 test("each profile rejects another profile's shard count and protocol", () => {
50 const full = fixture("full");
51 const short = fixture("short");
52 assert.throws(() => full.aggregate([full.report(1)]), /3 complete/);
53 assert.throws(() => short.aggregate([short.report(1), short.report(1)]), /1 complete/);
54 assert.throws(() => aggregateShards([short.report(1)], full.manifest, identity.sourceSHA));
55 assert.throws(() => memoryProtocol("unknown"), /unknown App memory profile/);
56 });
57
58 for (const [name, mutate] of [
59 ["duplicate shard", reports => { reports[2] = fixture("full").report(1); }],
60 ["different commit", reports => { reports[1].identity.sourceSHA = "b".repeat(40); }],
61 ["different build", reports => { reports[1].identity.buildSHA256 = "other-build"; }],
62 ["dirty source", reports => { reports[1].identity.sourceStatus = " M source.ts"; }],
63 ["another workflow attempt", reports => { reports[1].shard.executionId = "123:2"; }],
64 ["different fixture", reports => { reports[1].fixtures.windowed.label = "short-fixture"; }],
65 ["old protocol", reports => { reports[1].protocol.version = 3; }],
66 ["short cycles", reports => { reports[1].cycles = 127; }],
67 ["missing checkpoint", reports => { reports[1].processes[0].samples.splice(5, 1); }],
68 ["missing heap snapshot", reports => { reports[1].processes[0].snapshots.pop(); }],
69 ["different browser", reports => { reports[1].processes[0].browser = "another-browser"; }],
70 ["missing checks", reports => { reports[1].processes[0].checks = {}; }],
71 ["page error", reports => { reports[1].processes[0].metrics.pageErrors.push("boom"); }],
72 ["persistent DOM drift despite claimed pass", reports => { reports[1].processes[0].samples.at(-1).dom.nodes++; }],
73 ["unfinished operations despite claimed pass", reports => { reports[1].processes[0].samples.at(-1).lifecycle.activeOperations++; }],
74 ["missing token identity", reports => { delete reports[1].processes[0].samples[0].lifecycle.liveRenderTokenIds; }],
75 ]) test(`aggregate rejects ${name}`, () => {
76 const { aggregate, report } = fixture("full");
77 const reports = [report(1), report(2), report(3)];
78 mutate(reports);
79 assert.throws(() => aggregate(reports));
80 });
81
82 test("requested head and manifest protocol must match", () => {
83 const { manifest, report } = fixture("full");
84 assert.throws(() => aggregateShards([report(1), report(2), report(3)], manifest, "wrong-head"));
85 assert.throws(() => aggregateShards([report(1), report(2), report(3)], { ...manifest, protocol: { ...manifest.protocol, viewport: { width: 1, height: 1 } } }, identity.sourceSHA));
86 });
87
87 lines Plain Text