244 lines
20 KiB
TypeScript
244 lines
20 KiB
TypeScript
/** Actual ESM workflow; fixed dependencies mocked HERE ONLY.
|
|
* No production DI hooks, native transport, actual DB or waiting three seconds. */
|
|
import assert from "node:assert/strict"
|
|
import { afterEach, mock, test } from "node:test"
|
|
import { assertBandwidthTestCompleted } from "./bandwidth-test-status.js"
|
|
import { readBandwidthTestRates } from "./bandwidth-test-rates.js"
|
|
import { persistSpeedRun, SpeedRunPersistenceUnknown } from "./speed-run-persistence.js"
|
|
import { assertMcpSpeedBandwidthWorkflowRequest } from "../modules/mcp/speed-bandwidth-original.js"
|
|
let fixtureSequence = 0
|
|
afterEach(() => mock.restoreAll())
|
|
type Command = { runId?: string; probeId?: string; srcServerId: number; dstServerId: number; srcInterface: string; dstInterface: string;
|
|
protocol: "tcp" | "udp"; direction: "both" | "transmit" | "receive"; durationSec: number }
|
|
type Row = Record<string, unknown>
|
|
class HostError extends Error { constructor(readonly code: "REFUSED" | "OUTCOME_UNKNOWN") { super(code) } }
|
|
async function fixture(kind: "rest-speed" | "scheduled-speed" | "mcp-speed" = "rest-speed", overrides: Partial<Command> = {}) {
|
|
const initialWall = Date.now()
|
|
const owner = new AbortController()
|
|
let enteredNative!: () => void
|
|
const nativeEntered = new Promise<void>(resolve => { enteredNative = resolve })
|
|
const command: Command = { runId: "owned-run", probeId: "owned-probe", srcServerId: 1, dstServerId: 2,
|
|
srcInterface: "ether1", dstInterface: "ether2", protocol: "tcp", direction: "both", durationSec: 10, ...overrides }
|
|
const context = { command, address: "198.51.100.2", srcAddress: "192.0.2.1", dstAddress: "198.51.100.2",
|
|
srcInterfaceAddress: "192.0.2.1", dstInterfaceAddress: "198.51.100.2" }
|
|
const request: Record<string, unknown> = kind === "rest-speed" ? { command } : kind === "scheduled-speed" ? { command,
|
|
job: { job: "uptime_speed", generation: 4, executionId: "12345678-1234-4234-8234-123456789abc", deadlineAt: initialWall + 60000, monotonicDeadline: 60100 } } : { command,
|
|
mcp: { operationName: "uptime.speed-test", serviceName: "uptime.speed-test", operationVersion: 1, phase: "forward", originalExpiresAt: initialWall + 60000,
|
|
serverIds: [1, 2], objects: [1, 2].map(serverId => ({ kind: "server", serverId, id: String(serverId) })),
|
|
serviceInput: { command, expectedEndpoints: [1, 2].map(serverId => ({ serverId, proof: "a".repeat(64) })),
|
|
expectedProbe: command.probeId ? { id: command.probeId, srcServerId: 1, dstServerId: 2, srcInterface: command.srcInterface, dstInterface: command.dstInterface,
|
|
protocol: command.protocol, direction: command.direction, durationSec: command.durationSec, enabled: true } : null } } }
|
|
const intent = { callerKind: kind, sourceServerId: 1, credentialServerId: 2, actualRemotePeer: { kind: "server", serverId: 2 },
|
|
request, expiresAt: initialWall + 60000, durationSec: command.durationSec, socketTimeoutMs: 30000,
|
|
nativeBody: { address: context.address, protocol: command.protocol, direction: command.direction, duration: `${command.durationSec}s`, user: "owned-peer-user", password: "private-peer-password" } }
|
|
const source = { endpoint: { host: "source-host", username: "owned-source-user", password: "private-source-password" } }
|
|
const token = Object.freeze(Object.create(null))
|
|
// Synthetic completion identity for this unit harness ONLY; production uses
|
|
// the actual peer host's private receipt, covered by its owned acceptance.
|
|
const completions = new WeakMap<object, object>()
|
|
const state = { probe: command.probeId ? { ...command, id: command.probeId, telemetry: "old" } as Row : null,
|
|
runs: [] as Row[], transactions: 0, native: 0, pings: 0, contexts: 0, peers: 0, sleeps: [] as number[], events: [] as string[],
|
|
wall: initialWall, mono: 100, waitForAbort: false, observedAbort: false, nativeDeadline: 0, pingSignal: undefined as AbortSignal | undefined,
|
|
forgedCompletion: false, receiptIntentChanged: false, postPeerCredentialReads: 0,
|
|
nativeError: undefined as unknown, afterNative: undefined as (() => void) | undefined, pingError: undefined as unknown,
|
|
freshError: false, measured: true, failWrite: "" as "" | "update" | "insert" | "commit",
|
|
raw: [{ status: "testing", "tx-current": "1000000", "rx-current": "2M", extra: "retained" },
|
|
{ status: "done testing", "tx-total-average": "3000000", "rx-total-average": "4M", extra: "terminal-retained" }] as Row[] }
|
|
const lifetime = { expiresAt: state.wall + 60000, monotonicDeadline: state.mono + 60000, signal: owner.signal }
|
|
const originals = { async readLifetime(current: unknown) { assert.equal(current, token); return lifetime },
|
|
async readOriginal(current: unknown) { assert.equal(current, token); state.events.push("original"); return intent },
|
|
async readSpeedContext(current: unknown) { assert.equal(current, token); state.contexts++; return context },
|
|
async readPeer(current: unknown, peer: unknown) { assert.equal(current, token); assert.equal((peer as { kind: string }).kind, "server"); assert.equal((peer as { serverId: number }).serverId, 1); state.peers++
|
|
if (state.native && state.freshError) throw Error("original source/actor/selection drift")
|
|
if (command.probeId && (!state.probe || state.probe.durationSec !== command.durationSec)) throw Error("probe selection changed")
|
|
return source },
|
|
async readPeerAfterCompletion(current: unknown, result: object, peer: unknown) {
|
|
assert.equal(current, token)
|
|
if (completions.get(result) !== token) throw Error("completion receipt unavailable")
|
|
assert.equal((peer as { kind: string }).kind, "server"); assert.equal((peer as { serverId: number }).serverId, 1)
|
|
// Only selection is omitted after a genuine result. Actor/source changes
|
|
// still reject; credentials are not projected for an unrecognized receipt.
|
|
if (state.freshError) throw Error("original source/actor drift")
|
|
state.postPeerCredentialReads++
|
|
return source } }
|
|
const host = { async execute(current: unknown, scope: { deadlineAt: number; signal: AbortSignal }) { assert.equal(current, token); state.native++; state.events.push("native")
|
|
state.nativeDeadline = scope.deadlineAt; enteredNative()
|
|
if (state.waitForAbort) return new Promise<never>((_resolve, reject) => {
|
|
const abort = () => { state.observedAbort = true; reject(new HostError("OUTCOME_UNKNOWN")) }
|
|
if (scope.signal.aborted) abort(); else scope.signal.addEventListener("abort", abort, { once: true })
|
|
})
|
|
if (state.nativeError) throw state.nativeError
|
|
state.afterNative?.()
|
|
const result = Object.freeze({ remoteCompletionConfirmed: true, raw: state.raw })
|
|
completions.set(result, token)
|
|
return state.forgedCompletion ? { ...result } : result } }
|
|
const fields = ["id", "srcServerId", "dstServerId", "srcInterface", "dstInterface", "protocol", "direction", "durationSec"]
|
|
const schema = { uptimeSpeedProbes: Object.fromEntries(fields.map(field => [field, field])), uptimeSpeedTestRuns: {} }
|
|
const db = { async transaction(work: (tx: unknown) => Promise<void>) {
|
|
state.transactions++; state.events.push("transaction")
|
|
const pending = { probe: structuredClone(state.probe), runs: structuredClone(state.runs) }
|
|
const tx = { update() { return { set(values: Row) { return { where(conditions: Array<{ field: string; value: unknown }>) { return { async returning() {
|
|
if (state.failWrite === "update") throw Error("update failed")
|
|
const matched = !!pending.probe && conditions.every(condition => pending.probe![condition.field] === condition.value)
|
|
if (matched) { Object.assign(pending.probe!, values); return [{ id: command.probeId }] } return []
|
|
} } } } } } }, insert() { return { async values(value: Row) { pending.runs.push(value); if (state.failWrite === "insert") throw Error("insert failed") } } } }
|
|
await work(tx); if (state.failWrite === "commit") throw Error("commit unknown")
|
|
state.probe = pending.probe; state.runs = pending.runs
|
|
} }
|
|
class Client {
|
|
constructor(endpoint: unknown, id: number, options: unknown) { assert.equal(endpoint, source.endpoint); assert.equal(id, 1); assert.equal((options as { requireBandwidthPermit: boolean }).requireBandwidthPermit, true) }
|
|
async ping(address: string, count: number, iface: string | undefined, options: { interval: string; signal: AbortSignal; beforeDispatch: () => Promise<void> }) {
|
|
state.pings++; state.events.push("ping"); assert.equal(address, context.address); assert.equal(count, 4)
|
|
state.pingSignal = options.signal
|
|
assert.equal(iface, command.srcInterface || undefined); assert.equal(options.interval, "1s")
|
|
await options.beforeDispatch(); if (state.pingError) throw state.pingError
|
|
return [{ sent: "4", received: "3", "avg-rtt": "2ms", "packet-loss": "25%" }]
|
|
}
|
|
}
|
|
const assertOriginal = (value: unknown, expected: string) => { if (value !== originals || kind !== expected) throw Error("not genuine provider") }
|
|
const providers: Record<string, unknown> = {
|
|
"drizzle-orm": { and: (...conditions: unknown[]) => conditions, eq: (field: string, value: unknown) => ({ field, value }) },
|
|
"../db/index.js": { db }, "../db/schema.js": schema,
|
|
"node:perf_hooks": { performance: { now: () => state.mono } },
|
|
"./bandwidth-peer-execution-host.js": { BandwidthPeerExecutionHostError: HostError, assertBandwidthPeerExecutionHost(value: unknown) { if (value !== host) throw Error("not genuine host") },
|
|
readBandwidthPeerCompletion(value: object, current: object) { if (completions.get(value) !== current) throw Error("completion receipt unavailable"); return state.receiptIntentChanged ? { ...intent, durationSec: intent.durationSec + 1 } : intent } },
|
|
"./bandwidth-rest-speed-original.js": { assertRestSpeedBandwidthOriginalProvider: (value: unknown) => assertOriginal(value, "rest-speed") },
|
|
"./bandwidth-scheduled-speed-original.js": { assertScheduledSpeedBandwidthOriginalProvider: (value: unknown) => assertOriginal(value, "scheduled-speed") },
|
|
"../modules/mcp/speed-bandwidth-original.js": { assertMcpSpeedBandwidthOriginalProvider: (value: unknown) => assertOriginal(value, "mcp-speed"), assertMcpSpeedBandwidthWorkflowRequest },
|
|
"./mikrotik.js": { MikrotikClient: Client },
|
|
"./uptime-collector.js": { parsePing(rows: unknown[]) { assert.equal(rows.length, 1); return { measured: state.measured, avgRtt: 2, loss: 25 } } },
|
|
"./bandwidth-test-status.js": { assertBandwidthTestCompleted }, "./bandwidth-test-rates.js": { readBandwidthTestRates },
|
|
"./speed-run-persistence.js": { persistSpeedRun, SpeedRunPersistenceUnknown },
|
|
}
|
|
for (const [name, namedExports] of Object.entries(providers)) mock.module(name, { namedExports: namedExports as Record<string, unknown> })
|
|
mock.method(Date, "now", () => state.wall)
|
|
mock.method(globalThis, "setTimeout", ((callback: () => void, ms: number) => {
|
|
assert.equal(ms, 3000); state.sleeps.push(ms); state.events.push("pause"); queueMicrotask(callback); return 1
|
|
}) as unknown as typeof setTimeout)
|
|
const api = await import("./bandwidth-speed-workflow.js?workflow-fixture=" + ++fixtureSequence)
|
|
type Workflow = { run(token: unknown, scope: { deadlineAt: number }): Promise<import("./uptime-speed-service.js").SpeedTestRunResult> }
|
|
const create = api.createBandwidthSpeedWorkflow as (deps: unknown) => Workflow
|
|
return { state, command, context, intent, token, create, originals, host, owner, lifetime, nativeEntered, scope: { deadlineAt: Date.now() + 60000 },
|
|
run: () => create({ originals, peerHost: host }).run(token, { deadlineAt: Date.now() + 60000 }) }
|
|
}
|
|
for (const kind of ["rest-speed", "scheduled-speed", "mcp-speed"] as const) test(`${kind}: complete baseline raw/rates/pause/ping/current-probe transaction`, async () => {
|
|
const f = await fixture(kind), result = await f.run()
|
|
assert.equal(f.state.native, 1); assert.deepEqual(f.state.sleeps, [3000]); assert.equal(f.state.pings, 1); assert.equal(f.state.contexts, 1)
|
|
assert.deepEqual(f.state.events.filter(event => event !== "original"), ["native", "pause", "ping", "transaction"])
|
|
assert.equal(result.raw, f.state.raw); assert.equal(result.txAvgMbps, 3); assert.equal(result.rxAvgMbps, 4)
|
|
assert.deepEqual(result.txSeries, [1, 3]); assert.deepEqual(result.rxSeries, [2, 4])
|
|
assert.equal(result.afterBtPing.rttMs, 2); assert.equal(result.afterBtPing.lossPct, 25)
|
|
assert.equal(result.srcInterfaceAddress, "192.0.2.1"); assert.equal(result.dstInterfaceAddress, "198.51.100.2")
|
|
assert.equal(f.state.runs[0].probeId, "owned-probe"); assert.equal(f.state.runs[0].status, "done")
|
|
assert.equal(f.state.probe!.lastStatus, "done"); assert.equal(f.state.probe!.lastPingLossPct, 25)
|
|
})
|
|
test("factory denies structural arbitrary run/provider replacements; copies cannot execute", async () => {
|
|
const f = await fixture()
|
|
assert.throws(() => f.create({ originals: { ...f.originals }, peerHost: f.host }))
|
|
assert.throws(() => f.create({ originals: f.originals, peerHost: { ...f.host } }))
|
|
await assert.rejects(f.create({ originals: f.originals, peerHost: f.host }).run({ ...f.token }, f.scope)); assert.equal(f.state.native, 0)
|
|
})
|
|
for (const drift of ["missing", "wrong-job", "expiry", "monotonic", "unknown-field", "command"] as const) test(`scheduled request ${drift} refuses before native`, async () => {
|
|
const f = await fixture("scheduled-speed")
|
|
const job = f.intent.request.job as Record<string, unknown>
|
|
if (drift === "missing") delete f.intent.request.job
|
|
if (drift === "wrong-job") job.job = "uptime_ping"
|
|
if (drift === "expiry") job.deadlineAt = Number(job.deadlineAt) + 1
|
|
if (drift === "monotonic") job.monotonicDeadline = f.lifetime.monotonicDeadline - 1
|
|
if (drift === "unknown-field") job.extraAuthority = true
|
|
if (drift === "command") f.intent.request.command = { ...f.command, durationSec: 11 }
|
|
await assert.rejects(f.run(), /original context unavailable/)
|
|
assert.equal(f.state.native, 0); assert.equal(f.state.transactions, 0); assert.equal(f.state.pings, 0)
|
|
})
|
|
for (const drift of ["missing", "service", "version", "expiry", "scope", "command", "unknown-field"] as const) test(`MCP sealed request ${drift} refuses before native`, async () => {
|
|
const f = await fixture("mcp-speed"), metadata = f.intent.request.mcp as Record<string, unknown>
|
|
if (drift === "missing") delete f.intent.request.mcp
|
|
if (drift === "service") metadata.serviceName = "routing.measure"
|
|
if (drift === "version") metadata.operationVersion = 2
|
|
if (drift === "expiry") metadata.originalExpiresAt = Number(metadata.originalExpiresAt) + 1
|
|
if (drift === "scope") metadata.objects = [{ kind: "server", serverId: 1, id: "1" }]
|
|
if (drift === "command") metadata.serviceInput = { ...(metadata.serviceInput as object), command: { ...f.command, direction: "receive" } }
|
|
if (drift === "unknown-field") f.intent.request.extra = true
|
|
await assert.rejects(f.run(), /original context unavailable/)
|
|
assert.equal(f.state.native, 0); assert.equal(f.state.transactions, 0); assert.equal(f.state.pings, 0)
|
|
})
|
|
for (const durationSec of [3, 2147483647]) test(`no duration range narrowing: ${durationSec}`, async () => {
|
|
const f = await fixture("scheduled-speed", { durationSec, protocol: "udp", direction: "receive" })
|
|
const result = await f.run(); assert.equal(result.durationSec, durationSec); assert.equal(result.protocol, "udp"); assert.equal(result.direction, "receive")
|
|
})
|
|
for (const drift of ["changed", "deleted"] as const) test(`after native ${drift} probe persists real success without stale association`, async () => {
|
|
const f = await fixture()
|
|
f.state.afterNative = () => { if (drift === "deleted") f.state.probe = null; else f.state.probe!.durationSec = 99 }
|
|
const result = await f.run(); assert.equal(result.txAvgMbps, 3)
|
|
assert.equal(f.state.pings, 1); assert.equal(result.afterBtPing.error, null); assert.equal(result.afterBtPing.rttMs, 2)
|
|
assert.equal(f.state.postPeerCredentialReads, 2)
|
|
assert.equal(f.state.runs[0].probeId, null); assert.equal(f.state.runs[0].status, "done")
|
|
if (f.state.probe) assert.equal(f.state.probe.telemetry, "old")
|
|
})
|
|
test("ad-hoc/interface fallbacks preserve result and history without probe update", async () => {
|
|
const f = await fixture("rest-speed", { probeId: undefined, srcInterface: "", dstInterface: "" })
|
|
f.context.srcAddress = ""; f.context.srcInterfaceAddress = null as unknown as string; f.context.dstInterfaceAddress = null as unknown as string
|
|
const result = await f.run(); assert.equal(result.srcAddress, "source-host"); assert.equal(result.srcInterface, null)
|
|
assert.equal(result.dstInterface, null); assert.equal(f.state.runs[0].probeId, null)
|
|
})
|
|
for (const mode of ["transport", "unmeasured", "freshness"] as const) test(`after-ping ${mode} is telemetry error, native success remains success`, async () => {
|
|
const f = await fixture()
|
|
if (mode === "transport") f.state.pingError = Error("ping refused")
|
|
if (mode === "unmeasured") f.state.measured = false
|
|
if (mode === "freshness") f.state.freshError = true
|
|
const result = await f.run(); assert.equal(result.afterBtPing.rttMs, null); assert(result.afterBtPing.error)
|
|
assert.equal(result.txAvgMbps, 3); assert.equal(f.state.runs[0].status, "done")
|
|
})
|
|
test("predispatch refusal leaves legacy failure handling to caller", async () => {
|
|
const f = await fixture(); f.state.nativeError = new HostError("REFUSED")
|
|
await assert.rejects(f.run(), HostError); assert.equal(f.state.transactions, 0); assert.equal(f.state.pings, 0)
|
|
})
|
|
test("possibly sent native outcome suppresses second failure publication/replay", async () => {
|
|
const f = await fixture(); f.state.nativeError = new HostError("OUTCOME_UNKNOWN")
|
|
await assert.rejects(f.run(), error => {
|
|
assert(error instanceof SpeedRunPersistenceUnknown); assert.equal(error.runId, "owned-run")
|
|
assert.equal((error as unknown as { automaticReplay: boolean }).automaticReplay, false); assert(!error.message.includes("завершён")); return true
|
|
})
|
|
assert.equal(f.state.transactions, 0); assert.equal(f.state.pings, 0)
|
|
})
|
|
test("unconfirmed native rows never publish done/ping", async () => {
|
|
const f = await fixture(); f.state.raw = [{ status: "testing" }]
|
|
await assert.rejects(f.run(), SpeedRunPersistenceUnknown); assert.equal(f.state.transactions, 0); assert.equal(f.state.pings, 0)
|
|
})
|
|
for (const stage of ["update", "insert", "commit"] as const) test(`${stage} persistence uncertainty has no partial/second failure row`, async () => {
|
|
const f = await fixture(); f.state.failWrite = stage
|
|
await assert.rejects(f.run(), SpeedRunPersistenceUnknown)
|
|
assert.equal(f.state.runs.length, 0); assert.equal(f.state.probe!.telemetry, "old"); assert.equal(f.state.probe!.lastStatus, undefined)
|
|
assert.equal(f.state.transactions, 1); assert.equal(f.state.native, 1)
|
|
})
|
|
test("genuine original lifecycle abort reaches an already pending peer host without caller signal", async () => {
|
|
const f = await fixture(); f.state.waitForAbort = true
|
|
const pending = f.run(); await f.nativeEntered; f.owner.abort()
|
|
await assert.rejects(pending, SpeedRunPersistenceUnknown)
|
|
assert.equal(f.state.observedAbort, true); assert.equal(f.state.transactions, 0); assert.equal(f.state.pings, 0)
|
|
})
|
|
test("genuine original lifecycle is passed to after-ping transport", async () => {
|
|
const f = await fixture(); await f.run()
|
|
assert.equal(f.state.pingSignal, f.owner.signal); f.owner.abort(); assert.equal(f.state.pingSignal!.aborted, true)
|
|
})
|
|
test("earlier original monotonic horizon clips native deadline despite wall rollback", async () => {
|
|
const f = await fixture(); f.lifetime.monotonicDeadline = f.state.mono + 25
|
|
f.state.wall -= 100000
|
|
await f.run(); assert.equal(f.state.nativeDeadline, f.state.wall + 25)
|
|
mock.restoreAll()
|
|
const expired = await fixture(); expired.lifetime.monotonicDeadline = expired.state.mono - 1
|
|
await assert.rejects(expired.run(), /lifetime unavailable/); assert.equal(expired.state.native, 0)
|
|
})
|
|
test("copied completion is rejected before ping or post-completion credential projection", async () => {
|
|
const f = await fixture(); f.state.forgedCompletion = true
|
|
await assert.rejects(f.run(), SpeedRunPersistenceUnknown)
|
|
assert.equal(f.state.pings, 0); assert.equal(f.state.postPeerCredentialReads, 0)
|
|
assert.equal(f.state.transactions, 0); assert.equal(f.state.runs.length, 0); assert.equal(f.state.sleeps.length, 0)
|
|
})
|
|
test("completion receipt for another exact intent cannot publish history", async () => {
|
|
const f = await fixture(); f.state.receiptIntentChanged = true
|
|
await assert.rejects(f.run(), SpeedRunPersistenceUnknown)
|
|
assert.equal(f.state.transactions, 0); assert.equal(f.state.pings, 0); assert.equal(f.state.postPeerCredentialReads, 0)
|
|
})
|
|
|