mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:30:44 +00:00
test: cover session maintenance defaults (#69404) (thanks @bobrenze-bot)
This commit is contained in:
@@ -176,7 +176,7 @@ describe("session store lock (Promise chain mutex)", () => {
|
||||
it("serializes concurrent updateSessionStore calls without data loss", async () => {
|
||||
const key = "agent:main:test";
|
||||
const { storePath } = await makeTmpStore({
|
||||
[key]: { sessionId: "s1", updatedAt: 100, counter: 0 },
|
||||
[key]: { sessionId: "s1", updatedAt: Date.now(), counter: 0 },
|
||||
});
|
||||
|
||||
const N = 4;
|
||||
@@ -216,7 +216,7 @@ describe("session store lock (Promise chain mutex)", () => {
|
||||
it("multiple consecutive errors do not permanently poison the queue", async () => {
|
||||
const key = "agent:main:multi-err";
|
||||
const { storePath } = await makeTmpStore({
|
||||
[key]: { sessionId: "s1", updatedAt: 100 },
|
||||
[key]: { sessionId: "s1", updatedAt: Date.now() },
|
||||
});
|
||||
|
||||
const errors = Array.from({ length: 3 }, (_, i) =>
|
||||
@@ -287,7 +287,7 @@ describe("session store lock (Promise chain mutex)", () => {
|
||||
const { storePath } = await makeTmpStore({
|
||||
[key]: {
|
||||
sessionId: "sess-acp",
|
||||
updatedAt: 100,
|
||||
updatedAt: Date.now(),
|
||||
acp,
|
||||
},
|
||||
});
|
||||
@@ -295,7 +295,7 @@ describe("session store lock (Promise chain mutex)", () => {
|
||||
await updateSessionStore(storePath, (store) => {
|
||||
store[key] = {
|
||||
sessionId: "sess-acp",
|
||||
updatedAt: 200,
|
||||
updatedAt: Date.now(),
|
||||
modelProvider: "openai-codex",
|
||||
model: "gpt-5.4",
|
||||
};
|
||||
|
||||
@@ -246,6 +246,57 @@ describe("Integration: saveSessionStore with pruning", () => {
|
||||
expect(Object.keys(loaded)).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("loadSessionStore prunes stale entries from oversized stores by default", async () => {
|
||||
mockLoadConfig.mockReturnValue({
|
||||
session: {
|
||||
maintenance: {
|
||||
maxEntries: 2,
|
||||
pruneAfter: "7d",
|
||||
rotateBytes: 10_485_760,
|
||||
},
|
||||
},
|
||||
});
|
||||
const now = Date.now();
|
||||
const store: Record<string, SessionEntry> = {
|
||||
stale: makeEntry(now - 31 * DAY_MS),
|
||||
recent: makeEntry(now - DAY_MS),
|
||||
newest: makeEntry(now),
|
||||
};
|
||||
await fs.writeFile(storePath, JSON.stringify(store), "utf-8");
|
||||
|
||||
const loaded = loadSessionStore(storePath, { skipCache: true });
|
||||
|
||||
expect(loaded.stale).toBeUndefined();
|
||||
expect(loaded.recent).toBeDefined();
|
||||
expect(loaded.newest).toBeDefined();
|
||||
});
|
||||
|
||||
it("loadSessionStore caps oversized stores by default", async () => {
|
||||
mockLoadConfig.mockReturnValue({
|
||||
session: {
|
||||
maintenance: {
|
||||
maxEntries: 2,
|
||||
pruneAfter: "365d",
|
||||
rotateBytes: 10_485_760,
|
||||
},
|
||||
},
|
||||
});
|
||||
const now = Date.now();
|
||||
const store: Record<string, SessionEntry> = {
|
||||
oldest: makeEntry(now - 3 * DAY_MS),
|
||||
recent: makeEntry(now - DAY_MS),
|
||||
newest: makeEntry(now),
|
||||
};
|
||||
await fs.writeFile(storePath, JSON.stringify(store), "utf-8");
|
||||
|
||||
const loaded = loadSessionStore(storePath, { skipCache: true });
|
||||
|
||||
expect(Object.keys(loaded)).toHaveLength(2);
|
||||
expect(loaded.oldest).toBeUndefined();
|
||||
expect(loaded.recent).toBeDefined();
|
||||
expect(loaded.newest).toBeDefined();
|
||||
});
|
||||
|
||||
it("archives transcript files for entries evicted by maxEntries capping", async () => {
|
||||
applyCappedMaintenanceConfig(mockLoadConfig);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createFixtureSuite } from "../../test-utils/fixture-suite.js";
|
||||
import { resolveMaintenanceConfigFromInput } from "./store-maintenance.js";
|
||||
import {
|
||||
capEntryCount,
|
||||
getActiveSessionMaintenanceWarning,
|
||||
@@ -75,6 +76,14 @@ describe("capEntryCount", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveMaintenanceConfigFromInput", () => {
|
||||
it("defaults to enforcing session maintenance", () => {
|
||||
const maintenance = resolveMaintenanceConfigFromInput();
|
||||
|
||||
expect(maintenance.mode).toBe("enforce");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getActiveSessionMaintenanceWarning", () => {
|
||||
it("warns when the active session is outside the retained recent entries", () => {
|
||||
const now = Date.now();
|
||||
|
||||
@@ -118,13 +118,14 @@ describe("session store key normalization", () => {
|
||||
});
|
||||
|
||||
it("preserves updatedAt when recording inbound metadata for an existing session", async () => {
|
||||
const existingUpdatedAt = Date.now();
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
JSON.stringify(
|
||||
{
|
||||
[CANONICAL_KEY]: {
|
||||
sessionId: "existing-session",
|
||||
updatedAt: 1111,
|
||||
updatedAt: existingUpdatedAt,
|
||||
chatType: "direct",
|
||||
channel: "webchat",
|
||||
origin: {
|
||||
@@ -150,7 +151,7 @@ describe("session store key normalization", () => {
|
||||
|
||||
const store = loadSessionStore(storePath, { skipCache: true });
|
||||
expect(store[CANONICAL_KEY]?.sessionId).toBe("existing-session");
|
||||
expect(store[CANONICAL_KEY]?.updatedAt).toBe(1111);
|
||||
expect(store[CANONICAL_KEY]?.updatedAt).toBe(existingUpdatedAt);
|
||||
expect(store[CANONICAL_KEY]?.origin?.provider).toBe("webchat");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user