Squashed 'third_party/pi/' content from commit d981de122

git-subtree-dir: third_party/pi
git-subtree-split: d981de1229ef899957bbe968bc8dcda02a21f477
This commit is contained in:
2026-09-14 10:40:08 -04:00
commit 67b361f0e9
1669 changed files with 397627 additions and 0 deletions

View File

@@ -0,0 +1,175 @@
import { describe, expect, test } from "vitest";
import {
CborError,
DEFAULT_MAX_CBOR_BYTE_LENGTH,
DEFAULT_MAX_CBOR_CONTAINER_LENGTH,
DEFAULT_MAX_CBOR_DEPTH,
decodeCbor,
encodeCbor,
} from "../../src/index.ts";
function fromHex(hex: string): Uint8Array {
if (hex.length % 2 !== 0) throw new Error("Hex fixture must contain whole bytes");
const bytes = new Uint8Array(hex.length / 2);
for (let index = 0; index < bytes.length; index++)
bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
return bytes;
}
function toHex(bytes: Uint8Array): string {
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
}
const knownVectors: ReadonlyArray<readonly [unknown, string]> = [
[null, "f6"],
[false, "f4"],
[true, "f5"],
[0, "00"],
[1, "01"],
[10, "0a"],
[23, "17"],
[24, "1818"],
[25, "1819"],
[100, "1864"],
[1000, "1903e8"],
[1_000_000, "1a000f4240"],
[1_000_000_000_000, "1b000000e8d4a51000"],
[Number.MAX_SAFE_INTEGER, "1b001fffffffffffff"],
[-1, "20"],
[-10, "29"],
[-24, "37"],
[-25, "3818"],
[-100, "3863"],
[-1000, "3903e7"],
[-1_000_000, "3a000f423f"],
[Number.MIN_SAFE_INTEGER, "3b001ffffffffffffe"],
[1.1, "fb3ff199999999999a"],
[-0, "fb8000000000000000"],
[new Uint8Array([1, 2, 3, 4]), "4401020304"],
["", "60"],
["IETF", "6449455446"],
["ü", "62c3bc"],
["水", "63e6b0b4"],
["𐅑", "64f0908591"],
[[], "80"],
[[1, 2, 3], "83010203"],
[[1, [2, 3], [4, 5]], "8301820203820405"],
[{ a: 1, b: [2, 3] }, "a26161016162820203"],
];
describe("CBOR codec", () => {
test.each(knownVectors)("encodes and decodes RFC 8949 vector %#", (value, wire) => {
const encoded = encodeCbor(value);
expect(toHex(encoded)).toBe(wire);
const decoded = decodeCbor(fromHex(wire));
if (typeof value === "number" && Object.is(value, -0)) expect(Object.is(decoded, -0)).toBe(true);
else expect(decoded).toEqual(value);
});
test("omits undefined object properties without omitting falsey values", () => {
const value = { omitted: undefined, zero: 0, empty: "", no: false, nil: null };
expect(decodeCbor(encodeCbor(value))).toEqual({ zero: 0, empty: "", no: false, nil: null });
});
test("preserves a leading Unicode BOM and treats __proto__ as data", () => {
expect(decodeCbor(fromHex("63efbbbf"))).toBe("\ufeff");
const value: Record<string, unknown> = {};
Object.defineProperty(value, "__proto__", { enumerable: true, value: "safe" });
const decoded = decodeCbor(encodeCbor(value));
expect(decoded).toEqual(value);
expect(Object.getPrototypeOf(decoded)).toBe(Object.prototype);
expect(Object.hasOwn(decoded as object, "__proto__")).toBe(true);
});
test.each([
["top-level undefined", undefined],
["undefined array element", [undefined]],
["array hole", new Array(1)],
["NaN", Number.NaN],
["positive infinity", Number.POSITIVE_INFINITY],
["negative infinity", Number.NEGATIVE_INFINITY],
["unsafe positive integer", Number.MAX_SAFE_INTEGER + 1],
["unsafe negative integer", Number.MIN_SAFE_INTEGER - 1],
["bigint", 1n],
["symbol", Symbol("unsupported")],
["function", () => undefined],
["Date", new Date(0)],
["Map", new Map<string, unknown>()],
] as const)("rejects unsupported encoder value: %s", (_label, value) => {
expect(() => encodeCbor(value)).toThrow(CborError);
});
test("rejects maps with enumerable symbol keys", () => {
const value = { valid: true };
Object.defineProperty(value, Symbol("key"), { enumerable: true, value: false });
expect(() => encodeCbor(value)).toThrow(CborError);
});
test("rejects lossy strings, cycles, and excessive encoder depth", () => {
expect(() => encodeCbor("\ud800")).toThrow(/Unicode/i);
const cyclic: unknown[] = [];
cyclic.push(cyclic);
expect(() => encodeCbor(cyclic)).toThrow(/cycles/i);
let tooDeep: unknown = null;
for (let depth = 0; depth <= DEFAULT_MAX_CBOR_DEPTH; depth++) tooDeep = [tooDeep];
expect(() => encodeCbor(tooDeep)).toThrow(/depth/i);
});
test.each([
["empty input", ""],
["truncated integer", "18"],
["reserved additional information", "1c"],
["indefinite byte string", "5f"],
["indefinite text string", "7f"],
["indefinite array", "9f"],
["indefinite map", "bf"],
["tag", "c000"],
["undefined", "f7"],
["unsupported simple value", "e0"],
["break outside an indefinite item", "ff"],
["float16", "f93c00"],
["float32", "fa3f800000"],
["positive infinity", "fb7ff0000000000000"],
["NaN", "fb7ff8000000000000"],
["truncated float64", "fb3ff00000"],
["truncated byte string", "44010203"],
["truncated text string", "636162"],
["truncated array", "8201"],
["truncated map", "a16161"],
["trailing data", "0000"],
["non-string map key", "a10102"],
["duplicate map key", "a2616101616102"],
["invalid UTF-8 byte", "61ff"],
["overlong UTF-8", "62c080"],
["UTF-8 surrogate", "63eda080"],
["unsafe positive integer", "1b0020000000000000"],
["unsafe negative integer", "3b001fffffffffffff"],
["unsafe integer encoded as float64", "fb4340000000000000"],
] as const)("rejects invalid decoder input: %s", (_label, wire) => {
expect(() => decodeCbor(fromHex(wire))).toThrow(CborError);
});
test("enforces depth and declared length limits before traversing values", () => {
const tooDeep = new Uint8Array(DEFAULT_MAX_CBOR_DEPTH + 2);
tooDeep.fill(0x81, 0, -1);
tooDeep[tooDeep.length - 1] = 0xf6;
expect(() => decodeCbor(tooDeep)).toThrow(/depth/i);
const oversizedBytes = fromHex(`5a${(DEFAULT_MAX_CBOR_BYTE_LENGTH + 1).toString(16).padStart(8, "0")}`);
const oversizedText = fromHex(`7a${(DEFAULT_MAX_CBOR_BYTE_LENGTH + 1).toString(16).padStart(8, "0")}`);
const oversizedArray = fromHex(`9a${(DEFAULT_MAX_CBOR_CONTAINER_LENGTH + 1).toString(16).padStart(8, "0")}`);
const oversizedMap = fromHex(`ba${(DEFAULT_MAX_CBOR_CONTAINER_LENGTH + 1).toString(16).padStart(8, "0")}`);
for (const wire of [oversizedBytes, oversizedText, oversizedArray, oversizedMap]) {
expect(() => decodeCbor(wire)).toThrow(/limit/i);
}
});
test("supports stricter caller-provided limits", () => {
expect(() => decodeCbor(fromHex("83010203"), { maxContainerLength: 2 })).toThrow(/limit/i);
expect(() => decodeCbor(fromHex("626162"), { maxByteLength: 2 })).toThrow(/limit/i);
expect(() => encodeCbor([1, 2, 3], { maxContainerLength: 2 })).toThrow(/limit/i);
expect(() => encodeCbor("ab", { maxByteLength: 2 })).toThrow(/limit/i);
});
});

