180 lines
5.1 KiB
JavaScript
180 lines
5.1 KiB
JavaScript
|
|
const assert = require("node:assert/strict");
|
||
|
|
const test = require("node:test");
|
||
|
|
|
||
|
|
const {
|
||
|
|
addTerminalDataTap,
|
||
|
|
clearTerminalSessionPerformanceState,
|
||
|
|
configureTerminalSessionDataEmitter,
|
||
|
|
emitTerminalSessionData,
|
||
|
|
_getTerminalSessionPerformanceStateCountForTests,
|
||
|
|
} = require("./emitTerminalSessionData.cjs");
|
||
|
|
|
||
|
|
test("emitTerminalSessionData rejects output from a replaced backend session", () => {
|
||
|
|
const oldSession = { _terminalSessionGeneration: 0 };
|
||
|
|
const newSession = { _terminalSessionGeneration: 1 };
|
||
|
|
const sent = [];
|
||
|
|
const tapped = [];
|
||
|
|
const removeTap = addTerminalDataTap((sessionId, data) => tapped.push({ sessionId, data }));
|
||
|
|
configureTerminalSessionDataEmitter({
|
||
|
|
getSession: () => newSession,
|
||
|
|
outputChannel: { send: () => false },
|
||
|
|
});
|
||
|
|
|
||
|
|
const delivered = emitTerminalSessionData({
|
||
|
|
send(channel, payload) { sent.push({ channel, payload }); },
|
||
|
|
}, "session-1", "old-secret", { session: oldSession });
|
||
|
|
|
||
|
|
assert.equal(delivered, false);
|
||
|
|
assert.deepEqual(tapped, []);
|
||
|
|
assert.deepEqual(sent, []);
|
||
|
|
removeTap();
|
||
|
|
configureTerminalSessionDataEmitter({});
|
||
|
|
});
|
||
|
|
|
||
|
|
test("emitTerminalSessionData binds fallback output to the backend generation", () => {
|
||
|
|
const session = { _terminalSessionGeneration: 3 };
|
||
|
|
const sent = [];
|
||
|
|
configureTerminalSessionDataEmitter({
|
||
|
|
getSession: () => session,
|
||
|
|
outputChannel: { send: () => false },
|
||
|
|
});
|
||
|
|
|
||
|
|
emitTerminalSessionData({
|
||
|
|
send(channel, payload) { sent.push({ channel, payload }); },
|
||
|
|
}, "session-1", "hello", { session });
|
||
|
|
|
||
|
|
assert.deepEqual(sent, [{
|
||
|
|
channel: "netcatty:data",
|
||
|
|
payload: {
|
||
|
|
sessionId: "session-1",
|
||
|
|
data: "hello",
|
||
|
|
_terminalSessionGeneration: 3,
|
||
|
|
},
|
||
|
|
}]);
|
||
|
|
configureTerminalSessionDataEmitter({});
|
||
|
|
});
|
||
|
|
|
||
|
|
test("emitTerminalSessionData prefers the dedicated terminal output channel", () => {
|
||
|
|
const sent = [];
|
||
|
|
const outputChannel = {
|
||
|
|
send(sessionId, data) {
|
||
|
|
sent.push({ sessionId, data });
|
||
|
|
return true;
|
||
|
|
},
|
||
|
|
};
|
||
|
|
const contents = {
|
||
|
|
send() {
|
||
|
|
throw new Error("legacy ipc should not be used");
|
||
|
|
},
|
||
|
|
};
|
||
|
|
configureTerminalSessionDataEmitter({
|
||
|
|
outputChannel,
|
||
|
|
getSession: () => null,
|
||
|
|
});
|
||
|
|
|
||
|
|
emitTerminalSessionData(contents, "session-1", "hello");
|
||
|
|
|
||
|
|
assert.deepEqual(sent, [{ sessionId: "session-1", data: "hello" }]);
|
||
|
|
configureTerminalSessionDataEmitter({});
|
||
|
|
});
|
||
|
|
|
||
|
|
test("emitTerminalSessionData falls back to netcatty:data without an output port", () => {
|
||
|
|
const sent = [];
|
||
|
|
const outputChannel = {
|
||
|
|
send() {
|
||
|
|
return false;
|
||
|
|
},
|
||
|
|
};
|
||
|
|
const contents = {
|
||
|
|
send(channel, payload) {
|
||
|
|
sent.push({ channel, payload });
|
||
|
|
},
|
||
|
|
};
|
||
|
|
configureTerminalSessionDataEmitter({
|
||
|
|
outputChannel,
|
||
|
|
getSession: () => null,
|
||
|
|
});
|
||
|
|
|
||
|
|
emitTerminalSessionData(contents, "session-1", "hello");
|
||
|
|
|
||
|
|
assert.deepEqual(sent, [
|
||
|
|
{ channel: "netcatty:data", payload: { sessionId: "session-1", data: "hello" } },
|
||
|
|
]);
|
||
|
|
configureTerminalSessionDataEmitter({});
|
||
|
|
});
|
||
|
|
|
||
|
|
test("emitTerminalSessionData forwards terminal output metadata", () => {
|
||
|
|
const sent = [];
|
||
|
|
const outputChannel = {
|
||
|
|
send() {
|
||
|
|
return false;
|
||
|
|
},
|
||
|
|
};
|
||
|
|
const contents = {
|
||
|
|
send(channel, payload) {
|
||
|
|
sent.push({ channel, payload });
|
||
|
|
},
|
||
|
|
};
|
||
|
|
configureTerminalSessionDataEmitter({
|
||
|
|
outputChannel,
|
||
|
|
getSession: () => null,
|
||
|
|
});
|
||
|
|
|
||
|
|
emitTerminalSessionData(contents, "session-1", "hello", {
|
||
|
|
meta: { droppedOutputMayAffectTerminalState: true },
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.deepEqual(sent, [
|
||
|
|
{
|
||
|
|
channel: "netcatty:data",
|
||
|
|
payload: {
|
||
|
|
sessionId: "session-1",
|
||
|
|
data: "hello",
|
||
|
|
meta: { droppedOutputMayAffectTerminalState: true },
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
configureTerminalSessionDataEmitter({});
|
||
|
|
});
|
||
|
|
|
||
|
|
test("emitTerminalSessionData reports terminal output as session activity", () => {
|
||
|
|
const activity = [];
|
||
|
|
configureTerminalSessionDataEmitter({
|
||
|
|
getSession: () => null,
|
||
|
|
outputChannel: { send: () => true },
|
||
|
|
onSessionActivity: (event) => activity.push(event),
|
||
|
|
});
|
||
|
|
|
||
|
|
emitTerminalSessionData(null, "session-activity", "output");
|
||
|
|
|
||
|
|
assert.deepEqual(activity, [
|
||
|
|
{ sessionId: "session-activity", phase: "touch" },
|
||
|
|
]);
|
||
|
|
configureTerminalSessionDataEmitter({});
|
||
|
|
});
|
||
|
|
|
||
|
|
test("terminal output performance state is bounded and removable on session close", () => {
|
||
|
|
const previousDebug = process.env.NETCATTY_TERMINAL_PERF_DEBUG;
|
||
|
|
process.env.NETCATTY_TERMINAL_PERF_DEBUG = "1";
|
||
|
|
const originalConsoleInfo = console.info;
|
||
|
|
console.info = () => {};
|
||
|
|
try {
|
||
|
|
configureTerminalSessionDataEmitter({
|
||
|
|
getSession: () => null,
|
||
|
|
outputChannel: { send: () => true },
|
||
|
|
});
|
||
|
|
for (let index = 0; index < 700; index += 1) {
|
||
|
|
emitTerminalSessionData(null, `perf-${index}`, "x");
|
||
|
|
}
|
||
|
|
assert.equal(_getTerminalSessionPerformanceStateCountForTests(), 512);
|
||
|
|
|
||
|
|
clearTerminalSessionPerformanceState("perf-699");
|
||
|
|
assert.equal(_getTerminalSessionPerformanceStateCountForTests(), 511);
|
||
|
|
} finally {
|
||
|
|
console.info = originalConsoleInfo;
|
||
|
|
if (previousDebug === undefined) delete process.env.NETCATTY_TERMINAL_PERF_DEBUG;
|
||
|
|
else process.env.NETCATTY_TERMINAL_PERF_DEBUG = previousDebug;
|
||
|
|
configureTerminalSessionDataEmitter({});
|
||
|
|
}
|
||
|
|
});
|