mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-03-30 05:43:55 +00:00
73 lines
1.7 KiB
TypeScript
73 lines
1.7 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { Lock } from "../../src/util/lock"
|
|
|
|
function tick() {
|
|
return new Promise<void>((r) => queueMicrotask(r))
|
|
}
|
|
|
|
async function flush(n = 5) {
|
|
for (let i = 0; i < n; i++) await tick()
|
|
}
|
|
|
|
describe("util.lock", () => {
|
|
test("writer exclusivity: blocks reads and other writes while held", async () => {
|
|
const key = "lock:" + Math.random().toString(36).slice(2)
|
|
|
|
const state = {
|
|
writer2: false,
|
|
reader: false,
|
|
writers: 0,
|
|
}
|
|
|
|
// Acquire writer1
|
|
using writer1 = await Lock.write(key)
|
|
state.writers++
|
|
expect(state.writers).toBe(1)
|
|
|
|
// Start writer2 candidate (should block)
|
|
const writer2Task = (async () => {
|
|
const w = await Lock.write(key)
|
|
state.writers++
|
|
expect(state.writers).toBe(1)
|
|
state.writer2 = true
|
|
// Hold for a tick so reader cannot slip in
|
|
await tick()
|
|
return w
|
|
})()
|
|
|
|
// Start reader candidate (should block)
|
|
const readerTask = (async () => {
|
|
const r = await Lock.read(key)
|
|
state.reader = true
|
|
return r
|
|
})()
|
|
|
|
// Flush microtasks and assert neither acquired
|
|
await flush()
|
|
expect(state.writer2).toBe(false)
|
|
expect(state.reader).toBe(false)
|
|
|
|
// Release writer1
|
|
writer1[Symbol.dispose]()
|
|
state.writers--
|
|
|
|
// writer2 should acquire next
|
|
const writer2 = await writer2Task
|
|
expect(state.writer2).toBe(true)
|
|
|
|
// Reader still blocked while writer2 held
|
|
await flush()
|
|
expect(state.reader).toBe(false)
|
|
|
|
// Release writer2
|
|
writer2[Symbol.dispose]()
|
|
state.writers--
|
|
|
|
// Reader should now acquire
|
|
const reader = await readerTask
|
|
expect(state.reader).toBe(true)
|
|
|
|
reader[Symbol.dispose]()
|
|
})
|
|
})
|