Files
suaveplan/packages/networking/drive/drive-mesh-protocol/tests/empty-specific-rejected.test.ts
2026-05-27 23:47:53 +01:00

81 lines
2.6 KiB
TypeScript

/**
* DMP-03 / DMP-22 — `kind:'specific'` with empty `chunkIds` is rejected.
*
* Empty-array semantics MUST NOT be a synonym for "everything". Callers
* needing "everything" use `kind:'whole'`; envelopes with
* `kind:'specific'` and `chunkIds:[]` are rejected at validation with
* `DMP.EMPTY_REQUEST`.
*/
import { describe, expect, it } from "@suaveplan/testing/runner";
import {
DMP_CODES,
DmpError,
decodeRequestPayload,
encodeRequestPayload,
selectForm,
} from "../src/index.js";
const FILE_ID = "1".repeat(32);
describe("DMP-03 — kind:'specific' rejects empty array", () => {
it("kind:specific with empty chunkIds is rejected", {
timeout: 5000,
}, () => {
try {
encodeRequestPayload({
fileId: FILE_ID,
request: { kind: "specific", chunkIds: [] },
priority: "normal",
});
throw new Error("expected EMPTY_REQUEST");
} catch (err) {
expect(err).toBeInstanceOf(DmpError);
expect([
DMP_CODES.EMPTY_REQUEST,
DMP_CODES.ENVELOPE_MALFORMED,
]).toContain((err as DmpError).code);
}
});
it("selectForm([]) throws EMPTY_REQUEST without producing an envelope", {
timeout: 5000,
}, () => {
try {
selectForm([]);
throw new Error("expected EMPTY_REQUEST");
} catch (err) {
expect(err).toBeInstanceOf(DmpError);
expect((err as DmpError).code).toBe(DMP_CODES.EMPTY_REQUEST);
}
});
});
describe("DMP-22 — empty kind:'specific' rejection at decode", () => {
it("specific with empty chunkIds rejected at validation", {
timeout: 5000,
}, () => {
// Synthesise a wire envelope manually so we can carry an empty
// chunkIds array past the encoder's gate.
const wire = new TextEncoder().encode(
JSON.stringify({
fileId: FILE_ID,
request: { kind: "specific", chunkIds: [] },
priority: "normal",
})
);
try {
decodeRequestPayload(wire);
throw new Error("expected rejection");
} catch (err) {
expect(err).toBeInstanceOf(DmpError);
// Either schema rejects (chunkIds must be non-empty) or the
// explicit EMPTY_REQUEST gate fires — both satisfy DMP-22.
expect([
DMP_CODES.EMPTY_REQUEST,
DMP_CODES.ENVELOPE_MALFORMED,
]).toContain((err as DmpError).code);
}
});
});