Skip to content

Commit cb69501

Browse files
authored
test(opencode): deflake file and tool timing (anomalyco#17859)
1 parent a64f604 commit cb69501

6 files changed

Lines changed: 74 additions & 55 deletions

File tree

packages/opencode/src/file/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ export class FileService extends ServiceMap.Service<FileService, FileService.Ser
448448
}
449449

450450
const init = Effect.fn("FileService.init")(function* () {
451-
void kick()
451+
yield* Effect.promise(() => kick())
452452
})
453453

454454
const status = Effect.fn("FileService.status")(function* () {

packages/opencode/test/file/index.test.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -681,9 +681,7 @@ describe("file/index Filesystem patterns", () => {
681681
await Instance.provide({
682682
directory: tmp.path,
683683
fn: async () => {
684-
File.init()
685-
// Give the background scan time to populate
686-
await new Promise((r) => setTimeout(r, 500))
684+
await File.init()
687685

688686
const result = await File.search({ query: "", type: "file" })
689687
expect(result.length).toBeGreaterThan(0)
@@ -697,8 +695,7 @@ describe("file/index Filesystem patterns", () => {
697695
await Instance.provide({
698696
directory: tmp.path,
699697
fn: async () => {
700-
File.init()
701-
await new Promise((r) => setTimeout(r, 500))
698+
await File.init()
702699

703700
const result = await File.search({ query: "", type: "directory" })
704701
expect(result.length).toBeGreaterThan(0)
@@ -718,8 +715,7 @@ describe("file/index Filesystem patterns", () => {
718715
await Instance.provide({
719716
directory: tmp.path,
720717
fn: async () => {
721-
File.init()
722-
await new Promise((r) => setTimeout(r, 500))
718+
await File.init()
723719

724720
const result = await File.search({ query: "main", type: "file" })
725721
expect(result.some((f) => f.includes("main"))).toBe(true)
@@ -733,8 +729,7 @@ describe("file/index Filesystem patterns", () => {
733729
await Instance.provide({
734730
directory: tmp.path,
735731
fn: async () => {
736-
File.init()
737-
await new Promise((r) => setTimeout(r, 500))
732+
await File.init()
738733

739734
const result = await File.search({ query: "", type: "file" })
740735
// Files don't end with /
@@ -751,8 +746,7 @@ describe("file/index Filesystem patterns", () => {
751746
await Instance.provide({
752747
directory: tmp.path,
753748
fn: async () => {
754-
File.init()
755-
await new Promise((r) => setTimeout(r, 500))
749+
await File.init()
756750

757751
const result = await File.search({ query: "", type: "directory" })
758752
// Directories end with /
@@ -769,8 +763,7 @@ describe("file/index Filesystem patterns", () => {
769763
await Instance.provide({
770764
directory: tmp.path,
771765
fn: async () => {
772-
File.init()
773-
await new Promise((r) => setTimeout(r, 500))
766+
await File.init()
774767

775768
const result = await File.search({ query: "", type: "file", limit: 2 })
776769
expect(result.length).toBeLessThanOrEqual(2)
@@ -784,8 +777,7 @@ describe("file/index Filesystem patterns", () => {
784777
await Instance.provide({
785778
directory: tmp.path,
786779
fn: async () => {
787-
File.init()
788-
await new Promise((r) => setTimeout(r, 500))
780+
await File.init()
789781

790782
const result = await File.search({ query: ".hidden", type: "directory" })
791783
expect(result.length).toBeGreaterThan(0)

packages/opencode/test/file/time.test.ts

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ import { tmpdir } from "../fixture/fixture"
99

1010
afterEach(() => Instance.disposeAll())
1111

12+
async function touch(file: string, time: number) {
13+
const date = new Date(time)
14+
await fs.utimes(file, date, date)
15+
}
16+
17+
function gate() {
18+
let open!: () => void
19+
const wait = new Promise<void>((resolve) => {
20+
open = resolve
21+
})
22+
return { open, wait }
23+
}
24+
1225
describe("file/time", () => {
1326
const sessionID = SessionID.make("ses_00000000000000000000000001")
1427

@@ -25,7 +38,6 @@ describe("file/time", () => {
2538
expect(before).toBeUndefined()
2639

2740
await FileTime.read(sessionID, filepath)
28-
await Bun.sleep(10)
2941

3042
const after = await FileTime.get(sessionID, filepath)
3143
expect(after).toBeInstanceOf(Date)
@@ -44,7 +56,6 @@ describe("file/time", () => {
4456
fn: async () => {
4557
await FileTime.read(SessionID.make("ses_00000000000000000000000002"), filepath)
4658
await FileTime.read(SessionID.make("ses_00000000000000000000000003"), filepath)
47-
await Bun.sleep(10)
4859

4960
const time1 = await FileTime.get(SessionID.make("ses_00000000000000000000000002"), filepath)
5061
const time2 = await FileTime.get(SessionID.make("ses_00000000000000000000000003"), filepath)
@@ -63,14 +74,10 @@ describe("file/time", () => {
6374
await Instance.provide({
6475
directory: tmp.path,
6576
fn: async () => {
66-
FileTime.read(sessionID, filepath)
67-
await Bun.sleep(10)
77+
await FileTime.read(sessionID, filepath)
6878
const first = await FileTime.get(sessionID, filepath)
6979

70-
await Bun.sleep(10)
71-
72-
FileTime.read(sessionID, filepath)
73-
await Bun.sleep(10)
80+
await FileTime.read(sessionID, filepath)
7481
const second = await FileTime.get(sessionID, filepath)
7582

7683
expect(second!.getTime()).toBeGreaterThanOrEqual(first!.getTime())
@@ -84,12 +91,12 @@ describe("file/time", () => {
8491
await using tmp = await tmpdir()
8592
const filepath = path.join(tmp.path, "file.txt")
8693
await fs.writeFile(filepath, "content", "utf-8")
94+
await touch(filepath, 1_000)
8795

8896
await Instance.provide({
8997
directory: tmp.path,
9098
fn: async () => {
91-
FileTime.read(sessionID, filepath)
92-
await Bun.sleep(10)
99+
await FileTime.read(sessionID, filepath)
93100
await FileTime.assert(sessionID, filepath)
94101
},
95102
})
@@ -112,13 +119,14 @@ describe("file/time", () => {
112119
await using tmp = await tmpdir()
113120
const filepath = path.join(tmp.path, "file.txt")
114121
await fs.writeFile(filepath, "content", "utf-8")
122+
await touch(filepath, 1_000)
115123

116124
await Instance.provide({
117125
directory: tmp.path,
118126
fn: async () => {
119-
FileTime.read(sessionID, filepath)
120-
await Bun.sleep(100)
127+
await FileTime.read(sessionID, filepath)
121128
await fs.writeFile(filepath, "modified content", "utf-8")
129+
await touch(filepath, 2_000)
122130
await expect(FileTime.assert(sessionID, filepath)).rejects.toThrow("modified since it was last read")
123131
},
124132
})
@@ -128,13 +136,14 @@ describe("file/time", () => {
128136
await using tmp = await tmpdir()
129137
const filepath = path.join(tmp.path, "file.txt")
130138
await fs.writeFile(filepath, "content", "utf-8")
139+
await touch(filepath, 1_000)
131140

132141
await Instance.provide({
133142
directory: tmp.path,
134143
fn: async () => {
135144
await FileTime.read(sessionID, filepath)
136-
await Bun.sleep(100)
137145
await fs.writeFile(filepath, "modified", "utf-8")
146+
await touch(filepath, 2_000)
138147

139148
let error: Error | undefined
140149
try {
@@ -191,18 +200,25 @@ describe("file/time", () => {
191200
directory: tmp.path,
192201
fn: async () => {
193202
const order: number[] = []
203+
const hold = gate()
204+
const ready = gate()
194205

195206
const op1 = FileTime.withLock(filepath, async () => {
196207
order.push(1)
197-
await Bun.sleep(50)
208+
ready.open()
209+
await hold.wait
198210
order.push(2)
199211
})
200212

213+
await ready.wait
214+
201215
const op2 = FileTime.withLock(filepath, async () => {
202216
order.push(3)
203217
order.push(4)
204218
})
205219

220+
hold.open()
221+
206222
await Promise.all([op1, op2])
207223
expect(order).toEqual([1, 2, 3, 4])
208224
},
@@ -219,15 +235,21 @@ describe("file/time", () => {
219235
fn: async () => {
220236
let started1 = false
221237
let started2 = false
238+
const hold = gate()
239+
const ready = gate()
222240

223241
const op1 = FileTime.withLock(filepath1, async () => {
224242
started1 = true
225-
await Bun.sleep(50)
243+
ready.open()
244+
await hold.wait
226245
expect(started2).toBe(true)
227246
})
228247

248+
await ready.wait
249+
229250
const op2 = FileTime.withLock(filepath2, async () => {
230251
started2 = true
252+
hold.open()
231253
})
232254

233255
await Promise.all([op1, op2])
@@ -265,12 +287,12 @@ describe("file/time", () => {
265287
await using tmp = await tmpdir()
266288
const filepath = path.join(tmp.path, "file.txt")
267289
await fs.writeFile(filepath, "content", "utf-8")
290+
await touch(filepath, 1_000)
268291

269292
await Instance.provide({
270293
directory: tmp.path,
271294
fn: async () => {
272-
FileTime.read(sessionID, filepath)
273-
await Bun.sleep(10)
295+
await FileTime.read(sessionID, filepath)
274296

275297
const stats = Filesystem.stat(filepath)
276298
expect(stats?.mtime).toBeInstanceOf(Date)
@@ -285,17 +307,17 @@ describe("file/time", () => {
285307
await using tmp = await tmpdir()
286308
const filepath = path.join(tmp.path, "file.txt")
287309
await fs.writeFile(filepath, "original", "utf-8")
310+
await touch(filepath, 1_000)
288311

289312
await Instance.provide({
290313
directory: tmp.path,
291314
fn: async () => {
292-
FileTime.read(sessionID, filepath)
293-
await Bun.sleep(10)
315+
await FileTime.read(sessionID, filepath)
294316

295317
const originalStat = Filesystem.stat(filepath)
296318

297-
await Bun.sleep(100)
298319
await fs.writeFile(filepath, "modified", "utf-8")
320+
await touch(filepath, 2_000)
299321

300322
const newStat = Filesystem.stat(filepath)
301323
expect(newStat!.mtime.getTime()).toBeGreaterThan(originalStat!.mtime.getTime())

packages/opencode/test/preload.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ process.env["OPENCODE_TEST_HOME"] = testHome
4444
// Set test managed config directory to isolate tests from system managed settings
4545
const testManagedConfigDir = path.join(dir, "managed")
4646
process.env["OPENCODE_TEST_MANAGED_CONFIG_DIR"] = testManagedConfigDir
47+
process.env["OPENCODE_DISABLE_DEFAULT_PLUGINS"] = "true"
4748

4849
// Write the cache version file to prevent global/index.ts from clearing the cache
4950
const cacheDir = path.join(dir, "cache", "opencode")

0 commit comments

Comments
 (0)