test: isolate runtime state in memory tests

This commit is contained in:
Peter Steinberger
2026-04-03 07:13:12 +01:00
parent d2d9a928b1
commit 376a042ba1
3 changed files with 134 additions and 107 deletions

View File

@@ -1,4 +1,5 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { importFreshModule } from "../../../test/helpers/import-fresh.ts";
vi.mock("../../agents/auth-profiles/session-override.js", () => ({
resolveSessionAuthProfileOverride: vi.fn().mockResolvedValue(undefined),
@@ -99,14 +100,13 @@ let runReplyAgent: typeof import("./agent-runner.runtime.js").runReplyAgent;
let routeReply: typeof import("./route-reply.runtime.js").routeReply;
let drainFormattedSystemEvents: typeof import("./session-system-events.js").drainFormattedSystemEvents;
let resolveTypingMode: typeof import("./typing-mode.js").resolveTypingMode;
let loadScopeCounter = 0;
async function loadFreshGetReplyRunModuleForTest() {
vi.resetModules();
({ runReplyAgent } = await import("./agent-runner.runtime.js"));
({ routeReply } = await import("./route-reply.runtime.js"));
({ drainFormattedSystemEvents } = await import("./session-system-events.js"));
({ resolveTypingMode } = await import("./typing-mode.js"));
({ runPreparedReply } = await import("./get-reply-run.js"));
({ runPreparedReply } = await importFreshModule<typeof import("./get-reply-run.js")>(
import.meta.url,
`./get-reply-run.js?scope=media-only-${loadScopeCounter++}`,
));
}
function baseParams(
@@ -186,6 +186,13 @@ function baseParams(
}
describe("runPreparedReply media-only handling", () => {
beforeAll(async () => {
({ runReplyAgent } = await import("./agent-runner.runtime.js"));
({ routeReply } = await import("./route-reply.runtime.js"));
({ drainFormattedSystemEvents } = await import("./session-system-events.js"));
({ resolveTypingMode } = await import("./typing-mode.js"));
});
beforeEach(async () => {
storeRuntimeLoads.mockClear();
updateSessionStore.mockReset();

View File

@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import type { MsgContext } from "../auto-reply/templating.js";
import type { OpenClawConfig } from "../config/config.js";
import {
@@ -72,17 +72,7 @@ function setCompatibleActiveMediaUnderstandingRegistry(
}
describe("runCapability image skip", () => {
beforeEach(async () => {
vi.resetModules();
vi.doMock("../agents/model-catalog.js", async () => {
const actual = await vi.importActual<typeof import("../agents/model-catalog.js")>(
"../agents/model-catalog.js",
);
return {
...actual,
loadModelCatalog,
};
});
beforeAll(async () => {
({
buildProviderRegistry,
createMediaAttachmentCache,
@@ -90,7 +80,12 @@ describe("runCapability image skip", () => {
resolveAutoImageModel,
runCapability,
} = await import("./runner.js"));
});
beforeEach(() => {
loadModelCatalog.mockClear();
setActivePluginRegistry(createEmptyPluginRegistry());
vi.unstubAllEnvs();
});
it("skips image understanding when the active model supports vision", async () => {

View File

@@ -1,4 +1,5 @@
import { afterEach, describe, expect, it } from "vitest";
import { withTempDir } from "../test-helpers/temp-dir.js";
import {
findLatestTaskForRelatedSessionKeyForOwner,
findTaskByRunIdForOwner,
@@ -7,108 +8,132 @@ import {
} from "./task-owner-access.js";
import { createTaskRecord, resetTaskRegistryForTests } from "./task-registry.js";
const ORIGINAL_STATE_DIR = process.env.OPENCLAW_STATE_DIR;
afterEach(() => {
resetTaskRegistryForTests({ persist: false });
if (ORIGINAL_STATE_DIR == null) {
delete process.env.OPENCLAW_STATE_DIR;
} else {
process.env.OPENCLAW_STATE_DIR = ORIGINAL_STATE_DIR;
}
});
async function withTaskRegistryTempDir<T>(run: () => Promise<T> | T): Promise<T> {
return await withTempDir({ prefix: "openclaw-task-owner-access-" }, async (root) => {
process.env.OPENCLAW_STATE_DIR = root;
resetTaskRegistryForTests({ persist: false });
return await run();
});
}
describe("task owner access", () => {
it("returns owner-scoped tasks for owner and child-session lookups", () => {
const task = createTaskRecord({
runtime: "subagent",
ownerKey: "agent:main:main",
scopeKind: "session",
childSessionKey: "agent:main:subagent:child-1",
runId: "owner-visible-run",
task: "Owner visible task",
status: "running",
});
expect(
findLatestTaskForRelatedSessionKeyForOwner({
relatedSessionKey: "agent:main:subagent:child-1",
callerOwnerKey: "agent:main:main",
})?.taskId,
).toBe(task.taskId);
expect(
findTaskByRunIdForOwner({
it("returns owner-scoped tasks for owner and child-session lookups", async () => {
await withTaskRegistryTempDir(() => {
const task = createTaskRecord({
runtime: "subagent",
ownerKey: "agent:main:main",
scopeKind: "session",
childSessionKey: "agent:main:subagent:child-1",
runId: "owner-visible-run",
callerOwnerKey: "agent:main:main",
})?.taskId,
).toBe(task.taskId);
task: "Owner visible task",
status: "running",
});
expect(
findLatestTaskForRelatedSessionKeyForOwner({
relatedSessionKey: "agent:main:subagent:child-1",
callerOwnerKey: "agent:main:main",
})?.taskId,
).toBe(task.taskId);
expect(
findTaskByRunIdForOwner({
runId: "owner-visible-run",
callerOwnerKey: "agent:main:main",
})?.taskId,
).toBe(task.taskId);
});
});
it("denies cross-owner task reads", () => {
const task = createTaskRecord({
runtime: "acp",
ownerKey: "agent:main:main",
scopeKind: "session",
childSessionKey: "agent:main:acp:child-1",
runId: "owner-hidden-run",
task: "Hidden task",
status: "queued",
});
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:subagent:other-parent",
}),
).toBeUndefined();
expect(
findTaskByRunIdForOwner({
it("denies cross-owner task reads", async () => {
await withTaskRegistryTempDir(() => {
const task = createTaskRecord({
runtime: "acp",
ownerKey: "agent:main:main",
scopeKind: "session",
childSessionKey: "agent:main:acp:child-1",
runId: "owner-hidden-run",
callerOwnerKey: "agent:main:subagent:other-parent",
}),
).toBeUndefined();
expect(
resolveTaskForLookupTokenForOwner({
token: "agent:main:acp:child-1",
callerOwnerKey: "agent:main:subagent:other-parent",
}),
).toBeUndefined();
task: "Hidden task",
status: "queued",
});
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:subagent:other-parent",
}),
).toBeUndefined();
expect(
findTaskByRunIdForOwner({
runId: "owner-hidden-run",
callerOwnerKey: "agent:main:subagent:other-parent",
}),
).toBeUndefined();
expect(
resolveTaskForLookupTokenForOwner({
token: "agent:main:acp:child-1",
callerOwnerKey: "agent:main:subagent:other-parent",
}),
).toBeUndefined();
});
});
it("requires an exact owner-key match", () => {
const task = createTaskRecord({
runtime: "acp",
ownerKey: "agent:main:MixedCase",
scopeKind: "session",
runId: "case-sensitive-owner-run",
task: "Case-sensitive owner",
status: "queued",
});
it("requires an exact owner-key match", async () => {
await withTaskRegistryTempDir(() => {
const task = createTaskRecord({
runtime: "acp",
ownerKey: "agent:main:MixedCase",
scopeKind: "session",
runId: "case-sensitive-owner-run",
task: "Case-sensitive owner",
status: "queued",
});
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:mixedcase",
}),
).toBeUndefined();
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:mixedcase",
}),
).toBeUndefined();
});
});
it("does not expose system-owned tasks through owner-scoped readers", () => {
const task = createTaskRecord({
runtime: "cron",
ownerKey: "system:cron:nightly",
scopeKind: "system",
childSessionKey: "agent:main:cron:nightly",
runId: "system-task-run",
task: "Nightly cron",
status: "running",
deliveryStatus: "not_applicable",
});
it("does not expose system-owned tasks through owner-scoped readers", async () => {
await withTaskRegistryTempDir(() => {
const task = createTaskRecord({
runtime: "cron",
ownerKey: "system:cron:nightly",
scopeKind: "system",
requesterSessionKey: "system:cron:nightly",
childSessionKey: "agent:main:cron:nightly",
runId: "system-task-run",
task: "Nightly cron",
status: "running",
deliveryStatus: "not_applicable",
});
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:main",
}),
).toBeUndefined();
expect(
resolveTaskForLookupTokenForOwner({
token: "system-task-run",
callerOwnerKey: "agent:main:main",
}),
).toBeUndefined();
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:main",
}),
).toBeUndefined();
expect(
resolveTaskForLookupTokenForOwner({
token: "system-task-run",
callerOwnerKey: "agent:main:main",
}),
).toBeUndefined();
});
});
});