'use strict'; const assert = require('assert'); const fs = require('fs'); const path = require('path'); const RuleCompiler = require('./rule-compiler.js'); // 1. Bundled example ruleset compiles and produces expected cap/tag metadata. const rules = []; const caps = {}; const tags = {}; let err = RuleCompiler.compile( fs.readFileSync(path.join(__dirname, 'examples', 'capabilities-and-tags.ztrules')).toString(), rules, caps, tags); assert.strictEqual(err, null, 'example ruleset must compile, got: ' + JSON.stringify(err)); assert.ok(Array.isArray(rules) && rules.length > 0, 'document-level rules emitted'); assert.strictEqual(caps.ssh.id, 1000, 'cap ssh id'); assert.strictEqual(caps.ssh.default, false, 'cap ssh not default'); assert.ok(caps.ssh.rules.length > 0, 'cap ssh body rendered'); assert.strictEqual(tags.department.id, 1000, 'tag department id'); assert.strictEqual(tags.department.enums.engineering, 400, 'tag department enum'); assert.ok(rules.some(r => r.type === 'ACTION_ACCEPT'), 'example contains an accept rule'); // 2. Syntax/semantic errors return [line, col, message], not a throw. err = RuleCompiler.compile('tag broken\n;\n', [], {}, {}); assert.ok(Array.isArray(err) && err.length === 3, 'error tuple returned'); assert.ok(err[0] >= 1, 'error carries line number'); assert.strictEqual(typeof err[2], 'string'); assert.ok(err[2].length > 0, 'error carries message'); // 3. Undefined tag reference rejected with error tuple. err = RuleCompiler.compile('accept tdiff nosuchtag 1;\n', [], {}, {}); assert.ok(Array.isArray(err) && err.length === 3, 'undefined tag rejected'); // 4. Non-string src rejected without throwing. err = RuleCompiler.compile(42, [], {}, {}); assert.ok(Array.isArray(err), 'non-string src rejected'); console.log('rule-compiler: all tests passed');