nlocks/__tests__/tcp-lock.test.js

142 lines
3.4 KiB
JavaScript

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();
}
}
});
});