File
Blob: test/ofs-delta-converge.worker.test.ts
| 1 | import { it, expect } from "vitest"; |
| 2 | import { encodeOfsDeltaDistance } from "@/worker/git"; |
| 3 | |
| 4 | /** |
| 5 | * This is a logic-level test that simulates the header-length/offset |
| 6 | * recomputation loop used by the single-pack assembler for OFS_DELTA entries. |
| 7 | * |
| 8 | * It verifies that when a delta's relative distance crosses a varint length |
| 9 | * boundary due to offsets shifting, the iterative process converges to a |
| 10 | * stable set of header lengths and offsets within the iteration cap. |
| 11 | */ |
| 12 | it("ofs-delta header varint length converges when distances cross boundary", () => { |
| 13 | // Model three entries in order by original offsets: [base, delta] |
| 14 | // Entry 0: base (non-delta) |
| 15 | // Entry 1: OFS_DELTA referencing entry 0 |
| 16 | // Original offsets chosen so the initial guess uses a 1-byte ofs varint, |
| 17 | // but the recomputed new offsets increase the distance such that the ofs varint |
| 18 | // needs 2 bytes, forcing at least one iteration of recalculation. |
| 19 | |
| 20 | type Entry = { |
| 21 | type: number; // 1..7 (we use 1 for normal, 6 for OFS_DELTA) |
| 22 | baseIndex?: number; |
| 23 | payloadLen: number; |
| 24 | sizeVarBytesLen: number; |
| 25 | }; |
| 26 | |
| 27 | const entries: Entry[] = [ |
| 28 | { type: 1, payloadLen: 200, sizeVarBytesLen: 1 }, // base |
| 29 | { type: 6, baseIndex: 0, payloadLen: 10, sizeVarBytesLen: 1 }, // ofs-delta |
| 30 | ]; |
| 31 | |
| 32 | // Original offsets in the source pack (arbitrary but consistent) |
| 33 | // base at 100, delta at 140 -> original rel = 40 (1-byte ofs varint) |
| 34 | const origOffsets = [100, 140]; |
| 35 | |
| 36 | // Initial header-length guesses: for OFS delta, based on original rel distance |
| 37 | const newHeaderLen = new Map<number, number>(); |
| 38 | for (let i = 0; i < entries.length; i++) { |
| 39 | const e = entries[i]; |
| 40 | if (e.type === 6 && e.baseIndex !== undefined) { |
| 41 | const guessRel = origOffsets[i] - origOffsets[e.baseIndex]; |
| 42 | newHeaderLen.set(i, e.sizeVarBytesLen + encodeOfsDeltaDistance(guessRel).length); |
| 43 | } else if (e.type === 7) { |
| 44 | newHeaderLen.set(i, e.sizeVarBytesLen + 20); |
| 45 | } else { |
| 46 | newHeaderLen.set(i, e.sizeVarBytesLen); |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | // Iteratively recompute offsets and header lengths until convergence (cap 16) |
| 51 | let iter = 0; |
| 52 | let changed: boolean; |
| 53 | let newOffsets: Map<number, number> = new Map(); |
| 54 | do { |
| 55 | // Compute new offsets with current header-lengths |
| 56 | let cur = 12; // PACK header size |
| 57 | newOffsets = new Map<number, number>(); |
| 58 | for (let i = 0; i < entries.length; i++) { |
| 59 | newOffsets.set(i, cur); |
| 60 | cur += (newHeaderLen.get(i) || 0) + entries[i].payloadLen; |
| 61 | } |
| 62 | |
| 63 | // Re-evaluate OFS varints with accurate distances |
| 64 | changed = false; |
| 65 | for (let i = 0; i < entries.length; i++) { |
| 66 | const e = entries[i]; |
| 67 | if (e.type !== 6 || e.baseIndex === undefined) continue; |
| 68 | const rel = (newOffsets.get(i) || 0) - (newOffsets.get(e.baseIndex) || 0); |
| 69 | const desired = e.sizeVarBytesLen + encodeOfsDeltaDistance(rel).length; |
| 70 | if (desired !== newHeaderLen.get(i)) { |
| 71 | newHeaderLen.set(i, desired); |
| 72 | changed = true; |
| 73 | } |
| 74 | } |
| 75 | } while (changed && ++iter < 16); |
| 76 | |
| 77 | // Expectations: |
| 78 | // - We must have iterated at least once (varint length changed due to larger distance) |
| 79 | // - The delta's ofs varint length should now be 2 bytes (sizeVarBytesLen 1 + ofs 2 => header 3) |
| 80 | // - Subsequent recomputation would not change it further (converged) |
| 81 | expect(iter).toBeGreaterThanOrEqual(1); |
| 82 | const finalHeaderLenDelta = newHeaderLen.get(1)!; |
| 83 | expect(finalHeaderLenDelta).toBe(entries[1].sizeVarBytesLen + 2); |
| 84 | }); |