summaryrefslogtreecommitdiffhomepage
path: root/wgengine/wgcfg/device_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'wgengine/wgcfg/device_test.go')
-rw-r--r--wgengine/wgcfg/device_test.go196
1 files changed, 50 insertions, 146 deletions
diff --git a/wgengine/wgcfg/device_test.go b/wgengine/wgcfg/device_test.go
index 507f22311..07eb41adb 100644
--- a/wgengine/wgcfg/device_test.go
+++ b/wgengine/wgcfg/device_test.go
@@ -4,33 +4,22 @@
package wgcfg
import (
- "bufio"
- "bytes"
"io"
"net/netip"
"os"
- "sort"
- "strings"
- "sync"
"testing"
"github.com/tailscale/wireguard-go/conn"
"github.com/tailscale/wireguard-go/device"
"github.com/tailscale/wireguard-go/tun"
- "go4.org/mem"
"tailscale.com/types/key"
)
-func TestDeviceConfig(t *testing.T) {
- newK := func() (key.NodePublic, key.NodePrivate) {
- t.Helper()
- k := key.NewNode()
- return k.Public(), k
- }
+func TestReconfigDevice(t *testing.T) {
k1, pk1 := newK()
ip1 := netip.MustParsePrefix("10.0.0.1/32")
- k2, pk2 := newK()
+ k2, _ := newK()
ip2 := netip.MustParsePrefix("10.0.0.2/32")
k3, _ := newK()
@@ -38,165 +27,80 @@ func TestDeviceConfig(t *testing.T) {
cfg1 := &Config{
PrivateKey: pk1,
- Peers: []Peer{{
- PublicKey: k2,
- AllowedIPs: []netip.Prefix{ip2},
- }},
- }
-
- cfg2 := &Config{
- PrivateKey: pk2,
- Peers: []Peer{{
- PublicKey: k1,
- AllowedIPs: []netip.Prefix{ip1},
- PersistentKeepalive: 5,
- }},
+ Peers: []Peer{
+ {PublicKey: k2, AllowedIPs: []netip.Prefix{ip2}},
+ },
}
- device1 := NewDevice(newNilTun(), new(noopBind), device.NewLogger(device.LogLevelError, "device1"))
- device2 := NewDevice(newNilTun(), new(noopBind), device.NewLogger(device.LogLevelError, "device2"))
- defer device1.Close()
- defer device2.Close()
+ dev := NewDevice(newNilTun(), new(noopBind), device.NewLogger(device.LogLevelError, "test"))
+ defer dev.Close()
- cmp := func(t *testing.T, d *device.Device, want *Config) {
- t.Helper()
- got, err := DeviceConfig(d)
- if err != nil {
+ t.Run("initial-config", func(t *testing.T) {
+ if err := ReconfigDevice(dev, cfg1, t.Logf); err != nil {
t.Fatal(err)
}
- prev := new(Config)
- gotbuf := new(strings.Builder)
- err = got.ToUAPI(t.Logf, gotbuf, prev)
- gotStr := gotbuf.String()
- if err != nil {
- t.Errorf("got.ToUAPI(): error: %v", err)
- return
- }
- wantbuf := new(strings.Builder)
- err = want.ToUAPI(t.Logf, wantbuf, prev)
- wantStr := wantbuf.String()
- if err != nil {
- t.Errorf("want.ToUAPI(): error: %v", err)
- return
- }
- if gotStr != wantStr {
- buf := new(bytes.Buffer)
- w := bufio.NewWriter(buf)
- if err := d.IpcGetOperation(w); err != nil {
- t.Errorf("on error, could not IpcGetOperation: %v", err)
- }
- w.Flush()
- t.Errorf("config mismatch:\n---- got:\n%s\n---- want:\n%s\n---- uapi:\n%s", gotStr, wantStr, buf.String())
- }
- }
-
- t.Run("device1-config", func(t *testing.T) {
- if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
- t.Fatal(err)
- }
- cmp(t, device1, cfg1)
- })
-
- t.Run("device2-config", func(t *testing.T) {
- if err := ReconfigDevice(device2, cfg2, t.Logf); err != nil {
- t.Fatal(err)
- }
- cmp(t, device2, cfg2)
- })
-
- // This is only to test that Config and Reconfig are properly synchronized.
- t.Run("device2-config-reconfig", func(t *testing.T) {
- var wg sync.WaitGroup
- wg.Add(2)
-
- go func() {
- ReconfigDevice(device2, cfg2, t.Logf)
- wg.Done()
- }()
-
- go func() {
- DeviceConfig(device2)
- wg.Done()
- }()
-
- wg.Wait()
- })
-
- t.Run("device1-modify-peer", func(t *testing.T) {
- cfg1.Peers[0].DiscoKey = key.DiscoPublicFromRaw32(mem.B([]byte{0: 1, 31: 0}))
- if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
- t.Fatal(err)
+ // Peer should be creatable on demand via LookupPeer.
+ peer := dev.LookupPeer(k2.Raw32())
+ if peer == nil {
+ t.Fatal("expected peer k2 to exist via LookupPeer")
}
- cmp(t, device1, cfg1)
- })
-
- t.Run("device1-replace-endpoint", func(t *testing.T) {
- cfg1.Peers[0].DiscoKey = key.DiscoPublicFromRaw32(mem.B([]byte{0: 2, 31: 0}))
- if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
- t.Fatal(err)
+ // Unknown peer should not be found.
+ peer = dev.LookupPeer(k3.Raw32())
+ if peer != nil {
+ t.Fatal("expected unknown peer k3 to not exist")
}
- cmp(t, device1, cfg1)
})
- t.Run("device1-add-new-peer", func(t *testing.T) {
+ t.Run("add-peer", func(t *testing.T) {
cfg1.Peers = append(cfg1.Peers, Peer{
PublicKey: k3,
AllowedIPs: []netip.Prefix{ip3},
})
- sort.Slice(cfg1.Peers, func(i, j int) bool {
- return cfg1.Peers[i].PublicKey.Less(cfg1.Peers[j].PublicKey)
- })
-
- origCfg, err := DeviceConfig(device1)
- if err != nil {
+ if err := ReconfigDevice(dev, cfg1, t.Logf); err != nil {
t.Fatal(err)
}
-
- if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
- t.Fatal(err)
+ // Both peers should now be discoverable.
+ if p := dev.LookupPeer(k2.Raw32()); p == nil {
+ t.Fatal("expected peer k2 to exist")
}
- cmp(t, device1, cfg1)
-
- newCfg, err := DeviceConfig(device1)
- if err != nil {
- t.Fatal(err)
+ if p := dev.LookupPeer(k3.Raw32()); p == nil {
+ t.Fatal("expected peer k3 to exist")
}
+ })
- peer0 := func(cfg *Config) Peer {
- p, ok := cfg.PeerWithKey(k2)
- if !ok {
- t.Helper()
- t.Fatal("failed to look up peer 2")
- }
- return p
+ t.Run("remove-peer", func(t *testing.T) {
+ cfg2 := &Config{
+ PrivateKey: pk1,
+ Peers: []Peer{
+ {PublicKey: k2, AllowedIPs: []netip.Prefix{ip2}},
+ },
}
- peersEqual := func(p, q Peer) bool {
- return p.PublicKey == q.PublicKey && p.DiscoKey == q.DiscoKey && p.PersistentKeepalive == q.PersistentKeepalive && cidrsEqual(p.AllowedIPs, q.AllowedIPs)
+ if err := ReconfigDevice(dev, cfg2, t.Logf); err != nil {
+ t.Fatal(err)
+ }
+ // k2 should still be discoverable.
+ if p := dev.LookupPeer(k2.Raw32()); p == nil {
+ t.Fatal("expected peer k2 to exist")
}
- if !peersEqual(peer0(origCfg), peer0(newCfg)) {
- t.Error("reconfig modified old peer")
+ // k3 should no longer be discoverable.
+ if p := dev.LookupPeer(k3.Raw32()); p != nil {
+ t.Fatal("expected peer k3 to not exist after removal")
}
})
- t.Run("device1-remove-peer", func(t *testing.T) {
- removeKey := cfg1.Peers[len(cfg1.Peers)-1].PublicKey
- cfg1.Peers = cfg1.Peers[:len(cfg1.Peers)-1]
-
- if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
- t.Fatal(err)
+ t.Run("self-key-not-peer", func(t *testing.T) {
+ // The device's own key should not be a peer.
+ if p := dev.LookupPeer(k1.Raw32()); p != nil {
+ t.Fatal("expected own key to not be a peer")
}
- cmp(t, device1, cfg1)
+ })
- newCfg, err := DeviceConfig(device1)
- if err != nil {
- t.Fatal(err)
- }
+ _ = ip1 // suppress unused
+}
- _, ok := newCfg.PeerWithKey(removeKey)
- if ok {
- t.Error("reconfig failed to remove peer")
- }
- })
+func newK() (key.NodePublic, key.NodePrivate) {
+ k := key.NewNode()
+ return k.Public(), k
}
// TODO: replace with a loopback tunnel