Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
import { describe, expect, it } from "@suaveplan/testing/runner";
import { CHUNKS_CODES } from "../error-codes.js";
import { encodeChunk, parseChunk, validateChunk } from "./chunk.js";
describe("CHUNKS-FORMAT-V1-01 — Chunk binary layout is byte-exact", () => {
it("round-trips every field at exact offsets", { timeout: 5000 }, () => {
const metadata = {
version: 0x0001,
fileId: new Uint8Array(32).fill(0xab),
chunkId: 7,
totalChunks: 10,
fileSize: 12345n,
chunkSize: 65536,
payloadLen: 100,
flags: 0x0000,
nonce: new Uint8Array(24).fill(0xcd),
aeadTag: new Uint8Array(16).fill(0xef),
};
const sig = new Uint8Array(64).fill(0x12);
const ciphertext = new Uint8Array(100).fill(0x34);
const encoded = encodeChunk({ metadata, sig, ciphertext });
expect(encoded.length).toBe(164 + 100);
const view = new DataView(encoded.buffer, encoded.byteOffset);
expect(view.getUint16(0, false)).toBe(0x0001);
expect(encoded.slice(2, 34)).toEqual(metadata.fileId);
expect(view.getUint32(34, false)).toBe(7);
expect(view.getUint32(38, false)).toBe(10);
expect(view.getBigUint64(42, false)).toBe(12345n);
expect(view.getUint32(50, false)).toBe(65536);
expect(view.getUint32(54, false)).toBe(100);
expect(view.getUint16(58, false)).toBe(0x0000);
expect(encoded.slice(60, 84)).toEqual(metadata.nonce);
expect(encoded.slice(84, 100)).toEqual(metadata.aeadTag);
expect(encoded.slice(100, 164)).toEqual(sig);
expect(encoded.slice(164)).toEqual(ciphertext);
const parsed = parseChunk(encoded);
expect(parsed.metadata.version).toBe(0x0001);
expect(parsed.metadata.chunkId).toBe(7);
expect(parsed.metadata.payloadLen).toBe(100);
expect(parsed.sig).toEqual(sig);
expect(parsed.ciphertext).toEqual(ciphertext);
});
});
describe("CHUNKS-FORMAT-V1-02 — flags reserved in v1", () => {
it("rejects non-zero flags", { timeout: 5000 }, () => {
const metadata = {
version: 0x0001,
fileId: new Uint8Array(32),
chunkId: 0,
totalChunks: 1,
fileSize: 1n,
chunkSize: 65536,
payloadLen: 1,
flags: 0x0001,
nonce: new Uint8Array(24),
aeadTag: new Uint8Array(16),
};
const chunk = {
metadata,
sig: new Uint8Array(64),
ciphertext: new Uint8Array(1),
};
expect(() => validateChunk(chunk)).toThrow();
try {
validateChunk(chunk);
} catch (e) {
expect((e as Error).code).toBe(CHUNKS_CODES.FLAGS_RESERVED_NONZERO);
}
});
});
describe("CHUNKS-FORMAT-V1-03 — Payload length invariants", () => {
it("rejects non-final chunk payloadLen mismatch", { timeout: 5000 }, () => {
const metadata = {
version: 0x0001,
fileId: new Uint8Array(32),
chunkId: 0,
totalChunks: 2,
fileSize: 100000n,
chunkSize: 65536,
payloadLen: 100,
flags: 0x0000,
nonce: new Uint8Array(24),
aeadTag: new Uint8Array(16),
};
const chunk = {
metadata,
sig: new Uint8Array(64),
ciphertext: new Uint8Array(100),
};
expect(() => validateChunk(chunk)).toThrow();
try {
validateChunk(chunk);
} catch (e) {
expect((e as Error).code).toBe(CHUNKS_CODES.PAYLOAD_LEN_INVALID);
}
});
it("accepts correct non-final payloadLen", { timeout: 5000 }, () => {
const metadata = {
version: 0x0001,
fileId: new Uint8Array(32),
chunkId: 0,
totalChunks: 2,
fileSize: 100000n,
chunkSize: 65536,
payloadLen: 65536 - 164,
flags: 0x0000,
nonce: new Uint8Array(24),
aeadTag: new Uint8Array(16),
};
const chunk = {
metadata,
sig: new Uint8Array(64),
ciphertext: new Uint8Array(65536 - 164),
};
expect(() => validateChunk(chunk)).not.toThrow();
});
it("rejects final chunk payloadLen mismatch", { timeout: 5000 }, () => {
const metadata = {
version: 0x0001,
fileId: new Uint8Array(32),
chunkId: 1,
totalChunks: 2,
fileSize: 500n,
chunkSize: 65536,
payloadLen: 100,
flags: 0x0000,
nonce: new Uint8Array(24),
aeadTag: new Uint8Array(16),
};
const chunk = {
metadata,
sig: new Uint8Array(64),
ciphertext: new Uint8Array(100),
};
expect(() => validateChunk(chunk)).toThrow();
try {
validateChunk(chunk);
} catch (e) {
expect((e as Error).code).toBe(CHUNKS_CODES.PAYLOAD_LEN_INVALID);
}
});
});
describe("CHUNKS-FORMAT-V1-04 — parseChunk edge cases", () => {
it("rejects chunk shorter than header", { timeout: 5000 }, () => {
expect(() => parseChunk(new Uint8Array(10))).toThrow();
try {
parseChunk(new Uint8Array(10));
} catch (e) {
expect((e as Error).code).toBe(CHUNKS_CODES.METADATA_INVALID);
}
});
it("rejects unsupported chunk version", { timeout: 5000 }, () => {
const metadata = {
version: 0x0002,
fileId: new Uint8Array(32),
chunkId: 0,
totalChunks: 1,
fileSize: 1n,
chunkSize: 65536,
payloadLen: 1,
flags: 0x0000,
nonce: new Uint8Array(24),
aeadTag: new Uint8Array(16),
};
const chunk = {
metadata,
sig: new Uint8Array(64),
ciphertext: new Uint8Array(1),
};
expect(() => validateChunk(chunk)).toThrow();
try {
validateChunk(chunk);
} catch (e) {
expect((e as Error).code).toBe(CHUNKS_CODES.VERSION_UNSUPPORTED);
}
});
});