const TCPLockServer = require('../lock.tcp'); const TcpRwLock = require('../lock-client.tcp'); const net = require('net'); jest.setTimeout(30000); // Helper function to check if a port is available const isPortAvailable = (port) => { return new Promise((resolve) => { const tester = net.createServer(); tester.listen(port, () => { tester.once('close', () => { resolve(true); }); tester.close(); }); tester.on('error', () => { resolve(false); }); }); }; // Find an available port for testing const findAvailablePort = async (startPort = 7301) => { let port = startPort; while (!(await isPortAvailable(port))) { port++; } return port; }; describe('TCPLock', () => { let server; let port; let connect = {}; // Start server before all tests beforeAll(async () => { port = await findAvailablePort(); connect = { host: 'localhost', port }; server = new TCPLockServer({ host: 'localhost', port }); await server.start(); }); // Stop server after all tests afterAll(() => { if (server) { server.stop(); server = null; } }); test('should be able to create TCP lock client', () => { const lock = new TcpRwLock('test-resource', { connect }); expect(lock).toBeInstanceOf(TcpRwLock); expect(lock.host).toBe('localhost'); expect(lock.port).toBe(port); }); test('should be able to connect to TCP lock server', async () => { const lock = new TcpRwLock('test-resource', { connect }); try { await lock.connect(); // Since there's no isConnected method, we'll check if we can send a request expect(lock.socket).toBeDefined(); expect(lock.socket.destroyed).toBe(false); } finally { if (lock.socket) { lock.close(); } } }); test('should be able to acquire and release read lock', async () => { const lock = new TcpRwLock('test-resource', { connect }); try { await lock.connect(); await lock.readLock(); expect(lock.isLocked).toBe(true); await lock.unlock(); expect(lock.isLocked).toBe(false); } finally { if (lock.socket) { lock.close(); } } }); test('should be able to acquire and release write lock', async () => { const lock = new TcpRwLock('test-resource', { connect }); try { await lock.connect(); await lock.writeLock(); expect(lock.isLocked).toBe(true); await lock.unlock(); expect(lock.isLocked).toBe(false); } finally { if (lock.socket) { lock.close(); } } }); test('should handle multiple clients', async () => { const lock1 = new TcpRwLock('shared-resource', { connect }); const lock2 = new TcpRwLock('shared-resource', { connect }); try { await Promise.all([ lock1.connect(), lock2.connect() ]); // Both clients should be able to acquire read locks await Promise.all([ lock1.readLock(), lock2.readLock() ]); expect(lock1.isLocked).toBe(true); expect(lock2.isLocked).toBe(true); await Promise.all([ lock1.unlock(), lock2.unlock() ]); expect(lock1.isLocked).toBe(false); expect(lock2.isLocked).toBe(false); } finally { if (lock1.socket) { lock1.close(); } if (lock2.socket) { lock2.close(); } } }); });