Files
openclaw/src/agents/stable-stringify.test.ts
Gabriel 53fedc7084 refactor: unify stableStringify implementations (#80457)
Centralize agent stable serialization for cache tracing, models config fingerprinting, and tool-loop hashing.

Adds focused coverage for sorted keys, true cycles, repeated references, cache-trace edge types, and circular tool-call hashing.

Verification:
- pnpm test src/agents/stable-stringify.test.ts src/agents/tool-loop-detection.test.ts src/agents/cache-trace.test.ts -- --reporter=verbose
- OPENCLAW_TESTBOX=0 pnpm check:changed
- GitHub CI: https://github.com/openclaw/openclaw/actions/runs/25716851500
- Real behavior proof: https://github.com/openclaw/openclaw/actions/runs/25717047037

Co-authored-by: Gabriel Piss <gabriel@gabeos.dev>
2026-05-12 07:18:53 +01:00

47 lines
1.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { stableStringify } from "./stable-stringify.js";
describe("stableStringify", () => {
it("sorts object keys recursively", () => {
expect(stableStringify({ b: { d: 4, c: 3 }, a: 1 })).toBe('{"a":1,"b":{"c":3,"d":4}}');
});
it("marks true circular references without collapsing repeated references", () => {
const shared = { value: 1 };
const root: Record<string, unknown> = { first: shared, second: shared };
root.self = root;
expect(stableStringify(root)).toBe(
'{"first":{"value":1},"second":{"value":1},"self":"[Circular]"}',
);
});
it("handles circular arrays without treating later siblings as circular", () => {
const shared = { value: "same" };
const items: unknown[] = [shared, shared];
items.push(items);
expect(stableStringify(items)).toBe('[{"value":"same"},{"value":"same"},"[Circular]"]');
});
it("serializes cache-trace edge types deterministically", () => {
const error = new Error("boom");
error.stack = "Error: boom\n at test";
expect(
stableStringify({
bytes: new Uint8Array([1, 2, 3]),
error,
finite: 1,
infinity: Infinity,
nan: Number.NaN,
nil: null,
token: 123n,
undef: undefined,
}),
).toBe(
'{"bytes":{"data":"AQID","type":"Uint8Array"},"error":{"message":"boom","name":"Error","stack":"Error: boom\\n at test"},"finite":1,"infinity":"Infinity","nan":"NaN","nil":null,"token":"123","undef":undefined}',
);
});
});