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.
102 lines
2.8 KiB
JavaScript
102 lines
2.8 KiB
JavaScript
import { describe, test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { PeggyDSLParser } from '../../src/ast/parser/PeggyDSLParser.js';
|
|
|
|
describe('Peggy DSL Parser', () => {
|
|
const parser = new PeggyDSLParser();
|
|
|
|
test('Basic parsing', () => {
|
|
const dsl = `
|
|
definition User {
|
|
role: string
|
|
isActive: boolean
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
hasRole(user, 'admin')
|
|
}
|
|
`;
|
|
|
|
const program = parser.parse(dsl);
|
|
assert.ok(program !== null, 'Program should be created');
|
|
assert.ok(program.definitions.length === 1, 'Should have 1 definition');
|
|
assert.ok(program.facts.length === 1, 'Should have 1 fact');
|
|
assert.ok(program.evidence.length === 1, 'Should have 1 evidence');
|
|
});
|
|
|
|
test('Complex DSL parsing', () => {
|
|
const dsl = `
|
|
definition User {
|
|
role: string
|
|
isActive: boolean
|
|
clearance: string BEHAVES {
|
|
blurring adaptive confidence_95
|
|
} CACHE eager
|
|
}
|
|
|
|
fact hasRole(user: User, role: string) CACHE eager
|
|
fact isMember(user: User, group: Group) transitive CACHE lazy
|
|
|
|
evidence canRead(user: User, doc: Document) {
|
|
hasRole(user, 'admin')
|
|
|
|
isMember(user, *group) {
|
|
canRead(group, doc)
|
|
} limit 5
|
|
|
|
WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
|
|
}
|
|
`;
|
|
|
|
const program = parser.parse(dsl);
|
|
assert.ok(program !== null, 'Program should be created');
|
|
assert.ok(program.definitions.length === 1, 'Should have 1 definition');
|
|
assert.ok(program.facts.length === 2, 'Should have 2 facts');
|
|
assert.ok(program.evidence.length === 1, 'Should have 1 evidence');
|
|
});
|
|
|
|
test('Error handling', () => {
|
|
const invalidDSL = `
|
|
definition User {
|
|
role: string
|
|
// Missing closing brace
|
|
|
|
fact hasRole(user: User, role: string)
|
|
// Missing semicolon
|
|
`;
|
|
|
|
assert.throws(
|
|
() => parser.parse(invalidDSL),
|
|
/Parsing failed/,
|
|
'Should have parsing error message'
|
|
);
|
|
});
|
|
|
|
test('Validation', () => {
|
|
const validDSL = `
|
|
definition User {
|
|
role: string
|
|
isActive: boolean
|
|
}
|
|
|
|
fact hasRole(user: User, role: string)
|
|
`;
|
|
|
|
const invalidDSL = `
|
|
definition User {
|
|
role: string
|
|
// Missing closing brace
|
|
`;
|
|
|
|
const validResult = parser.validate(validDSL);
|
|
assert.ok(validResult.success, 'Valid DSL should pass validation');
|
|
assert.ok(validResult.program !== null, 'Valid DSL should return program');
|
|
|
|
const invalidResult = parser.validate(invalidDSL);
|
|
assert.ok(!invalidResult.success, 'Invalid DSL should fail validation');
|
|
assert.ok(invalidResult.errors.length > 0, 'Should have validation errors');
|
|
});
|
|
});
|