Files
MikrotikManager/backend/src/services/traffic-flow-ingest.test.ts
T
DenozordecandCursor cb799da13a
Docker images / prepare-release (push) Successful in 8s
Docker images / backend-image (push) Successful in 2m23s
Docker images / frontend-image (push) Successful in 3m16s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 57s
Docker images / publish-release (push) Successful in 12s
fix(netflow): изолировать коллектор IPFIX и срезать раздувание базы
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 09:50:24 +07:00

121 lines
3.3 KiB
TypeScript

import assert from "node:assert/strict"
import {
markIfaceRefreshAttempt,
rememberServerIfaces,
resetIfaceCacheForTests,
shouldRefreshIfaces,
} from "./traffic-flow-ifindex.js"
import {
applyHeartbeatForTests,
flushPendingForTests,
getFlowListenerState,
getFlowRuntimeCounters,
getFlowWorkerHealth,
ingestParsedFlowsForServerForTests,
lastFlushUsedTransactionForTests,
maybeRefreshIfaces,
peekPendingFlows,
resetFlowRingsForTests,
setPendingCapForTests,
setRefreshIfacesForTests,
setWantListenForTests,
simulateWorkerExitForTests,
} from "./traffic-flow-ingest.js"
import { configureEngine, droppedForTests, pendingSizeForTests } from "./traffic-flow-engine.js"
import { sqliteDatabase } from "../db/index.js"
resetIfaceCacheForTests()
resetFlowRingsForTests()
let refreshCalls = 0
setRefreshIfacesForTests(async () => {
refreshCalls += 1
})
rememberServerIfaces(1, [{ ".id": "*A", name: "wg-flow" }])
assert.equal(shouldRefreshIfaces(1), false)
assert.equal(maybeRefreshIfaces(1), false)
assert.equal(refreshCalls, 0)
resetIfaceCacheForTests()
assert.equal(shouldRefreshIfaces(2), true)
assert.equal(maybeRefreshIfaces(2), true)
assert.equal(refreshCalls, 1)
markIfaceRefreshAttempt(2)
assert.equal(shouldRefreshIfaces(2), false)
assert.equal(maybeRefreshIfaces(2), false)
assert.equal(refreshCalls, 1)
assert.equal(lastFlushUsedTransactionForTests(), false)
resetFlowRingsForTests()
setPendingCapForTests(3)
const many = Array.from({ length: 6 }, (_, i) => ({
src: `10.1.1.${i + 1}`,
dst: "8.8.8.8",
proto: 6,
srcPort: 50000 + i,
dstPort: 443,
bytes: 1000,
packets: 1,
inIface: "2",
outIface: "",
}))
ingestParsedFlowsForServerForTests(9, many)
assert.equal(pendingSizeForTests(), 3)
assert.equal(droppedForTests(), 3)
assert.equal(peekPendingFlows().length, 3)
setPendingCapForTests(null)
resetFlowRingsForTests()
configureEngine({ topN: 20 })
const talkers = Array.from({ length: 25 }, (_, i) => ({
src: `10.2.1.${i + 1}`,
dst: "1.1.1.1",
proto: 6,
srcPort: 40000 + i,
dstPort: 443,
bytes: 1000 + i,
packets: 1,
inIface: "2",
outIface: "",
}))
ingestParsedFlowsForServerForTests(9, talkers)
flushPendingForTests()
const stored = sqliteDatabase.prepare(`
SELECT COUNT(*) AS n FROM flow_buckets WHERE server_id = 9
`).get() as { n: number }
assert.ok(stored.n <= 20, `expected topN cap, got ${stored.n}`)
sqliteDatabase.prepare(`DELETE FROM flow_buckets WHERE server_id = 9`).run()
sqliteDatabase.prepare(`DELETE FROM flow_minute_stats WHERE server_id = 9`).run()
sqliteDatabase.prepare(`DELETE FROM flow_minute_dims WHERE server_id = 9`).run()
sqliteDatabase.prepare(`DELETE FROM flow_daily_dims WHERE server_id = 9`).run()
applyHeartbeatForTests({
bound: true,
address: "127.0.0.1:4739",
packetsReceived: 42,
lastExporterIp: "10.255.254.3",
lastError: "",
lastDatagramAt: new Date().toISOString(),
pendingSize: 1,
dropped: 0,
rowsStored: 1,
workerAlive: true,
rings: [],
})
assert.equal(getFlowListenerState().bound, true)
assert.equal(getFlowRuntimeCounters().packetsReceived, 42)
assert.equal(getFlowWorkerHealth().alive, false)
setWantListenForTests(true)
assert.equal(simulateWorkerExitForTests(), 1)
assert.equal(getFlowListenerState().bound, false)
setWantListenForTests(false)
resetFlowRingsForTests()
resetIfaceCacheForTests()
setRefreshIfacesForTests(null)
console.log("traffic-flow-ingest.test.ts: ok")