717ae1031e
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.
353 lines
8.1 KiB
JavaScript
353 lines
8.1 KiB
JavaScript
import { DSLCompiler } from '../DSLCompiler.js';
|
|
import { Arbiter } from '../../core/Arbiter.js';
|
|
|
|
/**
|
|
* Progressive Test Suite - Tests each language feature incrementally
|
|
*/
|
|
export function runProgressiveTestSuite() {
|
|
console.log('=== Progressive DSL Test Suite ===\n');
|
|
|
|
const arbiter = new Arbiter();
|
|
const compiler = new DSLCompiler(arbiter);
|
|
|
|
const tests = [
|
|
{
|
|
name: '1. Basic Definitions',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
age: number
|
|
}`,
|
|
expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
|
|
},
|
|
{
|
|
name: '2. Definitions with Arrays',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
roles: string[]
|
|
permissions: Permission[]
|
|
}`,
|
|
expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
|
|
},
|
|
{
|
|
name: '3. Definitions with Behaviors',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
lastActive: timestamp BEHAVES {
|
|
decaying down hourly
|
|
}
|
|
score: number BEHAVES {
|
|
blurring adaptive confidence_95
|
|
}
|
|
session: string BEHAVES {
|
|
ttl 24h
|
|
}
|
|
}`,
|
|
expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
|
|
},
|
|
{
|
|
name: '4. Definitions with Cache Directives',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
lastActive: timestamp BEHAVES {
|
|
decaying down hourly
|
|
} CACHE lazy
|
|
score: number BEHAVES {
|
|
blurring adaptive confidence_95
|
|
} CACHE eager
|
|
}`,
|
|
expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
|
|
},
|
|
{
|
|
name: '5. Basic Facts',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
fact isActive(user: User)`,
|
|
expected: { definitions: 1, facts: 2, evidence: 0, measures: 0 }
|
|
},
|
|
{
|
|
name: '6. Facts with Properties',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact hasRole(user: User, role: string) CACHE eager
|
|
fact isMember(user: User, group: Group) transitive CACHE lazy
|
|
fact isFriend(user: User, friend: User) symmetrical`,
|
|
expected: { definitions: 1, facts: 3, evidence: 0, measures: 0 }
|
|
},
|
|
{
|
|
name: '7. Facts with Limits',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact isMember(user: User, group: Group) transitive limit 10
|
|
fact isFriend(user: User, friend: User) symmetrical limit 100`,
|
|
expected: { definitions: 1, facts: 2, evidence: 0, measures: 0 }
|
|
},
|
|
{
|
|
name: '8. Simple Evidence',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
hasRole(user, 'admin')
|
|
}`,
|
|
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '9. Evidence with Multiple Statements',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
fact owns(user: User, doc: Document)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
owns(user, doc)
|
|
hasRole(user, 'admin')
|
|
}`,
|
|
expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '10. Evidence with ALWAYS',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact isActive(user: User)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
ALWAYS isActive(user)
|
|
}`,
|
|
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '11. Evidence with REQUIRES',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact hasClearance(user: User, level: string)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
REQUIRES hasClearance(user, doc.level)
|
|
}`,
|
|
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '12. Evidence with WHEN',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
WHEN hasRole(user, 'admin')
|
|
}`,
|
|
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '13. Evidence with WHEN UNLESS',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
fact isSuspended(user: User)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
|
|
}`,
|
|
expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '14. Evidence with Pattern Matching',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact isMember(user: User, group: Group)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
isMember(user, *group) {
|
|
canRead(group, doc)
|
|
}
|
|
}`,
|
|
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '15. Evidence with Pattern Matching and Limits',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact isMember(user: User, group: Group)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
isMember(user, *group) {
|
|
canRead(group, doc)
|
|
} limit 5
|
|
}`,
|
|
expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '16. Evidence with Fusion',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
fact isMember(user: User, group: Group)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
fusion max {
|
|
hasRole(user, 'admin')
|
|
isMember(user, *group) {
|
|
canRead(group, doc)
|
|
}
|
|
}
|
|
}`,
|
|
expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
|
|
},
|
|
{
|
|
name: '17. Basic Measures',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
role: string
|
|
}
|
|
|
|
measure userRole(user: User) {
|
|
user.role
|
|
} PROVIDES string`,
|
|
expected: { definitions: 1, facts: 0, evidence: 0, measures: 1 }
|
|
},
|
|
{
|
|
name: '18. Measures with Fusion',
|
|
dsl: `
|
|
definition User {
|
|
name: string
|
|
role: string
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
|
|
measure userPermissions(user: User) {
|
|
fusion max {
|
|
user.role.permissions
|
|
hasRole(user, 'admin')
|
|
}
|
|
} PROVIDES Permission[]`,
|
|
expected: { definitions: 1, facts: 1, evidence: 0, measures: 1 }
|
|
},
|
|
{
|
|
name: '19. Complete Example',
|
|
dsl: `
|
|
definition User {
|
|
role: string
|
|
isActive: boolean
|
|
lastActive: timestamp BEHAVES {
|
|
decaying down hourly
|
|
} CACHE lazy
|
|
}
|
|
|
|
definition Document {
|
|
level: string
|
|
owner: User
|
|
}
|
|
|
|
fact hasRole(user: User, role: string) CACHE eager
|
|
fact owns(user: User, doc: Document) CACHE eager
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
owns(user, doc)
|
|
|
|
WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
|
|
}
|
|
|
|
measure userRole(user: User) {
|
|
user.role
|
|
} PROVIDES string`,
|
|
expected: { definitions: 2, facts: 2, evidence: 1, measures: 1 }
|
|
}
|
|
];
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
for (const test of tests) {
|
|
console.log(`\n--- ${test.name} ---`);
|
|
|
|
try {
|
|
const result = compiler.compile(test.dsl, `test-${passed + failed + 1}`);
|
|
|
|
const actual = {
|
|
definitions: result.program.definitions.length,
|
|
facts: result.program.facts.length,
|
|
evidence: result.program.evidence.length,
|
|
measures: result.program.measures.length
|
|
};
|
|
|
|
const success = result.success &&
|
|
actual.definitions === test.expected.definitions &&
|
|
actual.facts === test.expected.facts &&
|
|
actual.evidence === test.expected.evidence &&
|
|
actual.measures === test.expected.measures;
|
|
|
|
if (success) {
|
|
console.log('✅ PASSED');
|
|
console.log(` Definitions: ${actual.definitions}, Facts: ${actual.facts}, Evidence: ${actual.evidence}, Measures: ${actual.measures}`);
|
|
passed++;
|
|
} else {
|
|
console.log('❌ FAILED');
|
|
console.log(` Expected: ${JSON.stringify(test.expected)}`);
|
|
console.log(` Actual: ${JSON.stringify(actual)}`);
|
|
if (result.errors.length > 0) {
|
|
console.log(` Errors: ${result.errors.join(', ')}`);
|
|
}
|
|
failed++;
|
|
}
|
|
} catch (error) {
|
|
console.log('❌ FAILED');
|
|
console.log(` Error: ${error.message}`);
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
console.log(`\n=== Test Suite Results ===`);
|
|
console.log(`Total Tests: ${passed + failed}`);
|
|
console.log(`Passed: ${passed}`);
|
|
console.log(`Failed: ${failed}`);
|
|
console.log(`Success Rate: ${((passed / (passed + failed)) * 100).toFixed(1)}%`);
|
|
|
|
return { passed, failed, total: passed + failed };
|
|
}
|
|
|
|
// Run the test suite
|
|
runProgressiveTestSuite();
|