fix: prevent stale database workers across extension tests (#147986)

* test: drain shared workers before extension fixture cleanup

Await the existing shared-state close owner before test store resets and
temporary-state removal in 37 verified extension fixtures. Expose that
existing operation through the private test SDK barrel. Preserve producer
completion, synchronous failure-latch resets, and all test assertions.

Eighteen selected ordinary cases, all 39 canonical scoped checks, and an
independent P2 review of the complete fixture packet pass.

* test(qa): scope attribution renderer to fixture docs
This commit is contained in:
Peter Steinberger 2026-09-14 08:26:56 -07:00 • committed by GitHub
parent a5fb8446c0
commit ddd91efa4f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 120 additions and 24 deletions

View file

@ -12,6 +12,7 @@ import type {
OpenKeyedStoreOptions,
PluginDoctorStateMigrationContext,
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
legacyConfigRules,
@ -109,6 +110,7 @@ describe("acpx doctor state migration", () => {
});
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(stateDir, { recursive: true, force: true });
});

View file

@ -11,6 +11,7 @@ import type {
OpenKeyedStoreOptions,
PluginDoctorStateMigrationContext,
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
legacyConfigRules,
@ -65,6 +66,7 @@ describe("active-memory doctor state migration", () => {
afterEach(async () => {
vi.useRealTimers();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(stateDir, { recursive: true, force: true });
});

View file

@ -17,7 +17,10 @@ import {
appendSessionTranscriptMessageByIdentity,
type SessionTranscriptTargetParams,
} from "openclaw/plugin-sdk/session-transcript-runtime";
import { closeOpenClawAgentDatabasesForTest } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import {
closeOpenClawAgentDatabasesForTest,
closeOpenClawStateDatabaseAsync,
} from "openclaw/plugin-sdk/sqlite-runtime-testing";
import {
afterAll,
afterEach,
@ -756,6 +759,7 @@ describe("active-memory plugin", () => {
afterAll(async () => {
closeOpenClawAgentDatabasesForTest();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(fixtureRoot, { recursive: true, force: true });
fixtureRoot = "";

View file

@ -12,6 +12,7 @@ import {
createPluginStateKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, expect, it, vi } from "vitest";
import { startBuzzBus, type BuzzBus } from "./buzz-bus.js";
import { createBuzzRelayFixture } from "./buzz-relay.test-harness.js";
@ -347,7 +348,8 @@ it("revokes the active bot immediately on a signed role downgrade", async () =>
await fixture.close();
}
});
afterEach(() => {
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
vi.restoreAllMocks();
vi.unstubAllEnvs();

View file

@ -8,6 +8,7 @@ import {
createPluginStateKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { ChannelGatewayContext } from "../runtime-api.js";
import type { BuzzInboundMessage } from "./message-event.js";
@ -325,9 +326,10 @@ beforeEach(() => {
);
});
afterEach(() => {
afterEach(async () => {
vi.restoreAllMocks();
vi.unstubAllGlobals();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
if (previousStateDir === undefined) {
delete process.env.OPENCLAW_STATE_DIR;

View file

@ -11,6 +11,7 @@ import type {
OpenKeyedStoreOptions,
PluginDoctorStateMigrationContext,
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { stateMigrations } from "./doctor-contract-api.js";
import {
@ -43,6 +44,7 @@ describe("device-pair doctor notify migration", () => {
});
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(stateDir, { recursive: true, force: true });
});

View file

@ -7,6 +7,7 @@ import {
createPluginStateKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, describe, expect, it, vi } from "vitest";
import { setDiscordRuntime } from "../runtime.js";
import {
@ -35,6 +36,7 @@ async function createStateEnv(): Promise<NodeJS.ProcessEnv> {
}
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await Promise.all(
tempDirs.splice(0).map(async (dir) => {

View file

@ -3,11 +3,11 @@ import { createHash } from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import {
closeOpenClawStateDatabaseForTest,
createPluginStateKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { buildLegacyMigrationPreview } from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import {
resolvePreferredOpenClawTmpDir,
tempWorkspaceSync,
@ -28,8 +28,8 @@ describe("detectIMessageLegacyStateMigrations", () => {
});
});
afterEach(() => {
closeOpenClawStateDatabaseForTest();
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
stateWorkspace.cleanup();
vi.doUnmock("./runtime.js");

View file

@ -9,6 +9,7 @@ import {
createPluginStateSyncKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getMatrixRuntime } from "../../runtime.js";
import { installMatrixTestRuntime } from "../../test-runtime.js";
@ -80,13 +81,14 @@ describe("SqliteBackedMatrixSyncStore", () => {
installMatrixTestRuntime();
});
afterEach(() => {
afterEach(async () => {
vi.restoreAllMocks();
vi.useRealTimers();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
resetPluginStateStoreForTests();
});
it("persists sync data so restart resumes from the saved cursor", async () => {

View file

@ -6,6 +6,7 @@ import {
createPluginStateSyncKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { resolveMatrixAccountStorageRoot } from "../../storage-paths.js";
import { installMatrixTestRuntime } from "../../test-runtime.js";
@ -38,8 +39,9 @@ describe("matrix client storage paths", () => {
resetPluginStateStoreForTests();
});
afterEach(() => {
afterEach(async () => {
vi.restoreAllMocks();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
@ -437,6 +439,7 @@ describe("matrix client storage paths", () => {
"synthetic migration archive denied",
);
rename.mockRestore();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
const expectPreservedState = () => {
@ -476,6 +479,7 @@ describe("matrix client storage paths", () => {
resetPluginStateStoreForTests();
await maybeMigrateLegacyStorage({ storagePaths, env });
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
expectPreservedState();

View file

@ -10,6 +10,7 @@ import {
openOpenClawStateDatabase,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { getMatrixRuntime } from "../../runtime.js";
import { installMatrixTestRuntime } from "../../test-runtime.js";
@ -53,6 +54,7 @@ describe("Matrix IndexedDB persistence", () => {
afterEach(async () => {
warnSpy.mockRestore();
await clearTestIndexedDbState();
await closeOpenClawStateDatabaseAsync();
resetFileLockStateForTest();
resetPluginStateStoreForTests();
fs.rmSync(tmpDir, { recursive: true, force: true });

View file

@ -16,6 +16,7 @@ import { appendSessionTranscriptMessageByIdentity } from "openclaw/plugin-sdk/se
import { resolveOpenClawAgentSqlitePath } from "openclaw/plugin-sdk/sqlite-runtime";
import {
closeOpenClawAgentDatabasesForTest,
closeOpenClawStateDatabaseAsync,
openOpenClawAgentDatabase,
} from "openclaw/plugin-sdk/sqlite-runtime-testing";
import {
@ -187,6 +188,7 @@ afterAll(async () => {
// The agent close releases its leases through shared state and reopens it, so the
// shared handle is released second; otherwise Windows fails the removal with EBUSY.
closeOpenClawAgentDatabasesForTest();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(fixtureRoot, { recursive: true, force: true });
resetMemoryCoreDreamingStateForTests();

View file

@ -6,6 +6,7 @@ import {
openOpenClawStateDatabase,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { useAutoCleanupTempDirTracker } from "openclaw/plugin-sdk/test-env";
import { afterEach, expect, test } from "vitest";
import {
@ -17,10 +18,11 @@ import {
} from "./dreaming-state.js";
const tempDirs = useAutoCleanupTempDirTracker((cleanup) =>
afterEach(() => {
afterEach(async () => {
configureMemoryCoreDreamingState(() => {
throw new Error("memory workspace test store is closed");
});
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
cleanup();
}),

View file

@ -7,6 +7,7 @@ import { upsertSessionEntry } from "openclaw/plugin-sdk/session-store-runtime";
import { openOpenClawAgentDatabase } from "openclaw/plugin-sdk/sqlite-runtime";
import {
closeOpenClawAgentDatabasesForTest,
closeOpenClawStateDatabaseAsync,
closeOpenClawStateDatabaseForTest,
} from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
@ -44,6 +45,7 @@ describe("memory forget", () => {
afterEach(async () => {
closeOpenClawAgentDatabasesForTest();
await closeOpenClawStateDatabaseAsync();
closeOpenClawStateDatabaseForTest();
resetPluginStateStoreForTests();
vi.unstubAllEnvs();

View file

@ -6,7 +6,10 @@ import { DatabaseSync } from "node:sqlite";
import type { OpenClawConfig } from "openclaw/plugin-sdk/memory-core-host-engine-foundation";
import { resetPluginStateStoreForTests } from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { resolveOpenClawAgentSqlitePath } from "openclaw/plugin-sdk/sqlite-runtime";
import { closeOpenClawAgentDatabasesForTest } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import {
closeOpenClawAgentDatabasesForTest,
closeOpenClawStateDatabaseAsync,
} from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { closeAllMemorySearchManagers, getMemorySearchManager } from "./index.js";
import type { MemoryIndexMeta } from "./manager-reindex-state.js";
@ -112,6 +115,7 @@ describe("memory manager FTS-only reindex", () => {
// The agent close releases its leases through shared state and reopens it, so the
// shared handle is released second; otherwise Windows fails the removal with EBUSY.
closeOpenClawAgentDatabasesForTest();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
if (fixtureRoot) {
await fs.rm(fixtureRoot, { recursive: true, force: true });

View file

@ -12,7 +12,10 @@ import { upsertSessionEntry } from "openclaw/plugin-sdk/session-store-runtime";
import { withSessionTranscriptWriteLock } from "openclaw/plugin-sdk/session-transcript-runtime";
import { resolveOpenClawAgentSqlitePath } from "openclaw/plugin-sdk/sqlite-runtime";
import * as sqliteRuntime from "openclaw/plugin-sdk/sqlite-runtime";
import { closeOpenClawAgentDatabasesForTest } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import {
closeOpenClawAgentDatabasesForTest,
closeOpenClawStateDatabaseAsync,
} from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import "./test-runtime-mocks.js";
import { recordMemorySessionTombstones } from "../memory-entry-origins.js";
@ -112,6 +115,7 @@ describe("memory manager reindex recovery", () => {
// The agent close releases its leases through shared state and reopens it, so the
// shared handle is released second; otherwise Windows fails the removal with EBUSY.
closeOpenClawAgentDatabasesForTest();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(fixtureRoot, { recursive: true, force: true });
});

View file

@ -5,6 +5,7 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/memory-core-host-engine
import { resetPluginStateStoreForTests } from "openclaw/plugin-sdk/plugin-state-test-runtime";
import {
closeOpenClawAgentDatabasesForTest,
closeOpenClawStateDatabaseAsync,
openOpenClawAgentDatabase,
} from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
@ -81,6 +82,7 @@ describe("memory manager self-heal missing identity with FTS-only chunks", () =>
// The agent close releases its leases through shared state and reopens it, so the
// shared handle is released second; otherwise Windows fails the removal with EBUSY.
closeOpenClawAgentDatabasesForTest();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
if (fixtureRoot) {
await fs.rm(fixtureRoot, { recursive: true, force: true });

View file

@ -11,6 +11,7 @@ import {
setMaxPluginStateEntriesPerPluginForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import type { PluginDoctorStateMigrationContext } from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { stateMigrations } from "./doctor-contract-api.js";
import {
@ -56,6 +57,7 @@ describe("Teams custom migration retention", () => {
});
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
setMaxPluginStateEntriesPerPluginForTests();
resetPluginStateStoreForTests();
await fs.rm(stateDir, { recursive: true, force: true });

View file

@ -14,6 +14,7 @@ import type {
PluginDoctorStateMigrationContext,
PluginStateKeyedStore,
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
legacyConfigRules,
@ -90,6 +91,7 @@ describe("msteams doctor state migration", () => {
});
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(stateDir, { recursive: true, force: true });
});

View file

@ -6,6 +6,7 @@ import {
createPluginStateKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { useAutoCleanupTempDirTracker } from "openclaw/plugin-sdk/test-env";
import { afterAll, beforeEach, describe, expect, it } from "vitest";
import { createMSTeamsConversationStoreState } from "./conversation-store-state.js";
@ -14,7 +15,8 @@ import { setMSTeamsRuntime } from "./runtime.js";
import { msteamsRuntimeStub } from "./test-support/runtime.js";
const tempDirs = useAutoCleanupTempDirTracker((cleanup) =>
afterAll(() => {
afterAll(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
cleanup();
}),

View file

@ -1,5 +1,6 @@
// Msteams tests cover conversation store.shared plugin behavior.
import { resetPluginStateStoreForTests } from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { useAutoCleanupTempDirTracker } from "openclaw/plugin-sdk/test-env";
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
import { createMSTeamsConversationStoreState } from "./conversation-store-state.js";
@ -7,7 +8,8 @@ import { setMSTeamsRuntime } from "./runtime.js";
import { msteamsRuntimeStub } from "./test-support/runtime.js";
const tempDirs = useAutoCleanupTempDirTracker((cleanup) =>
afterAll(() => {
afterAll(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
cleanup();
}),

View file

@ -7,6 +7,7 @@ import {
createPluginStateKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { useAutoCleanupTempDirTracker } from "openclaw/plugin-sdk/test-env";
import { afterAll, beforeEach, describe, expect, it, vi } from "vitest";
import {
@ -19,7 +20,8 @@ import { setMSTeamsRuntime } from "./runtime.js";
import { msteamsRuntimeStub } from "./test-support/runtime.js";
const tempDirs = useAutoCleanupTempDirTracker((cleanup) =>
afterAll(() => {
afterAll(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
cleanup();
}),

View file

@ -2,6 +2,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { resetPluginStateStoreForTests } from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { useAutoCleanupTempDirTracker } from "openclaw/plugin-sdk/test-env";
import { afterAll, beforeEach, describe, expect, it } from "vitest";
import { setMSTeamsRuntime } from "./runtime.js";
@ -9,7 +10,8 @@ import { createMSTeamsSsoTokenStoreFs } from "./sso-token-store.js";
import { msteamsRuntimeStub } from "./test-support/runtime.js";
const tempDirs = useAutoCleanupTempDirTracker((cleanup) =>
afterAll(() => {
afterAll(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
cleanup();
}),

View file

@ -11,6 +11,7 @@ import type {
OpenKeyedStoreOptions,
PluginDoctorStateMigrationContext,
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { stateMigrations } from "./doctor-contract-api.js";
@ -40,6 +41,7 @@ describe("nostr doctor state migration", () => {
});
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(stateDir, { recursive: true, force: true });
});

View file

@ -7,6 +7,7 @@ import {
createPluginStateKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { describe, expect, it } from "vitest";
import type { PluginRuntime } from "../runtime-api.js";
import {
@ -51,6 +52,7 @@ async function withTempStateDir<T>(fn: (dir: string) => Promise<T>) {
}
// The keyed store keeps the state database open under the temporary dir, so Windows
// fails the removal with EBUSY unless the cached handle is released first.
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(dir, { recursive: true, force: true });
}

View file

@ -224,6 +224,8 @@ describe.skipIf(process.platform === "win32")("onboarding assertion attribution"
expect(written.entries).toEqual(result.evidence.entries);
expect(written.evidenceMode).toBe(evidenceMode);
const docsRoot = path.join(tempRoot, "docs");
await fs.mkdir(docsRoot);
const taxonomyPath = path.join(tempRoot, "taxonomy.json");
const scoresPath = path.join(tempRoot, "scores.json");
const surface = { id: "cli", name: "CLI", family: "core", level: "experimental" };
@ -280,6 +282,8 @@ describe.skipIf(process.platform === "win32")("onboarding assertion attribution"
"--import",
"tsx",
"scripts/qa/render-maturity-docs.ts",
"--docs-root",
docsRoot,
"--taxonomy",
taxonomyPath,
"--scores",

View file

@ -12,6 +12,7 @@ import type {
OpenKeyedStoreOptions,
PluginDoctorStateMigrationContext,
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
legacyConfigRules,
@ -144,8 +145,9 @@ describe("Reef doctor contract", () => {
env = { ...process.env, OPENCLAW_STATE_DIR: stateDir };
});
afterEach(() => {
afterEach(async () => {
vi.restoreAllMocks();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
fs.rmSync(stateDir, { recursive: true, force: true });
});

View file

@ -23,6 +23,7 @@ import {
clearRuntimeConfigSnapshot,
setRuntimeConfigSnapshot,
} from "openclaw/plugin-sdk/runtime-config-snapshot";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { withEnvAsync } from "openclaw/plugin-sdk/test-env";
import { createRequireRecord, sanitizeTerminalText } from "openclaw/plugin-sdk/test-fixtures";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
@ -479,7 +480,8 @@ describe("createTelegramBot", () => {
process.env.TZ = ORIGINAL_TZ;
}
});
afterEach(() => {
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
pluginStateTestRuntime.resetPluginStateStoreForTests();
clearPluginInteractiveHandlers();
if (previousStateDir === undefined) {

View file

@ -9,6 +9,7 @@ import {
createPluginStateSyncKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { createRequireRecord, importFreshModule } from "openclaw/plugin-sdk/test-fixtures";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { markdownToTelegramHtml, telegramHtmlToPlainTextFallback } from "./format.js";
@ -517,9 +518,10 @@ async function capturedLogText(logFile: string): Promise<string> {
return content;
}
afterEach(() => {
afterEach(async () => {
resetTelegramSentMessageCacheForTest();
clearTelegramRuntime();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
setLoggerOverride(null);
resetLogger();

View file

@ -14,6 +14,7 @@ import {
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import type { MsgContext } from "openclaw/plugin-sdk/reply-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { expect, it, vi } from "vitest";
import { defaultTelegramBotDeps } from "./bot-deps.js";
import { telegramBotInfoForTest } from "./bot.create-telegram-bot.test-support.js";
@ -270,6 +271,7 @@ it.each(["none", "middleware", "handler"] as const)(
});
clearTelegramRuntimeForTest();
resetTelegramAccountThrottlersForTest();
await closeOpenClawStateDatabaseAsync();
closeOpenClawStateDatabaseForTest();
resetPluginStateStoreForTests({ closeDatabase: false });
if (previousStateDir === undefined) {

View file

@ -9,6 +9,7 @@ import {
createPluginStateKeyedStoreForTests,
createPluginStateSyncKeyedStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, describe, expect, it, vi } from "vitest";
import { beginTelegramPollRegistration } from "./poll-answer-context.js";
import { recordTelegramPollRegistryEntry } from "./poll-registry.js";
@ -54,13 +55,15 @@ async function withTempState<T>(
return await fn(stateDir, spoolDir);
} finally {
clearTelegramRuntimeForTest();
await closeOpenClawStateDatabaseAsync();
closeOpenClawStateDatabaseForTest();
await fs.rm(stateDir, { recursive: true, force: true });
}
}
afterEach(() => {
afterEach(async () => {
clearTelegramRuntimeForTest();
await closeOpenClawStateDatabaseAsync();
closeOpenClawStateDatabaseForTest();
});

View file

@ -14,6 +14,7 @@ import {
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { createTestPluginApi } from "openclaw/plugin-sdk/plugin-test-api";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import plugin from "./index.js";
import type { VisitorGrant } from "./src/visitors.js";
@ -79,6 +80,7 @@ describe("visitor-access plugin lifecycle", () => {
for (const cleanup of cleanups.splice(0)) {
await cleanup();
}
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
vi.useRealTimers();
vi.unstubAllGlobals();

View file

@ -13,6 +13,7 @@ import type {
OpenKeyedStoreOptions,
PluginDoctorStateMigrationContext,
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { resolveSessionStoreAgentIds, stateMigrations } from "./doctor-contract-api.js";
import {
@ -146,6 +147,7 @@ describe("voice-call doctor state migration", () => {
historyCallIds: history.map((entry) => entry.callId),
};
} finally {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(warmStateDir, { recursive: true, force: true });
await fs.rm(warmStorePath, { recursive: true, force: true });
@ -161,6 +163,7 @@ describe("voice-call doctor state migration", () => {
});
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(stateDir, { recursive: true, force: true });
await fs.rm(storePath, { recursive: true, force: true });
@ -467,6 +470,7 @@ describe("voice-call doctor state migration", () => {
chunk_index: index,
})),
);
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await expect(getCallHistoryFromStore(storePath)).resolves.toEqual([]);
const retried = await migration.migrateLegacyState({

View file

@ -8,6 +8,7 @@ import {
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import type { RealtimeVoiceProviderPlugin } from "openclaw/plugin-sdk/realtime-voice";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { expect, it, vi } from "vitest";
import { VoiceCallConfigSchema, type VoiceCallConfig } from "./config.js";
import { CallManager } from "./manager.js";
@ -115,6 +116,7 @@ async function withDelayedStore(
await manager.stop();
await Promise.allSettled(writes);
persistence.mockRestore();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
fs.rmSync(storePath, { recursive: true, force: true });
}

View file

@ -1,6 +1,7 @@
import fs from "node:fs";
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
import { resetPluginStateStoreForTests } from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { describe, expect, it, onTestFinished } from "vitest";
import { VoiceCallConfigSchema } from "./config.js";
import { CallManager } from "./manager.js";
@ -62,6 +63,7 @@ describe("CallManager termination lifecycle", () => {
await finalizeTestManagerCalls(owner);
}
} finally {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
fs.rmSync(storePath, { recursive: true, force: true });
}

View file

@ -11,6 +11,7 @@ import {
openOpenClawStateDatabase,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { registerVoiceCallLogs } from "../cli-call-log.js";
import {
@ -90,8 +91,9 @@ describe("voice-call call record store", () => {
installStateRuntime();
});
afterEach(() => {
afterEach(async () => {
vi.useRealTimers();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
});
@ -134,6 +136,7 @@ describe("voice-call call record store", () => {
).toEqual(since === 0 ? ["new"] : ["third", "new"]);
} finally {
stdout.mockRestore();
await closeOpenClawStateDatabaseAsync();
fs.rmSync(storePath, { recursive: true, force: true });
}
});
@ -248,6 +251,7 @@ describe("voice-call call record store", () => {
);
await expect(findCallInStore(storePath, "provider-batch-127")).resolves.toEqual(calls[127]);
} finally {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
fs.rmSync(storePath, { recursive: true, force: true });
}
@ -304,6 +308,7 @@ describe("voice-call call record store", () => {
);
await expect(getCallHistoryFromStore(storePath)).resolves.toEqual([]);
} finally {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
fs.rmSync(storePath, { recursive: true, force: true });
}
@ -415,6 +420,7 @@ describe("voice-call call record store", () => {
expect((await loadActiveCallsFromStore(storePath)).activeCalls.size).toBe(0);
} finally {
toString.mockRestore();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
fs.rmSync(storePath, { recursive: true, force: true });
}

View file

@ -6,6 +6,7 @@ import {
createPluginStateKeyedStoreForTests,
resetPluginStateStoreForTests,
} from "openclaw/plugin-sdk/plugin-state-test-runtime";
import { closeOpenClawStateDatabaseAsync } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { postRawWebhook } from "openclaw/plugin-sdk/test-env";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { VoiceCallConfigSchema, type VoiceCallConfig } from "./config.js";
@ -157,7 +158,8 @@ describe("Voice-call webhook hangup-once lifecycle", () => {
installStateRuntime();
});
afterEach(() => {
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
vi.restoreAllMocks();
});
@ -265,6 +267,7 @@ describe("Voice-call webhook hangup-once lifecycle", () => {
await server.stop();
} finally {
await finalizeTestManagerCalls(manager);
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
fs.rmSync(storePath, { recursive: true, force: true });
}
@ -332,7 +335,8 @@ describe("Voice-call webhook body limits", () => {
installStateRuntime();
});
afterEach(() => {
afterEach(async () => {
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
});

View file

@ -17,7 +17,10 @@ import {
normalizeSessionDeliveryState,
upsertSessionEntry,
} from "openclaw/plugin-sdk/session-store-runtime";
import { closeOpenClawAgentDatabasesForTest } from "openclaw/plugin-sdk/sqlite-runtime-testing";
import {
closeOpenClawAgentDatabasesForTest,
closeOpenClawStateDatabaseAsync,
} from "openclaw/plugin-sdk/sqlite-runtime-testing";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { stateMigrations } from "./doctor-contract-api.js";
import { setZalouserRuntime } from "./src/runtime.js";
@ -66,6 +69,7 @@ describe("zalouser doctor state migration", () => {
// resetPluginStateStoreForTests only releases plugin state plus shared state, so the
// cached agent handles must be closed here or Windows fails the removal with EBUSY.
closeOpenClawAgentDatabasesForTest();
await closeOpenClawStateDatabaseAsync();
resetPluginStateStoreForTests();
await fs.rm(stateDir, { recursive: true, force: true });
});

View file

@ -27,6 +27,7 @@ export {
openOpenClawAgentDatabase,
} from "../state/openclaw-agent-db.js";
export {
closeOpenClawStateDatabaseAsync,
closeOpenClawStateDatabaseForTest,
openOpenClawStateDatabase,
} from "../state/openclaw-state-db.js";