package peer import ( "net/netip" "testing" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "vppn/m" ) func testPoller(t *testing.T) (*HubPoller, chan HubPeer, chan wgtypes.Key) { t.Helper() addCh := make(chan HubPeer, 8) removeCh := make(chan wgtypes.Key, 8) hp := &HubPoller{ selfVPNIP: netip.MustParseAddr("10.0.0.1"), vpnNet: netip.MustParsePrefix("10.0.0.0/24"), addCh: addCh, removeCh: removeCh, known: make(map[wgtypes.Key]int64), } return hp, addCh, removeCh } func stateWith(key wgtypes.Key, peerIP byte, version int64) m.NetworkState { var s m.NetworkState s.Peers[peerIP] = &m.Peer{ PeerIP: peerIP, Version: version, WGPubKey: key[:], SignPubKey: make([]byte, 32), } return s } func TestApply_EmitsAddsAndReportsChange(t *testing.T) { hp, addCh, _ := testPoller(t) key := mustKey(t) if changed := hp.apply(stateWith(key, 2, 1)); !changed { t.Fatal("expected changed=true on first apply") } if len(addCh) != 1 { t.Fatalf("expected 1 add, got %d", len(addCh)) } if got := <-addCh; got.PubKey != key { t.Errorf("add pubkey mismatch") } } func TestApply_NoChangeWhenVersionSame(t *testing.T) { hp, addCh, _ := testPoller(t) key := mustKey(t) hp.apply(stateWith(key, 2, 1)) <-addCh // drain initial add if changed := hp.apply(stateWith(key, 2, 1)); changed { t.Fatal("expected changed=false when version unchanged") } if len(addCh) != 0 { t.Fatalf("expected no re-emit, got %d adds", len(addCh)) } } func TestApply_ReEmitsOnVersionBump(t *testing.T) { hp, addCh, _ := testPoller(t) key := mustKey(t) hp.apply(stateWith(key, 2, 1)) <-addCh if changed := hp.apply(stateWith(key, 2, 2)); !changed { t.Fatal("expected changed=true on version bump") } if len(addCh) != 1 { t.Fatalf("expected 1 re-emit, got %d", len(addCh)) } } func TestApply_RemovesVanishedPeer(t *testing.T) { hp, addCh, removeCh := testPoller(t) key := mustKey(t) hp.apply(stateWith(key, 2, 1)) <-addCh // Empty state: the peer is gone. if changed := hp.apply(m.NetworkState{}); !changed { t.Fatal("expected changed=true when peer vanishes") } if len(removeCh) != 1 { t.Fatalf("expected 1 remove, got %d", len(removeCh)) } if got := <-removeCh; got != key { t.Errorf("remove key mismatch") } }