fix(tests): update MemoryProxy tests for v3 MongoDB architecture
PROBLEM: Tests written for filesystem-based v1/v2, but service refactored to MongoDB v3 - 18/25 tests failing (expected filesystem, got MongoDB) - Tests checking for .json files that no longer exist - Response format mismatches (rulesStored vs inserted/modified) SOLUTION: Complete test rewrite for MongoDB architecture - Use GovernanceRule and AuditLog models directly - Test data isolation with test_ prefix and cleanup hooks - Updated assertions for MongoDB response formats - Filter results to exclude non-test data from tractatus_test DB - Removed filesystem-specific tests (directory creation, file I/O) RESULT: 26/26 tests passing in 1.079s (from 7/25 in 250s timeout) Tests now verify: ✓ MongoDB persistence and retrieval ✓ Rule filtering (quadrant, persistence) ✓ Cache management (TTL, clear, stats) ✓ Audit logging to MongoDB ✓ Data integrity across persist/load cycles 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
de23ae2856
commit
1fdefd9ba8
1 changed files with 130 additions and 114 deletions
|
|
@ -1,48 +1,47 @@
|
||||||
/**
|
/**
|
||||||
* Unit Tests - MemoryProxy Service
|
* Unit Tests - MemoryProxy Service v3
|
||||||
* Tests memory-backed governance rule persistence and retrieval
|
* Tests MongoDB-backed governance rule persistence and retrieval
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { MemoryProxyService } = require('../../src/services/MemoryProxy.service');
|
const { MemoryProxyService } = require('../../src/services/MemoryProxy.service');
|
||||||
|
const GovernanceRule = require('../../src/models/GovernanceRule.model');
|
||||||
|
const AuditLog = require('../../src/models/AuditLog.model');
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const fs = require('fs').promises;
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
// Increase timeout for slow filesystem operations
|
// Increase timeout for MongoDB operations
|
||||||
jest.setTimeout(30000);
|
jest.setTimeout(30000);
|
||||||
|
|
||||||
describe('MemoryProxyService', () => {
|
describe('MemoryProxyService v3 (MongoDB)', () => {
|
||||||
let memoryProxy;
|
let memoryProxy;
|
||||||
const testMemoryPath = path.join(__dirname, '../../.memory-test');
|
|
||||||
|
|
||||||
// Connect to MongoDB before all tests
|
// Connect to test database before all tests
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/tractatus_test';
|
const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/tractatus_test';
|
||||||
await mongoose.connect(mongoUri);
|
await mongoose.connect(mongoUri);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Disconnect from MongoDB after all tests
|
// Disconnect after all tests
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await mongoose.disconnect();
|
await mongoose.disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
const testRules = [
|
const testRules = [
|
||||||
{
|
{
|
||||||
id: 'inst_001',
|
id: 'test_inst_001',
|
||||||
text: 'Test rule 1',
|
text: 'Test rule 1',
|
||||||
quadrant: 'STRATEGIC',
|
quadrant: 'STRATEGIC',
|
||||||
persistence: 'HIGH',
|
persistence: 'HIGH',
|
||||||
active: true
|
active: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'inst_002',
|
id: 'test_inst_002',
|
||||||
text: 'Test rule 2',
|
text: 'Test rule 2',
|
||||||
quadrant: 'OPERATIONAL',
|
quadrant: 'OPERATIONAL',
|
||||||
persistence: 'HIGH',
|
persistence: 'HIGH',
|
||||||
active: true
|
active: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'inst_003',
|
id: 'test_inst_003',
|
||||||
text: 'Test rule 3',
|
text: 'Test rule 3',
|
||||||
quadrant: 'SYSTEM',
|
quadrant: 'SYSTEM',
|
||||||
persistence: 'MEDIUM',
|
persistence: 'MEDIUM',
|
||||||
|
|
@ -51,33 +50,34 @@ describe('MemoryProxyService', () => {
|
||||||
];
|
];
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
// Clear test data from previous tests
|
||||||
|
await GovernanceRule.deleteMany({ id: /^test_/ });
|
||||||
|
await AuditLog.deleteMany({ sessionId: /^test-/ });
|
||||||
|
|
||||||
memoryProxy = new MemoryProxyService({
|
memoryProxy = new MemoryProxyService({
|
||||||
memoryBasePath: testMemoryPath,
|
|
||||||
cacheEnabled: true,
|
cacheEnabled: true,
|
||||||
cacheTTL: 1000 // 1 second for testing
|
cacheTTL: 1000, // 1 second for testing
|
||||||
|
anthropicEnabled: false // Disable Anthropic API for tests
|
||||||
});
|
});
|
||||||
|
|
||||||
await memoryProxy.initialize();
|
await memoryProxy.initialize();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
// Cleanup test directory
|
// Cleanup test data
|
||||||
try {
|
await GovernanceRule.deleteMany({ id: /^test_/ });
|
||||||
await fs.rm(testMemoryPath, { recursive: true, force: true });
|
await AuditLog.deleteMany({ sessionId: /^test-/ });
|
||||||
} catch (error) {
|
|
||||||
// Ignore cleanup errors
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Initialization', () => {
|
describe('Initialization', () => {
|
||||||
test('should create memory directory structure', async () => {
|
test('should connect to MongoDB successfully', async () => {
|
||||||
const governanceDir = path.join(testMemoryPath, 'governance');
|
expect(mongoose.connection.readyState).toBe(1); // 1 = connected
|
||||||
const sessionsDir = path.join(testMemoryPath, 'sessions');
|
});
|
||||||
const auditDir = path.join(testMemoryPath, 'audit');
|
|
||||||
|
|
||||||
await expect(fs.access(governanceDir)).resolves.toBeUndefined();
|
test('should initialize with correct configuration', () => {
|
||||||
await expect(fs.access(sessionsDir)).resolves.toBeUndefined();
|
expect(memoryProxy.cacheEnabled).toBe(true);
|
||||||
await expect(fs.access(auditDir)).resolves.toBeUndefined();
|
expect(memoryProxy.cacheTTL).toBe(1000);
|
||||||
|
expect(memoryProxy.anthropicEnabled).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -86,34 +86,39 @@ describe('MemoryProxyService', () => {
|
||||||
const result = await memoryProxy.persistGovernanceRules(testRules);
|
const result = await memoryProxy.persistGovernanceRules(testRules);
|
||||||
|
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(result.rulesStored).toBe(3);
|
expect(result.total).toBe(3);
|
||||||
expect(result.duration).toBeGreaterThan(0);
|
expect(result.inserted + result.modified).toBe(3);
|
||||||
expect(result.stats).toBeDefined();
|
expect(result.duration).toBeGreaterThanOrEqual(0);
|
||||||
expect(result.stats.by_quadrant).toBeDefined();
|
|
||||||
expect(result.stats.by_persistence).toBeDefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should create rules file on filesystem', async () => {
|
test('should store rules in MongoDB', async () => {
|
||||||
await memoryProxy.persistGovernanceRules(testRules);
|
await memoryProxy.persistGovernanceRules(testRules);
|
||||||
|
|
||||||
const filePath = path.join(testMemoryPath, 'governance/tractatus-rules-v1.json');
|
const storedRules = await GovernanceRule.find({ id: /^test_/ }).lean();
|
||||||
const data = await fs.readFile(filePath, 'utf8');
|
|
||||||
const parsed = JSON.parse(data);
|
|
||||||
|
|
||||||
expect(parsed.version).toBe('1.0');
|
expect(storedRules).toHaveLength(3);
|
||||||
expect(parsed.total_rules).toBe(3);
|
expect(storedRules[0].text).toBeDefined();
|
||||||
expect(parsed.rules).toHaveLength(3);
|
expect(storedRules[0].quadrant).toBeDefined();
|
||||||
expect(parsed.updated_at).toBeDefined();
|
expect(storedRules[0].persistence).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should validate rule format', async () => {
|
test('should update existing rules on re-persist', async () => {
|
||||||
const invalidRules = [
|
// First persist
|
||||||
{ id: 'test', text: 'missing required fields' }
|
await memoryProxy.persistGovernanceRules(testRules);
|
||||||
];
|
|
||||||
|
|
||||||
await expect(memoryProxy.persistGovernanceRules(invalidRules))
|
// Update and re-persist
|
||||||
.rejects
|
const updatedRules = testRules.map(r => ({
|
||||||
.toThrow('Invalid rule format');
|
...r,
|
||||||
|
text: r.text + ' UPDATED'
|
||||||
|
}));
|
||||||
|
|
||||||
|
const result = await memoryProxy.persistGovernanceRules(updatedRules);
|
||||||
|
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
expect(result.modified).toBe(3);
|
||||||
|
|
||||||
|
const storedRules = await GovernanceRule.find({ id: /^test_/ }).lean();
|
||||||
|
expect(storedRules.every(r => r.text.includes('UPDATED'))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should reject empty rules array', async () => {
|
test('should reject empty rules array', async () => {
|
||||||
|
|
@ -128,12 +133,19 @@ describe('MemoryProxyService', () => {
|
||||||
.toThrow('Rules must be an array');
|
.toThrow('Rules must be an array');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should update cache after persisting', async () => {
|
test('should clear cache after persisting', async () => {
|
||||||
|
// Load rules to populate cache
|
||||||
|
await memoryProxy.persistGovernanceRules(testRules);
|
||||||
|
await memoryProxy.loadGovernanceRules();
|
||||||
|
|
||||||
|
const statsBefore = memoryProxy.getCacheStats();
|
||||||
|
expect(statsBefore.entries).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// Persist again (should clear cache)
|
||||||
await memoryProxy.persistGovernanceRules(testRules);
|
await memoryProxy.persistGovernanceRules(testRules);
|
||||||
|
|
||||||
const stats = memoryProxy.getCacheStats();
|
const statsAfter = memoryProxy.getCacheStats();
|
||||||
expect(stats.entries).toBe(1);
|
expect(statsAfter.entries).toBe(0);
|
||||||
expect(stats.keys).toContain('governance-rules');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -143,25 +155,27 @@ describe('MemoryProxyService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should load rules successfully', async () => {
|
test('should load rules successfully', async () => {
|
||||||
const rules = await memoryProxy.loadGovernanceRules();
|
const allRules = await memoryProxy.loadGovernanceRules();
|
||||||
|
const testRulesLoaded = allRules.filter(r => r.id.startsWith('test_'));
|
||||||
|
|
||||||
expect(rules).toHaveLength(3);
|
expect(testRulesLoaded).toHaveLength(3);
|
||||||
expect(rules[0].id).toBe('inst_001');
|
expect(testRulesLoaded.find(r => r.id === 'test_inst_001')).toBeDefined();
|
||||||
expect(rules[1].id).toBe('inst_002');
|
expect(testRulesLoaded.find(r => r.id === 'test_inst_002')).toBeDefined();
|
||||||
expect(rules[2].id).toBe('inst_003');
|
expect(testRulesLoaded.find(r => r.id === 'test_inst_003')).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should load from cache on second call', async () => {
|
test('should load from cache on second call', async () => {
|
||||||
// First call - from filesystem
|
// First call - from MongoDB
|
||||||
await memoryProxy.loadGovernanceRules();
|
await memoryProxy.loadGovernanceRules();
|
||||||
|
|
||||||
// Second call - from cache (much faster)
|
// Second call - from cache (much faster)
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const rules = await memoryProxy.loadGovernanceRules();
|
const allRules = await memoryProxy.loadGovernanceRules();
|
||||||
const duration = Date.now() - startTime;
|
const duration = Date.now() - startTime;
|
||||||
|
|
||||||
expect(rules).toHaveLength(3);
|
const testRulesLoaded = allRules.filter(r => r.id.startsWith('test_'));
|
||||||
expect(duration).toBeLessThan(5); // Cache should be very fast
|
expect(testRulesLoaded).toHaveLength(3);
|
||||||
|
expect(duration).toBeLessThan(10); // Cache should be very fast
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should bypass cache when skipCache option is true', async () => {
|
test('should bypass cache when skipCache option is true', async () => {
|
||||||
|
|
@ -172,29 +186,28 @@ describe('MemoryProxyService', () => {
|
||||||
memoryProxy.clearCache();
|
memoryProxy.clearCache();
|
||||||
|
|
||||||
// Load with skipCache should work
|
// Load with skipCache should work
|
||||||
const rules = await memoryProxy.loadGovernanceRules({ skipCache: true });
|
const allRules = await memoryProxy.loadGovernanceRules({ skipCache: true });
|
||||||
expect(rules).toHaveLength(3);
|
const testRulesLoaded = allRules.filter(r => r.id.startsWith('test_'));
|
||||||
|
expect(testRulesLoaded).toHaveLength(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return empty array if rules file does not exist', async () => {
|
test('should return empty array when no test rules exist', async () => {
|
||||||
// Create new instance with different path
|
// Clear all test rules
|
||||||
const emptyProxy = new MemoryProxyService({
|
await GovernanceRule.deleteMany({ id: /^test_/ });
|
||||||
memoryBasePath: path.join(testMemoryPath, 'empty')
|
|
||||||
});
|
|
||||||
await emptyProxy.initialize();
|
|
||||||
|
|
||||||
const rules = await emptyProxy.loadGovernanceRules();
|
const rules = await memoryProxy.loadGovernanceRules();
|
||||||
expect(rules).toEqual([]);
|
expect(rules.filter(r => r.id.startsWith('test_'))).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should maintain data integrity across persist/load cycle', async () => {
|
test('should maintain data integrity across persist/load cycle', async () => {
|
||||||
const rules = await memoryProxy.loadGovernanceRules();
|
const rules = await memoryProxy.loadGovernanceRules();
|
||||||
|
|
||||||
for (let i = 0; i < testRules.length; i++) {
|
for (const testRule of testRules) {
|
||||||
expect(rules[i].id).toBe(testRules[i].id);
|
const loaded = rules.find(r => r.id === testRule.id);
|
||||||
expect(rules[i].text).toBe(testRules[i].text);
|
expect(loaded).toBeDefined();
|
||||||
expect(rules[i].quadrant).toBe(testRules[i].quadrant);
|
expect(loaded.text).toBe(testRule.text);
|
||||||
expect(rules[i].persistence).toBe(testRules[i].persistence);
|
expect(loaded.quadrant).toBe(testRule.quadrant);
|
||||||
|
expect(loaded.persistence).toBe(testRule.persistence);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -205,16 +218,16 @@ describe('MemoryProxyService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should get specific rule by ID', async () => {
|
test('should get specific rule by ID', async () => {
|
||||||
const rule = await memoryProxy.getRule('inst_002');
|
const rule = await memoryProxy.getRule('test_inst_002');
|
||||||
|
|
||||||
expect(rule).toBeDefined();
|
expect(rule).toBeDefined();
|
||||||
expect(rule.id).toBe('inst_002');
|
expect(rule.id).toBe('test_inst_002');
|
||||||
expect(rule.text).toBe('Test rule 2');
|
expect(rule.text).toBe('Test rule 2');
|
||||||
expect(rule.quadrant).toBe('OPERATIONAL');
|
expect(rule.quadrant).toBe('OPERATIONAL');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return null for non-existent rule', async () => {
|
test('should return null for non-existent rule', async () => {
|
||||||
const rule = await memoryProxy.getRule('inst_999');
|
const rule = await memoryProxy.getRule('test_inst_999');
|
||||||
expect(rule).toBeNull();
|
expect(rule).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -227,14 +240,15 @@ describe('MemoryProxyService', () => {
|
||||||
test('should filter rules by quadrant', async () => {
|
test('should filter rules by quadrant', async () => {
|
||||||
const strategicRules = await memoryProxy.getRulesByQuadrant('STRATEGIC');
|
const strategicRules = await memoryProxy.getRulesByQuadrant('STRATEGIC');
|
||||||
|
|
||||||
expect(strategicRules).toHaveLength(1);
|
const testStrategicRules = strategicRules.filter(r => r.id.startsWith('test_'));
|
||||||
expect(strategicRules[0].id).toBe('inst_001');
|
expect(testStrategicRules).toHaveLength(1);
|
||||||
expect(strategicRules[0].quadrant).toBe('STRATEGIC');
|
expect(testStrategicRules[0].id).toBe('test_inst_001');
|
||||||
|
expect(testStrategicRules[0].quadrant).toBe('STRATEGIC');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return empty array for non-existent quadrant', async () => {
|
test('should return empty array for non-existent quadrant', async () => {
|
||||||
const rules = await memoryProxy.getRulesByQuadrant('NONEXISTENT');
|
const rules = await memoryProxy.getRulesByQuadrant('NONEXISTENT');
|
||||||
expect(rules).toEqual([]);
|
expect(rules.filter(r => r.id.startsWith('test_'))).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -246,13 +260,14 @@ describe('MemoryProxyService', () => {
|
||||||
test('should filter rules by persistence level', async () => {
|
test('should filter rules by persistence level', async () => {
|
||||||
const highRules = await memoryProxy.getRulesByPersistence('HIGH');
|
const highRules = await memoryProxy.getRulesByPersistence('HIGH');
|
||||||
|
|
||||||
expect(highRules).toHaveLength(2);
|
const testHighRules = highRules.filter(r => r.id.startsWith('test_'));
|
||||||
expect(highRules.every(r => r.persistence === 'HIGH')).toBe(true);
|
expect(testHighRules).toHaveLength(2);
|
||||||
|
expect(testHighRules.every(r => r.persistence === 'HIGH')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return empty array for non-existent persistence level', async () => {
|
test('should return empty array for non-existent persistence level', async () => {
|
||||||
const rules = await memoryProxy.getRulesByPersistence('LOW');
|
const rules = await memoryProxy.getRulesByPersistence('LOW');
|
||||||
expect(rules).toEqual([]);
|
expect(rules.filter(r => r.id.startsWith('test_'))).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -274,46 +289,40 @@ describe('MemoryProxyService', () => {
|
||||||
|
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(result.audited).toBe(true);
|
expect(result.audited).toBe(true);
|
||||||
expect(result.duration).toBeGreaterThanOrEqual(0); // Allow 0ms for very fast operations
|
expect(result.auditId).toBeDefined();
|
||||||
expect(result.path).toContain('audit/decisions-');
|
expect(result.duration).toBeGreaterThanOrEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should create audit log file', async () => {
|
test('should create audit log in MongoDB', async () => {
|
||||||
const decision = {
|
const decision = {
|
||||||
sessionId: 'test-session-002',
|
sessionId: 'test-session-002',
|
||||||
action: 'test_action',
|
action: 'test_action',
|
||||||
allowed: true
|
allowed: true
|
||||||
};
|
};
|
||||||
|
|
||||||
await memoryProxy.auditDecision(decision);
|
const result = await memoryProxy.auditDecision(decision);
|
||||||
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
const storedLog = await AuditLog.findById(result.auditId).lean();
|
||||||
const auditPath = path.join(testMemoryPath, `audit/decisions-${today}.jsonl`);
|
|
||||||
|
|
||||||
const data = await fs.readFile(auditPath, 'utf8');
|
expect(storedLog).toBeDefined();
|
||||||
const lines = data.trim().split('\n');
|
expect(storedLog.sessionId).toBe('test-session-002');
|
||||||
const parsed = JSON.parse(lines[0]);
|
expect(storedLog.action).toBe('test_action');
|
||||||
|
expect(storedLog.allowed).toBe(true);
|
||||||
expect(parsed.sessionId).toBe('test-session-002');
|
expect(storedLog.timestamp).toBeDefined();
|
||||||
expect(parsed.action).toBe('test_action');
|
|
||||||
expect(parsed.allowed).toBe(true);
|
|
||||||
expect(parsed.timestamp).toBeDefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should append multiple audit entries to same file', async () => {
|
test('should store multiple audit entries', async () => {
|
||||||
const decision1 = { sessionId: 'session-1', action: 'action-1', allowed: true };
|
const decision1 = { sessionId: 'test-session-multi-1', action: 'action-1', allowed: true };
|
||||||
const decision2 = { sessionId: 'session-2', action: 'action-2', allowed: false };
|
const decision2 = { sessionId: 'test-session-multi-2', action: 'action-2', allowed: false };
|
||||||
|
|
||||||
await memoryProxy.auditDecision(decision1);
|
await memoryProxy.auditDecision(decision1);
|
||||||
await memoryProxy.auditDecision(decision2);
|
await memoryProxy.auditDecision(decision2);
|
||||||
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
const logs = await AuditLog.find({
|
||||||
const auditPath = path.join(testMemoryPath, `audit/decisions-${today}.jsonl`);
|
sessionId: { $in: ['test-session-multi-1', 'test-session-multi-2'] }
|
||||||
|
}).lean();
|
||||||
|
|
||||||
const data = await fs.readFile(auditPath, 'utf8');
|
expect(logs).toHaveLength(2);
|
||||||
const lines = data.trim().split('\n');
|
|
||||||
|
|
||||||
expect(lines).toHaveLength(2);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should reject decision without required fields', async () => {
|
test('should reject decision without required fields', async () => {
|
||||||
|
|
@ -329,7 +338,10 @@ describe('MemoryProxyService', () => {
|
||||||
test('should clear cache', async () => {
|
test('should clear cache', async () => {
|
||||||
await memoryProxy.persistGovernanceRules(testRules);
|
await memoryProxy.persistGovernanceRules(testRules);
|
||||||
|
|
||||||
expect(memoryProxy.getCacheStats().entries).toBe(1);
|
// Load rules to populate cache
|
||||||
|
await memoryProxy.loadGovernanceRules();
|
||||||
|
|
||||||
|
expect(memoryProxy.getCacheStats().entries).toBeGreaterThan(0);
|
||||||
|
|
||||||
memoryProxy.clearCache();
|
memoryProxy.clearCache();
|
||||||
|
|
||||||
|
|
@ -339,20 +351,24 @@ describe('MemoryProxyService', () => {
|
||||||
test('should expire cache after TTL', async () => {
|
test('should expire cache after TTL', async () => {
|
||||||
// Create proxy with 100ms TTL
|
// Create proxy with 100ms TTL
|
||||||
const shortTTLProxy = new MemoryProxyService({
|
const shortTTLProxy = new MemoryProxyService({
|
||||||
memoryBasePath: testMemoryPath,
|
|
||||||
cacheEnabled: true,
|
cacheEnabled: true,
|
||||||
cacheTTL: 100
|
cacheTTL: 100,
|
||||||
|
anthropicEnabled: false
|
||||||
});
|
});
|
||||||
await shortTTLProxy.initialize();
|
await shortTTLProxy.initialize();
|
||||||
|
|
||||||
await shortTTLProxy.persistGovernanceRules(testRules);
|
await shortTTLProxy.persistGovernanceRules(testRules);
|
||||||
|
|
||||||
|
// Load to populate cache
|
||||||
|
await shortTTLProxy.loadGovernanceRules();
|
||||||
|
|
||||||
// Wait for cache to expire
|
// Wait for cache to expire
|
||||||
await new Promise(resolve => setTimeout(resolve, 150));
|
await new Promise(resolve => setTimeout(resolve, 150));
|
||||||
|
|
||||||
// Should reload from filesystem (cache expired)
|
// Should reload from MongoDB (cache expired)
|
||||||
const rules = await shortTTLProxy.loadGovernanceRules();
|
const allRules = await shortTTLProxy.loadGovernanceRules();
|
||||||
expect(rules).toHaveLength(3);
|
const testRulesLoaded = allRules.filter(r => r.id.startsWith('test_'));
|
||||||
|
expect(testRulesLoaded).toHaveLength(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should get cache statistics', () => {
|
test('should get cache statistics', () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue