open-standards/joule-code/joule-code-rs/crates/joule-moq-web/web/moq/capsule.test.mjs
Transaction Science f396180b4d joule-moq-web: the browser client, its test pages and its end-to-end harness
web/moq: the WebSocket binding's capsules, WebTransport and the binding behind one
transport interface (WebTransport first, offering moqt-22 and the relay's certificate
hash; the binding as the fallback, or forced), a MOQT session (SETUP with the token,
requests, every data stream read concurrently, GOAWAY), and the payload framings a WAI
track carries. web/room: the room client (WebCodecs publishing with receipts, verified
subscriptions, a late joiner's FETCH, the composed canvas and the mixed AudioWorklet,
the events timeline and captions with their origin, the move after GOAWAY). web/compose:
the composition corpus in the page. e2e: the relay on loopback from a test
configuration, real Chrome through Playwright with a fake camera and microphone, each
browser under memguard.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 13:44:37 -04:00

55 lines
2.8 KiB
JavaScript

// The WebSocket binding's capsules against the bytes joule-moq-relay's README states
// (`node --test web/moq/capsule.test.mjs`).
import test from "node:test";
import assert from "node:assert/strict";
import * as cap from "./capsule.js";
const bytes = (s) => Uint8Array.from(s.trim().split(/\s+/).map((x) => parseInt(x, 16)));
test("the relay's first capsules are its stream credit", () => {
assert.deepEqual(cap.maxStreamsCapsule(true, 256), bytes("99 0b 4d 3f 02 41 00"));
assert.deepEqual(cap.maxStreamsCapsule(false, 1024), bytes("99 0b 4d 40 02 44 00"));
assert.deepEqual(cap.decodeCapsule(bytes("99 0b 4d 3f 02 41 00")), { kind: "max_streams", bidi: true, max: 256 });
assert.deepEqual(cap.decodeCapsule(bytes("99 0b 4d 40 02 44 00")), { kind: "max_streams", bidi: false, max: 1024 });
});
test("a session closed at the GOAWAY timeout", () => {
const b = bytes("68 43 12 00 00 00 10 47 4f 41 57 41 59 20 74 69 6d 65 6f 75 74");
assert.deepEqual(cap.decodeCapsule(b), { kind: "close", code: 0x10, message: "GOAWAY timeout" });
assert.deepEqual(cap.closeSessionCapsule(0x10, "GOAWAY timeout"), b);
});
test("stream data, FIN, reset and stop round-trip", () => {
const d = new TextEncoder().encode("moqt");
for (const fin of [false, true]) {
const c = cap.decodeCapsule(cap.streamCapsule(6, d, fin));
assert.equal(c.kind, "stream");
assert.equal(c.id, 6);
assert.equal(c.fin, fin);
assert.deepEqual(c.data, d);
}
assert.deepEqual(cap.decodeCapsule(cap.resetStreamCapsule(3, 2)), { kind: "reset", id: 3, code: 2 });
assert.deepEqual(cap.decodeCapsule(cap.stopSendingCapsule(4, 1)), { kind: "stop", id: 4, code: 1 });
assert.deepEqual(cap.decodeCapsule(cap.streamsBlockedCapsule(false, 9)), { kind: "blocked", bidi: false, max: 9 });
});
test("QUIC varints at each length, and a message that is not one whole capsule", () => {
for (const v of [0, 63, 64, 16383, 16384, 2 ** 30 - 1, 2 ** 30, 2 ** 53 - 1]) {
const b = new Uint8Array(8);
const n = cap.putQvarint(b, 0, v);
assert.deepEqual(cap.getQvarint(b.subarray(0, n)), [v, n]);
}
const m = cap.maxStreamsCapsule(true, 5);
assert.throws(() => cap.decodeCapsule(Uint8Array.from([...m, 0])));
assert.throws(() => cap.decodeCapsule(m.subarray(0, m.length - 1)));
assert.deepEqual(cap.decodeCapsule(Uint8Array.from([0x80, 0x00, 0x7a, 0xbc, 0x00])), { kind: "ignored", type: 0x7abc });
});
test("stream IDs are numbered as QUIC numbers them", () => {
assert.equal(cap.streamId.nth(0, true, true), 0);
assert.equal(cap.streamId.nth(0, false, true), 1);
assert.equal(cap.streamId.nth(0, true, false), 2);
assert.equal(cap.streamId.nth(3, false, false), 15);
assert.ok(cap.streamId.clientInitiated(4) && cap.streamId.bidi(4) && !cap.streamId.bidi(6));
assert.equal(cap.streamId.index(15), 3);
});