Files
qinglong/test/back/ql3PhysicalEdgeFaultProbe.test.cjs

144 lines
3.9 KiB
JavaScript

const assert = require('node:assert/strict');
const { test } = require('node:test');
const {
buildFaultEvidenceReport,
normalizeFaultManifest,
parseArguments,
validateFaultEnvelope,
} = require('../../scripts/ql3-physical-edge-fault-probe.cjs');
function manifest(fault, overrides = {}) {
return normalizeFaultManifest({
schemaVersion: 1,
evidenceClass: 'physical_edge_fault_candidate',
profile: 'edge',
deviceId: 'router-a1',
fault,
probePath: '/mnt/ql3-fault',
expectedFilesystem: 'ext4',
maximumFilesystemBytes: 64 * 1024 * 1024,
...overrides,
});
}
function observed(overrides = {}) {
return {
platform: 'linux',
architecture: 'arm64',
node: 'v24.18.0',
bootId: '019f0000-0000-7000-8000-000000000001',
processUid: 1000,
probePath: '/mnt/ql3-fault',
mountPath: '/mnt/ql3-fault',
filesystem: 'ext4',
mountOptions: ['rw', 'nosuid', 'nodev'],
totalBytes: 32 * 1024 * 1024,
availableBytes: 0,
expectedErrorCode: 'ENOSPC',
probeEntryCreated: false,
probeEntryRemained: false,
...overrides,
};
}
test('normalizes only bounded dedicated fault filesystem manifests', () => {
assert.equal(manifest('enospc_filesystem').fault, 'enospc_filesystem');
assert.throws(() => manifest('disk_full'), /fault must be one of/);
assert.throws(
() => manifest('enospc_filesystem', { probePath: '/' }),
/absolute non-root path/,
);
assert.throws(
() =>
manifest('enospc_filesystem', {
maximumFilesystemBytes: 257 * 1024 * 1024,
}),
/between 1 and 256 MiB/,
);
assert.throws(
() => manifest('enospc_filesystem', { extra: true }),
/keys must be exactly/,
);
});
test('accepts exact non-root ENOSPC and read-only errno evidence', () => {
assert.deepEqual(
validateFaultEnvelope(manifest('enospc_filesystem'), observed()),
[],
);
assert.deepEqual(
validateFaultEnvelope(
manifest('read_only_filesystem'),
observed({
mountOptions: ['ro', 'nosuid', 'nodev'],
availableBytes: 8 * 1024 * 1024,
expectedErrorCode: 'EROFS',
}),
),
[],
);
});
test('fails widened mounts, capacity, root and wrong errno', () => {
assert.deepEqual(
validateFaultEnvelope(
manifest('enospc_filesystem'),
observed({
mountPath: '/',
filesystem: 'tmpfs',
totalBytes: 128 * 1024 * 1024,
availableBytes: 4096,
processUid: 0,
expectedErrorCode: 'EACCES',
probeEntryRemained: true,
}),
),
[
'probe path must be a dedicated mount point',
'filesystem tmpfs did not equal ext4',
'fault filesystem exceeded its declared capacity',
'fault filesystem still had available blocks',
'ENOSPC probe must run as non-root',
'write probe did not return ENOSPC',
'fault probe entry was not cleaned up',
],
);
});
test('builds digest-bound candidate evidence with explicit exclusions', () => {
const report = buildFaultEvidenceReport({
manifest: manifest('read_only_filesystem'),
observed: observed({
mountOptions: ['ro'],
expectedErrorCode: 'EROFS',
}),
generatedAt: '2026-07-22T00:00:00.000Z',
});
assert.equal(report.supported, false);
assert.equal(report.qualification.passed, true);
assert.ok(
report.qualification.doesNotProve.includes('application_level_recovery'),
);
assert.equal(report.sha256.length, 64);
});
test('requires absolute durable manifest and output paths', () => {
assert.deepEqual(
parseArguments([
'--',
'--manifest=/etc/qinglong/enospc.json',
'--output=/var/lib/qinglong/evidence/enospc.json',
'--json',
]),
{
manifestPath: '/etc/qinglong/enospc.json',
outputPath: '/var/lib/qinglong/evidence/enospc.json',
json: true,
},
);
assert.throws(
() => parseArguments(['--manifest=fault.json', '--output=/tmp/out.json']),
/manifestPath must be absolute/,
);
});