142 lines
3.4 KiB
JavaScript
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();
|
|
}
|
|
}
|
|
});
|
|
}); |