UNPKG

@joystick.js/db-canary

Version:

JoystickDB - A minimalist database server for the Joystick framework

222 lines (159 loc) 6.27 kB
import test from 'ava'; import sinon from 'sinon'; import { create_connection_manager } from '../../../src/server/lib/connection_manager.js'; test.beforeEach((t) => { t.context.clock = sinon.useFakeTimers(); t.context.mock_socket = { id: 'test_socket_1', destroy: sinon.stub() }; }); test.afterEach((t) => { t.context.clock.restore(); sinon.restore(); }); test('create_connection_manager - should create manager with default options', (t) => { const manager = create_connection_manager(); const stats = manager.get_stats(); t.is(stats.total_connections, 0); t.is(stats.max_connections, 1000); t.is(stats.idle_timeout_ms, 10 * 60 * 1000); t.is(stats.request_timeout_ms, 5 * 1000); }); test('create_connection_manager - should create manager with custom options', (t) => { const options = { max_connections: 500, idle_timeout: 5 * 60 * 1000, request_timeout: 3 * 1000 }; const manager = create_connection_manager(options); const stats = manager.get_stats(); t.is(stats.max_connections, 500); t.is(stats.idle_timeout_ms, 5 * 60 * 1000); t.is(stats.request_timeout_ms, 3 * 1000); }); test('add_connection - should add connection successfully', (t) => { const manager = create_connection_manager(); const result = manager.add_connection(t.context.mock_socket); t.true(result); const stats = manager.get_stats(); t.is(stats.total_connections, 1); }); test('add_connection - should reject connection when limit reached', (t) => { const manager = create_connection_manager({ max_connections: 1 }); const socket_1 = { id: 'socket_1', destroy: sinon.stub() }; const socket_2 = { id: 'socket_2', destroy: sinon.stub() }; const result_1 = manager.add_connection(socket_1); const result_2 = manager.add_connection(socket_2); t.true(result_1); t.false(result_2); t.true(socket_2.destroy.calledOnce); const stats = manager.get_stats(); t.is(stats.total_connections, 1); }); test('remove_connection - should remove connection', (t) => { const manager = create_connection_manager(); manager.add_connection(t.context.mock_socket); let stats = manager.get_stats(); t.is(stats.total_connections, 1); manager.remove_connection(t.context.mock_socket.id); stats = manager.get_stats(); t.is(stats.total_connections, 0); }); test('remove_connection - should handle non-existent connection', (t) => { const manager = create_connection_manager(); t.notThrows(() => { manager.remove_connection('non_existent_id'); }); }); test('update_activity - should update connection activity', (t) => { const manager = create_connection_manager(); manager.add_connection(t.context.mock_socket); t.context.clock.tick(5000); t.notThrows(() => { manager.update_activity(t.context.mock_socket.id); }); }); test('update_activity - should handle non-existent connection', (t) => { const manager = create_connection_manager(); t.notThrows(() => { manager.update_activity('non_existent_id'); }); }); test('idle timeout - should destroy connection after idle timeout', (t) => { const manager = create_connection_manager({ idle_timeout: 1000 }); manager.add_connection(t.context.mock_socket); let stats = manager.get_stats(); t.is(stats.total_connections, 1); t.context.clock.tick(1001); t.true(t.context.mock_socket.destroy.calledOnce); stats = manager.get_stats(); t.is(stats.total_connections, 0); }); test('idle timeout - should reset timer on activity', (t) => { const manager = create_connection_manager({ idle_timeout: 1000 }); manager.add_connection(t.context.mock_socket); t.context.clock.tick(500); manager.update_activity(t.context.mock_socket.id); t.context.clock.tick(500); t.false(t.context.mock_socket.destroy.called); t.context.clock.tick(501); t.true(t.context.mock_socket.destroy.calledOnce); }); test('create_request_timeout - should create timeout that destroys connection', (t) => { const manager = create_connection_manager({ request_timeout: 1000 }); manager.add_connection(t.context.mock_socket); const timeout = manager.create_request_timeout(t.context.mock_socket.id, 'test_op'); t.context.clock.tick(1001); t.true(t.context.mock_socket.destroy.calledOnce); clearTimeout(timeout); }); test('create_request_timeout - should handle non-existent connection', (t) => { const manager = create_connection_manager({ request_timeout: 1000 }); const timeout = manager.create_request_timeout('non_existent_id', 'test_op'); t.context.clock.tick(1001); clearTimeout(timeout); t.pass(); }); test('get_stats - should return accurate statistics', (t) => { const manager = create_connection_manager(); const socket_1 = { id: 'socket_1', destroy: sinon.stub() }; const socket_2 = { id: 'socket_2', destroy: sinon.stub() }; manager.add_connection(socket_1); manager.update_activity(socket_1.id); manager.update_activity(socket_1.id); t.context.clock.tick(1000); manager.add_connection(socket_2); manager.update_activity(socket_2.id); const stats = manager.get_stats(); t.is(stats.total_connections, 2); t.is(stats.total_requests, 3); t.is(stats.oldest_connection_age_ms, 1000); }); test('get_stats - should handle empty connections', (t) => { const manager = create_connection_manager(); const stats = manager.get_stats(); t.is(stats.total_connections, 0); t.is(stats.total_requests, 0); t.is(stats.oldest_connection_age_ms, 0); }); test('shutdown - should destroy all connections', (t) => { const manager = create_connection_manager(); const socket_1 = { id: 'socket_1', destroy: sinon.stub() }; const socket_2 = { id: 'socket_2', destroy: sinon.stub() }; manager.add_connection(socket_1); manager.add_connection(socket_2); let stats = manager.get_stats(); t.is(stats.total_connections, 2); manager.shutdown(); t.true(socket_1.destroy.calledOnce); t.true(socket_2.destroy.calledOnce); stats = manager.get_stats(); t.is(stats.total_connections, 0); }); test('shutdown - should handle empty connections', (t) => { const manager = create_connection_manager(); t.notThrows(() => { manager.shutdown(); }); });