Skip to content

Commit 5efcced

Browse files
committed
Add integration tests for allowed IP removal
Add testRemoveManyIPs to the integration tests to exercise the direct allowed IP removal capability and run the test suite on all platforms. $ WGCTRL_INTEGRATION go test . ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┓ ┃ OPERATING SYSTEM ┃ DRIVER ┃ REMOVE IP SUPPORTED ┃ RESULT ┃ ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━┩ │ FreeBSD 14.2 │ native │ no │ PASS │ ├──────────────────┼──────────────┼─────────────────────┼────────┤ │ OpenBSD 7.7 │ native │ no │ PASS* │ ├──────────────────┼──────────────┼─────────────────────┼────────┤ │ Windows 11 │ native │ no │ PASS** │ ├──────────────────┼──────────────┼─────────────────────┼────────┤ │ Linux │ native │ no │ PASS │ ├──────────────────┼──────────────┼─────────────────────┼────────┤ │ Linux │ wireguard-go │ no │ PASS │ ├──────────────────┼──────────────┼─────────────────────┼────────┤ │ Linux │ native │ yes │ │ ├──────────────────┼──────────────┼─────────────────────┼────────┤ │ Linux │ wireguard-go │ yes │ PASS │ └──────────────────┴──────────────┴─────────────────────┴────────┘ On systems where direct IP removal is not supported, I also made sure that ConfigureDevice returns an error when Remove is used without the shim. * OpenBSD skips this test case, since the driver is read only. ** Two assertions fail in Windows due to missing protocol version, but testRemoveManyIPs passes. Signed-off-by: Jordan Rife <[email protected]>
1 parent b8c2887 commit 5efcced

File tree

1 file changed

+105
-4
lines changed

1 file changed

+105
-4
lines changed

client_integration_test.go

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
)
2121

2222
func TestIntegrationClient(t *testing.T) {
23-
c, done := integrationClient(t)
23+
c, done := integrationClient(t, false)
2424
defer done()
2525

2626
devices, err := c.Devices()
@@ -43,6 +43,14 @@ func TestIntegrationClient(t *testing.T) {
4343
name: "configure",
4444
fn: testConfigure,
4545
},
46+
{
47+
name: "remove many IPs",
48+
fn: func(t *testing.T, _ *wgctrl.Client, d *wgtypes.Device) {
49+
c, done := integrationClient(t, true)
50+
defer done()
51+
testRemoveManyIPs(t, c, d)
52+
},
53+
},
4654
{
4755
name: "configure many IPs",
4856
fn: testConfigureManyIPs,
@@ -91,15 +99,15 @@ func TestIntegrationClient(t *testing.T) {
9199
}
92100

93101
func TestIntegrationClientIsNotExist(t *testing.T) {
94-
c, done := integrationClient(t)
102+
c, done := integrationClient(t, false)
95103
defer done()
96104

97105
if _, err := c.Device("wgnotexist0"); !errors.Is(err, os.ErrNotExist) {
98106
t.Fatalf("expected is not exist error, but got: %v", err)
99107
}
100108
}
101109

102-
func integrationClient(t *testing.T) (*wgctrl.Client, func()) {
110+
func integrationClient(t *testing.T, useShim bool) (*wgctrl.Client, func()) {
103111
t.Helper()
104112

105113
const (
@@ -112,7 +120,12 @@ func integrationClient(t *testing.T) (*wgctrl.Client, func()) {
112120
env, confirm)
113121
}
114122

115-
c, err := wgctrl.New()
123+
var opts []wgctrl.Option
124+
if useShim {
125+
opts = append(opts, wgctrl.WithShim)
126+
}
127+
128+
c, err := wgctrl.New(opts...)
116129
if err != nil {
117130
if errors.Is(err, os.ErrNotExist) {
118131
t.Skip("skipping, wgctrl is not available on this system")
@@ -223,6 +236,94 @@ func testConfigure(t *testing.T, c *wgctrl.Client, d *wgtypes.Device) {
223236
t.Log(out)
224237
}
225238

239+
func testRemoveManyIPs(t *testing.T, c *wgctrl.Client, d *wgtypes.Device) {
240+
// Apply 511 IPs per peer.
241+
var (
242+
countIPs int
243+
peers []wgtypes.PeerConfig
244+
peersRemoveIPs []wgtypes.PeerConfig
245+
)
246+
247+
for i := 0; i < 2; i++ {
248+
cidr := "2001:db8::/119"
249+
if i == 1 {
250+
cidr = "2001:db8:ffff::/119"
251+
}
252+
253+
cur, err := ipaddr.Parse(cidr)
254+
if err != nil {
255+
t.Fatalf("failed to create cursor: %v", err)
256+
}
257+
258+
var ips []net.IPNet
259+
for pos := cur.Next(); pos != nil; pos = cur.Next() {
260+
bits := 128
261+
if pos.IP.To4() != nil {
262+
bits = 32
263+
}
264+
265+
ips = append(ips, net.IPNet{
266+
IP: pos.IP,
267+
Mask: net.CIDRMask(bits, bits),
268+
})
269+
}
270+
271+
peers = append(peers, wgtypes.PeerConfig{
272+
PublicKey: wgtest.MustPublicKey(),
273+
ReplaceAllowedIPs: true,
274+
AllowedIPs: ipsToAllowedIPConfig(ips),
275+
})
276+
277+
peersRemoveIPs = append(peersRemoveIPs, wgtypes.PeerConfig{
278+
PublicKey: peers[len(peers)-1].PublicKey,
279+
AllowedIPs: ipsToAllowedIPConfig(ips),
280+
})
281+
282+
// Remove every other IP
283+
for i := range peersRemoveIPs[len(peersRemoveIPs)-1].AllowedIPs {
284+
peersRemoveIPs[len(peersRemoveIPs)-1].AllowedIPs[i].Remove = i%2 == 0
285+
}
286+
287+
countIPs += len(ips)
288+
}
289+
290+
cfg := wgtypes.Config{
291+
ReplacePeers: true,
292+
Peers: peers,
293+
}
294+
removeCfg := wgtypes.Config{
295+
Peers: peersRemoveIPs,
296+
}
297+
298+
tryConfigure(t, c, d.Name, cfg)
299+
300+
dn, err := c.Device(d.Name)
301+
if err != nil {
302+
t.Fatalf("failed to get %q by name: %v", d.Name, err)
303+
}
304+
305+
peerIPs := countPeerIPs(dn)
306+
if diff := cmp.Diff(countIPs, peerIPs); diff != "" {
307+
t.Fatalf("unexpected number of configured peer IPs (-want +got):\n%s", diff)
308+
}
309+
310+
t.Logf("device: %s: %d IPs", d.Name, peerIPs)
311+
312+
tryConfigure(t, c, d.Name, removeCfg)
313+
314+
dn, err = c.Device(d.Name)
315+
if err != nil {
316+
t.Fatalf("failed to get %q by name: %v", d.Name, err)
317+
}
318+
319+
peerIPs = countPeerIPs(dn)
320+
if diff := cmp.Diff(countIPs/2-1, peerIPs); diff != "" {
321+
t.Fatalf("unexpected number of configured peer IPs (-want +got):\n%s", diff)
322+
}
323+
324+
t.Logf("device: %s: %d IPs after remove", d.Name, peerIPs)
325+
}
326+
226327
func testConfigureManyIPs(t *testing.T, c *wgctrl.Client, d *wgtypes.Device) {
227328
// Apply 511 IPs per peer.
228329
var (

0 commit comments

Comments
 (0)