20ae3f8ba5
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
101 lines
2.6 KiB
TypeScript
101 lines
2.6 KiB
TypeScript
import { beforeEach, describe, expect, it } from "bun:test"
|
|
|
|
import {
|
|
clearAllSkips,
|
|
drainSkipsAfter,
|
|
recordFsyncSkip,
|
|
} from "./fsync-skip-tracker"
|
|
|
|
type PathClassification =
|
|
| "icloud"
|
|
| "onedrive"
|
|
| "desktop-sync"
|
|
| "network-drive"
|
|
| "unknown"
|
|
|
|
function recordSkip(index: number, pathClassification: PathClassification = "unknown"): void {
|
|
recordFsyncSkip({
|
|
filePath: `/tmp/file-${index}.txt`,
|
|
contextLabel: `atomicWrite:/tmp/file-${index}.txt`,
|
|
errorCode: "EPERM",
|
|
message: "operation not permitted",
|
|
pathClassification,
|
|
})
|
|
}
|
|
|
|
describe("fsync-skip-tracker", () => {
|
|
beforeEach(() => {
|
|
clearAllSkips()
|
|
})
|
|
|
|
it("recordFsyncSkip adds entry with timestamp", () => {
|
|
const before = Date.now()
|
|
recordSkip(1)
|
|
const entries = drainSkipsAfter(0)
|
|
|
|
expect(entries).toHaveLength(1)
|
|
expect(entries[0]?.filePath).toBe("/tmp/file-1.txt")
|
|
expect(entries[0]?.timestamp).toBeGreaterThanOrEqual(before)
|
|
})
|
|
|
|
it("drainSkipsAfter(timestamp) returns entries strictly after the timestamp", async () => {
|
|
recordSkip(1)
|
|
const firstTimestamp = Date.now()
|
|
|
|
await Bun.sleep(2)
|
|
|
|
recordSkip(2)
|
|
const drained = drainSkipsAfter(firstTimestamp)
|
|
expect(drained).toHaveLength(1)
|
|
expect(drained[0]?.filePath).toBe("/tmp/file-2.txt")
|
|
})
|
|
|
|
it("drainSkipsAfter removes drained entries from buffer", () => {
|
|
recordSkip(1)
|
|
recordSkip(2)
|
|
|
|
const drained = drainSkipsAfter(0)
|
|
expect(drained).toHaveLength(2)
|
|
expect(drainSkipsAfter(0)).toEqual([])
|
|
})
|
|
|
|
it("buffer is bounded to max 200 entries and drops oldest on overflow", () => {
|
|
for (let index = 1; index <= 205; index += 1) {
|
|
recordSkip(index)
|
|
}
|
|
|
|
const drained = drainSkipsAfter(0)
|
|
expect(drained).toHaveLength(200)
|
|
expect(drained[0]?.filePath).toBe("/tmp/file-6.txt")
|
|
expect(drained[199]?.filePath).toBe("/tmp/file-205.txt")
|
|
})
|
|
|
|
it("multiple records with same path are kept", () => {
|
|
recordSkip(1)
|
|
recordFsyncSkip({
|
|
filePath: "/tmp/file-1.txt",
|
|
contextLabel: "acquireLock:/tmp/file-1.txt",
|
|
errorCode: "EPERM",
|
|
message: "second",
|
|
pathClassification: "unknown",
|
|
})
|
|
|
|
const drained = drainSkipsAfter(0)
|
|
expect(drained).toHaveLength(2)
|
|
expect(drained[0]?.filePath).toBe("/tmp/file-1.txt")
|
|
expect(drained[1]?.filePath).toBe("/tmp/file-1.txt")
|
|
})
|
|
|
|
it("drainSkipsAfter(0) returns all entries", () => {
|
|
recordSkip(1)
|
|
recordSkip(2)
|
|
|
|
const drained = drainSkipsAfter(0)
|
|
expect(drained).toHaveLength(2)
|
|
})
|
|
|
|
it("empty buffer returns empty array", () => {
|
|
expect(drainSkipsAfter(0)).toEqual([])
|
|
})
|
|
})
|