UNPKG

@joystick.js/db-canary

Version:

JoystickDB - A minimalist database server for the Joystick framework

351 lines (288 loc) 12 kB
import test from 'ava'; import net from 'net'; import { create_server } from '../../../src/server/index.js'; import { encode_message, create_message_parser } from '../../../src/server/lib/tcp_protocol.js'; import { initialize_database } from '../../../src/server/lib/query_engine.js'; import { setup_initial_admin, reset_auth_state } from '../../../src/server/lib/user_auth_manager.js'; let server; let port; let admin_username = 'admin'; let admin_password = 'admin123'; test.before(async () => { try { // Reset auth state await reset_auth_state(); // Initialize database for testing initialize_database(); // Create server server = await create_server(); // Start server on random port await new Promise((resolve, reject) => { server.listen(0, (error) => { if (error) { reject(error); return; } port = server.address().port; resolve(); }); }); // Set up initial admin user for all tests await setup_initial_admin(admin_username, admin_password, 'admin@test.com'); } catch (error) { throw error; } }); test.after.always(async () => { if (server) { await server.cleanup(); await new Promise((resolve) => { server.close(resolve); }); } // Clean up auth state await reset_auth_state(); }); const create_client = () => { return new Promise((resolve, reject) => { const client = net.createConnection(port, 'localhost'); const parser = create_message_parser(); let responses = []; client.on('connect', () => { resolve({ client, send: (data) => { const encoded = encode_message(data); client.write(encoded); }, receive: () => { return new Promise((resolve) => { const handler = (data) => { try { const messages = parser.parse_messages(data); for (const message of messages) { // Message is already decoded from MessagePack, no need to JSON.parse responses.push(message); client.off('data', handler); resolve(message); return; } } catch (error) { // Continue listening } }; client.on('data', handler); }); }, close: () => { client.end(); } }); }); client.on('error', reject); }); }; test('production safety - ping operation returns ok: 1', async t => { const { client, send, receive, close } = await create_client(); try { send({ op: 'ping' }); const response = await receive(); t.is(response.ok, 1); } finally { close(); } }); test('production safety - admin stats include comprehensive monitoring', async t => { const { client, send, receive, close } = await create_client(); try { // Authenticate using username and password send({ op: 'authentication', data: { username: admin_username, password: admin_password } }); const auth_response = await receive(); t.is(auth_response.ok, 1); // Get admin stats send({ op: 'admin', data: { admin_action: 'stats' } }); const stats_response = await receive(); t.is(stats_response.ok, 1); // Check comprehensive stats structure t.truthy(stats_response.server); t.truthy(stats_response.memory); t.truthy(stats_response.database); t.truthy(stats_response.performance); t.truthy(stats_response.system); t.truthy(stats_response.connections); t.truthy(stats_response.authentication); // Check server stats t.true(typeof stats_response.server.uptime === 'number'); t.true(typeof stats_response.server.uptime_formatted === 'string'); t.true(typeof stats_response.server.node_version === 'string'); t.true(typeof stats_response.server.platform === 'string'); t.true(typeof stats_response.server.arch === 'string'); t.true(typeof stats_response.server.pid === 'number'); // Check memory stats t.true(typeof stats_response.memory.rss_mb === 'number'); t.true(typeof stats_response.memory.heap_total_mb === 'number'); t.true(typeof stats_response.memory.heap_used_mb === 'number'); t.true(typeof stats_response.memory.heap_used_percent === 'number'); t.true(typeof stats_response.memory.external_mb === 'number'); // Check database stats t.true(typeof stats_response.database.map_size_mb === 'number'); t.true(typeof stats_response.database.used_space_mb === 'number'); t.true(typeof stats_response.database.usage_percent === 'number'); // Check performance stats t.true(typeof stats_response.performance.ops_per_second === 'number'); t.true(typeof stats_response.performance.avg_response_time_ms === 'number'); // Check system stats t.true(typeof stats_response.system.node_version === 'string'); t.true(typeof stats_response.system.platform === 'string'); t.true(typeof stats_response.system.arch === 'string'); t.true(typeof stats_response.system.pid === 'number'); // Check connection stats t.true(typeof stats_response.connections.total_connections === 'number'); t.true(typeof stats_response.connections.max_connections === 'number'); // Check authentication stats t.true(typeof stats_response.authentication.authenticated_clients === 'number'); } finally { close(); } }); test('production safety - request timeout handling', async t => { const { client, send, receive, close } = await create_client(); try { // Authenticate using username and password send({ op: 'authentication', data: { username: admin_username, password: admin_password } }); const auth_response = await receive(); t.is(auth_response.ok, 1); // Send a normal operation that should complete quickly send({ op: 'insert_one', data: { collection: 'test_timeout', document: { name: 'test' } } }); const response = await receive(); t.is(response.ok, 1); t.truthy(response.inserted_id); } finally { close(); } }); test('production safety - connection limits', async t => { // This test verifies that connection management is working // We can't easily test the actual limit without creating 1000+ connections const { client, send, receive, close } = await create_client(); try { send({ op: 'ping' }); const response = await receive(); t.is(response.ok, 1); // Connection should be tracked // We can verify this by checking that the connection was accepted t.pass(); } finally { close(); } }); test('production safety - structured logging for operations', async t => { const { client, send, receive, close } = await create_client(); try { // Authenticate using username and password send({ op: 'authentication', data: { username: admin_username, password: admin_password } }); const auth_response = await receive(); t.is(auth_response.ok, 1); // Perform database operation that should be logged send({ op: 'insert_one', data: { collection: 'test_logging', document: { name: 'test_log' } } }); const response = await receive(); t.is(response.ok, 1); t.truthy(response.inserted_id); // The operation should have been logged with structured format // We can't easily verify the log output in tests, but we can verify the operation succeeded t.pass(); } finally { close(); } }); test('production safety - error handling and categorization', async t => { const { client, send, receive, close } = await create_client(); try { // Authenticate using username and password send({ op: 'authentication', data: { username: admin_username, password: admin_password } }); const auth_response = await receive(); t.is(auth_response.ok, 1); // Try an operation that should fail send({ op: 'insert_one', data: { collection: '', document: { name: 'test' } } }); const response = await receive(); t.is(response.ok, 0); t.truthy(response.error); t.true(response.error.includes('Collection name is required')); } finally { close(); } }); test('production safety - performance metrics tracking', async t => { const { client, send, receive, close } = await create_client(); try { // Authenticate using username and password send({ op: 'authentication', data: { username: admin_username, password: admin_password } }); const auth_response = await receive(); t.is(auth_response.ok, 1); // Perform several operations to generate metrics for (let i = 0; i < 5; i++) { send({ op: 'insert_one', data: { collection: 'test_metrics', document: { index: i } } }); await receive(); } // Get stats to verify metrics are being tracked send({ op: 'admin', data: { admin_action: 'stats' } }); const stats_response = await receive(); t.is(stats_response.ok, 1); t.true(typeof stats_response.performance.ops_per_second === 'number'); t.true(typeof stats_response.performance.avg_response_time_ms === 'number'); } finally { close(); } }); test('production safety - memory and resource monitoring', async t => { const { client, send, receive, close } = await create_client(); try { // Authenticate using username and password send({ op: 'authentication', data: { username: admin_username, password: admin_password } }); const auth_response = await receive(); t.is(auth_response.ok, 1); // Get stats to verify resource monitoring send({ op: 'admin', data: { admin_action: 'stats' } }); const stats_response = await receive(); t.is(stats_response.ok, 1); // Verify memory monitoring t.true(stats_response.memory.rss_mb > 0); t.true(stats_response.memory.heap_total_mb > 0); t.true(stats_response.memory.heap_used_mb > 0); t.true(stats_response.memory.heap_used_percent >= 0 && stats_response.memory.heap_used_percent <= 100); // Verify database resource monitoring t.true(stats_response.database.map_size_mb >= 0); t.true(stats_response.database.used_space_mb >= 0); t.true(stats_response.database.usage_percent >= 0 && stats_response.database.usage_percent <= 100); // Verify system resource monitoring t.true(stats_response.system.cpu_user_ms >= 0); t.true(stats_response.system.cpu_system_ms >= 0); } finally { close(); } }); test('production safety - connection management stats', async t => { const { client, send, receive, close } = await create_client(); try { // Authenticate using username and password send({ op: 'authentication', data: { username: admin_username, password: admin_password } }); const auth_response = await receive(); t.is(auth_response.ok, 1); // Get stats to verify connection management send({ op: 'admin', data: { admin_action: 'stats' } }); const stats_response = await receive(); t.is(stats_response.ok, 1); // Verify connection stats t.true(typeof stats_response.connections.total_connections === 'number'); t.true(typeof stats_response.connections.max_connections === 'number'); t.true(typeof stats_response.connections.total_requests === 'number'); t.true(typeof stats_response.connections.idle_timeout_ms === 'number'); t.true(typeof stats_response.connections.request_timeout_ms === 'number'); t.true(stats_response.connections.total_connections >= 1); // At least our connection t.is(stats_response.connections.max_connections, 1000); // Default max t.is(stats_response.connections.idle_timeout_ms, 10 * 60 * 1000); // 10 minutes t.is(stats_response.connections.request_timeout_ms, 5 * 1000); // 5 seconds } finally { close(); } });