c08fc277a9
A native macOS network monitor that renders live traffic as a top-down neon city: your Mac is downtown, remote orgs are glowing districts, and traffic is cars of light driving the roads. Architecture: - NetworkCityCore: swappable data layer behind a ConnectionSource protocol (nettop-backed today), plus pure/tested logic — traffic diffing, org classification (reverse-DNS + CIDR), traffic classes, hub-and-spoke expansion policy, label anti-overlap, and latency→distance layout. - NetworkCityApp: SwiftUI + SpriteKit city — auto-expanding districts, protocol-coloured cars, click-to-inspect panel, and latency-as-distance (districts glide to their measured RTT). - nettop-probe: CLI proof of the data layer. 44 tests passing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
68 lines
2.7 KiB
Swift
68 lines
2.7 KiB
Swift
import XCTest
|
|
@testable import NetworkCityCore
|
|
|
|
/// Fixtures are taken verbatim from real `nettop -L 1 -x -n -J time,bytes_in,bytes_out`
|
|
/// output captured on macOS 26, so the parser is pinned to reality.
|
|
final class NettopParserTests: XCTestCase {
|
|
|
|
let sample = """
|
|
time,,bytes_in,bytes_out,
|
|
23:49:56.574393,launchd.1,0,0,
|
|
23:49:56.573243,tcp4 127.0.0.1:8021<->*:*,,,
|
|
23:49:56.574395,apsd.571,15671580,11326466,
|
|
23:49:56.573044,tcp4 192.168.10.194:57359<->17.57.144.184:5223,15671580,11326466,
|
|
23:49:56.574397,trustd.609,10032,18469,
|
|
23:49:56.569491,quic4 192.168.10.194:51698<->17.248.242.102:443,5017,9232,
|
|
23:49:56.574410,mDNSResponder.647,974941537,77402609,
|
|
23:49:56.569906,udp6 *.5353<->*.*,176848739,34857088,
|
|
23:49:56.574316,tcp6 fe80::d08d:6eb7:1dcd:6466%utun4.1024<->fe80::9ed2:d4f7:aa69:9e47%utun4.1024,0,0,
|
|
"""
|
|
|
|
func testParsesProcessAndConnectionRows() {
|
|
let conns = NettopParser.parseConnections(sample)
|
|
// 4 connection rows present (launchd listener, apsd, trustd, mDNS, utun6)
|
|
XCTAssertEqual(conns.count, 5)
|
|
}
|
|
|
|
func testConnectionInheritsPrecedingProcess() {
|
|
let conns = NettopParser.parseConnections(sample)
|
|
let apsd = conns.first { $0.remote.host == "17.57.144.184" }
|
|
XCTAssertEqual(apsd?.processName, "apsd")
|
|
XCTAssertEqual(apsd?.pid, 571)
|
|
XCTAssertEqual(apsd?.proto, .tcp4)
|
|
XCTAssertEqual(apsd?.remote.port, 5223)
|
|
XCTAssertEqual(apsd?.bytesIn, 15671580)
|
|
XCTAssertEqual(apsd?.bytesOut, 11326466)
|
|
}
|
|
|
|
func testIPv4EndpointParsing() {
|
|
let ep = NettopParser.parseEndpoint("192.168.10.194:57359", isV6: false)
|
|
XCTAssertEqual(ep.host, "192.168.10.194")
|
|
XCTAssertEqual(ep.port, 57359)
|
|
}
|
|
|
|
func testIPv6EndpointParsingStripsZone() {
|
|
let ep = NettopParser.parseEndpoint("fe80::d08d:6eb7:1dcd:6466%utun4.1024", isV6: true)
|
|
XCTAssertEqual(ep.host, "fe80::d08d:6eb7:1dcd:6466")
|
|
XCTAssertEqual(ep.port, 1024)
|
|
}
|
|
|
|
func testWildcardEndpointHasNoPort() {
|
|
XCTAssertNil(NettopParser.parseEndpoint("*:*", isV6: false).port)
|
|
XCTAssertNil(NettopParser.parseEndpoint("*.*", isV6: true).port)
|
|
}
|
|
|
|
func testExternalClassification() {
|
|
let conns = NettopParser.parseConnections(sample)
|
|
let external = conns.filter(\.isExternal)
|
|
// Only apsd (17.57.x) and quic (17.248.x) are real off-box destinations.
|
|
// Loopback listener, mDNS wildcard, and fe80 link-local are excluded.
|
|
XCTAssertEqual(Set(external.map(\.remote.host)), ["17.57.144.184", "17.248.242.102"])
|
|
}
|
|
|
|
func testQuicProtocolRecognised() {
|
|
let conns = NettopParser.parseConnections(sample)
|
|
XCTAssertTrue(conns.contains { $0.proto == .quic4 })
|
|
}
|
|
}
|