63 lines
2.1 KiB
TypeScript
63 lines
2.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
aggregateMetrics,
|
|
calculateScenarioMetrics,
|
|
} from '../../scripts/comms/replay.mjs';
|
|
import { evaluateReport } from '../../scripts/comms/compare.mjs';
|
|
|
|
function buildPassingScenarioMetrics() {
|
|
return {
|
|
duplicate_event_rate: 0,
|
|
event_fanout_ratio: 1,
|
|
history_inflight_max: 1,
|
|
history_load_qps: 0.3,
|
|
rpc_p50_ms: 100,
|
|
rpc_p95_ms: 150,
|
|
rpc_timeout_rate: 0,
|
|
gateway_reconnect_count: 0,
|
|
message_loss_count: 0,
|
|
message_order_violation_count: 0,
|
|
};
|
|
}
|
|
|
|
describe('comms scripts', () => {
|
|
it('computes scenario metrics with dedupe and inflight tracking', () => {
|
|
const metrics = calculateScenarioMetrics([
|
|
{ ts: 0, type: 'gateway_event', runId: 'r1', sessionKey: 's1', seq: 1, state: 'started', fanout: 1 },
|
|
{ ts: 0.2, type: 'gateway_event', runId: 'r1', sessionKey: 's1', seq: 1, state: 'started', fanout: 1 },
|
|
{ ts: 0.5, type: 'history_load', sessionKey: 's1', action: 'start' },
|
|
{ ts: 0.7, type: 'history_load', sessionKey: 's1', action: 'end' },
|
|
{ ts: 1.0, type: 'rpc', latencyMs: 120, timeout: false },
|
|
{ ts: 1.5, type: 'message', lost: false, orderViolation: false },
|
|
]);
|
|
|
|
expect(metrics.duplicate_event_rate).toBeCloseTo(0.5, 6);
|
|
expect(metrics.history_inflight_max).toBe(1);
|
|
expect(metrics.rpc_p95_ms).toBe(120);
|
|
});
|
|
|
|
it('aggregates multiple scenario metrics deterministically', () => {
|
|
const aggregate = aggregateMetrics([
|
|
{ ...buildPassingScenarioMetrics(), rpc_p95_ms: 200 },
|
|
{ ...buildPassingScenarioMetrics(), rpc_p95_ms: 400 },
|
|
]);
|
|
expect(aggregate.rpc_p95_ms).toBe(300);
|
|
expect(aggregate.history_inflight_max).toBe(1);
|
|
});
|
|
|
|
it('fails report evaluation when required scenarios are missing', () => {
|
|
const passing = buildPassingScenarioMetrics();
|
|
const current = {
|
|
aggregate: passing,
|
|
scenarios: {
|
|
'happy-path-chat': passing,
|
|
},
|
|
};
|
|
const baseline = { aggregate: passing };
|
|
const result = evaluateReport(current, baseline);
|
|
|
|
expect(result.failures.some((f) => f.includes('missing scenario'))).toBe(true);
|
|
});
|
|
});
|