/** * Type Definition Tests * * Tests the type definition system of the Evidence DSL, * including fields, behaviors, caching, and complex type structures. */ import { DSLCompiler } from '../DSLCompiler.js'; export class DefinitionTests { constructor() { this.arbiter = null; this.compiler = null; this.testResults = []; } setup(arbiter) { this.arbiter = arbiter; this.compiler = new DSLCompiler(arbiter); } runAllTests() { console.log('=== Type Definition Tests ===\n'); this.testBasicDefinitions(); this.testFieldTypes(); this.testArrayTypes(); this.testBehaviors(); this.testCaching(); this.testComplexDefinitions(); this.testDefinitionErrors(); return this.getTestResults(); } testBasicDefinitions() { console.log('Testing Basic Definitions...'); const testCases = [ { input: `definition User { role: string }`, description: 'Simple definition with one field' }, { input: `definition User { role: string isActive: boolean }`, description: 'Definition with multiple fields' }, { input: `definition Group { name: string description: string created: timestamp }`, description: 'Definition with different field types' } ]; testCases.forEach(({ input, description }) => { try { const result = this.compiler.compile(input, `test-basic-def-${Date.now()}`); this.assert(result.success, `${description} should parse successfully`); this.assert(result.program.definitions.length > 0, 'Should have definitions'); console.log(` ✓ ${description}`); } catch (error) { this.fail(`Basic definition test: ${description}`, error); } }); } testFieldTypes() { console.log('Testing Field Types...'); const testCases = [ { type: 'string', description: 'String field type' }, { type: 'number', description: 'Number field type' }, { type: 'boolean', description: 'Boolean field type' }, { type: 'timestamp', description: 'Timestamp field type' }, { type: 'User', description: 'Custom type field' }, { type: 'Permission', description: 'Another custom type field' } ]; testCases.forEach(({ type, description }) => { try { const dsl = `definition Test { field: ${type} }`; const result = this.compiler.compile(dsl, `test-field-type-${Date.now()}`); this.assert(result.success, `${description} should parse successfully`); console.log(` ✓ ${description}`); } catch (error) { this.fail(`Field type test: ${description}`, error); } }); } testArrayTypes() { console.log('Testing Array Types...'); const testCases = [ { type: 'string[]', description: 'String array' }, { type: 'number[]', description: 'Number array' }, { type: 'boolean[]', description: 'Boolean array' }, { type: 'Permission[]', description: 'Custom type array' }, { type: 'User[]', description: 'User array' } ]; testCases.forEach(({ type, description }) => { try { const dsl = `definition Test { items: ${type} }`; const result = this.compiler.compile(dsl, `test-array-${Date.now()}`); this.assert(result.success, `${description} should parse successfully`); console.log(` ✓ ${description}`); } catch (error) { this.fail(`Array type test: ${description}`, error); } }); } testBehaviors() { console.log('Testing Behaviors...'); const testCases = [ { input: `definition User { balance: number BEHAVES { decaying down hourly } }`, description: 'Decay behavior - down hourly' }, { input: `definition User { reputation: number BEHAVES { decaying up daily } }`, description: 'Decay behavior - up daily' }, { input: `definition User { score: number BEHAVES { decaying neutral weekly } }`, description: 'Decay behavior - neutral weekly' }, { input: `definition User { stability: number BEHAVES { decaying stable monthly } }`, description: 'Decay behavior - stable monthly' }, { input: `definition User { confidence: number BEHAVES { blurring fixed } }`, description: 'Blur behavior - fixed' }, { input: `definition User { accuracy: number BEHAVES { blurring adaptive } }`, description: 'Blur behavior - adaptive' }, { input: `definition User { precision: number BEHAVES { blurring confidence confidence_90 } }`, description: 'Blur behavior - confidence with level' }, { input: `definition User { session: string BEHAVES { ttl 1h } }`, description: 'TTL behavior - hours' }, { input: `definition User { token: string BEHAVES { ttl 24h } }`, description: 'TTL behavior - 24 hours' }, { input: `definition User { cache: string BEHAVES { ttl 7d } }`, description: 'TTL behavior - days' } ]; testCases.forEach(({ input, description }) => { try { const result = this.compiler.compile(input, `test-behavior-${Date.now()}`); this.assert(result.success, `${description} should parse successfully`); console.log(` ✓ ${description}`); } catch (error) { this.fail(`Behavior test: ${description}`, error); } }); } testCaching() { console.log('Testing Caching...'); const testCases = [ { input: `definition User { role: string CACHE eager }`, description: 'Eager caching' }, { input: `definition User { score: number CACHE lazy }`, description: 'Lazy caching' }, { input: `definition User { balance: number BEHAVES { decaying down hourly } CACHE eager }`, description: 'Behavior with eager caching' }, { input: `definition User { reputation: number BEHAVES { blurring adaptive } CACHE lazy }`, description: 'Behavior with lazy caching' } ]; testCases.forEach(({ input, description }) => { try { const result = this.compiler.compile(input, `test-cache-${Date.now()}`); this.assert(result.success, `${description} should parse successfully`); console.log(` ✓ ${description}`); } catch (error) { this.fail(`Cache test: ${description}`, error); } }); } testComplexDefinitions() { console.log('Testing Complex Definitions...'); const testCases = [ { input: `definition User { role: string isActive: boolean lastActive: timestamp BEHAVES { decaying down hourly } CACHE lazy isSuspended: boolean balance: number BEHAVES { decaying down hourly } CACHE eager score: number BEHAVES { blurring adaptive confidence_95 } CACHE lazy session: string BEHAVES { ttl 24h } CACHE eager }`, description: 'Complex definition with multiple behaviors and caching' }, { input: `definition Group { name: string permissions: Permission[] members: User[] created: timestamp BEHAVES { decaying stable monthly } CACHE lazy isPublic: boolean CACHE eager }`, description: 'Definition with arrays and mixed behaviors' }, { input: `definition Document { level: string owner: User tags: string[] content: string BEHAVES { blurring fixed } CACHE lazy accessCount: number BEHAVES { decaying up daily } CACHE eager expiresAt: timestamp BEHAVES { ttl 30d } CACHE eager }`, description: 'Definition with all behavior types' } ]; testCases.forEach(({ input, description }) => { try { const result = this.compiler.compile(input, `test-complex-def-${Date.now()}`); this.assert(result.success, `${description} should parse successfully`); this.assert(result.program.definitions.length > 0, 'Should have definitions'); console.log(` ✓ ${description}`); } catch (error) { this.fail(`Complex definition test: ${description}`, error); } }); } testDefinitionErrors() { console.log('Testing Definition Error Handling...'); const testCases = [ { input: `definition User { role: string`, description: 'Missing closing brace should fail' }, { input: `definition User { role: }`, description: 'Missing field type should fail' }, { input: `definition User { : string }`, description: 'Missing field name should fail' }, { input: `definition User { role: string BEHAVES { }`, description: 'Incomplete behavior should fail' }, { input: `definition User { role: string CACHE }`, description: 'Incomplete cache directive should fail' }, { input: `definition User { role: string BEHAVES { invalid } }`, description: 'Invalid behavior should fail' } ]; testCases.forEach(({ input, description }) => { try { const result = this.compiler.compile(input, `test-def-error-${Date.now()}`); this.assert(!result.success, `${description} should fail to parse`); console.log(` ✓ ${description} (correctly failed)`); } catch (error) { // Expected to fail console.log(` ✓ ${description} (correctly failed)`); } }); } assert(condition, message) { if (!condition) { throw new Error(`Assertion failed: ${message}`); } } fail(testName, error) { console.log(` ✗ ${testName} failed: ${error.message}`); this.testResults.push({ test: testName, status: 'FAILED', error: error.message }); } getTestResults() { const passed = this.testResults.filter(r => r.status === 'PASSED').length; const failed = this.testResults.filter(r => r.status === 'FAILED').length; const total = this.testResults.length; return { total: total, passed: passed, failed: failed, success: failed === 0, results: this.testResults }; } } export function runDefinitionTests(arbiter) { const test = new DefinitionTests(); test.setup(arbiter); return test.runAllTests(); }