import { expect, tap } from '@git.zone/tstest/tapbundle'; import * as smartdb from '../ts/index.js'; import * as fs from 'fs'; import * as net from 'net'; import * as path from 'path'; import * as os from 'os'; // --------------------------------------------------------------------------- // Test: Stale socket cleanup on startup // Covers: LocalSmartDb.cleanStaleSockets(), isSocketAlive() // --------------------------------------------------------------------------- function makeTmpDir(): string { return fs.mkdtempSync(path.join(os.tmpdir(), 'smartdb-socket-test-')); } function cleanTmpDir(dir: string): void { if (fs.existsSync(dir)) { fs.rmSync(dir, { recursive: true, force: true }); } } // ============================================================================ // Stale socket cleanup: active sockets are preserved // ============================================================================ tap.test('stale-sockets: does not remove active sockets', async () => { const tmpDir = makeTmpDir(); const activeSocketPath = path.join(os.tmpdir(), `smartdb-active-${Date.now()}.sock`); // Create an active socket (server still listening) const activeServer = net.createServer(); await new Promise((resolve) => activeServer.listen(activeSocketPath, resolve)); expect(fs.existsSync(activeSocketPath)).toBeTrue(); // Start LocalSmartDb — should NOT remove the active socket const localDb = new smartdb.LocalSmartDb({ folderPath: tmpDir }); await localDb.start(); expect(fs.existsSync(activeSocketPath)).toBeTrue(); // Cleanup await localDb.stop(); await new Promise((resolve) => activeServer.close(() => resolve())); try { fs.unlinkSync(activeSocketPath); } catch {} cleanTmpDir(tmpDir); }); // ============================================================================ // Stale socket cleanup: startup works with no stale sockets // ============================================================================ tap.test('stale-sockets: startup works cleanly with no stale sockets', async () => { const tmpDir = makeTmpDir(); const localDb = new smartdb.LocalSmartDb({ folderPath: tmpDir }); const info = await localDb.start(); expect(localDb.running).toBeTrue(); expect(info.socketPath).toBeTruthy(); await localDb.stop(); cleanTmpDir(tmpDir); }); // ============================================================================ // Stale socket cleanup: the socket file for the current instance is cleaned on stop // ============================================================================ tap.test('stale-sockets: own socket file is removed on stop', async () => { const tmpDir = makeTmpDir(); const localDb = new smartdb.LocalSmartDb({ folderPath: tmpDir }); const info = await localDb.start(); expect(fs.existsSync(info.socketPath)).toBeTrue(); await localDb.stop(); // Socket file should be gone after graceful stop expect(fs.existsSync(info.socketPath)).toBeFalse(); cleanTmpDir(tmpDir); }); export default tap.start();