import { describe, test } from 'node:test'; import assert from 'node:assert/strict'; import fc from 'fast-check'; import { Arbiter } from '../../src/core/Arbiter.js'; function keyFor(srcId, dstId) { return `${srcId}->${dstId}`; } describe('Fast-check: direct relations invariants', () => { test('direct checks match add/remove sequence', () => { fc.assert( fc.property( fc.integer({ min: 1, max: 5 }), fc.integer({ min: 1, max: 5 }), fc.array( fc.record({ src: fc.integer({ min: 0, max: 4 }), dst: fc.integer({ min: 0, max: 4 }), op: fc.constantFrom('add', 'remove') }), { minLength: 1, maxLength: 50 } ), (userCount, docCount, ops) => { const arbiter = new Arbiter(); arbiter.setRelationConfig('owner', { type: 'direct' }); for (let u = 0; u < userCount; u++) { arbiter.addNode(`user:${u}`, 'user'); } for (let d = 0; d < docCount; d++) { arbiter.addNode(`doc:${d}`, 'doc'); } const model = new Set(); for (const op of ops) { const src = op.src % userCount; const dst = op.dst % docCount; if (op.op === 'add') { arbiter.addRelation(`user:${src}`, 'owner', `doc:${dst}`, 1.0); model.add(keyFor(src, dst)); } else { arbiter.removeRelation(`user:${src}`, 'owner', `doc:${dst}`); model.delete(keyFor(src, dst)); } } for (let u = 0; u < userCount; u++) { for (let d = 0; d < docCount; d++) { const result = arbiter.check(`user:${u}`, 'owner', `doc:${d}`); const hasEdge = model.has(keyFor(u, d)); assert.strictEqual(result.possibility > 0, hasEdge); } } } ), { numRuns: 50 } ); }); });