mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:40:43 +00:00
test(telegram): cover topic-name cache reload
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { resetTopicNameCacheForTest } from "./topic-name-cache.js";
|
||||
const { recordInboundSessionMock } = vi.hoisted(() => ({
|
||||
recordInboundSessionMock: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
@@ -34,10 +38,12 @@ const { clearRuntimeConfigSnapshot, setRuntimeConfigSnapshot } =
|
||||
|
||||
beforeEach(() => {
|
||||
clearRuntimeConfigSnapshot();
|
||||
resetTopicNameCacheForTest();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
clearRuntimeConfigSnapshot();
|
||||
resetTopicNameCacheForTest();
|
||||
recordInboundSessionMock.mockClear();
|
||||
});
|
||||
|
||||
@@ -161,6 +167,52 @@ describe("buildTelegramMessageContext group sessions without forum", () => {
|
||||
expect(ctx).not.toBeNull();
|
||||
expect(ctx?.ctxPayload?.TopicName).toBe("Deployments");
|
||||
});
|
||||
|
||||
it("reloads topic name from disk after cache reset", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-telegram-topic-name-"));
|
||||
const sessionStorePath = path.join(tempDir, "sessions.json");
|
||||
const buildPersistedContext = async (message: Record<string, unknown>) =>
|
||||
await buildTelegramMessageContextForTest({
|
||||
message,
|
||||
options: { forceWasMentioned: true },
|
||||
resolveGroupActivation: () => true,
|
||||
sessionRuntime: {
|
||||
resolveStorePath: () => sessionStorePath,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await buildPersistedContext({
|
||||
message_id: 4,
|
||||
chat: { id: -1001234567890, type: "supergroup", title: "Test Forum", is_forum: true },
|
||||
date: 1700000003,
|
||||
text: "@bot hello",
|
||||
message_thread_id: 99,
|
||||
from: { id: 42, first_name: "Alice" },
|
||||
reply_to_message: {
|
||||
message_id: 3,
|
||||
forum_topic_created: { name: "Deployments", icon_color: 0x6fb9f0 },
|
||||
},
|
||||
});
|
||||
|
||||
resetTopicNameCacheForTest();
|
||||
|
||||
const ctx = await buildPersistedContext({
|
||||
message_id: 5,
|
||||
chat: { id: -1001234567890, type: "supergroup", title: "Test Forum", is_forum: true },
|
||||
date: 1700000004,
|
||||
text: "@bot again",
|
||||
message_thread_id: 99,
|
||||
from: { id: 42, first_name: "Alice" },
|
||||
});
|
||||
|
||||
expect(ctx).not.toBeNull();
|
||||
expect(ctx?.ctxPayload?.TopicName).toBe("Deployments");
|
||||
} finally {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
resetTopicNameCacheForTest();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildTelegramMessageContext direct peer routing", () => {
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import syncFs from "node:fs";
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
clearTopicNameCache,
|
||||
getTopicEntry,
|
||||
getTopicName,
|
||||
resetTopicNameCacheForTest,
|
||||
topicNameCacheSize,
|
||||
updateTopicName,
|
||||
} from "./topic-name-cache.js";
|
||||
|
||||
describe("topic-name-cache", () => {
|
||||
beforeEach(() => {
|
||||
vi.useRealTimers();
|
||||
clearTopicNameCache();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
resetTopicNameCacheForTest();
|
||||
});
|
||||
|
||||
it("stores and retrieves a topic name", () => {
|
||||
@@ -63,11 +64,9 @@ describe("topic-name-cache", () => {
|
||||
});
|
||||
|
||||
it("updates timestamps on write", async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-04-13T22:00:00.000Z"));
|
||||
updateTopicName(-100123, 42, { name: "A" });
|
||||
const t1 = getTopicEntry(-100123, 42)?.updatedAt ?? 0;
|
||||
await vi.advanceTimersByTimeAsync(10);
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
updateTopicName(-100123, 42, { name: "B" });
|
||||
const t2 = getTopicEntry(-100123, 42)?.updatedAt ?? 0;
|
||||
expect(t2).toBeGreaterThan(t1);
|
||||
@@ -88,10 +87,8 @@ describe("topic-name-cache", () => {
|
||||
});
|
||||
|
||||
it("refreshes recency on read so active topics survive eviction", async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-04-13T22:00:00.000Z"));
|
||||
updateTopicName(-100000, 1, { name: "Active" });
|
||||
await vi.advanceTimersByTimeAsync(10);
|
||||
await new Promise((r) => setTimeout(r, 10));
|
||||
for (let i = 2; i <= 2048; i++) {
|
||||
updateTopicName(-100000, i, { name: `Topic ${i}` });
|
||||
}
|
||||
@@ -100,4 +97,37 @@ describe("topic-name-cache", () => {
|
||||
expect(getTopicName(-100000, 1)).toBe("Active");
|
||||
expect(topicNameCacheSize()).toBe(2048);
|
||||
});
|
||||
|
||||
it("reloads persisted entries from disk", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-topic-cache-"));
|
||||
const persistedPath = path.join(tempDir, "topic-names.json");
|
||||
try {
|
||||
updateTopicName(-100123, 42, { name: "Deployments" }, persistedPath);
|
||||
resetTopicNameCacheForTest();
|
||||
expect(getTopicName(-100123, 42, persistedPath)).toBe("Deployments");
|
||||
} finally {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
resetTopicNameCacheForTest();
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps separate in-memory stores for separate persisted paths", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-topic-cache-"));
|
||||
const firstPath = path.join(tempDir, "first-topic-names.json");
|
||||
const secondPath = path.join(tempDir, "second-topic-names.json");
|
||||
try {
|
||||
updateTopicName(-100123, 42, { name: "Deployments" }, firstPath);
|
||||
updateTopicName(-200456, 84, { name: "Incidents" }, secondPath);
|
||||
|
||||
const readFileSpy = vi.spyOn(syncFs, "readFileSync");
|
||||
|
||||
expect(getTopicName(-100123, 42, firstPath)).toBe("Deployments");
|
||||
expect(getTopicName(-200456, 84, secondPath)).toBe("Incidents");
|
||||
expect(readFileSpy).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
vi.restoreAllMocks();
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
resetTopicNameCacheForTest();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user