test(liveshare-protocol): round-trip the IPC fixtures with request tokens

The v1 host/worker fixtures carried no registrationToken or token, so a
legacy branch asserted them rejected and the optional-field case skipped
them. They now carry valid tokens and round-trip through their codecs. The
unknown access-mode fixture carries a token too, so its refusal is about
the mode rather than the missing identity. The unread required lists are
deleted; the optional lists now match what the parsers accept.
This commit is contained in:
mektpoy committed 2026-10-23 16:13:23 +08:00
1 parent 3a2a59a635
commit eab3bd4769
13 files changed
+20 -43

No files matched your search

@@ -3,6 +3,7 @@
"note": "a share whose access mode is outside the closed enum fails the whole command instead of widening it",
"frame": {
"type": "add-share",
"registrationToken": "11111111-1111-4111-8111-111111111111",
"share": {
"shareId": "share-three",
"sessionId": "session-three",
@@ -2,6 +2,5 @@
"dir": "gateway->relay",
"note": "the owner's opaque answer to one routed request",
"frame": { "type": "share-rpc-res", "id": 7, "status": 200, "body": { "ok": true } },
"required": ["id", "status"],
"optional": ["body"]
}
@@ -1,8 +1,9 @@
{
"dir": "host->worker",
"note": "a share as a build without the optional spec fields publishes it: no sessionMode, no allowsFork, no deadline",
"note": "a share with only the required spec fields and the parser's default relay connection: no sessionMode, no allowsFork, no deadline",
"frame": {
"type": "add-share",
"registrationToken": "11111111-1111-4111-8111-111111111111",
"share": {
"shareId": "share-two",
"sessionId": "session-two",
@@ -11,9 +12,9 @@
"relay": "wss://relay.example",
"gatewayToken": "token-two",
"ownerDisplayName": "Owner",
"allowedSubjectIds": []
"allowedSubjectIds": [],
"connection": { "mode": "relay" }
}
},
"required": ["type", "share"],
"optional": []
}
@@ -3,6 +3,7 @@
"note": "the owner host publishes one share to its gateway worker, every optional spec field present",
"frame": {
"type": "add-share",
"registrationToken": "11111111-1111-4111-8111-111111111111",
"share": {
"shareId": "share-one",
"sessionId": "session-one",
@@ -26,10 +27,5 @@
}
}
},
"required": [
"type",
"share",
"share.allowsFileUpload"
],
"optional": []
}
@@ -2,6 +2,5 @@
"dir": "host->worker",
"note": "the owner host withdraws one share",
"frame": { "type": "remove-share", "shareId": "share-one" },
"required": ["type", "shareId"],
"optional": []
}
@@ -3,6 +3,8 @@
"note": "the owner host hands its answer back for one in-flight request, naming the share it came through",
"frame": {
"type": "share-rpc-response",
"registrationToken": "11111111-1111-4111-8111-111111111111",
"token": "request-token",
"id": 7,
"status": 200,
"body": {
@@ -10,13 +12,5 @@
},
"shareId": "share-one"
},
"required": [
"type",
"id",
"status"
],
"optional": [
"body",
"shareId"
]
"optional": ["body"]
}
@@ -2,6 +2,5 @@
"dir": "relay->gateway",
"note": "the reader left, so the Relay cancels one in-flight request",
"frame": { "type": "share-rpc-cancel", "id": 8 },
"required": ["id"],
"optional": []
}
@@ -16,10 +16,5 @@
"credential": "signed-owner-verified-token"
}
},
"required": [
"id",
"body",
"actor"
],
"optional": []
}
@@ -2,6 +2,5 @@
"dir": "worker->host",
"note": "the gateway worker is up",
"frame": { "type": "ready" },
"required": ["type"],
"optional": []
}
@@ -1,7 +1,6 @@
{
"dir": "worker->host",
"note": "one share is registered on the Relay and reachable",
"frame": { "type": "share-connected", "shareId": "share-one" },
"required": ["type", "shareId"],
"frame": { "type": "share-connected", "registrationToken": "11111111-1111-4111-8111-111111111111", "shareId": "share-one" },
"optional": []
}
@@ -1,7 +1,6 @@
{
"dir": "worker->host",
"note": "one share could not be carried, with the reason the worker read",
"frame": { "type": "share-error", "shareId": "share-one", "message": "relay refused registration status=401" },
"required": ["type", "shareId", "message"],
"frame": { "type": "share-error", "registrationToken": "11111111-1111-4111-8111-111111111111", "shareId": "share-one", "message": "relay refused registration status=401" },
"optional": []
}
@@ -3,11 +3,12 @@
"note": "the gateway worker reports one routed request, with the identity the Relay asserted",
"frame": {
"type": "share-rpc-request",
"registrationToken": "11111111-1111-4111-8111-111111111111",
"token": "request-token",
"id": 7,
"shareId": "share-one",
"body": { "op": "stream-open", "id": 1, "endpoint": "trajectory", "payload": {} },
"actor": { "providerId": "example", "tenantId": "tenant-a", "subjectId": "user_viewer" }
},
"required": ["type", "id", "shareId", "actor"],
"optional": ["body"]
"optional": []
}
@@ -1,4 +1,4 @@
/** Relay wire v1 remains compatible; same-package Host/worker IPC requires request tokens. */
/** Relay wire version 1; same-package Host/worker IPC requires request tokens. */
import { readdirSync, readFileSync } from 'node:fs'
import { join } from 'node:path'
@@ -16,20 +16,18 @@ import {
/** Which two endpoints exchanged a recorded frame, which also names the codec that reads it. */
type Direction = 'relay->gateway' | 'gateway->relay' | 'host->worker' | 'worker->host'
/** One frame recorded from a released build, with the fields that version may omit. */
/** One frame the current build exchanges, with the fields it may omit. */
interface RecordedFrame {
readonly dir: Direction
readonly note: string
readonly frame: Record<string, unknown>
/** Raw socket text, when the recording pins bytes rather than the frame's fields. */
readonly text?: string
/** Top-level fields this build always sent. */
readonly required: readonly string[]
/** Top-level fields this build sent only when it had something to say. */
/** Top-level fields this build sends only when it has something to say. */
readonly optional?: readonly string[]
}
/** One frame this build must refuse: a later release's addition, or a value the vocabulary rejects. */
/** One frame this build must refuse: a later build's addition, or a value the vocabulary rejects. */
interface RefusedFrame {
readonly dir: Direction
readonly note: string
@@ -97,12 +95,9 @@ function withoutField(frame: Record<string, unknown>, field: string): Record<str
}
describe('recorded frames', () => {
it('reads released Relay frames and rejects superseded same-package IPC identity', () => {
it('round-trips every current frame through the codec its direction names', () => {
for (const recorded of readFrames<RecordedFrame>('v1')) {
const legacyIdentity = (recorded.dir === 'host->worker' || recorded.dir === 'worker->host')
&& recorded.frame.type !== 'ready' && recorded.frame.type !== 'remove-share'
if (legacyIdentity) expect(parseFrame(recorded.dir, wireText(recorded)), recorded.note).toBeUndefined()
else expect(parseFrame(recorded.dir, wireText(recorded)), recorded.note).toEqual(recorded.frame)
expect(parseFrame(recorded.dir, wireText(recorded)), recorded.note).toEqual(recorded.frame)
}
})