fix(uptime): проверять завершение теста перед записью успеха
This commit is contained in:
1 parent
9d5959601f
commit
fb32f87d33
6 files changed
+62
-2
No files matched your search
@@ -0,0 +1,24 @@
|
||||
import { test } from "node:test"
|
||||
import assert from "node:assert/strict"
|
||||
import { assertBandwidthTestCompleted } from "./bandwidth-test-status.js"
|
||||
import { readBandwidthTestRates } from "./bandwidth-test-rates.js"
|
||||
|
||||
test("confirmed completion preserves one-direction unknown and explicit zero", () => {
|
||||
const rows = [{ status: "connecting" }, { status: "running", "rx-current": "20Mbps" }, { status: "done testing", "rx-total-average": "0bps" }]
|
||||
assert.doesNotThrow(() => assertBandwidthTestCompleted(rows))
|
||||
const result = readBandwidthTestRates(rows)
|
||||
assert.equal(result.txAvgMbps, null)
|
||||
assert.equal(result.rxAvgMbps, 0)
|
||||
assert.doesNotThrow(() => assertBandwidthTestCompleted([{ status: "done testing" }, { "tx-total-average": "10Mbps" }]))
|
||||
})
|
||||
test("all native failures reject even with valid rates or a subsequent success marker", () => {
|
||||
for (const status of ["authentication failed", "can not connect", "can not start test", "remote is busy", "test unsupported", "disconnected"]) {
|
||||
assert.throws(() => assertBandwidthTestCompleted([{ status, "tx-total-average": "50Mbps" }]))
|
||||
assert.throws(() => assertBandwidthTestCompleted([{ status }, { status: "done testing" }]))
|
||||
}
|
||||
})
|
||||
test("missing, incomplete and malformed native replies never count as completed", () => {
|
||||
for (const raw of [null, {}, [], [null], [[]], [{ status: 8 }], [{ status: "" }], [{ "tx-total-average": "50Mbps" }], [{ status: "running" }], [{ status: "connecting" }], [{ status: "done testing" }, { status: "running" }], [{ status: "done testing" }, { status: "future status" }], [{ status: "done testing", error: "failure" }], [{ status: "done testing", failure: "failure" }], [{ status: "done testing", "!trap": true }]]) {
|
||||
assert.throws(() => assertBandwidthTestCompleted(raw), /Результат операции неизвестен/)
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,25 @@
|
||||
const failures: Record<string, string> = {
|
||||
"authentication failed": "RouterOS отклонил авторизацию bandwidth-test",
|
||||
"can not connect": "Bandwidth-test не смог подключиться к назначению",
|
||||
"can not start test": "RouterOS не смог начать bandwidth-test",
|
||||
"remote is busy": "Устройство назначения занято",
|
||||
"test unsupported": "Устройство назначения не поддерживает bandwidth-test",
|
||||
"disconnected": "Соединение bandwidth-test прервано до завершения",
|
||||
}
|
||||
|
||||
/** HTTP success is insufficient: the last reported native state must confirm completion. */
|
||||
export function assertBandwidthTestCompleted(raw: unknown): asserts raw is Array<Record<string, unknown>> {
|
||||
const unknown = () => new Error("RouterOS не подтвердил завершение bandwidth-test. Результат операции неизвестен")
|
||||
if (!Array.isArray(raw) || !raw.length) throw unknown()
|
||||
let lastStatus: string | undefined
|
||||
for (const row of raw) {
|
||||
if (!row || typeof row !== "object" || Array.isArray(row)) throw unknown()
|
||||
if ("error" in row || "failure" in row || "!trap" in row) throw unknown()
|
||||
if (row.status === undefined) continue
|
||||
if (typeof row.status !== "string" || !row.status.trim()) throw unknown()
|
||||
const status = row.status.trim().toLowerCase()
|
||||
if (Object.hasOwn(failures, status)) throw new Error(failures[status])
|
||||
lastStatus = status
|
||||
}
|
||||
if (lastStatus !== "done testing") throw unknown()
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import type { RosIpAddress } from "../types/server.js"
|
||||
import { withBtestNodeLocks } from "./btest-node-locks.js"
|
||||
import { MikrotikClient } from "./mikrotik.js"
|
||||
import { parsePing } from "./uptime-collector.js"
|
||||
import { assertBandwidthTestCompleted } from "./bandwidth-test-status.js"
|
||||
import { readBandwidthTestRates } from "./bandwidth-test-rates.js"
|
||||
|
||||
function firstUsableIpOnInterface(rows: RosIpAddress[], iface: string): string {
|
||||
@@ -106,6 +107,7 @@ export async function executeBandwidthSpeedTestInner(params: SpeedTestRunParams)
|
||||
direction,
|
||||
durationSec,
|
||||
})
|
||||
assertBandwidthTestCompleted(rows)
|
||||
const { txAvgMbps: txFinal, rxAvgMbps: rxFinal, txSeries, rxSeries } = readBandwidthTestRates(rows)
|
||||
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 3000))
|
||||
|
||||
Reference in new issue
Block a user