mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
test(ql3): qualify failed upgrades on edge devices
This commit is contained in:
@@ -117,6 +117,7 @@ test('builds tier-specific workload plans without shell commands', () => {
|
||||
'local-workflow-sqlite-lock',
|
||||
'local-workflow-admission-crash-recovery',
|
||||
'local-workflow-control-crash-recovery',
|
||||
'plugin-package-failed-upgrade',
|
||||
],
|
||||
);
|
||||
assert.match(edge[0].script, /ql3-edge-benchmark\.cjs$/);
|
||||
@@ -135,10 +136,7 @@ test('builds tier-specific workload plans without shell commands', () => {
|
||||
),
|
||||
true,
|
||||
);
|
||||
const edgeRelease = createWorkloadPlans(
|
||||
'/workspace',
|
||||
'edge-release-ci',
|
||||
);
|
||||
const edgeRelease = createWorkloadPlans('/workspace', 'edge-release-ci');
|
||||
assert.deepEqual(
|
||||
edgeRelease.map(({ name }) => name),
|
||||
[
|
||||
@@ -152,6 +150,7 @@ test('builds tier-specific workload plans without shell commands', () => {
|
||||
'local-workflow-control-crash-recovery',
|
||||
'local-ai-prompt-model-invocation-crash-recovery',
|
||||
'local-ai-prompt-outer-transaction-crash-recovery',
|
||||
'plugin-package-failed-upgrade',
|
||||
],
|
||||
);
|
||||
assert.equal(
|
||||
@@ -185,17 +184,11 @@ test('builds tier-specific workload plans without shell commands', () => {
|
||||
assert.equal(edgeRelease[3].contract.exactReplay, true);
|
||||
assert.equal(edgeRelease[3].contract.contentFree, true);
|
||||
assert.equal(edgeRelease[3].contract.durableOutputBytes, 512 * 1024);
|
||||
assert.equal(
|
||||
edgeRelease[3].contract.maxWalWriteAmplificationPermille,
|
||||
0,
|
||||
);
|
||||
assert.equal(edgeRelease[3].contract.maxWalWriteAmplificationPermille, 0);
|
||||
assert.equal(edgeRelease[4].contract.profile, 'standalone');
|
||||
assert.equal(edgeRelease[4].contract.journalMode, 'wal');
|
||||
assert.equal(edgeRelease[4].contract.requireWalGrowth, true);
|
||||
assert.match(
|
||||
edge[3].script,
|
||||
/ql3-local-workflow-resource-benchmark\.cjs$/,
|
||||
);
|
||||
assert.match(edge[3].script, /ql3-local-workflow-resource-benchmark\.cjs$/);
|
||||
assert.ok(edge[3].args.includes('--lock-samples=16'));
|
||||
assert.ok(edge[3].args.includes('--max-lock-p95-ms=500'));
|
||||
assert.equal(edge[4].contract.scenarios, 16);
|
||||
@@ -221,6 +214,12 @@ test('builds tier-specific workload plans without shell commands', () => {
|
||||
true,
|
||||
);
|
||||
assert.equal(edgeRelease[9].contract.physicalPowerLossProven, false);
|
||||
assert.match(
|
||||
edge.at(-1).script,
|
||||
/ql3-plugin-package-recovery-edge-benchmark\.cjs$/,
|
||||
);
|
||||
assert.ok(edge.at(-1).args.includes('--max-rss-delta-mb=64'));
|
||||
assert.ok(edgeRelease.at(-1).args.includes('--max-rss-delta-mb=96'));
|
||||
const cluster = createWorkloadPlans('/workspace', 'cluster-control-ci');
|
||||
assert.deepEqual(
|
||||
cluster.map(({ name }) => name),
|
||||
@@ -248,7 +247,9 @@ test('fails closed when durable Prompt resource evidence drifts', () => {
|
||||
const [edgePlan, standalonePlan] = createWorkloadPlans(
|
||||
'/workspace',
|
||||
'edge-release-ci',
|
||||
).filter(({ contract }) => contract?.kind === 'durable_prompt_output_resource');
|
||||
).filter(
|
||||
({ contract }) => contract?.kind === 'durable_prompt_output_resource',
|
||||
);
|
||||
const evidence = {
|
||||
profile: 'edge',
|
||||
journalMode: 'delete',
|
||||
@@ -268,7 +269,9 @@ test('fails closed when durable Prompt resource evidence drifts', () => {
|
||||
physicalPowerLossProven: false,
|
||||
};
|
||||
const output = (value) =>
|
||||
`tests 1\npass 1\nfail 0\nskipped 0\nQL3_RESOURCE_EVIDENCE=${JSON.stringify(value)}\n`;
|
||||
`tests 1\npass 1\nfail 0\nskipped 0\nQL3_RESOURCE_EVIDENCE=${JSON.stringify(
|
||||
value,
|
||||
)}\n`;
|
||||
assert.equal(
|
||||
parseNodeTestReport(output(evidence), edgePlan).evidence.profile,
|
||||
'edge',
|
||||
@@ -301,12 +304,8 @@ test('fails closed when durable Prompt resource evidence drifts', () => {
|
||||
});
|
||||
|
||||
test('fails closed when authenticated Workflow cancellation evidence drifts', () => {
|
||||
const plan = createWorkloadPlans(
|
||||
'/workspace',
|
||||
'edge-release-ci',
|
||||
).find(
|
||||
({ contract }) =>
|
||||
contract?.kind === 'local_workflow_product_lifecycle',
|
||||
const plan = createWorkloadPlans('/workspace', 'edge-release-ci').find(
|
||||
({ contract }) => contract?.kind === 'local_workflow_product_lifecycle',
|
||||
);
|
||||
assert.ok(plan);
|
||||
const completionEvidence = {
|
||||
@@ -332,10 +331,12 @@ test('fails closed when authenticated Workflow cancellation evidence drifts', ()
|
||||
physicalPowerLossProven: false,
|
||||
};
|
||||
const output = (value) =>
|
||||
`tests 2\npass 2\nfail 0\nskipped 0\nQL3_RESOURCE_EVIDENCE=${JSON.stringify(completionEvidence)}\nQL3_RESOURCE_EVIDENCE=${JSON.stringify(value)}\n`;
|
||||
`tests 2\npass 2\nfail 0\nskipped 0\nQL3_RESOURCE_EVIDENCE=${JSON.stringify(
|
||||
completionEvidence,
|
||||
)}\nQL3_RESOURCE_EVIDENCE=${JSON.stringify(value)}\n`;
|
||||
assert.equal(
|
||||
parseNodeTestReport(output(cancellationEvidence), plan)
|
||||
.evidenceRecords[1].processExited,
|
||||
parseNodeTestReport(output(cancellationEvidence), plan).evidenceRecords[1]
|
||||
.processExited,
|
||||
true,
|
||||
);
|
||||
assert.throws(
|
||||
|
||||
@@ -24,6 +24,9 @@ const {
|
||||
validateObservedPlatform,
|
||||
writeNoReplace,
|
||||
} = require('../../scripts/ql3-physical-edge-evidence.cjs');
|
||||
const {
|
||||
runBenchmark: runPluginPackageRecoveryEdgeBenchmark,
|
||||
} = require('../../scripts/ql3-plugin-package-recovery-edge-benchmark.cjs');
|
||||
const {
|
||||
buildReport: buildAdoptionScaleReport,
|
||||
normalizeManifest: normalizeAdoptionScaleManifest,
|
||||
@@ -168,15 +171,49 @@ test('fails closed on architecture, memory, filesystem and virtualization drift'
|
||||
);
|
||||
});
|
||||
|
||||
test('produces digest-bound candidate evidence but never supported status', () => {
|
||||
test('produces digest-bound candidate evidence but never supported status', async () => {
|
||||
const pluginPackageRecovery = await runPluginPackageRecoveryEdgeBenchmark({
|
||||
maxDatabaseGrowthBytes: 4 * 1024 * 1024,
|
||||
maxDurationMs: 10_000,
|
||||
maxRssDeltaBytes: 96 * 1024 * 1024,
|
||||
});
|
||||
const workloads = [
|
||||
{
|
||||
name: 'edge-executor',
|
||||
report: {
|
||||
schemaVersion: 1,
|
||||
profile: 'edge',
|
||||
gates: { passed: true, violations: [] },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'node-sqlite-on-device-storage',
|
||||
report: {
|
||||
journalMode: 'delete',
|
||||
synchronous: 'full',
|
||||
integrityCheck: 'ok',
|
||||
databaseBytes: 16_384,
|
||||
rssDeltaMb: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'plugin-package-failed-upgrade',
|
||||
report: pluginPackageRecovery,
|
||||
},
|
||||
];
|
||||
const report = buildEvidenceReport({
|
||||
manifest: manifest(),
|
||||
observed: observed(),
|
||||
workloads: [{ name: 'edge-executor', report: { gates: { passed: true } } }],
|
||||
workloads,
|
||||
generatedAt: '2026-07-22T00:00:00.000Z',
|
||||
});
|
||||
assert.equal(report.supported, false);
|
||||
assert.equal(report.qualification.physicalCandidate, true);
|
||||
assert.ok(
|
||||
report.qualification.collectedEvidence.includes(
|
||||
'plugin_package_failed_upgrade_retains_active_generation',
|
||||
),
|
||||
);
|
||||
assert.equal(report.sha256.length, 64);
|
||||
const changed = buildEvidenceReport({
|
||||
manifest: manifest({ deviceId: 'router-a2' }),
|
||||
@@ -184,6 +221,12 @@ test('produces digest-bound candidate evidence but never supported status', () =
|
||||
workloads: [],
|
||||
generatedAt: '2026-07-22T00:00:00.000Z',
|
||||
});
|
||||
assert.equal(changed.qualification.physicalCandidate, false);
|
||||
assert.ok(
|
||||
changed.qualification.remainingRequiredEvidence.includes(
|
||||
'plugin_package_failed_upgrade_retains_active_generation',
|
||||
),
|
||||
);
|
||||
assert.notEqual(changed.sha256, report.sha256);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { test } = require('node:test');
|
||||
|
||||
const {
|
||||
parseArguments,
|
||||
runBenchmark,
|
||||
validateReport,
|
||||
} = require('../../scripts/ql3-plugin-package-recovery-edge-benchmark.cjs');
|
||||
|
||||
test('parses bounded failed-upgrade benchmark thresholds', () => {
|
||||
assert.deepEqual(
|
||||
parseArguments([
|
||||
'--json',
|
||||
'--max-duration-ms=5000',
|
||||
'--max-rss-delta-mb=64',
|
||||
'--max-database-growth-bytes=2097152',
|
||||
]),
|
||||
{
|
||||
json: true,
|
||||
maxDatabaseGrowthBytes: 2 * 1024 * 1024,
|
||||
maxDurationMs: 5_000,
|
||||
maxRssDeltaBytes: 64 * 1024 * 1024,
|
||||
},
|
||||
);
|
||||
assert.throws(
|
||||
() => parseArguments(['--max-rss-delta-mb=0']),
|
||||
/positive number/,
|
||||
);
|
||||
assert.throws(() => parseArguments(['--unknown=1']), /unsupported argument/);
|
||||
});
|
||||
|
||||
test('uses real SQLite recovery to reject an invalid upgrade before publication', async () => {
|
||||
const report = await runBenchmark({
|
||||
maxDatabaseGrowthBytes: 4 * 1024 * 1024,
|
||||
maxDurationMs: 10_000,
|
||||
maxRssDeltaBytes: 96 * 1024 * 1024,
|
||||
});
|
||||
|
||||
assert.deepEqual(validateReport(report), []);
|
||||
assert.equal(report.durable.state, 'failed');
|
||||
assert.equal(report.durable.activeLockDigestPreserved, true);
|
||||
assert.equal(report.database.materializedCandidateRevisions, 0);
|
||||
assert.equal(report.calls.publisherPublish, 0);
|
||||
assert.equal(report.gates.passed, true);
|
||||
|
||||
assert.deepEqual(validateReport({ ...report, supported: true }), [
|
||||
'report identity is invalid',
|
||||
]);
|
||||
});
|
||||
Reference in New Issue
Block a user