Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

51 lines · 2.2 KBRaw History
1import { createHash } from "node:crypto";
2import { describe, expect, it } from "vitest";
3import { Sha1, concat, deflate, packStream, parsePack, utf8, writePack, type PackEntryInput } from "../src/index.js";
4
5describe("streamed packs", () => {
6 it("incremental SHA-1 matches Node's for any split of the input", () => {
7 const data = new Uint8Array(1000).map((_, i) => (i * 31 + 7) & 0xff);
8 for (const len of [0, 1, 55, 56, 63, 64, 65, 119, 120, 1000]) {
9 const want = createHash("sha1").update(data.subarray(0, len)).digest();
10 for (const step of [1, 7, 64, 1000]) {
11 const h = new Sha1();
12 for (let i = 0; i < len; i += step) h.update(data.subarray(i, Math.min(len, i + step)));
13 expect(Buffer.from(h.digest()).equals(want)).toBe(true);
14 }
15 }
16 });
17
18 it("is byte for byte the pack writePack builds, and reads one entry at a time", async () => {
19 const entries: PackEntryInput[] = Array.from({ length: 50 }, (_, i) => {
20 const content = utf8(`blob ${i}\n`.repeat(i * 100 + 1));
21 return { type: "blob", size: content.length, deflated: deflate(content) };
22 });
23 let pulled = 0;
24 async function* source() {
25 for (const e of entries) {
26 pulled++;
27 yield e;
28 }
29 }
30 const parts: Uint8Array[] = [];
31 let mostAhead = 0;
32 for await (const part of packStream(entries.length, source())) {
33 parts.push(part);
34 // Each entry is two parts (its header, then its data): the stream never runs ahead of its reader.
35 mostAhead = Math.max(mostAhead, pulled - Math.floor(parts.length / 2));
36 }
37 expect(mostAhead).toBeLessThanOrEqual(1);
38 const streamed = concat(parts);
39 expect(streamed).toEqual(await writePack(entries));
40 expect(await parsePack(streamed)).toHaveLength(50);
41 });
42
43 it("refuses a source that doesn't match the announced count", async () => {
44 const one: PackEntryInput = { type: "blob", size: 1, deflated: deflate(utf8("x")) };
45 const run = async (n: number, items: PackEntryInput[]) => {
46 for await (const _ of packStream(n, (async function* () { yield* items; })())) void _;
47 };
48 await expect(run(2, [one])).rejects.toThrow(/announced 2 objects but has 1/);
49 await expect(run(1, [one, one])).rejects.toThrow(/more than the 1 objects/);
50 });
51});