initial commit: @arbiter/core authorization engine with js-rigor hardening
Zanzibar-style authorization graph engine (direct/chain/TTU/defeasible/ binary modes, condensed snapshots, value relations) with 39 rigor test campaigns. Includes fixes for snapshot binary writer/reader format mismatch (snapshot-of-snapshot corruption), possibility write-boundary validation, empty-graph snapshot serialization, relation lookup cache direction collision, config-redefinition cache invalidation, binary threshold semantics, defeasible compiled routing, and comparator reason whitelisting.
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import { test, describe, it, beforeEach } from 'node:test';
|
||||
import assert from 'node:assert';
|
||||
import { Arbiter } from '../../src/core/Arbiter.js';
|
||||
import { ChainRule } from '../../src/authorization/rules/ChainRule.js';
|
||||
|
||||
describe('Cache Memory Improvements (SimpleLRUCache default, injectable factory)', () => {
|
||||
let arbiter;
|
||||
let chainRule;
|
||||
|
||||
beforeEach(() => {
|
||||
arbiter = new Arbiter({
|
||||
directCheckCacheSize: 1000,
|
||||
directCheckCacheTTL: 60000
|
||||
});
|
||||
chainRule = new ChainRule(arbiter);
|
||||
});
|
||||
|
||||
it('should use SimpleLRUCache (default cacheFactory) for chain caches', () => {
|
||||
// Verify ChainRule uses the default SimpleLRUCache
|
||||
assert.ok(chainRule.chainResultCache.constructor.name === 'SimpleLRUCache');
|
||||
|
||||
// Verify cache capacity
|
||||
assert.strictEqual(chainRule.maxCacheSize, 2000);
|
||||
});
|
||||
|
||||
it('should use SimpleLRUCache for direct check cache', () => {
|
||||
// Verify Arbiter uses the default SimpleLRUCache
|
||||
assert.ok(arbiter.directCheckCache.constructor.name === 'SimpleLRUCache');
|
||||
|
||||
// Verify cache capacity
|
||||
assert.strictEqual(arbiter.directCheckCacheSize, 1000);
|
||||
});
|
||||
|
||||
it('should use SimpleLRUCache for relation manager caches', () => {
|
||||
// Cache state lives in RelationCaches (RF-08): reach it via `_caches`.
|
||||
assert.ok(arbiter.relationManager._caches.relationLookupCache.constructor.name === 'SimpleLRUCache');
|
||||
assert.ok(arbiter.relationManager._caches.valueLookupCache.constructor.name === 'SimpleLRUCache');
|
||||
|
||||
// Verify cache capacity
|
||||
assert.strictEqual(arbiter.relationManager._caches.maxCacheSize, 10000);
|
||||
});
|
||||
|
||||
it('should use SimpleLRUCache for value manager caches', () => {
|
||||
// Verify ValueManager uses the default SimpleLRUCache
|
||||
assert.ok(arbiter.valueManager.blurredValueCache.constructor.name === 'SimpleLRUCache');
|
||||
assert.ok(arbiter.valueManager.distributionCache.constructor.name === 'SimpleLRUCache');
|
||||
});
|
||||
|
||||
it('should use SimpleLRUCache for similarity manager cache', () => {
|
||||
// SimilarityManager is only constructed when similarityParams are provided
|
||||
const simArbiter = new Arbiter({ similarityParams: {} });
|
||||
assert.ok(simArbiter.similarityManager.nodeKeyToVector.constructor.name === 'SimpleLRUCache');
|
||||
});
|
||||
|
||||
it('should handle cache eviction automatically', () => {
|
||||
// Test that the default cache handles eviction automatically
|
||||
const cache = chainRule.chainResultCache;
|
||||
const initialSize = cache.size();
|
||||
|
||||
// Fill cache beyond capacity
|
||||
for (let i = 0; i < chainRule.maxCacheSize + 100; i++) {
|
||||
cache.set(`key_${i}`, { result: { possibility: 0.5 }, timestamp: Date.now() });
|
||||
}
|
||||
|
||||
// Cache should not exceed capacity
|
||||
assert.ok(cache.size() <= chainRule.maxCacheSize);
|
||||
console.log(`Cache size after overflow: ${cache.size()} (max: ${chainRule.maxCacheSize})`);
|
||||
});
|
||||
|
||||
it('should track eviction statistics', () => {
|
||||
// Test that eviction statistics are tracked
|
||||
const cache = chainRule.chainResultCache;
|
||||
|
||||
// Fill cache beyond capacity to trigger evictions
|
||||
for (let i = 0; i < chainRule.maxCacheSize + 50; i++) {
|
||||
cache.set(`key_${i}`, { result: { possibility: 0.5 }, timestamp: Date.now() });
|
||||
}
|
||||
|
||||
// Check if eviction stats are tracked
|
||||
if (chainRule.stats) {
|
||||
console.log(`Chain result cache evictions: ${chainRule.stats.evictedResults || 0}`);
|
||||
console.log(`Chain path cache evictions: ${chainRule.stats.evictedPaths || 0}`);
|
||||
}
|
||||
});
|
||||
|
||||
it('should provide better memory management than Map', () => {
|
||||
// Compare memory usage patterns
|
||||
const mapCache = new Map();
|
||||
const hyperbolicCache = chainRule.chainResultCache;
|
||||
|
||||
// Fill both caches
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const value = { result: { possibility: 0.5 }, timestamp: Date.now() };
|
||||
mapCache.set(`key_${i}`, value);
|
||||
hyperbolicCache.set(`key_${i}`, value);
|
||||
}
|
||||
|
||||
// Map grows indefinitely, the default cache is bounded
|
||||
assert.ok(mapCache.size === 1000);
|
||||
assert.ok(hyperbolicCache.size() <= chainRule.maxCacheSize);
|
||||
|
||||
console.log(`Map size: ${mapCache.size}`);
|
||||
console.log(`SimpleLRUCache size: ${hyperbolicCache.size()}`);
|
||||
});
|
||||
|
||||
it('should handle TTL without manual cleanup', () => {
|
||||
// Test that TTL is handled without manual cleanup
|
||||
const cache = arbiter.directCheckCache;
|
||||
|
||||
// Add entries with different timestamps
|
||||
const now = Date.now();
|
||||
cache.set('key1', { result: { possibility: 0.5 }, timestamp: now });
|
||||
cache.set('key2', { result: { possibility: 0.5 }, timestamp: now - 70000 }); // Expired
|
||||
|
||||
// SimpleLRUCache keeps both entries; TTL is enforced at read time
|
||||
// No manual cleanup needed
|
||||
assert.ok(cache.has('key1'));
|
||||
assert.ok(cache.has('key2')); // Still in cache, but will be evicted based on frequency
|
||||
});
|
||||
});
|
||||
|
||||
console.log('✅ Cache Memory Improvements Test Suite');
|
||||
console.log('📊 Benefits:');
|
||||
console.log(' - Automatic eviction based on frequency and recency');
|
||||
console.log(' - No manual TTL cleanup needed');
|
||||
console.log(' - Bounded memory usage');
|
||||
console.log(' - Better cache hit rates through intelligent eviction');
|
||||
console.log(' - Protection against memory leaks');
|
||||
Reference in New Issue
Block a user