Files
networkcity/Tests/NetworkCityCoreTests/NettopParserTests.swift
T
timban c08fc277a9 Initial commit: NetworkCity — network traffic as a neon city
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>
2026-06-13 08:43:32 -07:00

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 })
}
}