import { describe, expect, test } from 'bun:test' import { lastRate, pushWindow, routeDeltas, windowBytes, type ConnTotals, type RouteSample, } from './telemetry.ts' import type { ConnectionItem } from './connections.ts' function conn(id: string, inbound: string, upload: number, download: number): ConnectionItem { return { id, upload, download, start: '2026-08-11T00:00:00+08:00', chains: ['DIRECT'], rule: 'Match', rulePayload: '', metadata: { host: 'example.com', destinationIP: '1.2.3.4', destinationPort: '443', inboundName: inbound, inboundPort: '7890', }, } } describe('pushWindow', () => { test('把窗口外的老点挤掉,保留窗口内的', () => { const list = [{ t: 0 }, { t: 5_000 }, { t: 9_000 }] const next = pushWindow(list, { t: 12_000 }, 5_000) expect(next.map((p) => p.t)).toEqual([9_000, 12_000]) }) test('全部过期时只剩新点', () => { const next = pushWindow([{ t: 0 }], { t: 60_000 }, 5_000) expect(next.map((p) => p.t)).toEqual([60_000]) }) }) describe('routeDeltas', () => { test('已有连接算差值,并按入站聚合', () => { const prev: ConnTotals = new Map([ ['a', { up: 100, down: 200 }], ['b', { up: 10, down: 20 }], ]) const { deltas } = routeDeltas(prev, [ conn('a', 'lan-a', 150, 260), conn('b', 'lan-a', 30, 21), ]) expect(deltas['lan-a']).toEqual({ up: 70, down: 61 }) }) test('新连接把累计全部记入本次间隔', () => { const { deltas } = routeDeltas(new Map(), [conn('a', 'lan-a', 500, 700)]) expect(deltas['lan-a']).toEqual({ up: 500, down: 700 }) }) test('累计变小(内核重启)按全新连接处理,不出负数', () => { const prev: ConnTotals = new Map([['a', { up: 900, down: 900 }]]) const { deltas } = routeDeltas(prev, [conn('a', 'lan-a', 50, 60)]) expect(deltas['lan-a']).toEqual({ up: 50, down: 60 }) }) test('消失的连接不再出现在 next 里', () => { const prev: ConnTotals = new Map([['gone', { up: 1, down: 1 }]]) const { next } = routeDeltas(prev, [conn('a', 'lan-a', 5, 5)]) expect(next.has('gone')).toBe(false) expect(next.get('a')).toEqual({ up: 5, down: 5 }) }) test('没有名字的入站退回端口做键', () => { const item = conn('a', '', 5, 5) const { deltas } = routeDeltas(new Map(), [item]) expect(Object.keys(deltas)).toEqual(['7890']) }) }) describe('windowBytes / lastRate', () => { const samples: RouteSample[] = [ { t: 0, ms: 3_000, up: 100, down: 100 }, { t: 3_000, ms: 3_000, up: 300, down: 300 }, { t: 6_000, ms: 2_000, up: 400, down: 600 }, ] test('windowBytes 只算窗口内的样本', () => { expect(windowBytes(samples, 3_000)).toBe(300 + 300 + 400 + 600) }) test('lastRate 按实际间隔换算成每秒', () => { expect(lastRate(samples)).toEqual({ up: 200, down: 300 }) }) test('lastRate 没有样本时是 null', () => { expect(lastRate([])).toBeNull() }) })