deskpaw-memory/test/server-timeline.test.js

32 lines
2.1 KiB
JavaScript

import { spawn } from "node:child_process";
import { mkdtempSync, rmSync } from "node:fs";
import { createConnection } from "node:net";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { once } from "node:events";
import assert from "node:assert/strict";
import { test } from "node:test";
test("real socket supports timeline calls and refuses a second live owner", { timeout: 15000 }, async () => {
const dir = mkdtempSync(join(tmpdir(), "timeline-server-"));
const env = { ...process.env, DESKPAW_STATE_DIR: dir, DESKPAW_MEMORY_SOCKET: join(dir, "runtime", "memory.sock"), DESKPAW_MEMORY_DB: join(dir, "memory.sqlite"), DESKPAW_MEMORY_BUNDLES: join(dir, "bundles") };
const server = spawn(process.execPath, ["src/server.js"], { env, stdio: ["ignore", "pipe", "pipe"] });
const exited = once(server, "exit");
const call = (method, params) => new Promise((resolve, reject) => {
const socket = createConnection(env.DESKPAW_MEMORY_SOCKET); let data = "";
socket.setTimeout(2000, () => socket.destroy(new Error("timeout")));
socket.on("error", reject); socket.on("connect", () => socket.write(JSON.stringify({ id: "test", method, params }) + "\n"));
socket.on("data", chunk => { data += chunk; });
socket.on("end", () => { try { resolve(JSON.parse(data)); } catch (error) { reject(error); } });
});
try {
await Promise.race([once(server.stdout, "data"), exited.then(() => { throw new Error("Server exited before ready"); })]);
assert.equal((await call("timeline.append", { id: "meeting", kind: "user", at: 1, text: "报销会议", source: { sender: "owner" } })).ok, true);
assert.equal((await call("timeline.query", { query: "报销" })).result.entries[0].id, "meeting");
const invalid = await call("timeline.read", { id: "missing" }); assert.equal(invalid.ok, false); assert.equal(invalid.id, "test");
const second = spawn(process.execPath, ["src/server.js"], { env, stdio: "ignore" });
assert.notEqual((await once(second, "exit"))[0], 0);
assert.equal((await call("health", {})).ok, true);
} finally { server.kill("SIGTERM"); await exited; rmSync(dir, { recursive: true, force: true }); }
});