View File

@@ -0,0 +1,110 @@
import { describe, expect, test } from "vitest";
import { DEFAULT_MAX_FRAME_LENGTH, encodeFrame, FrameDecoder, FrameError } from "../src/index.ts";
function concatenate(...chunks: Uint8Array[]): Uint8Array {
const result = new Uint8Array(chunks.reduce((length, chunk) => length + chunk.byteLength, 0));
let offset = 0;
for (const chunk of chunks) {
result.set(chunk, offset);
offset += chunk.byteLength;
}
return result;
}
describe("binary framing", () => {
test("prefixes payloads with a four-byte big-endian length", () => {
expect(encodeFrame(new Uint8Array([0xaa, 0xbb, 0xcc]))).toEqual(
new Uint8Array([0x00, 0x00, 0x00, 0x03, 0xaa, 0xbb, 0xcc]),
);
expect(encodeFrame(new Uint8Array())).toEqual(new Uint8Array([0, 0, 0, 0]));
});
test("decodes fragmented, coalesced, and empty frames in order", () => {
const wire = concatenate(
encodeFrame(new Uint8Array([1, 2, 3])),
encodeFrame(new Uint8Array()),
encodeFrame(new Uint8Array([4])),
);
const decoder = new FrameDecoder();
const frames: Uint8Array[] = [];
for (const byte of wire) frames.push(...decoder.push(new Uint8Array([byte])));
decoder.end();
expect(frames).toEqual([new Uint8Array([1, 2, 3]), new Uint8Array(), new Uint8Array([4])]);
const coalesced = new FrameDecoder();
expect(coalesced.push(wire)).toEqual(frames);
coalesced.end();
});
test("assembles payloads spanning multiple internal blocks", () => {
const payload = Uint8Array.from({ length: 70_000 }, (_, index) => index % 251);
const wire = encodeFrame(payload);
const decoder = new FrameDecoder();
const frames = [
...decoder.push(wire.subarray(0, 101)),
...decoder.push(wire.subarray(101, 65_541)),
...decoder.push(wire.subarray(65_541)),
];
decoder.end();
expect(frames).toEqual([payload]);
});
test("handles every split point across a frame", () => {
const wire = encodeFrame(new Uint8Array([10, 20, 30, 40]));
for (let split = 0; split <= wire.byteLength; split++) {
const decoder = new FrameDecoder();
const frames = [...decoder.push(wire.subarray(0, split)), ...decoder.push(wire.subarray(split))];
decoder.end();
expect(frames).toEqual([new Uint8Array([10, 20, 30, 40])]);
}
});
test("copies payload bytes instead of retaining or aliasing input chunks", () => {
const chunk = encodeFrame(new Uint8Array([1, 2, 3]));
const decoder = new FrameDecoder();
const frames = decoder.push(chunk);
chunk.fill(9);
expect(frames).toEqual([new Uint8Array([1, 2, 3])]);
});
test("accepts empty chunks and a clean empty stream", () => {
const decoder = new FrameDecoder();
expect(decoder.push(new Uint8Array())).toEqual([]);
expect(() => decoder.end()).not.toThrow();
});
test.each([
["partial header", new Uint8Array([0, 0, 0])],
["partial payload", new Uint8Array([0, 0, 0, 2, 1])],
] as const)("rejects a truncated stream at end: %s", (_label, wire) => {
const decoder = new FrameDecoder();
expect(decoder.push(wire)).toEqual([]);
expect(() => decoder.end()).toThrow(FrameError);
});
test("rejects an oversized declared length as soon as its header is complete", () => {
const decoder = new FrameDecoder({ maxFrameLength: 3 });
expect(() => decoder.push(new Uint8Array([0, 0, 0, 4]))).toThrow(/limit/i);
expect(() => decoder.push(new Uint8Array([1]))).toThrow(/failed/i);
});
test("accepts a frame exactly at the configured maximum", () => {
const decoder = new FrameDecoder({ maxFrameLength: 3 });
expect(decoder.push(encodeFrame(new Uint8Array([1, 2, 3])))).toEqual([new Uint8Array([1, 2, 3])]);
decoder.end();
});
test("cannot be pushed after end", () => {
const decoder = new FrameDecoder();
decoder.end();
expect(() => decoder.push(new Uint8Array())).toThrow(/ended/i);
expect(() => decoder.end()).toThrow(/ended/i);
});
test.each([-1, 1.5, Number.NaN, DEFAULT_MAX_FRAME_LENGTH * 1_000])(
"rejects invalid maximum frame length: %s",
(maxFrameLength) => {
expect(() => new FrameDecoder({ maxFrameLength })).toThrow(RangeError);
},
);
});

