diff options
| author | Dax Raad <[email protected]> | 2025-12-01 16:35:03 -0500 |
|---|---|---|
| committer | Dax Raad <[email protected]> | 2025-12-01 16:35:07 -0500 |
| commit | 3d99dc78dbff982cde6dd61a0629b7ee9de1a8f3 (patch) | |
| tree | 4c8dabb52db7c26d2d412c1be861f7599168a7d3 /packages/enterprise/test | |
| parent | 95c3a8b80505fcb3140989daf6fece3377aa3b95 (diff) | |
| download | opencode-3d99dc78dbff982cde6dd61a0629b7ee9de1a8f3.tar.gz opencode-3d99dc78dbff982cde6dd61a0629b7ee9de1a8f3.zip | |
core: reduce latency when loading shared sessions through event compaction
Diffstat (limited to 'packages/enterprise/test')
| -rw-r--r-- | packages/enterprise/test/core/share.test.ts | 269 | ||||
| -rw-r--r-- | packages/enterprise/test/core/storage.test.ts | 67 |
2 files changed, 336 insertions, 0 deletions
diff --git a/packages/enterprise/test/core/share.test.ts b/packages/enterprise/test/core/share.test.ts new file mode 100644 index 000000000..d3bf6a2c2 --- /dev/null +++ b/packages/enterprise/test/core/share.test.ts @@ -0,0 +1,269 @@ +import { describe, expect, test, afterAll } from "bun:test" +import { Share } from "../../src/core/share" +import { Storage } from "../../src/core/storage" +import { Identifier } from "@opencode-ai/util/identifier" + +describe.concurrent("core.share", () => { + test("should create a share", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + expect(share.sessionID).toBe(sessionID) + expect(share.secret).toBeDefined() + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + test("should sync data to a share", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + const data: Share.Data[] = [ + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Hello" }, + }, + ] + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data, + }) + + const events = await Storage.list({ prefix: ["share_event", share.id] }) + expect(events.length).toBe(1) + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + test("should sync multiple batches of data", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + const data1: Share.Data[] = [ + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Hello" }, + }, + ] + + const data2: Share.Data[] = [ + { + type: "part", + data: { id: "part2", sessionID, messageID: "msg1", type: "text", text: "World" }, + }, + ] + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data: data1, + }) + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data: data2, + }) + + const events = await Storage.list({ prefix: ["share_event", share.id] }) + expect(events.length).toBe(2) + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + test("should retrieve synced data", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + const data: Share.Data[] = [ + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Hello" }, + }, + { + type: "part", + data: { id: "part2", sessionID, messageID: "msg1", type: "text", text: "World" }, + }, + ] + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data, + }) + + const result = await Share.data(share.id) + + expect(result.length).toBe(2) + expect(result[0].type).toBe("part") + expect(result[1].type).toBe("part") + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + test("should retrieve data from multiple syncs", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + const data1: Share.Data[] = [ + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Hello" }, + }, + ] + + const data2: Share.Data[] = [ + { + type: "part", + data: { id: "part2", sessionID, messageID: "msg2", type: "text", text: "World" }, + }, + ] + + const data3: Share.Data[] = [ + { type: "part", data: { id: "part3", sessionID, messageID: "msg3", type: "text", text: "!" } }, + ] + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data: data1, + }) + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data: data2, + }) + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data: data3, + }) + + const result = await Share.data(share.id) + + expect(result.length).toBe(3) + const parts = result.filter((d) => d.type === "part") + expect(parts.length).toBe(3) + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + test("should return latest data when syncing duplicate parts", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + const data1: Share.Data[] = [ + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Hello" }, + }, + ] + + const data2: Share.Data[] = [ + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Hello Updated" }, + }, + ] + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data: data1, + }) + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data: data2, + }) + + const result = await Share.data(share.id) + + expect(result.length).toBe(1) + const [first] = result + expect(first.type).toBe("part") + expect(first.type === "part" && first.data.type === "text" && first.data.text).toBe("Hello Updated") + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + test("should return empty array for share with no data", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + const result = await Share.data(share.id) + + expect(result).toEqual([]) + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + test("should throw error for invalid secret", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + const data: Share.Data[] = [ + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Test" }, + }, + ] + + expect(async () => { + await Share.sync({ + share: { id: share.id, secret: "invalid-secret" }, + data, + }) + }).toThrow() + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + test("should throw error for non-existent share", async () => { + const sessionID = Identifier.descending() + const data: Share.Data[] = [ + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Test" }, + }, + ] + + expect(async () => { + await Share.sync({ + share: { id: "non-existent-id", secret: "some-secret" }, + data, + }) + }).toThrow() + }) + + test("should handle different data types", async () => { + const sessionID = Identifier.descending() + const share = await Share.create({ sessionID }) + + const data: Share.Data[] = [ + { type: "session", data: { id: sessionID, status: "running" } as any }, + { type: "message", data: { id: "msg1", sessionID } as any }, + { + type: "part", + data: { id: "part1", sessionID, messageID: "msg1", type: "text", text: "Hello" }, + }, + ] + + await Share.sync({ + share: { id: share.id, secret: share.secret }, + data, + }) + + const result = await Share.data(share.id) + + expect(result.length).toBe(3) + expect(result.some((d) => d.type === "session")).toBe(true) + expect(result.some((d) => d.type === "message")).toBe(true) + expect(result.some((d) => d.type === "part")).toBe(true) + + await Share.remove({ id: share.id, secret: share.secret }) + }) + + afterAll(async () => { + const files = await Storage.list() + for (const file of files) { + Storage.remove(file) + } + }) +}) diff --git a/packages/enterprise/test/core/storage.test.ts b/packages/enterprise/test/core/storage.test.ts new file mode 100644 index 000000000..27e51384c --- /dev/null +++ b/packages/enterprise/test/core/storage.test.ts @@ -0,0 +1,67 @@ +import { describe, expect, test, afterAll } from "bun:test" +import { Storage } from "../../src/core/storage" + +describe("core.storage", () => { + test("should list files with start and end range", async () => { + await Storage.write(["test", "users", "user1"], { name: "user1" }) + await Storage.write(["test", "users", "user2"], { name: "user2" }) + await Storage.write(["test", "users", "user3"], { name: "user3" }) + await Storage.write(["test", "users", "user4"], { name: "user4" }) + await Storage.write(["test", "users", "user5"], { name: "user5" }) + + const result = await Storage.list({ prefix: ["test", "users"], start: "user2", end: "user4" }) + + expect(result).toEqual([ + ["test", "users", "user3"], + ["test", "users", "user4"], + ]) + }) + + test("should list files with start only", async () => { + const result = await Storage.list({ prefix: ["test", "users"], start: "user3" }) + + expect(result).toEqual([ + ["test", "users", "user4"], + ["test", "users", "user5"], + ]) + }) + + test("should list files with limit", async () => { + const result = await Storage.list({ prefix: ["test", "users"], limit: 3 }) + + expect(result).toEqual([ + ["test", "users", "user1"], + ["test", "users", "user2"], + ["test", "users", "user3"], + ]) + }) + + test("should list all files without prefix", async () => { + const result = await Storage.list() + + expect(result.length).toBeGreaterThan(0) + }) + + test("should list all files with prefix", async () => { + const result = await Storage.list({ prefix: ["test", "users"] }) + + expect(result).toEqual([ + ["test", "users", "user1"], + ["test", "users", "user2"], + ["test", "users", "user3"], + ["test", "users", "user4"], + ["test", "users", "user5"], + ]) + }) + + afterAll(async () => { + const testFiles = await Storage.list({ prefix: ["test"] }) + + for (const file of testFiles) { + await Storage.remove(file) + } + + const remainingFiles = await Storage.list({ prefix: ["test"] }) + expect(remainingFiles).toEqual([]) + }) +}) |
