UNPKG

knowledgegraph-mcp

Version:

MCP server for enabling persistent knowledge storage for Claude through a knowledge graph with multiple storage backends

171 lines 6.71 kB
/** * Multi-Backend Test Runner * * Provides utilities for running the same test suite against multiple database backends * to ensure compatibility and feature parity across SQLite and PostgreSQL. */ import { StorageType } from '../../storage/types.js'; /** * Configuration for different database backends used in testing */ export const BACKEND_CONFIGS = [ { name: 'SQLite', config: { type: StorageType.SQLITE, connectionString: 'sqlite://:memory:' }, available: true // SQLite is always available }, { name: 'PostgreSQL', config: { type: StorageType.POSTGRESQL, connectionString: process.env.KNOWLEDGEGRAPH_TEST_CONNECTION_STRING || 'postgresql://postgres:1@localhost:5432/knowledgegraph_test' }, available: true // Will be checked at runtime } ]; /** * Get PostgreSQL connection strings to try (in order of preference) */ function getPostgreSQLConnectionStrings() { // Try environment variable first if (process.env.KNOWLEDGEGRAPH_TEST_CONNECTION_STRING && process.env.KNOWLEDGEGRAPH_TEST_CONNECTION_STRING.startsWith('postgresql://')) { return [process.env.KNOWLEDGEGRAPH_TEST_CONNECTION_STRING]; } // Common PostgreSQL setups to try return [ 'postgresql://postgres:1@localhost:5432/knowledgegraph_test', // Default test password 'postgresql://postgres:password@localhost:5432/knowledgegraph_test', 'postgresql://postgres:@localhost:5432/knowledgegraph_test', // No password 'postgresql://postgres:postgres@localhost:5432/knowledgegraph_test', // Default password ]; } /** * Check if PostgreSQL is available for testing */ export async function checkPostgreSQLAvailability() { const { Pool } = await import('pg'); const connectionStrings = getPostgreSQLConnectionStrings(); for (const connectionString of connectionStrings) { try { console.log(`Testing PostgreSQL connection: ${connectionString.replace(/:[^:@]*@/, ':***@')}`); const pool = new Pool({ connectionString, max: 1, idleTimeoutMillis: 1000, connectionTimeoutMillis: 2000, }); const client = await pool.connect(); client.release(); await pool.end(); console.log('PostgreSQL connection successful'); // Update the backend config with the working connection string const pgBackend = BACKEND_CONFIGS.find(b => b.name === 'PostgreSQL'); if (pgBackend) { pgBackend.config.connectionString = connectionString; } return true; } catch (error) { console.warn(`PostgreSQL connection failed for ${connectionString.replace(/:[^:@]*@/, ':***@')}:`, error instanceof Error ? error.message : error); } } console.warn('PostgreSQL not available for testing - tried all connection strings'); return false; } /** * Get available backend configurations for testing */ export async function getAvailableBackends() { // Create deep copies to avoid mutation issues const backends = BACKEND_CONFIGS.map(config => ({ ...config, config: { ...config.config } })); // Check PostgreSQL availability const pgBackend = backends.find(b => b.name === 'PostgreSQL'); if (pgBackend) { pgBackend.available = await checkPostgreSQLAvailability(); if (!pgBackend.available) { pgBackend.skipReason = 'PostgreSQL server not available at localhost:5432'; } } return backends; } /** * Run a test suite against all available backends * * @param testSuite Function that defines the test suite * @param options Configuration options */ export function runTestsForAllBackends(testSuite, options = {}) { const { skipUnavailable = true, requireAllBackends = false } = options; describe('Multi-Backend Tests', () => { let availableBackends; beforeAll(async () => { availableBackends = await getAvailableBackends(); if (requireAllBackends) { const unavailable = availableBackends.filter(b => !b.available); if (unavailable.length > 0) { throw new Error(`Required backends not available: ${unavailable.map(b => `${b.name} (${b.skipReason})`).join(', ')}`); } } }); // Create test suites for each backend BACKEND_CONFIGS.forEach((backend) => { const testDescription = `${backend.name} Backend`; describe(testDescription, () => { if (skipUnavailable && backend.name === 'PostgreSQL') { // For PostgreSQL, check availability before each test beforeEach(async () => { const available = availableBackends?.find(b => b.name === backend.name); const isAvailable = available?.available ?? false; if (!isAvailable) { const skipReason = available?.skipReason || 'PostgreSQL server not available'; console.log(`Skipping PostgreSQL test: ${skipReason}`); pending(`PostgreSQL test skipped: ${skipReason}`); } }); } testSuite(backend.config, backend.name); }); }); }); } /** * Run a test suite against only available backends (skips unavailable ones) */ export function runTestsForAvailableBackends(testSuite) { return runTestsForAllBackends(testSuite, { skipUnavailable: true }); } /** * Run a test suite against all backends (fails if any backend is unavailable) */ export function runTestsForRequiredBackends(testSuite) { return runTestsForAllBackends(testSuite, { requireAllBackends: true }); } /** * Utility to create backend-specific test data */ export function createTestProject(backendName, testName) { const timestamp = Date.now(); const sanitizedTestName = testName.replace(/[^a-zA-Z0-9]/g, '_'); return `test_${backendName.toLowerCase()}_${sanitizedTestName}_${timestamp}`; } /** * Utility to add backend-specific test timeouts */ export function getBackendTimeout(backendName) { switch (backendName) { case 'PostgreSQL': return 10000; // 10 seconds for PostgreSQL (network overhead) case 'SQLite': return 5000; // 5 seconds for SQLite (in-memory) default: return 5000; } } //# sourceMappingURL=multi-backend-runner.js.map