package control_test import ( "net/netip" "testing" "vppn/peer/control" ) func TestRoundTrip(t *testing.T) { cases := []struct { name string ping control.Ping }{ { name: "zero", ping: control.Ping{}, }, { name: "client ping", ping: control.Ping{ PingTS: 1234567890, SrcV4: netip.MustParseAddrPort("1.2.3.4:51820"), Dst: netip.MustParseAddrPort("5.6.7.8:51820"), }, }, { name: "server response", ping: control.Ping{ PingTS: 1234567890, SrcV4: netip.MustParseAddrPort("5.6.7.8:51820"), Dst: netip.MustParseAddrPort("1.2.3.4:9999"), }, }, { name: "IPv6 only", ping: control.Ping{ PingTS: 999, SrcV6: netip.MustParseAddrPort("[2001:db8::1]:51820"), Dst: netip.MustParseAddrPort("[2001:db8::2]:51820"), }, }, { name: "dual stack", ping: control.Ping{ PingTS: 555, SrcV4: netip.MustParseAddrPort("1.2.3.4:51820"), SrcV6: netip.MustParseAddrPort("[2001:db8::1]:51820"), Dst: netip.MustParseAddrPort("5.6.7.8:9999"), }, }, { name: "no src known", ping: control.Ping{ Dst: netip.MustParseAddrPort("5.6.7.8:51820"), }, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { var buf [control.Size]byte tc.ping.Marshal(buf[:]) got, err := control.Unmarshal(buf) if err != nil { t.Fatalf("Unmarshal: %v", err) } if got != tc.ping { t.Fatalf("round-trip mismatch:\n got %+v\n want %+v", got, tc.ping) } }) } } func TestUnmarshalBadVersion(t *testing.T) { var buf [control.Size]byte buf[0] = 99 if _, err := control.Unmarshal(buf); err == nil { t.Fatal("expected error for unknown version, got nil") } } func TestZeroEncoding(t *testing.T) { var buf [control.Size]byte (control.Ping{}).Marshal(buf[:]) for i, b := range buf { if i == 0 { continue // version byte } if b != 0 { t.Fatalf("expected zero encoding at byte %d, got %d", i, b) } } } func TestRoleFor(t *testing.T) { lo := netip.MustParseAddr("10.0.0.1") hi := netip.MustParseAddr("10.0.0.2") if control.RoleFor(lo, hi) != control.Client { t.Error("lower IP should be client") } if control.RoleFor(hi, lo) != control.Server { t.Error("higher IP should be server") } }