View File

@@ -0,0 +1,282 @@
import { describe, expect, test } from "vitest";
import {
type ClientHello,
type ClientMessage,
ClientMessageDecoder,
decodeCbor,
encodeCbor,
encodeClientMessage,
encodeFrame,
encodeServerMessage,
FrameDecoder,
isSupportedProtocolVersion,
PROTOCOL_VERSION,
ProtocolValidationError,
parseClientMessage,
parseServerMessage,
type ServerHello,
type ServerMessage,
ServerMessageDecoder,
} from "../src/index.ts";
const clientHello: ClientHello = { type: "hello", version: PROTOCOL_VERSION };
const serverHello: ServerHello = {
type: "hello",
version: PROTOCOL_VERSION,
serverId: "00000000-0000-4000-8000-000000000001",
};
describe("protocol validation", () => {
test("negotiates protocol version 8", () => {
expect(PROTOCOL_VERSION).toBe(8);
expect(isSupportedProtocolVersion(8)).toBe(true);
expect(isSupportedProtocolVersion(7)).toBe(false);
expect(isSupportedProtocolVersion(8.5)).toBe(false);
});
test.each([0, PROTOCOL_VERSION, PROTOCOL_VERSION + 1])(
"accepts integer client hello version %s for negotiation",
(version) => expect(parseClientMessage({ ...clientHello, version })).toEqual({ ...clientHello, version }),
);
test.each([
{ type: "hello", version: String(PROTOCOL_VERSION) },
{ type: "hello", version: PROTOCOL_VERSION + 0.5 },
{ type: "hello", version: PROTOCOL_VERSION, extra: true },
])("rejects an invalid client hello", (message) => {
expect(() => parseClientMessage(message)).toThrow(ProtocolValidationError);
});
test.each([
"",
"server-1",
"00000000-0000-7000-8000-000000000001",
"00000000-0000-4000-7000-000000000001",
"00000000-0000-4000-8000-00000000000A",
])("rejects non-canonical UUIDv4 server ID %j", (serverId) => {
expect(() =>
parseClientMessage({
type: "request",
id: "request-1",
target: { serverId },
call: { serviceId: "pi.models", member: "list", args: [] },
}),
).toThrow(ProtocolValidationError);
});
test("keeps routed request and event payloads opaque", () => {
const request: ClientMessage = {
type: "request",
id: "request-1",
target: {
serverId: "00000000-0000-4000-8000-000000000001",
sessionId: "session-1",
attachmentId: "attachment-1",
},
call: {
serviceId: "application.custom",
instance: { key: "instance-1", generation: 2 },
member: "invoke",
args: [{ arbitrary: true }, ["opaque"]],
},
};
expect(parseClientMessage(request)).toEqual(request);
expect(
parseClientMessage({
...request,
call: { arbitrary: "strict JSON whose service meaning belongs to Chord" },
}),
).toMatchObject({ call: { arbitrary: expect.any(String) } });
expect(
parseServerMessage({
type: "service_update",
subscriptionId: "subscription-1",
update: { applicationDefined: true },
}),
).toMatchObject({ update: { applicationDefined: true } });
});
test("rejects non-JSON opaque payloads", () => {
const request = {
type: "request",
id: "request-1",
target: { serverId: "00000000-0000-4000-8000-000000000001" },
call: { serviceId: "application.custom", member: "invoke", args: [] },
};
const cyclic: { self?: unknown } = {};
cyclic.self = cyclic;
for (const [label, value] of [
["byte array", new Uint8Array([1])],
["non-finite number", Number.NaN],
["undefined property", { value: undefined }],
["cycle", cyclic],
] as const) {
expect(() => parseClientMessage({ ...request, call: { ...request.call, args: [value] } }), label).toThrow(
ProtocolValidationError,
);
expect(
() => parseServerMessage({ type: "response", id: "request-1", ok: true, result: value }),
label,
).toThrow(ProtocolValidationError);
}
});
test("validates request cancellation envelopes", () => {
const cancel: ClientMessage = {
type: "cancel",
id: "request-1",
target: { serverId: "00000000-0000-4000-8000-000000000001" },
};
expect(parseClientMessage(cancel)).toEqual(cancel);
expect(() => parseClientMessage({ ...cancel, id: "" })).toThrow(ProtocolValidationError);
expect(() => parseClientMessage({ ...cancel, extra: true })).toThrow(ProtocolValidationError);
});
test("validates attachment route updates", () => {
const attached: ServerMessage = {
type: "attachment",
attachment: {
serverId: "00000000-0000-4000-8000-000000000001",
sessionId: "session-1",
attachmentId: "attachment-1",
},
};
const detached: ServerMessage = { type: "attachment", attachment: null };
expect(parseServerMessage(attached)).toEqual(attached);
expect(parseServerMessage(detached)).toEqual(detached);
expect(() => parseServerMessage({ ...attached, attachment: { sessionId: "session-1" } })).toThrow(
ProtocolValidationError,
);
});
test.each([
[
"empty request id",
{
type: "request",
id: "",
target: { serverId: "00000000-0000-4000-8000-000000000001" },
call: { serviceId: "pi.models", member: "list", args: [] },
},
],
[
"extra envelope field",
{
type: "request",
id: "request-1",
target: { serverId: "00000000-0000-4000-8000-000000000001" },
call: { serviceId: "pi.models", member: "list", args: [] },
extra: true,
},
],
] as const)("rejects malformed request boundaries: %s", (_label, message) => {
expect(() => parseClientMessage(message)).toThrow(ProtocolValidationError);
});
test("accepts a successful void response without a result field", () => {
expect(parseServerMessage({ type: "response", id: "request-1", ok: true })).toEqual({
type: "response",
id: "request-1",
ok: true,
});
});
test.each([
["invalid server id", { ...serverHello, serverId: "server-1" }],
["extra response field", { type: "response", id: "request-1", ok: true, result: [], extra: true }],
["empty error code", { type: "response", id: "request-1", ok: false, error: { code: "", message: "bad" } }],
] as const)("rejects malformed server boundaries: %s", (_label, message) => {
expect(() => parseServerMessage(message)).toThrow(ProtocolValidationError);
});
test.each(["wrong_server", "cancelled", "service_not_found", "application_error"] as const)(
"accepts the opaque %s error code",
(code) => {
const message: ServerMessage = {
type: "response",
id: "request-1",
ok: false,
error: { code, message: "safe" },
};
expect(parseServerMessage(message)).toEqual(message);
},
);
test("rejects unknown messages and fields", () => {
expect(() => parseServerMessage({ ...serverHello, snapshot: {} })).toThrow(ProtocolValidationError);
expect(() => parseServerMessage({ type: "unknown", event: {} })).toThrow(ProtocolValidationError);
});
test("does not parse JSON strings as messages", () => {
expect(() => parseClientMessage(JSON.stringify(clientHello))).toThrow(ProtocolValidationError);
expect(() => parseServerMessage(JSON.stringify(serverHello))).toThrow(ProtocolValidationError);
});
});
describe("validated framed protocol APIs", () => {
test("encodes complete client and server frames", () => {
const clientFrames = new FrameDecoder().push(encodeClientMessage(clientHello));
expect(parseClientMessage(decodeCbor(clientFrames[0]!))).toEqual(clientHello);
const serverFrames = new FrameDecoder().push(encodeServerMessage(serverHello));
expect(parseServerMessage(decodeCbor(serverFrames[0]!))).toEqual(serverHello);
});
test("enforces outbound frame limits", () => {
expect(() => encodeClientMessage(clientHello, { maxFrameLength: 8 })).toThrow(ProtocolValidationError);
expect(() => encodeServerMessage(serverHello, { maxFrameLength: 8 })).toThrow(ProtocolValidationError);
});
test("incrementally decodes fragmented and coalesced client messages", () => {
const request: ClientMessage = {
type: "request",
id: "request-1",
target: { serverId: "00000000-0000-4000-8000-000000000001" },
call: { serviceId: "pi.session-directory", member: "list", args: [] },
};
const first = encodeClientMessage(clientHello);
const second = encodeClientMessage(request);
const wire = new Uint8Array(first.byteLength + second.byteLength);
wire.set(first);
wire.set(second, first.byteLength);
for (let split = 0; split <= wire.byteLength; split++) {
const decoder = new ClientMessageDecoder();
const messages = [...decoder.push(wire.subarray(0, split)), ...decoder.push(wire.subarray(split))];
decoder.end();
expect(messages).toEqual([clientHello, request]);
}
});
test("incrementally decodes fragmented and coalesced server messages", () => {
const response: ServerMessage = { type: "response", id: "request-1", ok: true, result: [] };
const first = encodeServerMessage(serverHello);
const second = encodeServerMessage(response);
const wire = new Uint8Array(first.byteLength + second.byteLength);
wire.set(first);
wire.set(second, first.byteLength);
const split = first.byteLength + Math.floor(second.byteLength / 2);
const decoder = new ServerMessageDecoder();
expect(decoder.push(wire.subarray(0, split))).toEqual([serverHello]);
expect(decoder.push(wire.subarray(split))).toEqual([response]);
decoder.end();
});
test.each([
["empty CBOR payload", encodeFrame(new Uint8Array())],
["malformed CBOR", encodeFrame(new Uint8Array([0xff]))],
["schema-invalid CBOR", encodeFrame(encodeCbor({ type: "hello", version: 1, extra: true }))],
] as const)("rejects invalid framed input: %s", (_label, wire) => {
const decoder = new ClientMessageDecoder();
expect(() => decoder.push(wire)).toThrow(ProtocolValidationError);
expect(() => decoder.push(encodeClientMessage(clientHello))).toThrow(/failed/i);
});
test("rejects truncated and oversized framing", () => {
const truncated = new ServerMessageDecoder();
expect(truncated.push(new Uint8Array([0, 0, 0, 2, 1]))).toEqual([]);
expect(() => truncated.end()).toThrow(ProtocolValidationError);
const oversized = new ClientMessageDecoder({ maxFrameLength: 3 });
expect(() => oversized.push(new Uint8Array([0, 0, 0, 4]))).toThrow(ProtocolValidationError);
});
});