Initial Commit
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user