perf(test): speed up qmd manager suite
This commit is contained in:
@@ -92,6 +92,22 @@ describe("QmdMemoryManager", () => {
|
||||
let cfg: OpenClawConfig;
|
||||
const agentId = "main";
|
||||
|
||||
async function createManager(params?: { mode?: "full" | "status"; cfg?: OpenClawConfig }) {
|
||||
const cfgToUse = params?.cfg ?? cfg;
|
||||
const resolved = resolveMemoryBackendConfig({ cfg: cfgToUse, agentId });
|
||||
const manager = await QmdMemoryManager.create({
|
||||
cfg: cfgToUse,
|
||||
agentId,
|
||||
resolved,
|
||||
mode: params?.mode ?? "status",
|
||||
});
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
return { manager, resolved };
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), "qmd-manager-test-fixtures-"));
|
||||
});
|
||||
@@ -134,12 +150,7 @@ describe("QmdMemoryManager", () => {
|
||||
});
|
||||
|
||||
it("debounces back-to-back sync calls", async () => {
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager, resolved } = await createManager();
|
||||
|
||||
const baselineCalls = spawnMock.mock.calls.length;
|
||||
|
||||
@@ -182,8 +193,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
const { manager } = await createManager({ mode: "full" });
|
||||
expect(releaseUpdate).not.toBeNull();
|
||||
releaseUpdate?.();
|
||||
await manager?.close();
|
||||
@@ -202,9 +212,7 @@ describe("QmdMemoryManager", () => {
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved, mode: "status" });
|
||||
expect(manager).toBeTruthy();
|
||||
const { manager } = await createManager({ mode: "status" });
|
||||
expect(spawnMock).not.toHaveBeenCalled();
|
||||
await manager?.close();
|
||||
});
|
||||
@@ -240,7 +248,7 @@ describe("QmdMemoryManager", () => {
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const createPromise = QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
const createPromise = QmdMemoryManager.create({ cfg, agentId, resolved, mode: "full" });
|
||||
await updateSpawned.promise;
|
||||
let created = false;
|
||||
void createPromise.then(() => {
|
||||
@@ -278,9 +286,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
const { manager } = await createManager({ mode: "full" });
|
||||
await manager?.close();
|
||||
});
|
||||
|
||||
@@ -310,7 +316,7 @@ describe("QmdMemoryManager", () => {
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const createPromise = QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
const createPromise = QmdMemoryManager.create({ cfg, agentId, resolved, mode: "status" });
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
const manager = await createPromise;
|
||||
expect(manager).toBeTruthy();
|
||||
@@ -346,12 +352,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager, resolved } = await createManager();
|
||||
const maxResults = resolved.qmd?.limits.maxResults;
|
||||
if (!maxResults) {
|
||||
throw new Error("qmd maxResults missing");
|
||||
@@ -403,12 +404,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager, resolved } = await createManager();
|
||||
const maxResults = resolved.qmd?.limits.maxResults;
|
||||
if (!maxResults) {
|
||||
throw new Error("qmd maxResults missing");
|
||||
@@ -465,12 +461,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
const inFlight = manager.sync({ reason: "interval" });
|
||||
const forced = manager.sync({ reason: "manual", force: true });
|
||||
@@ -530,12 +521,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
const inFlight = manager.sync({ reason: "interval" });
|
||||
const forcedOne = manager.sync({ reason: "manual", force: true });
|
||||
@@ -585,12 +571,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager, resolved } = await createManager();
|
||||
|
||||
await manager.search("test", { sessionKey: "agent:main:slack:dm:u123" });
|
||||
const searchCall = spawnMock.mock.calls.find((call) => call[1]?.[0] === "search");
|
||||
@@ -625,12 +606,7 @@ describe("QmdMemoryManager", () => {
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
const results = await manager.search("test", { sessionKey: "agent:main:slack:dm:u123" });
|
||||
expect(results).toEqual([]);
|
||||
@@ -664,7 +640,7 @@ describe("QmdMemoryManager", () => {
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const createPromise = QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
const createPromise = QmdMemoryManager.create({ cfg, agentId, resolved, mode: "status" });
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
const manager = await createPromise;
|
||||
expect(manager).toBeTruthy();
|
||||
@@ -694,12 +670,7 @@ describe("QmdMemoryManager", () => {
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
const isAllowed = (key?: string) =>
|
||||
(manager as unknown as { isScopeAllowed: (key?: string) => boolean }).isScopeAllowed(key);
|
||||
@@ -728,12 +699,7 @@ describe("QmdMemoryManager", () => {
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
logWarnMock.mockClear();
|
||||
const beforeCalls = spawnMock.mock.calls.length;
|
||||
@@ -748,57 +714,8 @@ describe("QmdMemoryManager", () => {
|
||||
await manager.close();
|
||||
});
|
||||
|
||||
it("symlinks shared qmd models into the agent cache", async () => {
|
||||
const defaultCacheHome = path.join(tmpRoot, "default-cache");
|
||||
const sharedModelsDir = path.join(defaultCacheHome, "qmd", "models");
|
||||
await fs.mkdir(sharedModelsDir, { recursive: true });
|
||||
const previousXdgCacheHome = process.env.XDG_CACHE_HOME;
|
||||
process.env.XDG_CACHE_HOME = defaultCacheHome;
|
||||
const symlinkSpy = vi.spyOn(fs, "symlink");
|
||||
|
||||
try {
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
|
||||
const targetModelsDir = path.join(
|
||||
stateDir,
|
||||
"agents",
|
||||
agentId,
|
||||
"qmd",
|
||||
"xdg-cache",
|
||||
"qmd",
|
||||
"models",
|
||||
);
|
||||
const modelsStat = await fs.lstat(targetModelsDir);
|
||||
expect(modelsStat.isSymbolicLink() || modelsStat.isDirectory()).toBe(true);
|
||||
expect(
|
||||
symlinkSpy.mock.calls.some(
|
||||
(call) => call[0] === sharedModelsDir && call[1] === targetModelsDir,
|
||||
),
|
||||
).toBe(true);
|
||||
|
||||
await manager.close();
|
||||
} finally {
|
||||
symlinkSpy.mockRestore();
|
||||
if (previousXdgCacheHome === undefined) {
|
||||
delete process.env.XDG_CACHE_HOME;
|
||||
} else {
|
||||
process.env.XDG_CACHE_HOME = previousXdgCacheHome;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("blocks non-markdown or symlink reads for qmd paths", async () => {
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
const textPath = path.join(workspaceDir, "secret.txt");
|
||||
await fs.writeFile(textPath, "nope", "utf-8");
|
||||
@@ -822,12 +739,7 @@ describe("QmdMemoryManager", () => {
|
||||
const text = Array.from({ length: 50 }, (_, index) => `line-${index + 1}`).join("\n");
|
||||
await fs.writeFile(path.join(workspaceDir, "window.md"), text, "utf-8");
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
const result = await manager.readFile({ relPath: "window.md", from: 10, lines: 3 });
|
||||
expect(result.text).toBe("line-10\nline-11\nline-12");
|
||||
@@ -861,12 +773,7 @@ describe("QmdMemoryManager", () => {
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
const reasonCount = writeFileSpy.mock.calls.length;
|
||||
await manager.sync({ reason: "manual" });
|
||||
@@ -890,12 +797,7 @@ describe("QmdMemoryManager", () => {
|
||||
});
|
||||
|
||||
it("throws when sqlite index is busy", async () => {
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
const inner = manager as unknown as {
|
||||
db: { prepare: () => { get: () => never }; close: () => void } | null;
|
||||
resolveDocLocation: (docid?: string) => Promise<unknown>;
|
||||
@@ -928,12 +830,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
const inner = manager as unknown as {
|
||||
db: { prepare: () => { get: () => never }; close: () => void } | null;
|
||||
};
|
||||
@@ -969,12 +866,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
const inner = manager as unknown as {
|
||||
db: { prepare: (query: string) => { get: (arg: unknown) => unknown }; close: () => void };
|
||||
@@ -1027,12 +919,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
await expect(
|
||||
manager.search("noise", { sessionKey: "agent:main:slack:dm:u123" }),
|
||||
@@ -1050,12 +937,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
await expect(
|
||||
manager.search("missing", { sessionKey: "agent:main:slack:dm:u123" }),
|
||||
@@ -1073,12 +955,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
await expect(
|
||||
manager.search("missing", { sessionKey: "agent:main:slack:dm:u123" }),
|
||||
@@ -1096,12 +973,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
await expect(
|
||||
manager.search("missing", { sessionKey: "agent:main:slack:dm:u123" }),
|
||||
@@ -1123,12 +995,7 @@ describe("QmdMemoryManager", () => {
|
||||
return createMockChild();
|
||||
});
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
expect(manager).toBeTruthy();
|
||||
if (!manager) {
|
||||
throw new Error("manager missing");
|
||||
}
|
||||
const { manager } = await createManager();
|
||||
|
||||
await expect(
|
||||
manager.search("missing", { sessionKey: "agent:main:slack:dm:u123" }),
|
||||
@@ -1163,8 +1030,7 @@ describe("QmdMemoryManager", () => {
|
||||
});
|
||||
|
||||
it("symlinks default model cache into custom XDG_CACHE_HOME on first run", async () => {
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
const { manager } = await createManager({ mode: "full" });
|
||||
expect(manager).toBeTruthy();
|
||||
|
||||
const stat = await fs.lstat(customModelsDir);
|
||||
@@ -1176,7 +1042,7 @@ describe("QmdMemoryManager", () => {
|
||||
const content = await fs.readFile(path.join(customModelsDir, "model.bin"), "utf-8");
|
||||
expect(content).toBe("fake-model");
|
||||
|
||||
await manager!.close();
|
||||
await manager.close();
|
||||
});
|
||||
|
||||
it("does not overwrite existing models directory", async () => {
|
||||
@@ -1184,8 +1050,7 @@ describe("QmdMemoryManager", () => {
|
||||
await fs.mkdir(customModelsDir, { recursive: true });
|
||||
await fs.writeFile(path.join(customModelsDir, "custom-model.bin"), "custom");
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
const { manager } = await createManager({ mode: "full" });
|
||||
expect(manager).toBeTruthy();
|
||||
|
||||
// Should still be a real directory, not a symlink.
|
||||
@@ -1197,15 +1062,14 @@ describe("QmdMemoryManager", () => {
|
||||
const content = await fs.readFile(path.join(customModelsDir, "custom-model.bin"), "utf-8");
|
||||
expect(content).toBe("custom");
|
||||
|
||||
await manager!.close();
|
||||
await manager.close();
|
||||
});
|
||||
|
||||
it("skips symlink when no default models exist", async () => {
|
||||
// Remove the default models dir.
|
||||
await fs.rm(defaultModelsDir, { recursive: true, force: true });
|
||||
|
||||
const resolved = resolveMemoryBackendConfig({ cfg, agentId });
|
||||
const manager = await QmdMemoryManager.create({ cfg, agentId, resolved });
|
||||
const { manager } = await createManager({ mode: "full" });
|
||||
expect(manager).toBeTruthy();
|
||||
|
||||
// Custom models dir should not exist (no symlink created).
|
||||
@@ -1214,7 +1078,7 @@ describe("QmdMemoryManager", () => {
|
||||
expect.stringContaining("failed to symlink qmd models directory"),
|
||||
);
|
||||
|
||||
await manager!.close();
|
||||
await manager.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user