import { describe, expect, it } from 'vitest'; import { decodeResult, digest, encodeResult } from '../src/sim/cache'; import type { SimResult } from '../src/sim/types'; describe('result cache encoding', () => { it('round-trips a result, optional arrays included', () => { const r: SimResult = { audio: new Float32Array([0.5, -1, 3]), fs: 48000, frames: new Float32Array(7).map((_, i) => i * 0.1), frameTimes: new Float64Array([0, 0.5]), energy: new Float64Array([1e-3, 2e-3]), balance: new Float64Array([0, 1e-12]), dt: 1e-6, stepsPerSample: 21, omegaMax: 12345.6, wallSeconds: 3.2, maxStretch: 0.01, contactForce: new Float32Array([0, 4, 2]), backend: 'CPU', }; const bytes = encodeResult(r); expect(bytes.length % 8).toBe(0); const back = decodeResult(bytes.buffer); expect(back).toEqual(r); expect(back.frameTimes).toBeInstanceOf(Float64Array); expect(back.malletPos).toBeUndefined(); }); it('hashes inputs canonically: key order does not matter, values and array types do', async () => { const a = await digest({ x: 1, arr: new Float64Array([1, 2]), y: undefined }); expect(await digest({ arr: new Float64Array([1, 2]), x: 1 })).toBe(a); expect(await digest({ x: 1, arr: new Float64Array([1, 2.0000001]) })).not.toBe(a); expect(await digest({ x: 1, arr: new Float32Array([1, 2]) })).not.toBe(a); expect(await digest({ x: 2, arr: new Float64Array([1, 2]) })).not.toBe(a); }); });