runa/vscode/test/fixtures.ts

83 lines
2.7 KiB
TypeScript
Raw Permalink Normal View History

import { once } from "node:events";
import WebSocket, { WebSocketServer } from "ws";
import { TestContext } from "node:test";
import { stringify } from "lossless-json";
import { ActorSnapshot, WEBSOCKET_SUBPROTOCOL } from "../src/protocol";
export const REF = "abcdefghijklmnopqrstu";
export function actor(): ActorSnapshot {
return {
behavior_path: null,
pending_behavior_path: null,
temporary_behavior: false,
log_level: "info",
actor_ref: REF,
mailbox_id: 18446744073709551615n,
implementation_id: "implementation:test",
incarnation: 1n,
state: {
type: "record",
data: {
minimum: { type: "integer", data: -9223372036854775808n },
maximum: { type: "integer", data: 9223372036854775807n },
reference: { type: "actor_ref", data: REF },
text: { type: "string", data: `@${REF} "雪"` },
list: { type: "list", data: [{ type: "null" }, { type: "bool", data: true }] },
},
},
status: { status: "paused" },
execution: { vm_steps: 20n, instruction_pointer: 12n, call_depth: 1n },
queued: [{ type: "bool", data: false }],
reserved: { type: "null" },
};
}
export function json(value: unknown): string {
const result = stringify(value);
if (result === undefined) throw new Error("Cannot encode test fixture");
return result;
}
export interface TestRequest {
version: number;
request_id: string;
command: { operation: string; parameters?: Record<string, unknown> };
}
export function response(request: TestRequest, reply: unknown): string {
return json({ version: 5, request_id: request.request_id, result: { Ok: reply } });
}
export async function fakeImage(
t: TestContext,
handle: (request: TestRequest, socket: WebSocket) => void,
protocol = WEBSOCKET_SUBPROTOCOL,
): Promise<string> {
const server = new WebSocketServer({
host: "127.0.0.1",
port: 0,
handleProtocols: (offered) => (offered.has(protocol) ? protocol : false),
});
server.on("connection", (socket) => {
socket.on("error", () => {
// Transport-failure tests intentionally close a socket while the fixture is writing.
});
socket.on("message", (data) => handle(JSON.parse(data.toString()), socket));
});
await once(server, "listening");
t.after(async () => {
for (const socket of server.clients) socket.terminate();
await new Promise<void>((resolve, reject) =>
server.close((error) => (error ? reject(error) : resolve())),
);
});
const address = server.address();
if (!address || typeof address === "string") throw new Error("Missing test listener");
return `127.0.0.1:${address.port}`;
}
export function notification(revision: bigint): string {
return json({ version: 5, event: { event: "image_changed", data: { revision } } });
}