43 lines
4.7 KiB
TypeScript
43 lines
4.7 KiB
TypeScript
import assert from "node:assert/strict"
|
|
import { test } from "node:test"
|
|
import { getTrafficFlowSettings, putTrafficFlowSettings, generateTrafficFlowKeys, getTrafficFlowHostFiles, purgeTrafficFlowData } from "./traffic-flow"
|
|
const base = "http://fixture.test"
|
|
const settings = { enabled: false, collectorIp: "10.255.254.1", flowListenPort: 4739, wgListenPort: 51821, prefix: "10.255.254.0/24", publicEndpoint: "", hostPublicKey: "", hasHostPrivateKey: false, hubServerId: null, retentionHours: 24, topN: 200, mapServiceMinSharePct: 0, lastDatagramAt: null, lastExporterIp: null, lastError: null, packetsReceived: 0, listenerBound: false, listenerAddress: null, peers: [] }
|
|
const keyed = { ...settings, hasHostPrivateKey: true, hostPublicKey: "fixture-public-only" }
|
|
const json = (value: unknown) => new Response(JSON.stringify(value))
|
|
test("NetFlow GET requires complete DTO and preserves zero/false/known empty peers", async () => {
|
|
const original = globalThis.fetch
|
|
try { globalThis.fetch = async () => json(settings); assert.deepEqual(await getTrafficFlowSettings(base), settings)
|
|
for (const raw of [{}, null, { ...settings, enabled: undefined }, { ...settings, flowListenPort: 65536 }, { ...settings, hasHostPrivateKey: true }, { ...settings, listenerBound: true }, { ...settings, lastDatagramAt: "bad" }]) { globalThis.fetch = async () => json(raw); await assert.rejects(() => getTrafficFlowSettings(base), /не подтверждены/) }
|
|
} finally { globalThis.fetch = original }
|
|
})
|
|
test("NetFlow PUT validates before HTTP and requires literal ack and exact sent fields", async () => {
|
|
const original = globalThis.fetch; let calls = 0
|
|
try {
|
|
globalThis.fetch = async (_url, init) => { calls++; assert.equal(init?.method, "PUT"); assert.deepEqual(JSON.parse(String(init?.body)), { enabled: false }); return json({ ok: true, settings }) }; await putTrafficFlowSettings(base, { enabled: false }); assert.equal(calls, 1)
|
|
for (const raw of [{}, { ok: false, settings }, { ok: true, settings: { ...settings, enabled: true } }]) { globalThis.fetch = async () => json(raw); await assert.rejects(() => putTrafficFlowSettings(base, { enabled: false })) }
|
|
for (const patch of [{}, { flowListenPort: 65536 }, { wgListenPort: 30.5 }]) { calls = 0; globalThis.fetch = async () => { calls++; return json({}) }; await assert.rejects(() => putTrafficFlowSettings(base, patch)); assert.equal(calls, 0) }
|
|
} finally { globalThis.fetch = original }
|
|
})
|
|
test("NetFlow keys require real created flag and same public key with configured private key", async () => {
|
|
const original = globalThis.fetch
|
|
try { globalThis.fetch = async () => json({ ok: true, created: false, publicKey: keyed.hostPublicKey, settings: keyed }); assert.equal((await generateTrafficFlowKeys(base)).created, false)
|
|
for (const raw of [{}, { ok: true, publicKey: keyed.hostPublicKey, settings: keyed }, { ok: true, created: true, publicKey: "other", settings: keyed }, { ok: true, created: true, publicKey: "fixture", settings }]) { globalThis.fetch = async () => json(raw); await assert.rejects(() => generateTrafficFlowKeys(base)) }
|
|
} finally { globalThis.fetch = original }
|
|
})
|
|
test("NetFlow export validates files, identity and leaf filename without synthesizing data", async () => {
|
|
const original = globalThis.fetch; const file = { id: "wg", label: "WG", filename: "wg-flow.conf", code: "fixture-only" }
|
|
try { globalThis.fetch = async () => json({ files: [file] }); assert.deepEqual((await getTrafficFlowHostFiles(base)).files, [file])
|
|
for (const raw of [{}, { files: [] }, { files: [file, file] }, { files: [{ ...file, filename: "../wg.conf" }] }, { files: [{ ...file, code: "" }] }]) { globalThis.fetch = async () => json(raw); await assert.rejects(() => getTrafficFlowHostFiles(base)) }
|
|
} finally { globalThis.fetch = original }
|
|
})
|
|
test("NetFlow purge requires confirmed actual counts and never repeats an unknown POST", async () => {
|
|
const original = globalThis.fetch
|
|
try {
|
|
const receipt = { ok: true, deleted: { buckets: 0, minuteStats: 0, minuteDims: 0, dailyDims: 0 }, fileBytesBefore: 0, fileBytesAfter: 0, vacuumed: false }
|
|
globalThis.fetch = async () => json(receipt); assert.deepEqual(await purgeTrafficFlowData(base), receipt)
|
|
const partial = {...receipt, fileBytesBefore: null, fileBytesAfter: null, listenerError: "listener unavailable", partitionError: "partition unavailable", eventError: "journal unavailable"}; globalThis.fetch = async () => json(partial); assert.deepEqual(await purgeTrafficFlowData(base), partial)
|
|
for (const raw of [{}, { ...receipt, ok: false }, { ...receipt, deleted: { buckets: -1 } }]) { let calls = 0; globalThis.fetch = async () => { calls++; return json(raw) }; await assert.rejects(() => purgeTrafficFlowData(base)); assert.equal(calls, 1) }
|
|
} finally { globalThis.fetch = original }
|
|
})
|