mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-22 19:29:13 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { test } = require('node:test');
|
||||
|
||||
const {
|
||||
RUN_CANCELLATION_SCHEMA,
|
||||
RunCancellationFenceRejectedError,
|
||||
RunCancellationNotFoundError,
|
||||
RunCancellationUnavailableError,
|
||||
} = require('@qinglong/runtime-core/run-cancellation');
|
||||
const {
|
||||
createLocalApiRunCancellationRoute,
|
||||
} = require('../dist/run/runCancellationRoute.js');
|
||||
|
||||
const PRINCIPAL = Object.freeze({
|
||||
subject: Object.freeze({ type: 'user', id: 'user-1' }),
|
||||
authenticationId: 'credential:user-1',
|
||||
authenticatedAtMs: 9_000,
|
||||
expiresAtMs: 11_000,
|
||||
assurance: 'single_factor',
|
||||
});
|
||||
const FENCE = Object.freeze({ projectVersion: 2, bindingVersion: 3 });
|
||||
|
||||
function accepted(overrides = {}) {
|
||||
return {
|
||||
status: 'accepted',
|
||||
projectId: 'project-1',
|
||||
runId: 'run-1',
|
||||
runStatus: 'running',
|
||||
runVersion: 5,
|
||||
eventSequence: 7,
|
||||
cancelRequestedAtMs: 10_000,
|
||||
cancelReason: 'user',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function request(overrides = {}) {
|
||||
return {
|
||||
projectId: 'project-1',
|
||||
runId: 'run-1',
|
||||
body: { schema: RUN_CANCELLATION_SCHEMA, mutationId: 'mutation-1' },
|
||||
principal: PRINCIPAL,
|
||||
policyFence: FENCE,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test('publishes one profile-neutral durable cancellation command', async () => {
|
||||
let observed;
|
||||
const route = createLocalApiRunCancellationRoute(
|
||||
{
|
||||
async requestUserCancellation(command) {
|
||||
observed = command;
|
||||
return accepted();
|
||||
},
|
||||
},
|
||||
() => '018f0000-0000-7000-8000-000000000001',
|
||||
);
|
||||
assert.deepEqual(await route.handle(request()), {
|
||||
statusCode: 202,
|
||||
body: { schema: RUN_CANCELLATION_SCHEMA, ...accepted() },
|
||||
});
|
||||
assert.deepEqual(observed, {
|
||||
projectId: 'project-1',
|
||||
runId: 'run-1',
|
||||
mutationId: 'mutation-1',
|
||||
eventId: '018f0000-0000-7000-8000-000000000001',
|
||||
subject: PRINCIPAL.subject,
|
||||
policyFence: FENCE,
|
||||
});
|
||||
});
|
||||
|
||||
test('rejects malformed bodies and incomplete authorization fences', async () => {
|
||||
let calls = 0;
|
||||
const route = createLocalApiRunCancellationRoute(
|
||||
{
|
||||
async requestUserCancellation() {
|
||||
calls += 1;
|
||||
return accepted();
|
||||
},
|
||||
},
|
||||
() => '018f0000-0000-7000-8000-000000000001',
|
||||
);
|
||||
assert.deepEqual(await route.handle(request({ body: { mutationId: 'x' } })), {
|
||||
statusCode: 400,
|
||||
body: {
|
||||
code: 'invalid_run_cancellation_request',
|
||||
schema: RUN_CANCELLATION_SCHEMA,
|
||||
},
|
||||
});
|
||||
assert.deepEqual(await route.handle(request({ policyFence: null })), {
|
||||
statusCode: 503,
|
||||
body: { code: 'run_cancellation_unavailable' },
|
||||
});
|
||||
assert.equal(calls, 0);
|
||||
});
|
||||
|
||||
test('maps replay, terminal, missing, fence and unavailable outcomes', async () => {
|
||||
for (const outcome of [
|
||||
accepted({ status: 'already_requested' }),
|
||||
{
|
||||
status: 'already_terminal',
|
||||
projectId: 'project-1',
|
||||
runId: 'run-1',
|
||||
runStatus: 'succeeded',
|
||||
runVersion: 6,
|
||||
eventSequence: 8,
|
||||
},
|
||||
]) {
|
||||
const route = createLocalApiRunCancellationRoute(
|
||||
{ async requestUserCancellation() { return outcome; } },
|
||||
() => '018f0000-0000-7000-8000-000000000001',
|
||||
);
|
||||
assert.equal((await route.handle(request())).statusCode, 200);
|
||||
}
|
||||
for (const [error, statusCode, code] of [
|
||||
[new RunCancellationNotFoundError(), 404, 'run_not_found'],
|
||||
[
|
||||
new RunCancellationFenceRejectedError('authorization_changed'),
|
||||
409,
|
||||
'run_cancellation_fence_rejected',
|
||||
],
|
||||
[
|
||||
new RunCancellationUnavailableError(),
|
||||
503,
|
||||
'run_cancellation_unavailable',
|
||||
],
|
||||
]) {
|
||||
const route = createLocalApiRunCancellationRoute(
|
||||
{ async requestUserCancellation() { throw error; } },
|
||||
() => '018f0000-0000-7000-8000-000000000001',
|
||||
);
|
||||
const response = await route.handle(request());
|
||||
assert.equal(response.statusCode, statusCode);
|
||||
assert.equal(response.body.code, code);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user