Files
2026-05-27 23:47:53 +01:00

96 lines
3.0 KiB
TypeScript

/**
* DMP-02 / DMP-07 — `kind:'whole'` returns capped chunk set; `maxChunks`
* default and enforcement.
*
* The codec does not "respond" to whole requests itself — that's the job
* of the request scheduler in `drive-mesh`. What the codec MUST enforce
* is that envelopes carrying `maxChunks > 1024` are rejected with
* `DMP.MAX_CHUNKS_EXCEEDED` so the scheduler never sees them. We
* separately exercise the caller-side cap with a tiny in-memory
* scheduler that proves the contract documented in DMP-02.
*/
import { describe, expect, it } from "@suaveplan/testing/runner";
import {
DMP_CODES,
DmpError,
encodeRequestPayload,
MAX_CHUNKS_DEFAULT,
MAX_CHUNKS_HARD_CAP,
selectWhole,
} from "../src/index.js";
import type { ChunkRequestPayload } from "../src/types/protocol.types.js";
const FILE_ID = "f".repeat(32);
/** Caller-side cap helper. The actual scheduler lives in drive-mesh. */
function answerWhole(
inventory: number[],
maxChunks: number = MAX_CHUNKS_DEFAULT
): number[] {
return [...inventory].sort((a, b) => a - b).slice(0, maxChunks);
}
describe("DMP-02 — kind:'whole' returns capped chunk set", () => {
it("whole-form request returns at most maxChunks chunks", {
timeout: 5000,
}, () => {
const inventory = Array.from({ length: 1000 }, (_, i) => i);
const out = answerWhole(inventory, 64);
expect(out.length).toBe(64);
expect(out[0]).toBe(0);
expect(out[63]).toBe(63);
});
it("whole-form returns ALL chunks when inventory < maxChunks", {
timeout: 5000,
}, () => {
const out = answerWhole([0, 5, 12], 64);
expect(out).toEqual([0, 5, 12]);
});
it("responder honors maxChunks", { timeout: 5000 }, () => {
const out = answerWhole(
Array.from({ length: 200 }, (_, i) => i),
50
);
expect(out.length).toBe(50);
});
});
describe("DMP-07 — maxChunks enforcement", () => {
it("default is 64", { timeout: 5000 }, () => {
expect(MAX_CHUNKS_DEFAULT).toBe(64);
});
it("hard cap is 1024", { timeout: 5000 }, () => {
expect(MAX_CHUNKS_HARD_CAP).toBe(1024);
});
it("maxChunks > 1024 rejected", { timeout: 5000 }, () => {
const payload: ChunkRequestPayload = {
fileId: FILE_ID,
request: selectWhole(),
priority: "normal",
maxChunks: 4096,
};
try {
encodeRequestPayload(payload);
throw new Error("expected cap rejection");
} catch (err) {
expect(err).toBeInstanceOf(DmpError);
expect((err as DmpError).code).toBe(DMP_CODES.MAX_CHUNKS_EXCEEDED);
}
});
it("maxChunks at exactly 1024 accepted", { timeout: 5000 }, () => {
const payload: ChunkRequestPayload = {
fileId: FILE_ID,
request: selectWhole(),
priority: "normal",
maxChunks: 1024,
};
expect(() => encodeRequestPayload(payload)).not.toThrow();
});
});