Ambient system companions over one privacy-preserving signal daemon (aggregate-only, no keystroke content): a git-driven terminal garden and IOKit hardware collectors. ambient daemon macos privacy terminal

macos-collector/Tests/CollectorCoreTests/WireTests.swift

66 lines · 3167 bytes

 1import XCTest
 2@testable import CollectorCore
 3
 4final class WireTests: XCTestCase {
 5    /// The canonical hardware frame, shared **verbatim** with the Rust decode
 6    /// test (`crates/signal-schema/tests/hardware_wire.rs`). Both languages
 7    /// independently commit to these exact bytes  that shared literal *is* the
 8    /// cross-language wire contract, so no cross-process execution is needed to
 9    /// prove Swift and Rust agree.
10    ///
11    /// Signal: schema_version=3, ts=0, source=Hardware(3), name=CpuLoad(28),
12    /// value=0.5, tag=none.
13    func testCanonicalHardwareFrameMatchesRust() {
14        let signal = Signal(ts: 0, source: .hardware, name: .cpuLoad, value: 0.5)
15        let expected: [UInt8] = [
16            0x15, 0x00, 0x00, 0x00,                          // body_len = 21
17            0x04, 0x00,                                      // schema_version = 4
18            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // ts = 0
19            0x03,                                            // source = Hardware
20            0x0A,                                            // name = CpuLoad (10)
21            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x3F,  // value = 0.5 (f64 LE)
22            0x00,                                            // tag_present = 0
23        ]
24        XCTAssertEqual(encode(signal), expected)
25    }
26
27    /// The schema version must equal the Rust `SCHEMA_VERSION`, or the daemon
28    /// drops every frame this collector sends.
29    func testSchemaVersionMatchesRust() {
30        XCTAssertEqual(SCHEMA_VERSION, 4)
31    }
32
33    /// The tagged-frame layout matches Rust too (hardware signals are untagged,
34    /// but the encoder must still agree on the audited-tag case).
35    func testTaggedFrameLayout() {
36        let signal = Signal(ts: 0, source: .macos, name: .batteryPct, value: 1.0, tag: "ab")
37        let frame = encode(signal)
38        // body = 2+8+1+1+8+1 + (2 + 2) = 25 ; frame = 4 + 25 = 29
39        XCTAssertEqual(frame.count, 29)
40        XCTAssertEqual(Array(frame.prefix(4)), [0x19, 0x00, 0x00, 0x00]) // body_len = 25
41        XCTAssertEqual(frame[24], 0x01)                     // tag_present
42        XCTAssertEqual([frame[25], frame[26]], [0x02, 0x00]) // tag_len = 2
43        XCTAssertEqual([frame[27], frame[28]], Array("ab".utf8))
44    }
45
46    /// Hardware signals never carry a tag and never carry content  the payload
47    /// is a single `Double`. This mirrors the Rust privacy invariant.
48    func testHardwareSignalsAreUntaggedScalars() {
49        for name in [SignalName.cpuLoad, .batteryPct, .charging, .batteryDrawW, .thermalState] {
50            let s = Signal(ts: 1, source: .hardware, name: name, value: 0.0)
51            XCTAssertNil(s.tag)
52        }
53    }
54
55    /// The IOKit CPU read yields a plausible fraction in `[0, 1]` (or nil while
56    /// unavailable)  a real read against real hardware.
57    func testCPUSamplerInRange() {
58        let sampler = CPUSampler()
59        _ = sampler.sample()
60        Thread.sleep(forTimeInterval: 0.1)
61        if let load = sampler.sample() {
62            XCTAssertGreaterThanOrEqual(load, 0.0)
63            XCTAssertLessThanOrEqual(load, 1.0)
64        }
65    }
66}