import { test, expect } from "@playwright/test"; import fs from "fs"; import path from "path"; // We import the module after setting up a temporary log path by monkey patching electron-log. // Since the project primarily uses Playwright for tests, we leverage its expect assertion library. // NOTE: This is a lightweight test that simulates the pruning logic indirectly by invoking the exported ongoingMemoryDump // function and creating artificial heap snapshot files exceeding the threshold. // Because ongoingMemoryDump sets an interval, we invoke its internal logic by importing the file and manually calling dumpMemoryStats. // For simplicity and to avoid altering production code for testability, we replicate the size enforcement logic here and assert behavior. function createDummySnapshots(dir: string, count: number, sizeBytes: number) { fs.mkdirSync(dir, { recursive: true }); for (let i = 0; i < count; i++) { const file = path.join(dir, `dummy-${i}.heapsnapshot`); const fd = fs.openSync(file, "w"); // Write sizeBytes of zeros const buf = Buffer.alloc(1024 * 1024, 0); // 1MB chunk let written = 0; while (written < sizeBytes) { fs.writeSync(fd, buf, 0, Math.min(buf.length, sizeBytes - written)); written += Math.min(buf.length, sizeBytes - written); } fs.closeSync(fd); // Stagger mtime for deterministic pruning ordering const mtime = new Date(Date.now() - (count - i) * 1000); fs.utimesSync(file, mtime, mtime); } } test("heap snapshot directory pruning reduces size below simulated hard cap", async () => { const baseDir = fs.mkdtempSync(path.join(process.cwd(), "heap-test-")); const heapDir = path.join(baseDir, "heap-snapshots"); // Simulate oversize: 15 files of 5MB each = 75MB createDummySnapshots(heapDir, 15, 5 * 1024 * 1024); // Use smaller cap to keep test resource usage low. const MAX_DIR_BYTES = 50 * 1024 * 1024; // 50MB simulated cap const TARGET_REDUCED_BYTES = Math.floor(MAX_DIR_BYTES * 0.9); const files = fs .readdirSync(heapDir) .filter((f) => f.endsWith(".heapsnapshot")); let totalSize = 0; const fileStats: Array<{ file: string; size: number; mtimeMs: number }> = []; for (const file of files) { const stat = fs.statSync(path.join(heapDir, file)); totalSize += stat.size; fileStats.push({ file, size: stat.size, mtimeMs: stat.mtimeMs }); } expect(totalSize).toBeGreaterThan(MAX_DIR_BYTES); fileStats.sort((a, b) => a.mtimeMs - b.mtimeMs); let bytesAfter = totalSize; for (const info of fileStats) { if (bytesAfter <= TARGET_REDUCED_BYTES) break; fs.unlinkSync(path.join(heapDir, info.file)); bytesAfter -= info.size; } expect(bytesAfter).toBeLessThanOrEqual(TARGET_REDUCED_BYTES); // Cleanup fs.rmSync(baseDir, { recursive: true, force: true }); });