@joystick.js/db-canary
Version:
JoystickDB - A minimalist database server for the Joystick framework
269 lines (205 loc) • 9.29 kB
JavaScript
import test from 'ava';
import { initialize_database, cleanup_database } from '../../../src/server/lib/query_engine.js';
import { initialize_index_database, get_indexes, cleanup_index_database } from '../../../src/server/lib/index_manager.js';
import { initialize_auto_index_database, cleanup_auto_index_database } from '../../../src/server/lib/auto_index_manager.js';
import find from '../../../src/server/lib/operations/find.js';
import find_one from '../../../src/server/lib/operations/find_one.js';
import insert_one from '../../../src/server/lib/operations/insert_one.js';
import admin from '../../../src/server/lib/operations/admin.js';
test.beforeEach(async (t) => {
initialize_database('./test_data');
initialize_index_database();
initialize_auto_index_database();
const test_documents = [
{ name: 'Alice', age: 25, department: 'Engineering', salary: 75000 },
{ name: 'Bob', age: 30, department: 'Marketing', salary: 65000 },
{ name: 'Charlie', age: 35, department: 'Engineering', salary: 85000 },
{ name: 'Diana', age: 28, department: 'Sales', salary: 70000 },
{ name: 'Eve', age: 32, department: 'Engineering', salary: 80000 }
];
for (const doc of test_documents) {
await insert_one('default', 'employees', doc);
}
});
test.afterEach(async (t) => {
cleanup_auto_index_database();
cleanup_index_database();
await cleanup_database();
});
test('should record query statistics during find operations', async (t) => {
await find('default', 'employees', { name: 'Alice' });
await find('default', 'employees', { age: 25 });
await find('default', 'employees', { department: 'Engineering' });
const stats = await admin('get_query_stats', { collection: 'employees' });
t.truthy(stats.name);
t.truthy(stats.age);
t.truthy(stats.department);
t.is(stats.name.query_count, 1);
t.is(stats.age.query_count, 1);
t.is(stats.department.query_count, 1);
});
test('should record query statistics during find_one operations', async (t) => {
await find_one('default', 'employees', { name: 'Bob' });
await find_one('default', 'employees', { age: 30 });
const stats = await admin('get_query_stats', { collection: 'employees' });
t.truthy(stats.name);
t.truthy(stats.age);
t.is(stats.name.query_count, 1);
t.is(stats.age.query_count, 1);
});
test('should track execution times for queries', async (t) => {
await find('default', 'employees', { name: 'Alice' });
await find('default', 'employees', { name: 'Bob' });
await find('default', 'employees', { name: 'Charlie' });
const stats = await admin('get_query_stats', { collection: 'employees' });
t.is(stats.name.query_count, 3);
t.true(stats.name.total_time_ms >= 0);
t.true(stats.name.avg_time_ms >= 0);
t.is(stats.name.avg_time_ms, stats.name.total_time_ms / 3);
});
test('should get auto index statistics', async (t) => {
const stats = await admin('get_auto_index_stats');
t.is(typeof stats, 'object');
t.is(stats.total_auto_indexes, 0);
t.is(typeof stats.collections, 'object');
});
test('should force index evaluation', async (t) => {
for (let i = 0; i < 50; i++) {
await find('default', 'employees', { name: `User${i}` });
}
const result = await admin('evaluate_auto_indexes', { collection: 'employees' });
t.is(result.acknowledged, true);
});
test('should force index evaluation for all collections', async (t) => {
await find('default', 'employees', { name: 'Alice' });
await find('default', 'products', { category: 'Electronics' });
const result = await admin('evaluate_auto_indexes');
t.is(result.acknowledged, true);
});
test('should remove automatic indexes', async (t) => {
const result = await admin('remove_auto_indexes', {
collection: 'employees',
field_names: ['name']
});
t.is(result.acknowledged, true);
t.is(typeof result.removed_count, 'number');
});
test('should remove all automatic indexes from collection', async (t) => {
const result = await admin('remove_auto_indexes', { collection: 'employees' });
t.is(result.acknowledged, true);
t.is(typeof result.removed_count, 'number');
});
test('should handle complex query filters', async (t) => {
await find('default', 'employees', {
age: { $gte: 25, $lte: 35 },
department: { $in: ['Engineering', 'Marketing'] },
salary: { $gt: 70000 }
});
const stats = await admin('get_query_stats', { collection: 'employees' });
t.truthy(stats.age);
t.truthy(stats.department);
t.truthy(stats.salary);
t.is(stats.age.query_count, 1);
t.is(stats.department.query_count, 1);
t.is(stats.salary.query_count, 1);
});
test('should track index usage when indexes exist', async (t) => {
await admin('create_index', { collection: 'employees', field: 'name' });
await find('default', 'employees', { name: 'Alice' });
await find('default', 'employees', { name: 'Bob' });
const stats = await admin('get_query_stats', { collection: 'employees' });
t.is(stats.name.query_count, 2);
t.is(stats.name.used_index_count, 2);
});
test('should differentiate between indexed and non-indexed queries', async (t) => {
await admin('create_index', { collection: 'employees', field: 'name' });
await find('default', 'employees', { name: 'Alice' });
await find('default', 'employees', { age: 25 });
const stats = await admin('get_query_stats', { collection: 'employees' });
t.is(stats.name.used_index_count, 1);
t.is(stats.age.used_index_count, 0);
});
test('should handle queries with projection and sorting', async (t) => {
await find('default', 'employees', { department: 'Engineering' }, {
projection: { name: 1, salary: 1 },
sort: { salary: -1 },
limit: 2
});
const stats = await admin('get_query_stats', { collection: 'employees' });
t.truthy(stats.department);
t.is(stats.department.query_count, 1);
});
test('should handle find_one with projection', async (t) => {
await find_one('default', 'employees', { name: 'Alice' }, {
projection: { age: 1, department: 1 }
});
const stats = await admin('get_query_stats', { collection: 'employees' });
t.truthy(stats.name);
t.is(stats.name.query_count, 1);
});
test('should accumulate statistics across multiple operations', async (t) => {
await find('default', 'employees', { name: 'Alice' });
await find_one('default', 'employees', { name: 'Bob' });
await find('default', 'employees', { name: 'Charlie' });
const stats = await admin('get_query_stats', { collection: 'employees' });
t.is(stats.name.query_count, 3);
t.true(stats.name.total_time_ms >= 0);
});
test('should handle empty result sets', async (t) => {
await find('default', 'employees', { name: 'NonExistent' });
await find_one('default', 'employees', { age: 999 });
const stats = await admin('get_query_stats', { collection: 'employees' });
t.truthy(stats.name);
t.truthy(stats.age);
t.is(stats.name.query_count, 1);
t.is(stats.age.query_count, 1);
});
test('should handle queries on non-existent collections', async (t) => {
await find('default', 'non_existent_collection', { field: 'value' });
const stats = await admin('get_query_stats', { collection: 'non_existent_collection' });
t.truthy(stats.field);
t.is(stats.field.query_count, 1);
});
test('should track slow queries correctly', async (t) => {
for (let i = 0; i < 10; i++) {
await find('default', 'employees', { department: 'Engineering' });
}
const stats = await admin('get_query_stats', { collection: 'employees' });
t.is(stats.department.query_count, 10);
t.true(stats.department.slow_query_count >= 0);
});
test('should get statistics for specific collection only', async (t) => {
await find('default', 'employees', { name: 'Alice' });
await find('default', 'products', { category: 'Electronics' });
const employee_stats = await admin('get_query_stats', { collection: 'employees' });
const product_stats = await admin('get_query_stats', { collection: 'products' });
t.truthy(employee_stats.name);
t.falsy(employee_stats.category);
t.truthy(product_stats.category);
t.falsy(product_stats.name);
});
test('should get statistics for all collections', async (t) => {
await find('default', 'employees', { name: 'Alice' });
await find('default', 'products', { category: 'Electronics' });
const all_stats = await admin('get_query_stats');
t.truthy(all_stats.employees);
t.truthy(all_stats.products);
t.truthy(all_stats.employees.name);
t.truthy(all_stats.products.category);
});
test('should handle admin operations without errors', async (t) => {
await t.notThrowsAsync(async () => {
await admin('get_auto_index_stats');
await admin('get_query_stats');
await admin('evaluate_auto_indexes');
await admin('remove_auto_indexes', { collection: 'test' });
});
});
test('should maintain statistics persistence across operations', async (t) => {
await find('default', 'employees', { name: 'Alice' });
let stats = await admin('get_query_stats', { collection: 'employees' });
t.is(stats.name.query_count, 1);
await find('default', 'employees', { name: 'Bob' });
stats = await admin('get_query_stats', { collection: 'employees' });
t.is(stats.name.query_count, 2);
});