Browse code

tests: Move libnetwork/testutils to internal/testutils/netnsutils

We don't want to maintain backward compatibility for this package, so
better make it an internal.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>

Albin Kerouanton authored on 2023/07/27 04:06:35
Showing 30 changed files
... ...
@@ -10,7 +10,7 @@ import (
10 10
 	"testing"
11 11
 
12 12
 	containertypes "github.com/docker/docker/api/types/container"
13
-	"github.com/docker/docker/libnetwork/testutils"
13
+	"github.com/docker/docker/internal/testutils/netnsutils"
14 14
 	"github.com/docker/docker/libnetwork/types"
15 15
 	"github.com/google/go-cmp/cmp/cmpopts"
16 16
 	"github.com/moby/sys/mount"
... ...
@@ -357,7 +357,7 @@ func TestIfaceAddrs(t *testing.T) {
357 357
 		},
358 358
 	} {
359 359
 		t.Run(tt.name, func(t *testing.T) {
360
-			defer testutils.SetupTestOSContext(t)()
360
+			defer netnsutils.SetupTestOSContext(t)()
361 361
 
362 362
 			createBridge(t, "test", tt.nws...)
363 363
 
364 364
new file mode 100644
... ...
@@ -0,0 +1,41 @@
0
+package netnsutils
1
+
2
+import "testing"
3
+
4
+// Logger is used to log non-fatal messages during tests.
5
+type Logger interface {
6
+	Logf(format string, args ...any)
7
+}
8
+
9
+var _ Logger = (*testing.T)(nil)
10
+
11
+// SetupTestOSContext joins the current goroutine to a new network namespace,
12
+// and returns its associated teardown function.
13
+//
14
+// Example usage:
15
+//
16
+//	defer SetupTestOSContext(t)()
17
+func SetupTestOSContext(t *testing.T) func() {
18
+	c := SetupTestOSContextEx(t)
19
+	return func() { c.Cleanup(t) }
20
+}
21
+
22
+// Go starts running fn in a new goroutine inside the test OS context.
23
+func (c *OSContext) Go(t *testing.T, fn func()) {
24
+	t.Helper()
25
+	errCh := make(chan error, 1)
26
+	go func() {
27
+		teardown, err := c.Set()
28
+		if err != nil {
29
+			errCh <- err
30
+			return
31
+		}
32
+		defer teardown(t)
33
+		close(errCh)
34
+		fn()
35
+	}()
36
+
37
+	if err := <-errCh; err != nil {
38
+		t.Fatalf("%+v", err)
39
+	}
40
+}
0 41
new file mode 100644
... ...
@@ -0,0 +1,168 @@
0
+//go:build linux || freebsd
1
+
2
+package netnsutils
3
+
4
+import (
5
+	"fmt"
6
+	"runtime"
7
+	"strconv"
8
+	"testing"
9
+
10
+	"github.com/docker/docker/libnetwork/ns"
11
+	"github.com/pkg/errors"
12
+	"github.com/vishvananda/netns"
13
+	"golang.org/x/sys/unix"
14
+)
15
+
16
+// OSContext is a handle to a test OS context.
17
+type OSContext struct {
18
+	origNS, newNS netns.NsHandle
19
+
20
+	tid    int
21
+	caller string // The file:line where SetupTestOSContextEx was called, for interpolating into error messages.
22
+}
23
+
24
+// SetupTestOSContextEx joins the current goroutine to a new network namespace.
25
+//
26
+// Compared to [SetupTestOSContext], this function allows goroutines to be
27
+// spawned which are associated with the same OS context via the returned
28
+// OSContext value.
29
+//
30
+// Example usage:
31
+//
32
+//	c := SetupTestOSContext(t)
33
+//	defer c.Cleanup(t)
34
+func SetupTestOSContextEx(t *testing.T) *OSContext {
35
+	runtime.LockOSThread()
36
+	origNS, err := netns.Get()
37
+	if err != nil {
38
+		runtime.UnlockOSThread()
39
+		t.Fatalf("Failed to open initial netns: %v", err)
40
+	}
41
+
42
+	c := OSContext{
43
+		tid:    unix.Gettid(),
44
+		origNS: origNS,
45
+	}
46
+	c.newNS, err = netns.New()
47
+	if err != nil {
48
+		// netns.New() is not atomic: it could have encountered an error
49
+		// after unsharing the current thread's network namespace.
50
+		c.restore(t)
51
+		t.Fatalf("Failed to enter netns: %v", err)
52
+	}
53
+
54
+	// Since we are switching to a new test namespace make
55
+	// sure to re-initialize initNs context
56
+	ns.Init()
57
+
58
+	nl := ns.NlHandle()
59
+	lo, err := nl.LinkByName("lo")
60
+	if err != nil {
61
+		c.restore(t)
62
+		t.Fatalf("Failed to get handle to loopback interface 'lo' in new netns: %v", err)
63
+	}
64
+	if err := nl.LinkSetUp(lo); err != nil {
65
+		c.restore(t)
66
+		t.Fatalf("Failed to enable loopback interface in new netns: %v", err)
67
+	}
68
+
69
+	_, file, line, ok := runtime.Caller(0)
70
+	if ok {
71
+		c.caller = file + ":" + strconv.Itoa(line)
72
+	}
73
+
74
+	return &c
75
+}
76
+
77
+// Cleanup tears down the OS context. It must be called from the same goroutine
78
+// as the [SetupTestOSContextEx] call which returned c.
79
+//
80
+// Explicit cleanup is required as (*testing.T).Cleanup() makes no guarantees
81
+// about which goroutine the cleanup functions are invoked on.
82
+func (c *OSContext) Cleanup(t *testing.T) {
83
+	t.Helper()
84
+	if unix.Gettid() != c.tid {
85
+		t.Fatalf("c.Cleanup() must be called from the same goroutine as SetupTestOSContextEx() (%s)", c.caller)
86
+	}
87
+	if err := c.newNS.Close(); err != nil {
88
+		t.Logf("Warning: netns closing failed (%v)", err)
89
+	}
90
+	c.restore(t)
91
+	ns.Init()
92
+}
93
+
94
+func (c *OSContext) restore(t *testing.T) {
95
+	t.Helper()
96
+	if err := netns.Set(c.origNS); err != nil {
97
+		t.Logf("Warning: failed to restore thread netns (%v)", err)
98
+	} else {
99
+		runtime.UnlockOSThread()
100
+	}
101
+
102
+	if err := c.origNS.Close(); err != nil {
103
+		t.Logf("Warning: netns closing failed (%v)", err)
104
+	}
105
+}
106
+
107
+// Set sets the OS context of the calling goroutine to c and returns a teardown
108
+// function to restore the calling goroutine's OS context and release resources.
109
+// The teardown function accepts an optional Logger argument.
110
+//
111
+// This is a lower-level interface which is less ergonomic than c.Go() but more
112
+// composable with other goroutine-spawning utilities such as [sync.WaitGroup]
113
+// or [golang.org/x/sync/errgroup.Group].
114
+//
115
+// Example usage:
116
+//
117
+//	func TestFoo(t *testing.T) {
118
+//		osctx := testutils.SetupTestOSContextEx(t)
119
+//		defer osctx.Cleanup(t)
120
+//		var eg errgroup.Group
121
+//		eg.Go(func() error {
122
+//			teardown, err := osctx.Set()
123
+//			if err != nil {
124
+//				return err
125
+//			}
126
+//			defer teardown(t)
127
+//			// ...
128
+//		})
129
+//		if err := eg.Wait(); err != nil {
130
+//			t.Fatalf("%+v", err)
131
+//		}
132
+//	}
133
+func (c *OSContext) Set() (func(Logger), error) {
134
+	runtime.LockOSThread()
135
+	orig, err := netns.Get()
136
+	if err != nil {
137
+		runtime.UnlockOSThread()
138
+		return nil, errors.Wrap(err, "failed to open initial netns for goroutine")
139
+	}
140
+	if err := errors.WithStack(netns.Set(c.newNS)); err != nil {
141
+		runtime.UnlockOSThread()
142
+		return nil, errors.Wrap(err, "failed to set goroutine network namespace")
143
+	}
144
+
145
+	tid := unix.Gettid()
146
+	_, file, line, callerOK := runtime.Caller(0)
147
+
148
+	return func(log Logger) {
149
+		if unix.Gettid() != tid {
150
+			msg := "teardown function must be called from the same goroutine as c.Set()"
151
+			if callerOK {
152
+				msg += fmt.Sprintf(" (%s:%d)", file, line)
153
+			}
154
+			panic(msg)
155
+		}
156
+
157
+		if err := netns.Set(orig); err != nil && log != nil {
158
+			log.Logf("Warning: failed to restore goroutine thread netns (%v)", err)
159
+		} else {
160
+			runtime.UnlockOSThread()
161
+		}
162
+
163
+		if err := orig.Close(); err != nil && log != nil {
164
+			log.Logf("Warning: netns closing failed (%v)", err)
165
+		}
166
+	}, nil
167
+}
0 168
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+package netnsutils
1
+
2
+import "testing"
3
+
4
+type OSContext struct{}
5
+
6
+func SetupTestOSContextEx(*testing.T) *OSContext {
7
+	return nil
8
+}
9
+
10
+func (*OSContext) Cleanup(t *testing.T) {}
11
+
12
+func (*OSContext) Set() (func(Logger), error) {
13
+	return func(Logger) {}, nil
14
+}
0 15
new file mode 100644
... ...
@@ -0,0 +1,43 @@
0
+package netnsutils
1
+
2
+import (
3
+	"errors"
4
+	"syscall"
5
+	"testing"
6
+
7
+	"github.com/vishvananda/netns"
8
+	"golang.org/x/sys/unix"
9
+	"gotest.tools/v3/assert"
10
+)
11
+
12
+// AssertSocketSameNetNS makes a best-effort attempt to assert that conn is in
13
+// the same network namespace as the current goroutine's thread.
14
+func AssertSocketSameNetNS(t testing.TB, conn syscall.Conn) {
15
+	t.Helper()
16
+
17
+	sc, err := conn.SyscallConn()
18
+	assert.NilError(t, err)
19
+	sc.Control(func(fd uintptr) {
20
+		srvnsfd, err := unix.IoctlRetInt(int(fd), unix.SIOCGSKNS)
21
+		if err != nil {
22
+			if errors.Is(err, unix.EPERM) {
23
+				t.Log("Cannot determine socket's network namespace. Do we have CAP_NET_ADMIN?")
24
+				return
25
+			}
26
+			if errors.Is(err, unix.ENOSYS) {
27
+				t.Log("Cannot query socket's network namespace due to missing kernel support.")
28
+				return
29
+			}
30
+			t.Fatal(err)
31
+		}
32
+		srvns := netns.NsHandle(srvnsfd)
33
+		defer srvns.Close()
34
+
35
+		curns, err := netns.Get()
36
+		assert.NilError(t, err)
37
+		defer curns.Close()
38
+		if !srvns.Equal(curns) {
39
+			t.Fatalf("Socket is in network namespace %s, but test goroutine is in %s", srvns, curns)
40
+		}
41
+	})
42
+}
0 43
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+//go:build !linux
1
+
2
+package netnsutils
3
+
4
+import (
5
+	"syscall"
6
+	"testing"
7
+)
8
+
9
+// AssertSocketSameNetNS is a no-op on platforms other than Linux.
10
+func AssertSocketSameNetNS(t testing.TB, conn syscall.Conn) {}
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"strconv"
12 12
 	"testing"
13 13
 
14
+	"github.com/docker/docker/internal/testutils/netnsutils"
14 15
 	"github.com/docker/docker/libnetwork/driverapi"
15 16
 	"github.com/docker/docker/libnetwork/ipamutils"
16 17
 	"github.com/docker/docker/libnetwork/iptables"
... ...
@@ -18,7 +19,6 @@ import (
18 18
 	"github.com/docker/docker/libnetwork/netutils"
19 19
 	"github.com/docker/docker/libnetwork/options"
20 20
 	"github.com/docker/docker/libnetwork/portallocator"
21
-	"github.com/docker/docker/libnetwork/testutils"
22 21
 	"github.com/docker/docker/libnetwork/types"
23 22
 	"github.com/vishvananda/netlink"
24 23
 )
... ...
@@ -181,7 +181,7 @@ func getIPv4Data(t *testing.T, iface string) []driverapi.IPAMData {
181 181
 }
182 182
 
183 183
 func TestCreateFullOptions(t *testing.T) {
184
-	defer testutils.SetupTestOSContext(t)()
184
+	defer netnsutils.SetupTestOSContext(t)()
185 185
 	d := newDriver()
186 186
 
187 187
 	config := &configuration{
... ...
@@ -235,7 +235,7 @@ func TestCreateFullOptions(t *testing.T) {
235 235
 }
236 236
 
237 237
 func TestCreateNoConfig(t *testing.T) {
238
-	defer testutils.SetupTestOSContext(t)()
238
+	defer netnsutils.SetupTestOSContext(t)()
239 239
 	d := newDriver()
240 240
 
241 241
 	netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
... ...
@@ -248,7 +248,7 @@ func TestCreateNoConfig(t *testing.T) {
248 248
 }
249 249
 
250 250
 func TestCreateFullOptionsLabels(t *testing.T) {
251
-	defer testutils.SetupTestOSContext(t)()
251
+	defer netnsutils.SetupTestOSContext(t)()
252 252
 	d := newDriver()
253 253
 
254 254
 	config := &configuration{
... ...
@@ -354,7 +354,7 @@ func TestCreateFullOptionsLabels(t *testing.T) {
354 354
 }
355 355
 
356 356
 func TestCreate(t *testing.T) {
357
-	defer testutils.SetupTestOSContext(t)()
357
+	defer netnsutils.SetupTestOSContext(t)()
358 358
 
359 359
 	d := newDriver()
360 360
 
... ...
@@ -380,7 +380,7 @@ func TestCreate(t *testing.T) {
380 380
 }
381 381
 
382 382
 func TestCreateFail(t *testing.T) {
383
-	defer testutils.SetupTestOSContext(t)()
383
+	defer netnsutils.SetupTestOSContext(t)()
384 384
 
385 385
 	d := newDriver()
386 386
 
... ...
@@ -398,7 +398,7 @@ func TestCreateFail(t *testing.T) {
398 398
 }
399 399
 
400 400
 func TestCreateMultipleNetworks(t *testing.T) {
401
-	defer testutils.SetupTestOSContext(t)()
401
+	defer netnsutils.SetupTestOSContext(t)()
402 402
 
403 403
 	d := newDriver()
404 404
 
... ...
@@ -606,7 +606,7 @@ func TestQueryEndpointInfoHairpin(t *testing.T) {
606 606
 }
607 607
 
608 608
 func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
609
-	defer testutils.SetupTestOSContext(t)()
609
+	defer netnsutils.SetupTestOSContext(t)()
610 610
 	d := newDriver()
611 611
 	d.portAllocator = portallocator.NewInstance()
612 612
 
... ...
@@ -708,7 +708,7 @@ func getPortMapping() []types.PortBinding {
708 708
 }
709 709
 
710 710
 func TestLinkContainers(t *testing.T) {
711
-	defer testutils.SetupTestOSContext(t)()
711
+	defer netnsutils.SetupTestOSContext(t)()
712 712
 
713 713
 	d := newDriver()
714 714
 	iptable := iptables.GetIptable(iptables.IPv4)
... ...
@@ -862,7 +862,7 @@ func TestLinkContainers(t *testing.T) {
862 862
 }
863 863
 
864 864
 func TestValidateConfig(t *testing.T) {
865
-	defer testutils.SetupTestOSContext(t)()
865
+	defer netnsutils.SetupTestOSContext(t)()
866 866
 
867 867
 	// Test mtu
868 868
 	c := networkConfiguration{Mtu: -2}
... ...
@@ -933,7 +933,7 @@ func TestValidateConfig(t *testing.T) {
933 933
 }
934 934
 
935 935
 func TestSetDefaultGw(t *testing.T) {
936
-	defer testutils.SetupTestOSContext(t)()
936
+	defer netnsutils.SetupTestOSContext(t)()
937 937
 
938 938
 	d := newDriver()
939 939
 
... ...
@@ -985,7 +985,7 @@ func TestSetDefaultGw(t *testing.T) {
985 985
 }
986 986
 
987 987
 func TestCleanupIptableRules(t *testing.T) {
988
-	defer testutils.SetupTestOSContext(t)()
988
+	defer netnsutils.SetupTestOSContext(t)()
989 989
 	bridgeChain := []iptables.ChainInfo{
990 990
 		{Name: DockerChain, Table: iptables.Nat},
991 991
 		{Name: DockerChain, Table: iptables.Filter},
... ...
@@ -1015,7 +1015,7 @@ func TestCleanupIptableRules(t *testing.T) {
1015 1015
 }
1016 1016
 
1017 1017
 func TestCreateWithExistingBridge(t *testing.T) {
1018
-	defer testutils.SetupTestOSContext(t)()
1018
+	defer netnsutils.SetupTestOSContext(t)()
1019 1019
 	d := newDriver()
1020 1020
 
1021 1021
 	if err := d.configure(nil); err != nil {
... ...
@@ -1085,7 +1085,7 @@ func TestCreateWithExistingBridge(t *testing.T) {
1085 1085
 }
1086 1086
 
1087 1087
 func TestCreateParallel(t *testing.T) {
1088
-	c := testutils.SetupTestOSContextEx(t)
1088
+	c := netnsutils.SetupTestOSContextEx(t)
1089 1089
 	defer c.Cleanup(t)
1090 1090
 
1091 1091
 	d := newDriver()
... ...
@@ -5,12 +5,12 @@ package bridge
5 5
 import (
6 6
 	"testing"
7 7
 
8
-	"github.com/docker/docker/libnetwork/testutils"
8
+	"github.com/docker/docker/internal/testutils/netnsutils"
9 9
 	"github.com/vishvananda/netlink"
10 10
 )
11 11
 
12 12
 func TestInterfaceDefaultName(t *testing.T) {
13
-	defer testutils.SetupTestOSContext(t)()
13
+	defer netnsutils.SetupTestOSContext(t)()
14 14
 
15 15
 	nh, err := netlink.NewHandle()
16 16
 	if err != nil {
... ...
@@ -28,7 +28,7 @@ func TestInterfaceDefaultName(t *testing.T) {
28 28
 }
29 29
 
30 30
 func TestAddressesEmptyInterface(t *testing.T) {
31
-	defer testutils.SetupTestOSContext(t)()
31
+	defer netnsutils.SetupTestOSContext(t)()
32 32
 
33 33
 	nh, err := netlink.NewHandle()
34 34
 	if err != nil {
... ...
@@ -5,14 +5,14 @@ package bridge
5 5
 import (
6 6
 	"testing"
7 7
 
8
+	"github.com/docker/docker/internal/testutils/netnsutils"
8 9
 	"github.com/docker/docker/libnetwork/driverapi"
9 10
 	"github.com/docker/docker/libnetwork/netlabel"
10
-	"github.com/docker/docker/libnetwork/testutils"
11 11
 	"github.com/vishvananda/netlink"
12 12
 )
13 13
 
14 14
 func TestLinkCreate(t *testing.T) {
15
-	defer testutils.SetupTestOSContext(t)()
15
+	defer netnsutils.SetupTestOSContext(t)()
16 16
 	d := newDriver()
17 17
 
18 18
 	if err := d.configure(nil); err != nil {
... ...
@@ -107,7 +107,7 @@ func TestLinkCreate(t *testing.T) {
107 107
 }
108 108
 
109 109
 func TestLinkCreateTwo(t *testing.T) {
110
-	defer testutils.SetupTestOSContext(t)()
110
+	defer netnsutils.SetupTestOSContext(t)()
111 111
 	d := newDriver()
112 112
 
113 113
 	if err := d.configure(nil); err != nil {
... ...
@@ -145,7 +145,7 @@ func TestLinkCreateTwo(t *testing.T) {
145 145
 }
146 146
 
147 147
 func TestLinkCreateNoEnableIPv6(t *testing.T) {
148
-	defer testutils.SetupTestOSContext(t)()
148
+	defer netnsutils.SetupTestOSContext(t)()
149 149
 	d := newDriver()
150 150
 
151 151
 	if err := d.configure(nil); err != nil {
... ...
@@ -180,7 +180,7 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
180 180
 }
181 181
 
182 182
 func TestLinkDelete(t *testing.T) {
183
-	defer testutils.SetupTestOSContext(t)()
183
+	defer netnsutils.SetupTestOSContext(t)()
184 184
 	d := newDriver()
185 185
 
186 186
 	if err := d.configure(nil); err != nil {
... ...
@@ -5,14 +5,14 @@ package bridge
5 5
 import (
6 6
 	"testing"
7 7
 
8
+	"github.com/docker/docker/internal/testutils/netnsutils"
8 9
 	"github.com/docker/docker/libnetwork/netlabel"
9 10
 	"github.com/docker/docker/libnetwork/ns"
10
-	"github.com/docker/docker/libnetwork/testutils"
11 11
 	"github.com/docker/docker/libnetwork/types"
12 12
 )
13 13
 
14 14
 func TestPortMappingConfig(t *testing.T) {
15
-	defer testutils.SetupTestOSContext(t)()
15
+	defer netnsutils.SetupTestOSContext(t)()
16 16
 	d := newDriver()
17 17
 
18 18
 	config := &configuration{
... ...
@@ -91,7 +91,7 @@ func TestPortMappingConfig(t *testing.T) {
91 91
 }
92 92
 
93 93
 func TestPortMappingV6Config(t *testing.T) {
94
-	defer testutils.SetupTestOSContext(t)()
94
+	defer netnsutils.SetupTestOSContext(t)()
95 95
 	if err := loopbackUp(); err != nil {
96 96
 		t.Fatalf("Could not bring loopback iface up: %v", err)
97 97
 	}
... ...
@@ -7,13 +7,13 @@ import (
7 7
 	"net"
8 8
 	"testing"
9 9
 
10
+	"github.com/docker/docker/internal/testutils/netnsutils"
10 11
 	"github.com/docker/docker/libnetwork/netutils"
11
-	"github.com/docker/docker/libnetwork/testutils"
12 12
 	"github.com/vishvananda/netlink"
13 13
 )
14 14
 
15 15
 func TestSetupNewBridge(t *testing.T) {
16
-	defer testutils.SetupTestOSContext(t)()
16
+	defer netnsutils.SetupTestOSContext(t)()
17 17
 
18 18
 	nh, err := netlink.NewHandle()
19 19
 	if err != nil {
... ...
@@ -39,7 +39,7 @@ func TestSetupNewBridge(t *testing.T) {
39 39
 }
40 40
 
41 41
 func TestSetupNewNonDefaultBridge(t *testing.T) {
42
-	defer testutils.SetupTestOSContext(t)()
42
+	defer netnsutils.SetupTestOSContext(t)()
43 43
 
44 44
 	nh, err := netlink.NewHandle()
45 45
 	if err != nil {
... ...
@@ -61,7 +61,7 @@ func TestSetupNewNonDefaultBridge(t *testing.T) {
61 61
 }
62 62
 
63 63
 func TestSetupDeviceUp(t *testing.T) {
64
-	defer testutils.SetupTestOSContext(t)()
64
+	defer netnsutils.SetupTestOSContext(t)()
65 65
 
66 66
 	nh, err := netlink.NewHandle()
67 67
 	if err != nil {
... ...
@@ -86,7 +86,7 @@ func TestSetupDeviceUp(t *testing.T) {
86 86
 }
87 87
 
88 88
 func TestGenerateRandomMAC(t *testing.T) {
89
-	defer testutils.SetupTestOSContext(t)()
89
+	defer netnsutils.SetupTestOSContext(t)()
90 90
 
91 91
 	mac1 := netutils.GenerateRandomMAC()
92 92
 	mac2 := netutils.GenerateRandomMAC()
... ...
@@ -6,9 +6,9 @@ import (
6 6
 	"net"
7 7
 	"testing"
8 8
 
9
+	"github.com/docker/docker/internal/testutils/netnsutils"
9 10
 	"github.com/docker/docker/libnetwork/iptables"
10 11
 	"github.com/docker/docker/libnetwork/portmapper"
11
-	"github.com/docker/docker/libnetwork/testutils"
12 12
 	"github.com/vishvananda/netlink"
13 13
 )
14 14
 
... ...
@@ -18,7 +18,7 @@ const (
18 18
 
19 19
 func TestProgramIPTable(t *testing.T) {
20 20
 	// Create a test bridge with a basic bridge configuration (name + IPv4).
21
-	defer testutils.SetupTestOSContext(t)()
21
+	defer netnsutils.SetupTestOSContext(t)()
22 22
 
23 23
 	nh, err := netlink.NewHandle()
24 24
 	if err != nil {
... ...
@@ -48,7 +48,7 @@ func TestProgramIPTable(t *testing.T) {
48 48
 
49 49
 func TestSetupIPChains(t *testing.T) {
50 50
 	// Create a test bridge with a basic bridge configuration (name + IPv4).
51
-	defer testutils.SetupTestOSContext(t)()
51
+	defer netnsutils.SetupTestOSContext(t)()
52 52
 
53 53
 	nh, err := netlink.NewHandle()
54 54
 	if err != nil {
... ...
@@ -6,7 +6,7 @@ import (
6 6
 	"net"
7 7
 	"testing"
8 8
 
9
-	"github.com/docker/docker/libnetwork/testutils"
9
+	"github.com/docker/docker/internal/testutils/netnsutils"
10 10
 	"github.com/vishvananda/netlink"
11 11
 )
12 12
 
... ...
@@ -23,7 +23,7 @@ func setupTestInterface(t *testing.T, nh *netlink.Handle) (*networkConfiguration
23 23
 }
24 24
 
25 25
 func TestSetupBridgeIPv4Fixed(t *testing.T) {
26
-	defer testutils.SetupTestOSContext(t)()
26
+	defer netnsutils.SetupTestOSContext(t)()
27 27
 
28 28
 	ip, netw, err := net.ParseCIDR("192.168.1.1/24")
29 29
 	if err != nil {
... ...
@@ -61,7 +61,7 @@ func TestSetupBridgeIPv4Fixed(t *testing.T) {
61 61
 }
62 62
 
63 63
 func TestSetupGatewayIPv4(t *testing.T) {
64
-	defer testutils.SetupTestOSContext(t)()
64
+	defer netnsutils.SetupTestOSContext(t)()
65 65
 
66 66
 	nh, err := netlink.NewHandle()
67 67
 	if err != nil {
... ...
@@ -9,12 +9,12 @@ import (
9 9
 	"os"
10 10
 	"testing"
11 11
 
12
-	"github.com/docker/docker/libnetwork/testutils"
12
+	"github.com/docker/docker/internal/testutils/netnsutils"
13 13
 	"github.com/vishvananda/netlink"
14 14
 )
15 15
 
16 16
 func TestSetupIPv6(t *testing.T) {
17
-	defer testutils.SetupTestOSContext(t)()
17
+	defer netnsutils.SetupTestOSContext(t)()
18 18
 
19 19
 	nh, err := netlink.NewHandle()
20 20
 	if err != nil {
... ...
@@ -55,7 +55,7 @@ func TestSetupIPv6(t *testing.T) {
55 55
 }
56 56
 
57 57
 func TestSetupGatewayIPv6(t *testing.T) {
58
-	defer testutils.SetupTestOSContext(t)()
58
+	defer netnsutils.SetupTestOSContext(t)()
59 59
 
60 60
 	_, nw, _ := net.ParseCIDR("2001:db8:ea9:9abc:ffff::/80")
61 61
 	gw := net.ParseIP("2001:db8:ea9:9abc:ffff::254")
... ...
@@ -6,7 +6,7 @@ import (
6 6
 	"net"
7 7
 	"testing"
8 8
 
9
-	"github.com/docker/docker/libnetwork/testutils"
9
+	"github.com/docker/docker/internal/testutils/netnsutils"
10 10
 	"github.com/vishvananda/netlink"
11 11
 )
12 12
 
... ...
@@ -29,7 +29,7 @@ func setupVerifyTest(t *testing.T) *bridgeInterface {
29 29
 }
30 30
 
31 31
 func TestSetupVerify(t *testing.T) {
32
-	defer testutils.SetupTestOSContext(t)()
32
+	defer netnsutils.SetupTestOSContext(t)()
33 33
 
34 34
 	addrv4 := net.IPv4(192, 168, 1, 1)
35 35
 	inf := setupVerifyTest(t)
... ...
@@ -46,7 +46,7 @@ func TestSetupVerify(t *testing.T) {
46 46
 }
47 47
 
48 48
 func TestSetupVerifyBad(t *testing.T) {
49
-	defer testutils.SetupTestOSContext(t)()
49
+	defer netnsutils.SetupTestOSContext(t)()
50 50
 
51 51
 	addrv4 := net.IPv4(192, 168, 1, 1)
52 52
 	inf := setupVerifyTest(t)
... ...
@@ -64,7 +64,7 @@ func TestSetupVerifyBad(t *testing.T) {
64 64
 }
65 65
 
66 66
 func TestSetupVerifyMissing(t *testing.T) {
67
-	defer testutils.SetupTestOSContext(t)()
67
+	defer netnsutils.SetupTestOSContext(t)()
68 68
 
69 69
 	addrv4 := net.IPv4(192, 168, 1, 1)
70 70
 	inf := setupVerifyTest(t)
... ...
@@ -77,7 +77,7 @@ func TestSetupVerifyMissing(t *testing.T) {
77 77
 }
78 78
 
79 79
 func TestSetupVerifyIPv6(t *testing.T) {
80
-	defer testutils.SetupTestOSContext(t)()
80
+	defer netnsutils.SetupTestOSContext(t)()
81 81
 
82 82
 	addrv4 := net.IPv4(192, 168, 1, 1)
83 83
 	inf := setupVerifyTest(t)
... ...
@@ -98,7 +98,7 @@ func TestSetupVerifyIPv6(t *testing.T) {
98 98
 }
99 99
 
100 100
 func TestSetupVerifyIPv6Missing(t *testing.T) {
101
-	defer testutils.SetupTestOSContext(t)()
101
+	defer netnsutils.SetupTestOSContext(t)()
102 102
 
103 103
 	addrv4 := net.IPv4(192, 168, 1, 1)
104 104
 	inf := setupVerifyTest(t)
... ...
@@ -6,13 +6,13 @@ import (
6 6
 	"os"
7 7
 	"testing"
8 8
 
9
+	"github.com/docker/docker/internal/testutils/netnsutils"
9 10
 	"github.com/docker/docker/libnetwork/ipamapi"
10 11
 	"github.com/docker/docker/libnetwork/osl"
11
-	"github.com/docker/docker/libnetwork/testutils"
12 12
 )
13 13
 
14 14
 func TestHostsEntries(t *testing.T) {
15
-	defer testutils.SetupTestOSContext(t)()
15
+	defer netnsutils.SetupTestOSContext(t)()
16 16
 
17 17
 	expectedHostsFile := `127.0.0.1	localhost
18 18
 ::1	localhost ip6-localhost ip6-loopback
... ...
@@ -5,11 +5,11 @@ import (
5 5
 	"strings"
6 6
 	"testing"
7 7
 
8
+	"github.com/docker/docker/internal/testutils/netnsutils"
8 9
 	"github.com/docker/docker/libnetwork/config"
9 10
 	"github.com/docker/docker/libnetwork/iptables"
10 11
 	"github.com/docker/docker/libnetwork/netlabel"
11 12
 	"github.com/docker/docker/libnetwork/options"
12
-	"github.com/docker/docker/libnetwork/testutils"
13 13
 	"gotest.tools/v3/assert"
14 14
 	is "gotest.tools/v3/assert/cmp"
15 15
 )
... ...
@@ -51,7 +51,7 @@ func TestUserChain(t *testing.T) {
51 51
 	for _, tc := range tests {
52 52
 		tc := tc
53 53
 		t.Run(fmt.Sprintf("iptables=%v,insert=%v", tc.iptables, tc.insert), func(t *testing.T) {
54
-			defer testutils.SetupTestOSContext(t)()
54
+			defer netnsutils.SetupTestOSContext(t)()
55 55
 			defer resetIptables(t)
56 56
 
57 57
 			c, err := New(config.OptionDriverConfig("bridge", map[string]any{
... ...
@@ -8,13 +8,13 @@ import (
8 8
 	"testing"
9 9
 	"time"
10 10
 
11
+	"github.com/docker/docker/internal/testutils/netnsutils"
11 12
 	"github.com/docker/docker/libnetwork/datastore"
12 13
 	"github.com/docker/docker/libnetwork/discoverapi"
13 14
 	"github.com/docker/docker/libnetwork/driverapi"
14 15
 	"github.com/docker/docker/libnetwork/ipamapi"
15 16
 	"github.com/docker/docker/libnetwork/netlabel"
16 17
 	"github.com/docker/docker/libnetwork/netutils"
17
-	"github.com/docker/docker/libnetwork/testutils"
18 18
 	"github.com/docker/docker/libnetwork/types"
19 19
 	"gotest.tools/v3/skip"
20 20
 )
... ...
@@ -311,7 +311,7 @@ func compareNwLists(a, b []*net.IPNet) bool {
311 311
 }
312 312
 
313 313
 func TestAuxAddresses(t *testing.T) {
314
-	defer testutils.SetupTestOSContext(t)()
314
+	defer netnsutils.SetupTestOSContext(t)()
315 315
 
316 316
 	c, err := New()
317 317
 	if err != nil {
... ...
@@ -350,7 +350,7 @@ func TestAuxAddresses(t *testing.T) {
350 350
 func TestSRVServiceQuery(t *testing.T) {
351 351
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
352 352
 
353
-	defer testutils.SetupTestOSContext(t)()
353
+	defer netnsutils.SetupTestOSContext(t)()
354 354
 
355 355
 	c, err := New()
356 356
 	if err != nil {
... ...
@@ -447,7 +447,7 @@ func TestSRVServiceQuery(t *testing.T) {
447 447
 func TestServiceVIPReuse(t *testing.T) {
448 448
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
449 449
 
450
-	defer testutils.SetupTestOSContext(t)()
450
+	defer netnsutils.SetupTestOSContext(t)()
451 451
 
452 452
 	c, err := New()
453 453
 	if err != nil {
... ...
@@ -564,7 +564,7 @@ func TestServiceVIPReuse(t *testing.T) {
564 564
 func TestIpamReleaseOnNetDriverFailures(t *testing.T) {
565 565
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
566 566
 
567
-	defer testutils.SetupTestOSContext(t)()
567
+	defer netnsutils.SetupTestOSContext(t)()
568 568
 
569 569
 	c, err := New(OptionBoltdbWithRandomDBFile(t))
570 570
 	if err != nil {
... ...
@@ -13,12 +13,12 @@ import (
13 13
 	"testing"
14 14
 
15 15
 	"github.com/containerd/containerd/log"
16
+	"github.com/docker/docker/internal/testutils/netnsutils"
16 17
 	"github.com/docker/docker/libnetwork"
17 18
 	"github.com/docker/docker/libnetwork/ipamapi"
18 19
 	"github.com/docker/docker/libnetwork/netlabel"
19 20
 	"github.com/docker/docker/libnetwork/options"
20 21
 	"github.com/docker/docker/libnetwork/osl"
21
-	"github.com/docker/docker/libnetwork/testutils"
22 22
 	"github.com/docker/docker/libnetwork/types"
23 23
 	"github.com/docker/docker/pkg/reexec"
24 24
 	"github.com/pkg/errors"
... ...
@@ -41,7 +41,7 @@ func makeTesthostNetwork(t *testing.T, c *libnetwork.Controller) *libnetwork.Net
41 41
 }
42 42
 
43 43
 func TestHost(t *testing.T) {
44
-	defer testutils.SetupTestOSContext(t)()
44
+	defer netnsutils.SetupTestOSContext(t)()
45 45
 	controller := newController(t)
46 46
 
47 47
 	sbx1, err := controller.NewSandbox("host_c1",
... ...
@@ -142,7 +142,7 @@ func TestHost(t *testing.T) {
142 142
 
143 143
 // Testing IPV6 from MAC address
144 144
 func TestBridgeIpv6FromMac(t *testing.T) {
145
-	defer testutils.SetupTestOSContext(t)()
145
+	defer netnsutils.SetupTestOSContext(t)()
146 146
 	controller := newController(t)
147 147
 
148 148
 	netOption := options.Generic{
... ...
@@ -217,7 +217,7 @@ func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) {
217 217
 }
218 218
 
219 219
 func TestEndpointJoin(t *testing.T) {
220
-	defer testutils.SetupTestOSContext(t)()
220
+	defer netnsutils.SetupTestOSContext(t)()
221 221
 	controller := newController(t)
222 222
 
223 223
 	// Create network 1 and add 2 endpoint: ep11, ep12
... ...
@@ -392,7 +392,7 @@ func TestExternalKey(t *testing.T) {
392 392
 }
393 393
 
394 394
 func externalKeyTest(t *testing.T, reexec bool) {
395
-	defer testutils.SetupTestOSContext(t)()
395
+	defer netnsutils.SetupTestOSContext(t)()
396 396
 	controller := newController(t)
397 397
 
398 398
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
... ...
@@ -553,7 +553,7 @@ func reexecSetKey(key string, containerID string, controllerID string) error {
553 553
 }
554 554
 
555 555
 func TestEnableIPv6(t *testing.T) {
556
-	defer testutils.SetupTestOSContext(t)()
556
+	defer netnsutils.SetupTestOSContext(t)()
557 557
 	controller := newController(t)
558 558
 
559 559
 	tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888\n")
... ...
@@ -630,7 +630,7 @@ func TestEnableIPv6(t *testing.T) {
630 630
 }
631 631
 
632 632
 func TestResolvConfHost(t *testing.T) {
633
-	defer testutils.SetupTestOSContext(t)()
633
+	defer netnsutils.SetupTestOSContext(t)()
634 634
 	controller := newController(t)
635 635
 
636 636
 	tmpResolvConf := []byte("search localhost.net\nnameserver 127.0.0.1\nnameserver 2001:4860:4860::8888\n")
... ...
@@ -705,7 +705,7 @@ func TestResolvConfHost(t *testing.T) {
705 705
 }
706 706
 
707 707
 func TestResolvConf(t *testing.T) {
708
-	defer testutils.SetupTestOSContext(t)()
708
+	defer netnsutils.SetupTestOSContext(t)()
709 709
 	controller := newController(t)
710 710
 
711 711
 	tmpResolvConf1 := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888\n")
... ...
@@ -845,7 +845,7 @@ func TestResolvConf(t *testing.T) {
845 845
 }
846 846
 
847 847
 type parallelTester struct {
848
-	osctx      *testutils.OSContext
848
+	osctx      *netnsutils.OSContext
849 849
 	controller *libnetwork.Controller
850 850
 	net1, net2 *libnetwork.Network
851 851
 	iterCnt    int
... ...
@@ -912,7 +912,7 @@ func TestParallel(t *testing.T) {
912 912
 		iterCnt    = 25
913 913
 	)
914 914
 
915
-	osctx := testutils.SetupTestOSContextEx(t)
915
+	osctx := netnsutils.SetupTestOSContextEx(t)
916 916
 	defer osctx.Cleanup(t)
917 917
 	controller := newController(t)
918 918
 
... ...
@@ -974,7 +974,7 @@ func TestParallel(t *testing.T) {
974 974
 }
975 975
 
976 976
 func TestBridge(t *testing.T) {
977
-	defer testutils.SetupTestOSContext(t)()
977
+	defer netnsutils.SetupTestOSContext(t)()
978 978
 	controller := newController(t)
979 979
 
980 980
 	netOption := options.Generic{
... ...
@@ -1062,7 +1062,7 @@ func isV6Listenable() bool {
1062 1062
 }
1063 1063
 
1064 1064
 func TestNullIpam(t *testing.T) {
1065
-	defer testutils.SetupTestOSContext(t)()
1065
+	defer netnsutils.SetupTestOSContext(t)()
1066 1066
 	controller := newController(t)
1067 1067
 
1068 1068
 	_, err := controller.NewNetwork(bridgeNetType, "testnetworkinternal", "", libnetwork.NetworkOptionIpam(ipamapi.NullIPAM, "", nil, nil, nil))
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"path/filepath"
12 12
 	"testing"
13 13
 
14
+	"github.com/docker/docker/internal/testutils/netnsutils"
14 15
 	"github.com/docker/docker/libnetwork"
15 16
 	"github.com/docker/docker/libnetwork/config"
16 17
 	"github.com/docker/docker/libnetwork/datastore"
... ...
@@ -18,7 +19,6 @@ import (
18 18
 	"github.com/docker/docker/libnetwork/ipamapi"
19 19
 	"github.com/docker/docker/libnetwork/netlabel"
20 20
 	"github.com/docker/docker/libnetwork/options"
21
-	"github.com/docker/docker/libnetwork/testutils"
22 21
 	"github.com/docker/docker/libnetwork/types"
23 22
 	"github.com/docker/docker/pkg/plugins"
24 23
 )
... ...
@@ -73,7 +73,7 @@ func isNotFound(err error) bool {
73 73
 }
74 74
 
75 75
 func TestNull(t *testing.T) {
76
-	defer testutils.SetupTestOSContext(t)()
76
+	defer netnsutils.SetupTestOSContext(t)()
77 77
 	controller := newController(t)
78 78
 
79 79
 	cnt, err := controller.NewSandbox("null_container",
... ...
@@ -123,7 +123,7 @@ func TestNull(t *testing.T) {
123 123
 }
124 124
 
125 125
 func TestUnknownDriver(t *testing.T) {
126
-	defer testutils.SetupTestOSContext(t)()
126
+	defer netnsutils.SetupTestOSContext(t)()
127 127
 	controller := newController(t)
128 128
 
129 129
 	_, err := createTestNetwork(controller, "unknowndriver", "testnetwork", options.Generic{}, nil, nil)
... ...
@@ -137,7 +137,7 @@ func TestUnknownDriver(t *testing.T) {
137 137
 }
138 138
 
139 139
 func TestNilRemoteDriver(t *testing.T) {
140
-	defer testutils.SetupTestOSContext(t)()
140
+	defer netnsutils.SetupTestOSContext(t)()
141 141
 	controller := newController(t)
142 142
 
143 143
 	_, err := controller.NewNetwork("framerelay", "dummy", "",
... ...
@@ -152,7 +152,7 @@ func TestNilRemoteDriver(t *testing.T) {
152 152
 }
153 153
 
154 154
 func TestNetworkName(t *testing.T) {
155
-	defer testutils.SetupTestOSContext(t)()
155
+	defer netnsutils.SetupTestOSContext(t)()
156 156
 	controller := newController(t)
157 157
 
158 158
 	netOption := options.Generic{
... ...
@@ -187,7 +187,7 @@ func TestNetworkName(t *testing.T) {
187 187
 }
188 188
 
189 189
 func TestNetworkType(t *testing.T) {
190
-	defer testutils.SetupTestOSContext(t)()
190
+	defer netnsutils.SetupTestOSContext(t)()
191 191
 	controller := newController(t)
192 192
 
193 193
 	netOption := options.Generic{
... ...
@@ -212,7 +212,7 @@ func TestNetworkType(t *testing.T) {
212 212
 }
213 213
 
214 214
 func TestNetworkID(t *testing.T) {
215
-	defer testutils.SetupTestOSContext(t)()
215
+	defer netnsutils.SetupTestOSContext(t)()
216 216
 	controller := newController(t)
217 217
 
218 218
 	netOption := options.Generic{
... ...
@@ -237,7 +237,7 @@ func TestNetworkID(t *testing.T) {
237 237
 }
238 238
 
239 239
 func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
240
-	defer testutils.SetupTestOSContext(t)()
240
+	defer netnsutils.SetupTestOSContext(t)()
241 241
 	controller := newController(t)
242 242
 
243 243
 	netOption := options.Generic{
... ...
@@ -277,7 +277,7 @@ func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
277 277
 }
278 278
 
279 279
 func TestNetworkConfig(t *testing.T) {
280
-	defer testutils.SetupTestOSContext(t)()
280
+	defer netnsutils.SetupTestOSContext(t)()
281 281
 	controller := newController(t)
282 282
 
283 283
 	// Verify config network cannot inherit another config network
... ...
@@ -378,7 +378,7 @@ func TestNetworkConfig(t *testing.T) {
378 378
 }
379 379
 
380 380
 func TestUnknownNetwork(t *testing.T) {
381
-	defer testutils.SetupTestOSContext(t)()
381
+	defer netnsutils.SetupTestOSContext(t)()
382 382
 	controller := newController(t)
383 383
 
384 384
 	netOption := options.Generic{
... ...
@@ -409,7 +409,7 @@ func TestUnknownNetwork(t *testing.T) {
409 409
 }
410 410
 
411 411
 func TestUnknownEndpoint(t *testing.T) {
412
-	defer testutils.SetupTestOSContext(t)()
412
+	defer netnsutils.SetupTestOSContext(t)()
413 413
 	controller := newController(t)
414 414
 
415 415
 	netOption := options.Generic{
... ...
@@ -450,7 +450,7 @@ func TestUnknownEndpoint(t *testing.T) {
450 450
 }
451 451
 
452 452
 func TestNetworkEndpointsWalkers(t *testing.T) {
453
-	defer testutils.SetupTestOSContext(t)()
453
+	defer netnsutils.SetupTestOSContext(t)()
454 454
 	controller := newController(t)
455 455
 
456 456
 	// Create network 1 and add 2 endpoint: ep11, ep12
... ...
@@ -579,7 +579,7 @@ func TestNetworkEndpointsWalkers(t *testing.T) {
579 579
 }
580 580
 
581 581
 func TestDuplicateEndpoint(t *testing.T) {
582
-	defer testutils.SetupTestOSContext(t)()
582
+	defer netnsutils.SetupTestOSContext(t)()
583 583
 	controller := newController(t)
584 584
 
585 585
 	netOption := options.Generic{
... ...
@@ -627,7 +627,7 @@ func TestDuplicateEndpoint(t *testing.T) {
627 627
 }
628 628
 
629 629
 func TestControllerQuery(t *testing.T) {
630
-	defer testutils.SetupTestOSContext(t)()
630
+	defer netnsutils.SetupTestOSContext(t)()
631 631
 	controller := newController(t)
632 632
 
633 633
 	// Create network 1
... ...
@@ -728,7 +728,7 @@ func TestControllerQuery(t *testing.T) {
728 728
 }
729 729
 
730 730
 func TestNetworkQuery(t *testing.T) {
731
-	defer testutils.SetupTestOSContext(t)()
731
+	defer netnsutils.SetupTestOSContext(t)()
732 732
 	controller := newController(t)
733 733
 
734 734
 	// Create network 1 and add 2 endpoint: ep11, ep12
... ...
@@ -814,7 +814,7 @@ func TestNetworkQuery(t *testing.T) {
814 814
 const containerID = "valid_c"
815 815
 
816 816
 func TestEndpointDeleteWithActiveContainer(t *testing.T) {
817
-	defer testutils.SetupTestOSContext(t)()
817
+	defer netnsutils.SetupTestOSContext(t)()
818 818
 	controller := newController(t)
819 819
 
820 820
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
... ...
@@ -888,7 +888,7 @@ func TestEndpointDeleteWithActiveContainer(t *testing.T) {
888 888
 }
889 889
 
890 890
 func TestEndpointMultipleJoins(t *testing.T) {
891
-	defer testutils.SetupTestOSContext(t)()
891
+	defer netnsutils.SetupTestOSContext(t)()
892 892
 	controller := newController(t)
893 893
 
894 894
 	n, err := createTestNetwork(controller, bridgeNetType, "testmultiple", options.Generic{
... ...
@@ -961,7 +961,7 @@ func TestEndpointMultipleJoins(t *testing.T) {
961 961
 }
962 962
 
963 963
 func TestLeaveAll(t *testing.T) {
964
-	defer testutils.SetupTestOSContext(t)()
964
+	defer netnsutils.SetupTestOSContext(t)()
965 965
 	controller := newController(t)
966 966
 
967 967
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
... ...
@@ -1025,7 +1025,7 @@ func TestLeaveAll(t *testing.T) {
1025 1025
 }
1026 1026
 
1027 1027
 func TestContainerInvalidLeave(t *testing.T) {
1028
-	defer testutils.SetupTestOSContext(t)()
1028
+	defer netnsutils.SetupTestOSContext(t)()
1029 1029
 	controller := newController(t)
1030 1030
 
1031 1031
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
... ...
@@ -1090,7 +1090,7 @@ func TestContainerInvalidLeave(t *testing.T) {
1090 1090
 }
1091 1091
 
1092 1092
 func TestEndpointUpdateParent(t *testing.T) {
1093
-	defer testutils.SetupTestOSContext(t)()
1093
+	defer netnsutils.SetupTestOSContext(t)()
1094 1094
 	controller := newController(t)
1095 1095
 
1096 1096
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
... ...
@@ -7,8 +7,8 @@ import (
7 7
 	"strings"
8 8
 	"testing"
9 9
 
10
+	"github.com/docker/docker/internal/testutils/netnsutils"
10 11
 	"github.com/docker/docker/libnetwork/ipamutils"
11
-	"github.com/docker/docker/libnetwork/testutils"
12 12
 	"github.com/docker/docker/libnetwork/types"
13 13
 	"github.com/vishvananda/netlink"
14 14
 	"gotest.tools/v3/assert"
... ...
@@ -247,7 +247,7 @@ func TestUtilGenerateRandomMAC(t *testing.T) {
247 247
 }
248 248
 
249 249
 func TestNetworkRequest(t *testing.T) {
250
-	defer testutils.SetupTestOSContext(t)()
250
+	defer netnsutils.SetupTestOSContext(t)()
251 251
 
252 252
 	nw, err := FindAvailableNetwork(ipamutils.GetLocalScopeDefaultNetworks())
253 253
 	if err != nil {
... ...
@@ -12,8 +12,8 @@ import (
12 12
 	"testing"
13 13
 	"time"
14 14
 
15
+	"github.com/docker/docker/internal/testutils/netnsutils"
15 16
 	"github.com/docker/docker/libnetwork/ns"
16
-	"github.com/docker/docker/libnetwork/testutils"
17 17
 	"github.com/docker/docker/libnetwork/types"
18 18
 	"github.com/vishvananda/netlink"
19 19
 	"github.com/vishvananda/netlink/nl"
... ...
@@ -160,7 +160,7 @@ func verifyCleanup(t *testing.T, s Sandbox, wait bool) {
160 160
 }
161 161
 
162 162
 func TestDisableIPv6DAD(t *testing.T) {
163
-	defer testutils.SetupTestOSContext(t)()
163
+	defer netnsutils.SetupTestOSContext(t)()
164 164
 
165 165
 	key, err := newKey(t)
166 166
 	if err != nil {
... ...
@@ -219,7 +219,7 @@ func destroyTest(t *testing.T, s Sandbox) {
219 219
 }
220 220
 
221 221
 func TestSetInterfaceIP(t *testing.T) {
222
-	defer testutils.SetupTestOSContext(t)()
222
+	defer netnsutils.SetupTestOSContext(t)()
223 223
 
224 224
 	key, err := newKey(t)
225 225
 	if err != nil {
... ...
@@ -293,7 +293,7 @@ func TestSetInterfaceIP(t *testing.T) {
293 293
 }
294 294
 
295 295
 func TestLiveRestore(t *testing.T) {
296
-	defer testutils.SetupTestOSContext(t)()
296
+	defer netnsutils.SetupTestOSContext(t)()
297 297
 
298 298
 	key, err := newKey(t)
299 299
 	if err != nil {
... ...
@@ -384,7 +384,7 @@ func TestLiveRestore(t *testing.T) {
384 384
 }
385 385
 
386 386
 func TestSandboxCreate(t *testing.T) {
387
-	defer testutils.SetupTestOSContext(t)()
387
+	defer netnsutils.SetupTestOSContext(t)()
388 388
 
389 389
 	key, err := newKey(t)
390 390
 	if err != nil {
... ...
@@ -435,7 +435,7 @@ func TestSandboxCreate(t *testing.T) {
435 435
 }
436 436
 
437 437
 func TestSandboxCreateTwice(t *testing.T) {
438
-	defer testutils.SetupTestOSContext(t)()
438
+	defer netnsutils.SetupTestOSContext(t)()
439 439
 
440 440
 	key, err := newKey(t)
441 441
 	if err != nil {
... ...
@@ -483,7 +483,7 @@ func TestSandboxGC(t *testing.T) {
483 483
 }
484 484
 
485 485
 func TestAddRemoveInterface(t *testing.T) {
486
-	defer testutils.SetupTestOSContext(t)()
486
+	defer netnsutils.SetupTestOSContext(t)()
487 487
 
488 488
 	key, err := newKey(t)
489 489
 	if err != nil {
... ...
@@ -11,7 +11,7 @@ import (
11 11
 	"time"
12 12
 
13 13
 	"github.com/containerd/containerd/log"
14
-	"github.com/docker/docker/libnetwork/testutils"
14
+	"github.com/docker/docker/internal/testutils/netnsutils"
15 15
 	"github.com/miekg/dns"
16 16
 	"github.com/sirupsen/logrus"
17 17
 	"gotest.tools/v3/assert"
... ...
@@ -98,7 +98,7 @@ func checkDNSRRType(t *testing.T, actual, expected uint16) {
98 98
 func TestDNSIPQuery(t *testing.T) {
99 99
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
100 100
 
101
-	defer testutils.SetupTestOSContext(t)()
101
+	defer netnsutils.SetupTestOSContext(t)()
102 102
 	c, err := New()
103 103
 	if err != nil {
104 104
 		t.Fatal(err)
... ...
@@ -237,7 +237,7 @@ func waitForLocalDNSServer(t *testing.T) {
237 237
 func TestDNSProxyServFail(t *testing.T) {
238 238
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
239 239
 
240
-	osctx := testutils.SetupTestOSContextEx(t)
240
+	osctx := netnsutils.SetupTestOSContextEx(t)
241 241
 	defer osctx.Cleanup(t)
242 242
 
243 243
 	c, err := New()
... ...
@@ -501,7 +501,7 @@ func TestProxyNXDOMAIN(t *testing.T) {
501 501
 	// whether we are leaking unlocked OS threads set to the wrong network
502 502
 	// namespace. Make a best-effort attempt to detect that situation so we
503 503
 	// are not left chasing ghosts next time.
504
-	testutils.AssertSocketSameNetNS(t, srv.PacketConn.(*net.UDPConn))
504
+	netnsutils.AssertSocketSameNetNS(t, srv.PacketConn.(*net.UDPConn))
505 505
 
506 506
 	srvAddr := srv.PacketConn.LocalAddr().(*net.UDPAddr)
507 507
 	rsv := NewResolver("", true, noopDNSBackend{})
... ...
@@ -5,12 +5,12 @@ import (
5 5
 	"strconv"
6 6
 	"testing"
7 7
 
8
+	"github.com/docker/docker/internal/testutils/netnsutils"
8 9
 	"github.com/docker/docker/libnetwork/config"
9 10
 	"github.com/docker/docker/libnetwork/ipamapi"
10 11
 	"github.com/docker/docker/libnetwork/netlabel"
11 12
 	"github.com/docker/docker/libnetwork/options"
12 13
 	"github.com/docker/docker/libnetwork/osl"
13
-	"github.com/docker/docker/libnetwork/testutils"
14 14
 	"gotest.tools/v3/skip"
15 15
 )
16 16
 
... ...
@@ -74,7 +74,7 @@ func TestSandboxAddEmpty(t *testing.T) {
74 74
 
75 75
 // // If different priorities are specified, internal option and ipv6 addresses mustn't influence endpoint order
76 76
 func TestSandboxAddMultiPrio(t *testing.T) {
77
-	defer testutils.SetupTestOSContext(t)()
77
+	defer netnsutils.SetupTestOSContext(t)()
78 78
 
79 79
 	opts := [][]NetworkOption{
80 80
 		{NetworkOptionEnableIPv6(true), NetworkOptionIpam(ipamapi.DefaultIPAM, "", nil, []*IpamConf{{PreferredPool: "fe90::/64"}}, nil)},
... ...
@@ -158,7 +158,7 @@ func TestSandboxAddMultiPrio(t *testing.T) {
158 158
 }
159 159
 
160 160
 func TestSandboxAddSamePrio(t *testing.T) {
161
-	defer testutils.SetupTestOSContext(t)()
161
+	defer netnsutils.SetupTestOSContext(t)()
162 162
 
163 163
 	opts := [][]NetworkOption{
164 164
 		{},
... ...
@@ -5,8 +5,8 @@ import (
5 5
 	"runtime"
6 6
 	"testing"
7 7
 
8
+	"github.com/docker/docker/internal/testutils/netnsutils"
8 9
 	"github.com/docker/docker/libnetwork/resolvconf"
9
-	"github.com/docker/docker/libnetwork/testutils"
10 10
 	"gotest.tools/v3/assert"
11 11
 	is "gotest.tools/v3/assert/cmp"
12 12
 	"gotest.tools/v3/skip"
... ...
@@ -15,7 +15,7 @@ import (
15 15
 func TestCleanupServiceDiscovery(t *testing.T) {
16 16
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
17 17
 
18
-	defer testutils.SetupTestOSContext(t)()
18
+	defer netnsutils.SetupTestOSContext(t)()
19 19
 	c, err := New()
20 20
 	assert.NilError(t, err)
21 21
 	defer c.Stop()
22 22
deleted file mode 100644
... ...
@@ -1,41 +0,0 @@
1
-package testutils
2
-
3
-import "testing"
4
-
5
-// Logger is used to log non-fatal messages during tests.
6
-type Logger interface {
7
-	Logf(format string, args ...any)
8
-}
9
-
10
-var _ Logger = (*testing.T)(nil)
11
-
12
-// SetupTestOSContext joins the current goroutine to a new network namespace,
13
-// and returns its associated teardown function.
14
-//
15
-// Example usage:
16
-//
17
-//	defer SetupTestOSContext(t)()
18
-func SetupTestOSContext(t *testing.T) func() {
19
-	c := SetupTestOSContextEx(t)
20
-	return func() { c.Cleanup(t) }
21
-}
22
-
23
-// Go starts running fn in a new goroutine inside the test OS context.
24
-func (c *OSContext) Go(t *testing.T, fn func()) {
25
-	t.Helper()
26
-	errCh := make(chan error, 1)
27
-	go func() {
28
-		teardown, err := c.Set()
29
-		if err != nil {
30
-			errCh <- err
31
-			return
32
-		}
33
-		defer teardown(t)
34
-		close(errCh)
35
-		fn()
36
-	}()
37
-
38
-	if err := <-errCh; err != nil {
39
-		t.Fatalf("%+v", err)
40
-	}
41
-}
42 1
deleted file mode 100644
... ...
@@ -1,168 +0,0 @@
1
-//go:build linux || freebsd
2
-
3
-package testutils
4
-
5
-import (
6
-	"fmt"
7
-	"runtime"
8
-	"strconv"
9
-	"testing"
10
-
11
-	"github.com/docker/docker/libnetwork/ns"
12
-	"github.com/pkg/errors"
13
-	"github.com/vishvananda/netns"
14
-	"golang.org/x/sys/unix"
15
-)
16
-
17
-// OSContext is a handle to a test OS context.
18
-type OSContext struct {
19
-	origNS, newNS netns.NsHandle
20
-
21
-	tid    int
22
-	caller string // The file:line where SetupTestOSContextEx was called, for interpolating into error messages.
23
-}
24
-
25
-// SetupTestOSContextEx joins the current goroutine to a new network namespace.
26
-//
27
-// Compared to [SetupTestOSContext], this function allows goroutines to be
28
-// spawned which are associated with the same OS context via the returned
29
-// OSContext value.
30
-//
31
-// Example usage:
32
-//
33
-//	c := SetupTestOSContext(t)
34
-//	defer c.Cleanup(t)
35
-func SetupTestOSContextEx(t *testing.T) *OSContext {
36
-	runtime.LockOSThread()
37
-	origNS, err := netns.Get()
38
-	if err != nil {
39
-		runtime.UnlockOSThread()
40
-		t.Fatalf("Failed to open initial netns: %v", err)
41
-	}
42
-
43
-	c := OSContext{
44
-		tid:    unix.Gettid(),
45
-		origNS: origNS,
46
-	}
47
-	c.newNS, err = netns.New()
48
-	if err != nil {
49
-		// netns.New() is not atomic: it could have encountered an error
50
-		// after unsharing the current thread's network namespace.
51
-		c.restore(t)
52
-		t.Fatalf("Failed to enter netns: %v", err)
53
-	}
54
-
55
-	// Since we are switching to a new test namespace make
56
-	// sure to re-initialize initNs context
57
-	ns.Init()
58
-
59
-	nl := ns.NlHandle()
60
-	lo, err := nl.LinkByName("lo")
61
-	if err != nil {
62
-		c.restore(t)
63
-		t.Fatalf("Failed to get handle to loopback interface 'lo' in new netns: %v", err)
64
-	}
65
-	if err := nl.LinkSetUp(lo); err != nil {
66
-		c.restore(t)
67
-		t.Fatalf("Failed to enable loopback interface in new netns: %v", err)
68
-	}
69
-
70
-	_, file, line, ok := runtime.Caller(0)
71
-	if ok {
72
-		c.caller = file + ":" + strconv.Itoa(line)
73
-	}
74
-
75
-	return &c
76
-}
77
-
78
-// Cleanup tears down the OS context. It must be called from the same goroutine
79
-// as the [SetupTestOSContextEx] call which returned c.
80
-//
81
-// Explicit cleanup is required as (*testing.T).Cleanup() makes no guarantees
82
-// about which goroutine the cleanup functions are invoked on.
83
-func (c *OSContext) Cleanup(t *testing.T) {
84
-	t.Helper()
85
-	if unix.Gettid() != c.tid {
86
-		t.Fatalf("c.Cleanup() must be called from the same goroutine as SetupTestOSContextEx() (%s)", c.caller)
87
-	}
88
-	if err := c.newNS.Close(); err != nil {
89
-		t.Logf("Warning: netns closing failed (%v)", err)
90
-	}
91
-	c.restore(t)
92
-	ns.Init()
93
-}
94
-
95
-func (c *OSContext) restore(t *testing.T) {
96
-	t.Helper()
97
-	if err := netns.Set(c.origNS); err != nil {
98
-		t.Logf("Warning: failed to restore thread netns (%v)", err)
99
-	} else {
100
-		runtime.UnlockOSThread()
101
-	}
102
-
103
-	if err := c.origNS.Close(); err != nil {
104
-		t.Logf("Warning: netns closing failed (%v)", err)
105
-	}
106
-}
107
-
108
-// Set sets the OS context of the calling goroutine to c and returns a teardown
109
-// function to restore the calling goroutine's OS context and release resources.
110
-// The teardown function accepts an optional Logger argument.
111
-//
112
-// This is a lower-level interface which is less ergonomic than c.Go() but more
113
-// composable with other goroutine-spawning utilities such as [sync.WaitGroup]
114
-// or [golang.org/x/sync/errgroup.Group].
115
-//
116
-// Example usage:
117
-//
118
-//	func TestFoo(t *testing.T) {
119
-//		osctx := testutils.SetupTestOSContextEx(t)
120
-//		defer osctx.Cleanup(t)
121
-//		var eg errgroup.Group
122
-//		eg.Go(func() error {
123
-//			teardown, err := osctx.Set()
124
-//			if err != nil {
125
-//				return err
126
-//			}
127
-//			defer teardown(t)
128
-//			// ...
129
-//		})
130
-//		if err := eg.Wait(); err != nil {
131
-//			t.Fatalf("%+v", err)
132
-//		}
133
-//	}
134
-func (c *OSContext) Set() (func(Logger), error) {
135
-	runtime.LockOSThread()
136
-	orig, err := netns.Get()
137
-	if err != nil {
138
-		runtime.UnlockOSThread()
139
-		return nil, errors.Wrap(err, "failed to open initial netns for goroutine")
140
-	}
141
-	if err := errors.WithStack(netns.Set(c.newNS)); err != nil {
142
-		runtime.UnlockOSThread()
143
-		return nil, errors.Wrap(err, "failed to set goroutine network namespace")
144
-	}
145
-
146
-	tid := unix.Gettid()
147
-	_, file, line, callerOK := runtime.Caller(0)
148
-
149
-	return func(log Logger) {
150
-		if unix.Gettid() != tid {
151
-			msg := "teardown function must be called from the same goroutine as c.Set()"
152
-			if callerOK {
153
-				msg += fmt.Sprintf(" (%s:%d)", file, line)
154
-			}
155
-			panic(msg)
156
-		}
157
-
158
-		if err := netns.Set(orig); err != nil && log != nil {
159
-			log.Logf("Warning: failed to restore goroutine thread netns (%v)", err)
160
-		} else {
161
-			runtime.UnlockOSThread()
162
-		}
163
-
164
-		if err := orig.Close(); err != nil && log != nil {
165
-			log.Logf("Warning: netns closing failed (%v)", err)
166
-		}
167
-	}, nil
168
-}
169 1
deleted file mode 100644
... ...
@@ -1,15 +0,0 @@
1
-package testutils
2
-
3
-import "testing"
4
-
5
-type OSContext struct{}
6
-
7
-func SetupTestOSContextEx(*testing.T) *OSContext {
8
-	return nil
9
-}
10
-
11
-func (*OSContext) Cleanup(t *testing.T) {}
12
-
13
-func (*OSContext) Set() (func(Logger), error) {
14
-	return func(Logger) {}, nil
15
-}
16 1
deleted file mode 100644
... ...
@@ -1,43 +0,0 @@
1
-package testutils
2
-
3
-import (
4
-	"errors"
5
-	"syscall"
6
-	"testing"
7
-
8
-	"github.com/vishvananda/netns"
9
-	"golang.org/x/sys/unix"
10
-	"gotest.tools/v3/assert"
11
-)
12
-
13
-// AssertSocketSameNetNS makes a best-effort attempt to assert that conn is in
14
-// the same network namespace as the current goroutine's thread.
15
-func AssertSocketSameNetNS(t testing.TB, conn syscall.Conn) {
16
-	t.Helper()
17
-
18
-	sc, err := conn.SyscallConn()
19
-	assert.NilError(t, err)
20
-	sc.Control(func(fd uintptr) {
21
-		srvnsfd, err := unix.IoctlRetInt(int(fd), unix.SIOCGSKNS)
22
-		if err != nil {
23
-			if errors.Is(err, unix.EPERM) {
24
-				t.Log("Cannot determine socket's network namespace. Do we have CAP_NET_ADMIN?")
25
-				return
26
-			}
27
-			if errors.Is(err, unix.ENOSYS) {
28
-				t.Log("Cannot query socket's network namespace due to missing kernel support.")
29
-				return
30
-			}
31
-			t.Fatal(err)
32
-		}
33
-		srvns := netns.NsHandle(srvnsfd)
34
-		defer srvns.Close()
35
-
36
-		curns, err := netns.Get()
37
-		assert.NilError(t, err)
38
-		defer curns.Close()
39
-		if !srvns.Equal(curns) {
40
-			t.Fatalf("Socket is in network namespace %s, but test goroutine is in %s", srvns, curns)
41
-		}
42
-	})
43
-}
44 1
deleted file mode 100644
... ...
@@ -1,11 +0,0 @@
1
-//go:build !linux
2
-
3
-package testutils
4
-
5
-import (
6
-	"syscall"
7
-	"testing"
8
-)
9
-
10
-// AssertSocketSameNetNS is a no-op on platforms other than Linux.
11
-func AssertSocketSameNetNS(t testing.TB, conn syscall.Conn) {}