Files
NetMesh/electron/plugins/terminalInterceptorTransport.test.cjs
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

125 lines
3.5 KiB
JavaScript

"use strict";
const assert = require("node:assert/strict");
const test = require("node:test");
const { runInNewContext } = require("node:vm");
const {
TERMINAL_INTERCEPTOR_MAX_CHUNK_BYTES,
TERMINAL_INTERCEPTOR_MAX_WINDOW_BYTES,
createTerminalInterceptorEnvelope,
} = require("./terminalInterceptorTransport.cjs");
test("terminal interceptor envelopes validate canonical ready, chunk, and result frames", () => {
assert.deepEqual(createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:ready",
sessionId: "session-1",
direction: "output",
windowBytes: TERMINAL_INTERCEPTOR_MAX_WINDOW_BYTES,
}), {
frame: {
type: "netcatty:terminal-interceptor:ready",
sessionId: "session-1",
direction: "output",
windowBytes: TERMINAL_INTERCEPTOR_MAX_WINDOW_BYTES,
},
});
const chunkData = new Uint8Array([1, 2, 3]).buffer;
const chunk = createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:chunk",
sequence: 1,
direction: "input",
creditBytes: TERMINAL_INTERCEPTOR_MAX_CHUNK_BYTES,
byteLength: 3,
}, chunkData);
assert.equal(chunk.transfer, chunkData);
const resultData = runInNewContext("new Uint8Array([4, 5]).buffer");
const result = createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:result",
sequence: Number.MAX_SAFE_INTEGER,
status: "ok",
creditBytes: 3,
byteLength: 2,
}, resultData);
assert.equal(result.transfer, resultData);
assert.deepEqual(createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:result",
sequence: 2,
status: "failed",
}), {
frame: {
type: "netcatty:terminal-interceptor:result",
sequence: 2,
status: "failed",
},
});
});
test("terminal interceptor envelopes fail closed on schema or transfer mismatches", () => {
const data = new ArrayBuffer(4);
assert.throws(
() => createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:chunk",
sequence: 0,
direction: "input",
creditBytes: 1,
byteLength: 4,
}, data),
/violates the plugin contract/,
);
assert.throws(
() => createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:chunk",
sequence: 1,
direction: "input",
creditBytes: 1,
byteLength: 3,
}, data),
/byteLength mismatch/,
);
assert.throws(
() => createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:result",
sequence: 1,
status: "ok",
creditBytes: 4,
byteLength: 4,
}),
/requires a transferred ArrayBuffer/,
);
assert.throws(
() => createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:ready",
sessionId: "session-1",
direction: "input",
windowBytes: TERMINAL_INTERCEPTOR_MAX_CHUNK_BYTES,
extra: true,
}),
/violates the plugin contract/,
);
assert.throws(
() => createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:result",
sequence: 1,
status: "failed",
}, data),
/must not include a transferred buffer/,
);
const detached = new ArrayBuffer(0);
structuredClone(detached, { transfer: [detached] });
assert.throws(
() => createTerminalInterceptorEnvelope({
type: "netcatty:terminal-interceptor:chunk",
sequence: 1,
direction: "input",
creditBytes: 1,
byteLength: 0,
}, detached),
/requires a real, attached ArrayBuffer/,
);
});