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,165 @@
|
||||
require('ts-node/register/transpile-only');
|
||||
|
||||
const assert = require('node:assert/strict');
|
||||
const { test } = require('node:test');
|
||||
const {
|
||||
RuntimeRolloutPolicy,
|
||||
shadowOnlyRollout,
|
||||
} = require('../../back/runtime/domain/runtimeRollout');
|
||||
const {
|
||||
MAX_RUNTIME_ROLLOUT_APPROVAL_MS,
|
||||
parseRuntimeRolloutManifest,
|
||||
} = require('../../back/runtime/domain/runtimeRolloutManifest');
|
||||
|
||||
const NOW = 1_750_000_000_000;
|
||||
|
||||
function enabledManifest(overrides = {}) {
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
revision: 'manual-primary-canary-1',
|
||||
enabled: true,
|
||||
approvedBy: 'operator:admin',
|
||||
approvedAtMs: NOW - 1_000,
|
||||
expiresAtMs: NOW + 60_000,
|
||||
rollbackPlanRef: 'docs/runbooks/disable-primary.md',
|
||||
rollout: {
|
||||
defaultMode: 'off',
|
||||
origins: { manual: 'primary' },
|
||||
allowLegacyFallbackBeforeStart: false,
|
||||
},
|
||||
gates: {
|
||||
durableCancellation: 'passed',
|
||||
startupReconciliation: 'passed',
|
||||
atomicLegacyProjection: 'passed',
|
||||
rollbackDrill: 'passed',
|
||||
edgeBudget: 'passed',
|
||||
},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test('resolves per-origin rollout ownership without mutating caller config', () => {
|
||||
const origins = { manual: 'shadow', scheduled_node: 'primary' };
|
||||
const policy = new RuntimeRolloutPolicy({
|
||||
defaultMode: 'off',
|
||||
origins,
|
||||
allowLegacyFallbackBeforeStart: true,
|
||||
});
|
||||
origins.manual = 'off';
|
||||
|
||||
assert.deepEqual(policy.decide('manual'), {
|
||||
origin: 'manual',
|
||||
mode: 'shadow',
|
||||
owner: 'legacy',
|
||||
});
|
||||
assert.deepEqual(policy.decide('scheduled_node'), {
|
||||
origin: 'scheduled_node',
|
||||
mode: 'primary',
|
||||
owner: 'runtime',
|
||||
});
|
||||
assert.deepEqual(policy.decide('grpc'), {
|
||||
origin: 'grpc',
|
||||
mode: 'off',
|
||||
owner: 'legacy',
|
||||
});
|
||||
|
||||
const snapshot = policy.snapshot();
|
||||
snapshot.origins.manual = 'off';
|
||||
assert.equal(policy.modeFor('manual'), 'shadow');
|
||||
});
|
||||
|
||||
test('builds a default-off shadow-only rollout policy', () => {
|
||||
const policy = shadowOnlyRollout(['manual', 'scheduled_node']);
|
||||
|
||||
assert.equal(policy.modeFor('manual'), 'shadow');
|
||||
assert.equal(policy.modeFor('scheduled_node'), 'shadow');
|
||||
assert.equal(policy.modeFor('scheduled_system'), 'off');
|
||||
assert.equal(policy.snapshot().allowLegacyFallbackBeforeStart, false);
|
||||
});
|
||||
|
||||
test('rejects unknown modes and origins at the configuration boundary', () => {
|
||||
assert.throws(
|
||||
() =>
|
||||
new RuntimeRolloutPolicy({
|
||||
defaultMode: 'invalid',
|
||||
origins: {},
|
||||
allowLegacyFallbackBeforeStart: false,
|
||||
}),
|
||||
TypeError,
|
||||
);
|
||||
assert.throws(
|
||||
() =>
|
||||
new RuntimeRolloutPolicy({
|
||||
defaultMode: 'off',
|
||||
origins: { unknown: 'shadow' },
|
||||
allowLegacyFallbackBeforeStart: false,
|
||||
}),
|
||||
TypeError,
|
||||
);
|
||||
assert.throws(
|
||||
() =>
|
||||
new RuntimeRolloutPolicy({
|
||||
defaultMode: 'off',
|
||||
origins: { manual: 'invalid' },
|
||||
allowLegacyFallbackBeforeStart: false,
|
||||
}),
|
||||
TypeError,
|
||||
);
|
||||
});
|
||||
|
||||
test('parses a time-bounded, manual-only rollout manifest', () => {
|
||||
const decision = parseRuntimeRolloutManifest(enabledManifest(), NOW);
|
||||
|
||||
assert.equal(decision.manifest.enabled, true);
|
||||
assert.equal(decision.manifest.revision, 'manual-primary-canary-1');
|
||||
assert.equal(decision.policy.modeFor('manual'), 'primary');
|
||||
assert.equal(decision.policy.modeFor('scheduled_system'), 'off');
|
||||
assert.equal(
|
||||
decision.policy.snapshot().allowLegacyFallbackBeforeStart,
|
||||
false,
|
||||
);
|
||||
|
||||
const disabled = parseRuntimeRolloutManifest(
|
||||
{ schemaVersion: 1, revision: 'disabled-1', enabled: false },
|
||||
NOW,
|
||||
);
|
||||
assert.equal(disabled.policy.modeFor('manual'), 'off');
|
||||
});
|
||||
|
||||
test('rejects broad, stale, incomplete, and extensible rollout manifests', () => {
|
||||
const cases = [
|
||||
enabledManifest({
|
||||
rollout: {
|
||||
defaultMode: 'primary',
|
||||
origins: { manual: 'primary' },
|
||||
allowLegacyFallbackBeforeStart: false,
|
||||
},
|
||||
}),
|
||||
enabledManifest({
|
||||
rollout: {
|
||||
defaultMode: 'off',
|
||||
origins: { scheduled_system: 'primary' },
|
||||
allowLegacyFallbackBeforeStart: false,
|
||||
},
|
||||
}),
|
||||
enabledManifest({
|
||||
expiresAtMs: NOW,
|
||||
}),
|
||||
enabledManifest({
|
||||
expiresAtMs: NOW - 1_000 + MAX_RUNTIME_ROLLOUT_APPROVAL_MS + 1,
|
||||
}),
|
||||
enabledManifest({
|
||||
gates: {
|
||||
durableCancellation: 'passed',
|
||||
startupReconciliation: 'passed',
|
||||
atomicLegacyProjection: 'passed',
|
||||
rollbackDrill: 'passed',
|
||||
},
|
||||
}),
|
||||
{ ...enabledManifest(), futureField: true },
|
||||
];
|
||||
|
||||
for (const manifest of cases) {
|
||||
assert.throws(() => parseRuntimeRolloutManifest(manifest, NOW), TypeError);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user