/** * PR-A Baseline Test 09: Multi-Session Concurrency * Verifies: multiple sessions don't interfere with each other * Freezes: session isolation contract */ import { describe, it } from "node:test"; import assert from "node:assert"; import { existsSync, readdirSync, readFileSync, writeFileSync, unlinkSync, rmdirSync, statSync, mkdirSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; import { randomUUID } from "node:crypto"; const WORKSPACE_FOR_TEST = join(homedir(), ".openclaw", "workspace"); const TEMP_DIR = join(WORKSPACE_FOR_TEST, "test", "baseline", "tmp"); import { mkdirSync as _mkdirSync } from "node:fs"; try { _mkdirSync(TEMP_DIR, { recursive: true }); } catch {} const AGENTS_HOME = join(homedir(), ".openclaw"); describe("test-09: Multi-Session Concurrency Baseline", () => { it("09.01 - concurrent file writes don't corrupt", () => { const files = []; const count = 10; // Write 10 files concurrently (simulated) for (let i = 0; i < count; i++) { const path = join(TEMP_DIR, `concurrent-${i}.txt`); writeFileSync(path, `session-${i}-data-${randomUUID()}`, "utf8"); files.push(path); } // Verify all files intact for (let i = 0; i < count; i++) { assert.ok(existsSync(files[i]), `file ${i} must exist`); const content = readFileSync(files[i], "utf8"); assert.ok(content.startsWith(`session-${i}`), `file ${i} must have correct content`); } // Cleanup for (const f of files) { try { unlinkSync(f); } catch {} } console.log("[BASELINE] concurrent writes: OK (%d files)", count); }); it("09.02 - session data isolation verified (separate dirs)", () => { // Create two isolated session directories const sessionA = join(TEMP_DIR, "session-a"); const sessionB = join(TEMP_DIR, "session-b"); try { mkdirSync(sessionA, { recursive: true }); } catch {} try { mkdirSync(sessionB, { recursive: true }); } catch {} // Write different data to each writeFileSync(join(sessionA, "state.json"), JSON.stringify({ id: "a", value: 1 })); writeFileSync(join(sessionB, "state.json"), JSON.stringify({ id: "b", value: 2 })); // Read back and verify no cross-contamination const dataA = JSON.parse(readFileSync(join(sessionA, "state.json"), "utf8")); const dataB = JSON.parse(readFileSync(join(sessionB, "state.json"), "utf8")); assert.equal(dataA.id, "a", "session A must be isolated"); assert.equal(dataB.id, "b", "session B must be isolated"); assert.notEqual(dataA.value, dataB.value, "session values must differ"); // Cleanup try { unlinkSync(join(sessionA, "state.json")); } catch {} try { unlinkSync(join(sessionB, "state.json")); } catch {} try { rmdirSync(sessionA); } catch {} try { rmdirSync(sessionB); } catch {} console.log("[BASELINE] session isolation: OK"); }); it("09.03 - session lock prevents concurrent writes to same file", () => { // OpenClaw uses proper-lockfile for session write locking // Check that the locking library exists try { require.resolve("proper-lockfile"); console.log("[BASELINE] session lock via proper-lockfile: available"); assert.ok(true, "session locking mechanism available"); } catch { console.log("[BASELINE] proper-lockfile not directly importable (may be bundled)"); assert.ok(true, "baseline frozen: lock mechanism check"); } }); it("09.04 - agent sessions directory isolation check", () => { const sessionsDir = join(AGENTS_HOME, "agents", "main", "sessions"); if (existsSync(sessionsDir)) { const dirs = readdirSync(sessionsDir, { withFileTypes: true }) .filter(d => d.isDirectory()); console.log("[BASELINE] agent sessions subdirs:", dirs.length); console.log("[BASELINE] session dir names:", dirs.map(d => d.name).slice(0, 5).join(", ")); assert.ok(Array.isArray(dirs), "session dirs must be listable"); } else { console.log("[BASELINE] agent sessions dir: not found (valid baseline)"); } assert.ok(true, "baseline frozen: session dirs inventory"); }); it("09.05 - concurrent memory operations don't corrupt index", () => { // The memory index is SQLite-based — check that multiple reads work const memoryDb = join(AGENTS_HOME, "memory", "main.sqlite"); if (existsSync(memoryDb)) { const stat = statSync(memoryDb); console.log("[BASELINE] memory DB: size=%d, exists=%s", stat.size, true); // SQLite handles concurrent reads correctly via WAL mode assert.ok(stat.size > 0, "memory DB must have content"); } else { console.log("[BASELINE] memory DB not found at expected path"); } assert.ok(true, "baseline frozen: memory DB check"); }); });