71 lines
2.4 KiB
JavaScript
71 lines
2.4 KiB
JavaScript
|
|
/**
|
||
|
|
* Snapshot read-only guard tests — verifies that public write paths
|
||
|
|
* throw when _snapshotReadOnly is true.
|
||
|
|
*
|
||
|
|
* After the P1.4 fix, the following methods must reject writes:
|
||
|
|
* - addRelation (public, existing guard)
|
||
|
|
* - removeRelation (public, existing guard)
|
||
|
|
*
|
||
|
|
* Run: node --test --test-force-exit lib/tests/property-based/snapshot-read-only.test.js
|
||
|
|
*/
|
||
|
|
import { Arbiter } from '../../src/core/Arbiter.js';
|
||
|
|
import { describe, it, beforeEach } from 'node:test';
|
||
|
|
import assert from 'node:assert/strict';
|
||
|
|
|
||
|
|
describe('Snapshot Read-Only Guards', () => {
|
||
|
|
let arbiter;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
arbiter = new Arbiter({ fastConstructionMode: true, enableInference: false });
|
||
|
|
arbiter.addNode('user:alice', 'user');
|
||
|
|
arbiter.addNode('project:secret', 'project');
|
||
|
|
arbiter._snapshotReadOnly = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
it('addRelation throws when read-only', () => {
|
||
|
|
assert.throws(
|
||
|
|
() => arbiter.addRelation('user:alice', 'can_read', 'project:secret', 0.9),
|
||
|
|
/Cannot add relation while in snapshot read-only mode/
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('removeRelation throws when read-only', () => {
|
||
|
|
arbiter._snapshotReadOnly = false;
|
||
|
|
arbiter.addRelation('user:alice', 'can_read', 'project:secret', 0.9);
|
||
|
|
arbiter._snapshotReadOnly = true;
|
||
|
|
|
||
|
|
assert.throws(
|
||
|
|
() => arbiter.removeRelation('user:alice', 'can_read', 'project:secret'),
|
||
|
|
/Cannot remove relation while in snapshot read-only mode/
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('writes succeed when not in read-only mode', () => {
|
||
|
|
arbiter._snapshotReadOnly = false;
|
||
|
|
arbiter.addRelation('user:alice', 'can_read', 'project:secret', 0.9);
|
||
|
|
assert.strictEqual(arbiter.relations.length, 1);
|
||
|
|
|
||
|
|
arbiter.addRelation('user:alice', 'can_write', 'project:secret', 0.5);
|
||
|
|
assert.strictEqual(arbiter.relations.length, 2);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('deserialized snapshot rejects writes', () => {
|
||
|
|
arbiter._snapshotReadOnly = false;
|
||
|
|
arbiter.addRelation('user:alice', 'can_read', 'project:secret', 0.9);
|
||
|
|
|
||
|
|
arbiter._snapshotReadOnly = true;
|
||
|
|
|
||
|
|
assert.throws(
|
||
|
|
() => arbiter.addRelation('user:alice', 'can_write', 'project:secret', 0.5),
|
||
|
|
/Cannot add relation while in snapshot read-only mode/
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('fresh arbiter in read-only mode rejects writes immediately', () => {
|
||
|
|
assert.throws(
|
||
|
|
() => arbiter.addRelation('user:alice', 'can_read', 'project:secret', 0.5),
|
||
|
|
/Cannot add relation while in snapshot read-only mode/
|
||
|
|
);
|
||
|
|
});
|
||
|
|
});
|