1 Test Gaps
Claude edited this page 2026-02-19 23:29:30 +00:00

Test Gaps

Detailed analysis of untested code to guide the dedicated domain expert.

Current State

logging/   86.2% coverage — 12 tests (good)
node/      42.0% coverage — 76 tests (critical gaps below)
ueps/       0.0% coverage — 0 tests (CRITICAL)

Priority 1: UEPS Wire Protocol (0 tests, 262 lines)

packet.go — PacketBuilder + MarshalAndSign

Test What to verify
TestNewBuilder_DefaultFields Version=0x09, CurrentLayer=5, TargetLayer=5, ThreatScore=0
TestMarshalAndSign_Roundtrip Build packet, marshal, then ReadAndVerify, assert fields match
TestMarshalAndSign_HMACCoversHeadersAndPayload Tamper with payload after signing, verify HMAC rejects
TestMarshalAndSign_EmptyPayload Payload=nil, should still produce valid signed packet
TestMarshalAndSign_MaxThreatScore ThreatScore=65535, verify uint16 boundary
TestWriteTLV_ValueTooLarge Value >255 bytes should error (1-byte length limit)

reader.go — ReadAndVerify

Test What to verify
TestReadAndVerify_ValidPacket Full roundtrip from MarshalAndSign
TestReadAndVerify_TamperedPayload Flip a payload byte, expect HMAC mismatch error
TestReadAndVerify_TamperedHeader Change header byte after signing, expect HMAC mismatch
TestReadAndVerify_MissingHMAC Packet with no 0x06 tag, expect "missing HMAC" error
TestReadAndVerify_WrongSecret Sign with key A, verify with key B, expect mismatch
TestReadAndVerify_TruncatedPacket Short read / EOF mid-TLV, expect io error
TestReadAndVerify_UnknownTag Unknown TLV tag between header and HMAC, verify it's skipped but included in signature

Key Implementation Note

The 0xFF payload tag has no length prefix — reader.go calls io.ReadAll(r) which reads until EOF. This means the caller must frame the packet externally (e.g. TCP length prefix). Test with bytes.NewReader(data) which naturally provides EOF framing.

Priority 2: Transport (0 tests, 934 lines)

Testing transport requires spinning up real WebSocket connections. Use httptest.NewServer with the transport's handleWSUpgrade handler.

Challenges

  • SMSG encryption: encryptMessage/decryptMessage use github.com/Snider/Borg/pkg/smsg. Tests need a real shared secret derived from two X25519 keypairs.
  • Handshake: Requires two NodeManager instances with valid identities. Each side does challenge-response auth.

Suggested Test Approach

func setupTestPair(t *testing.T) (serverTransport *Transport, clientTransport *Transport) {
    // Create two identities
    serverNode := NewNodeManager(NewNodeIdentity("server", RoleWorker))
    clientNode := NewNodeManager(NewNodeIdentity("client", RoleController))

    // Create registries (open auth for tests)
    serverRegistry := NewPeerRegistry(WithAuthMode(PeerAuthOpen))
    clientRegistry := NewPeerRegistry(WithAuthMode(PeerAuthOpen))

    // Create transports on different ports
    serverCfg := DefaultTransportConfig()
    serverCfg.ListenAddr = ":0" // kernel-assigned
    // ...
}

Key Tests Needed

Test What to verify
TestTransport_ConnectAndHandshake Full handshake, shared secret derived, challenge verified
TestTransport_HandshakeRejectWrongVersion Peer with incompatible protocol version rejected
TestTransport_AllowlistReject Peer not in allowlist gets rejection message
TestTransport_SendEncrypted Send message, verify SMSG decrypt on receiver
TestTransport_Deduplication Send same message ID twice, second is dropped
TestTransport_RateLimiting Burst >100 messages, verify drops after limit
TestTransport_MaxConns Hit MaxConns limit, verify 503 response
TestTransport_KeepaliveTimeout No activity beyond PingInterval+PongTimeout, verify disconnect
TestTransport_GracefulClose GracefulClose sends disconnect message before closing
TestTransport_ConcurrentSend Multiple goroutines sending, no races (writeMu)

Priority 3: Controller (0 tests, 327 lines)

Controller wraps transport for request-response patterns. Test by mocking or using a real transport pair.

Test What to verify
TestController_SendRequest Send message, get correlated response via ReplyTo
TestController_Timeout No response within deadline, returns timeout error
TestController_AutoConnect Peer not connected, controller auto-connects before sending
TestController_GetAllStats Multiple peers, parallel stat collection
TestController_PingPeer RTT calculated correctly
TestController_ConcurrentRequests Multiple requests in flight, correct correlation

Priority 4: Dispatcher Implementation

Currently a commented-out stub. Once UEPS tests exist and transport tests pass, implement:

  1. Threat circuit breaker (ThreatScore > 50000 = drop)
  2. Intent-based routing (0x01 handshake, 0x20 compute, 0x30 rehab, 0xFF custom)
  3. Integration with Transport for incoming UEPS packets

What's Already Well-Tested

  • identity.go — 5 tests, good coverage
  • peer.go — 19 tests, good coverage (scoring, allowlist, persistence)
  • message.go — 8 tests, good coverage (all message types, serialisation)
  • worker.go — 10 tests, good coverage (command handlers with mock managers)
  • bundle.go — 9 tests, good coverage (TIM encryption, Zip Slip defence)
  • protocol.go — 5 tests, good coverage (response validation)