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
99 lines
3.0 KiB
TypeScript
99 lines
3.0 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { createConnectionLogBuffer } from "./connectionLogBuffer.ts";
|
|
|
|
test("concatenates appended chunks while under the cap", () => {
|
|
const buf = createConnectionLogBuffer(100);
|
|
buf.append("foo");
|
|
buf.append("bar");
|
|
buf.append("baz");
|
|
assert.equal(buf.toString(), "foobarbaz");
|
|
});
|
|
|
|
test("keeps only the last maxChars, matching slice(-max) semantics", () => {
|
|
const max = 10;
|
|
const buf = createConnectionLogBuffer(max);
|
|
const chunks = ["abcd", "efgh", "ijkl", "mnop"]; // 16 chars total
|
|
let naive = "";
|
|
for (const c of chunks) {
|
|
buf.append(c);
|
|
naive += c;
|
|
}
|
|
assert.equal(buf.toString(), naive.slice(-max));
|
|
assert.equal(buf.toString().length, max);
|
|
});
|
|
|
|
test("trims a single chunk larger than the cap to its last maxChars", () => {
|
|
const buf = createConnectionLogBuffer(5);
|
|
buf.append("0123456789");
|
|
assert.equal(buf.toString(), "56789");
|
|
});
|
|
|
|
test("partial-trims the boundary chunk to keep exactly maxChars", () => {
|
|
const buf = createConnectionLogBuffer(6);
|
|
buf.append("abcde"); // 5
|
|
buf.append("fghij"); // total 10 -> keep last 6 => "efghij"
|
|
assert.equal(buf.toString(), "efghij");
|
|
});
|
|
|
|
test("stays correct across many small appends (ring semantics)", () => {
|
|
const max = 50;
|
|
const buf = createConnectionLogBuffer(max);
|
|
let naive = "";
|
|
for (let i = 0; i < 500; i++) {
|
|
const chunk = `x${i}-`;
|
|
buf.append(chunk);
|
|
naive += chunk;
|
|
}
|
|
assert.equal(buf.toString(), naive.slice(-max));
|
|
});
|
|
|
|
test("reset clears the buffer", () => {
|
|
const buf = createConnectionLogBuffer(100);
|
|
buf.append("hello");
|
|
buf.reset();
|
|
assert.equal(buf.toString(), "");
|
|
buf.append("world");
|
|
assert.equal(buf.toString(), "world");
|
|
});
|
|
|
|
test("ignores empty appends", () => {
|
|
const buf = createConnectionLogBuffer(100);
|
|
buf.append("a");
|
|
buf.append("");
|
|
buf.append("b");
|
|
assert.equal(buf.toString(), "ab");
|
|
});
|
|
|
|
test("keeps the segment count bounded across many tiny appends", () => {
|
|
// The whole point of the rewrite: trimming must not walk one array entry
|
|
// per append. With a blockSize of 10 and a 100-char cap, the buffer should
|
|
// never hold more than ~ceil(cap/blockSize)+1 segments no matter how many
|
|
// single-char appends arrive once it's at capacity.
|
|
const maxChars = 100;
|
|
const blockSize = 10;
|
|
const buf = createConnectionLogBuffer(maxChars, blockSize);
|
|
let naive = "";
|
|
for (let i = 0; i < 10000; i++) {
|
|
buf.append("x");
|
|
naive += "x";
|
|
}
|
|
assert.ok(
|
|
buf.segmentCount() <= Math.ceil(maxChars / blockSize) + 1,
|
|
`segmentCount ${buf.segmentCount()} exceeded the bound`,
|
|
);
|
|
assert.equal(buf.toString(), naive.slice(-maxChars));
|
|
});
|
|
|
|
test("seals and trims whole blocks with a small blockSize", () => {
|
|
const buf = createConnectionLogBuffer(10, 4);
|
|
const chunks = ["abcd", "efgh", "ijkl"]; // 12 chars total
|
|
let naive = "";
|
|
for (const c of chunks) {
|
|
buf.append(c);
|
|
naive += c;
|
|
}
|
|
assert.equal(buf.toString(), naive.slice(-10)); // "cdefghijkl"
|
|
});
|