mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
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/,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user