Browse code

libnetwork_test: isolate tests from each other

Reusing the same "OS context" (read: network namespace) and
NetworkController across multiple tests risks tests interfering with
each other, or worse: _depending on_ other tests to set up
preconditions. Construct a new controller for every test which needs
one, and run every test which mutates or inspects the host environment
in a fresh OS context.

The only outlier is runParallelTests. It is the only remaining test
implementation which references the "global" package-scoped controller,
so the global controller instance is effectively private to that one
test.

Signed-off-by: Cory Snider <csnider@mirantis.com>

Cory Snider authored on 2022/11/09 06:35:14
Showing 6 changed files
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"github.com/docker/docker/libnetwork/iptables"
9 9
 	"github.com/docker/docker/libnetwork/netlabel"
10 10
 	"github.com/docker/docker/libnetwork/options"
11
+	"github.com/docker/docker/libnetwork/testutils"
11 12
 	"gotest.tools/v3/assert"
12 13
 )
13 14
 
... ...
@@ -19,9 +20,6 @@ const (
19 19
 func TestUserChain(t *testing.T) {
20 20
 	iptable := iptables.GetIptable(iptables.IPv4)
21 21
 
22
-	nc, err := New()
23
-	assert.NilError(t, err)
24
-
25 22
 	tests := []struct {
26 23
 		iptables  bool
27 24
 		insert    bool // insert other rules to FORWARD
... ...
@@ -47,10 +45,15 @@ func TestUserChain(t *testing.T) {
47 47
 		},
48 48
 	}
49 49
 
50
-	resetIptables(t)
51 50
 	for _, tc := range tests {
52 51
 		tc := tc
53 52
 		t.Run(fmt.Sprintf("iptables=%v,insert=%v", tc.iptables, tc.insert), func(t *testing.T) {
53
+			defer testutils.SetupTestOSContext(t)()
54
+			defer resetIptables(t)
55
+
56
+			nc, err := New()
57
+			assert.NilError(t, err)
58
+			defer nc.Stop()
54 59
 			c := nc.(*controller)
55 60
 			c.cfg.DriverCfg["bridge"] = map[string]interface{}{
56 61
 				netlabel.GenericData: options.Generic{
... ...
@@ -75,7 +78,6 @@ func TestUserChain(t *testing.T) {
75 75
 				assert.Assert(t, err != nil, "chain %v: created unexpectedly", usrChainName)
76 76
 			}
77 77
 		})
78
-		resetIptables(t)
79 78
 	}
80 79
 }
81 80
 
... ...
@@ -312,6 +312,8 @@ func compareNwLists(a, b []*net.IPNet) bool {
312 312
 }
313 313
 
314 314
 func TestAuxAddresses(t *testing.T) {
315
+	defer testutils.SetupTestOSContext(t)()
316
+
315 317
 	c, err := New()
316 318
 	if err != nil {
317 319
 		t.Fatal(err)
... ...
@@ -349,6 +351,8 @@ func TestAuxAddresses(t *testing.T) {
349 349
 func TestSRVServiceQuery(t *testing.T) {
350 350
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
351 351
 
352
+	defer testutils.SetupTestOSContext(t)()
353
+
352 354
 	c, err := New()
353 355
 	if err != nil {
354 356
 		t.Fatal(err)
... ...
@@ -447,6 +451,8 @@ 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)()
451
+
450 452
 	c, err := New()
451 453
 	if err != nil {
452 454
 		t.Fatal(err)
... ...
@@ -31,22 +31,17 @@ const (
31 31
 	bridgeNetType = "bridge"
32 32
 )
33 33
 
34
+// Shared state for createGlobalInstance() and runParallelTests().
34 35
 var (
35 36
 	origins = netns.None()
36 37
 	testns  = netns.None()
37
-)
38 38
 
39
-var createTesthostNetworkOnce sync.Once
39
+	controller libnetwork.NetworkController
40
+)
40 41
 
41
-func getTesthostNetwork(t *testing.T) libnetwork.Network {
42
+func makeTesthostNetwork(t *testing.T, c libnetwork.NetworkController) libnetwork.Network {
42 43
 	t.Helper()
43
-	createTesthostNetworkOnce.Do(func() {
44
-		_, err := createTestNetwork(controller, "host", "testhost", options.Generic{}, nil, nil)
45
-		if err != nil {
46
-			t.Fatal(err)
47
-		}
48
-	})
49
-	n, err := controller.NetworkByName("testhost")
44
+	n, err := createTestNetwork(c, "host", "testhost", options.Generic{}, nil, nil)
50 45
 	if err != nil {
51 46
 		t.Fatal(err)
52 47
 	}
... ...
@@ -67,13 +62,16 @@ func createGlobalInstance(t *testing.T) {
67 67
 		t.Fatal(err)
68 68
 	}
69 69
 
70
+	controller = newController(t)
71
+	t.Cleanup(controller.Stop)
72
+
70 73
 	netOption := options.Generic{
71 74
 		netlabel.GenericData: options.Generic{
72 75
 			"BridgeName": "network",
73 76
 		},
74 77
 	}
75 78
 
76
-	net1 := getTesthostNetwork(t)
79
+	net1 := makeTesthostNetwork(t, controller)
77 80
 	net2, err := createTestNetwork(controller, "bridge", "network2", netOption, nil, nil)
78 81
 	if err != nil {
79 82
 		t.Fatal(err)
... ...
@@ -105,6 +103,9 @@ func createGlobalInstance(t *testing.T) {
105 105
 }
106 106
 
107 107
 func TestHost(t *testing.T) {
108
+	defer testutils.SetupTestOSContext(t)()
109
+	controller := newController(t)
110
+
108 111
 	sbx1, err := controller.NewSandbox("host_c1",
109 112
 		libnetwork.OptionHostname("test1"),
110 113
 		libnetwork.OptionDomainname("docker.io"),
... ...
@@ -133,7 +134,7 @@ func TestHost(t *testing.T) {
133 133
 		}
134 134
 	}()
135 135
 
136
-	network := getTesthostNetwork(t)
136
+	network := makeTesthostNetwork(t, controller)
137 137
 	ep1, err := network.CreateEndpoint("testep1")
138 138
 	if err != nil {
139 139
 		t.Fatal(err)
... ...
@@ -204,6 +205,7 @@ func TestHost(t *testing.T) {
204 204
 // Testing IPV6 from MAC address
205 205
 func TestBridgeIpv6FromMac(t *testing.T) {
206 206
 	defer testutils.SetupTestOSContext(t)()
207
+	controller := newController(t)
207 208
 
208 209
 	netOption := options.Generic{
209 210
 		netlabel.GenericData: options.Generic{
... ...
@@ -278,6 +280,7 @@ func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) {
278 278
 
279 279
 func TestEndpointJoin(t *testing.T) {
280 280
 	defer testutils.SetupTestOSContext(t)()
281
+	controller := newController(t)
281 282
 
282 283
 	// Create network 1 and add 2 endpoint: ep11, ep12
283 284
 	netOption := options.Generic{
... ...
@@ -452,6 +455,7 @@ func TestExternalKey(t *testing.T) {
452 452
 
453 453
 func externalKeyTest(t *testing.T, reexec bool) {
454 454
 	defer testutils.SetupTestOSContext(t)()
455
+	controller := newController(t)
455 456
 
456 457
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
457 458
 		netlabel.GenericData: options.Generic{
... ...
@@ -612,6 +616,7 @@ func reexecSetKey(key string, containerID string, controllerID string) error {
612 612
 
613 613
 func TestEnableIPv6(t *testing.T) {
614 614
 	defer testutils.SetupTestOSContext(t)()
615
+	controller := newController(t)
615 616
 
616 617
 	tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888\n")
617 618
 	expectedResolvConf := []byte("search pommesfrites.fr\nnameserver 127.0.0.11\nnameserver 2001:4860:4860::8888\noptions ndots:0\n")
... ...
@@ -688,6 +693,7 @@ func TestEnableIPv6(t *testing.T) {
688 688
 
689 689
 func TestResolvConfHost(t *testing.T) {
690 690
 	defer testutils.SetupTestOSContext(t)()
691
+	controller := newController(t)
691 692
 
692 693
 	tmpResolvConf := []byte("search localhost.net\nnameserver 127.0.0.1\nnameserver 2001:4860:4860::8888\n")
693 694
 
... ...
@@ -703,7 +709,7 @@ func TestResolvConfHost(t *testing.T) {
703 703
 		}
704 704
 	}()
705 705
 
706
-	n := getTesthostNetwork(t)
706
+	n := makeTesthostNetwork(t, controller)
707 707
 	ep1, err := n.CreateEndpoint("ep1", libnetwork.CreateOptionDisableResolution())
708 708
 	if err != nil {
709 709
 		t.Fatal(err)
... ...
@@ -762,6 +768,7 @@ func TestResolvConfHost(t *testing.T) {
762 762
 
763 763
 func TestResolvConf(t *testing.T) {
764 764
 	defer testutils.SetupTestOSContext(t)()
765
+	controller := newController(t)
765 766
 
766 767
 	tmpResolvConf1 := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888\n")
767 768
 	tmpResolvConf2 := []byte("search pommesfrites.fr\nnameserver 112.34.56.78\nnameserver 2001:4860:4860::8888\n")
... ...
@@ -980,7 +987,10 @@ func runParallelTests(t *testing.T, thrNumber int) {
980 980
 		}
981 981
 	}()
982 982
 
983
-	net1 := getTesthostNetwork(t)
983
+	net1, err := controller.NetworkByName("testhost")
984
+	if err != nil {
985
+		t.Fatal(err)
986
+	}
984 987
 	if net1 == nil {
985 988
 		t.Fatal("Could not find testhost")
986 989
 	}
... ...
@@ -1054,6 +1064,7 @@ func TestParallel2(t *testing.T) {
1054 1054
 
1055 1055
 func TestBridge(t *testing.T) {
1056 1056
 	defer testutils.SetupTestOSContext(t)()
1057
+	controller := newController(t)
1057 1058
 
1058 1059
 	netOption := options.Generic{
1059 1060
 		netlabel.EnableIPv6: true,
... ...
@@ -1144,6 +1155,9 @@ func TestParallel3(t *testing.T) {
1144 1144
 }
1145 1145
 
1146 1146
 func TestNullIpam(t *testing.T) {
1147
+	defer testutils.SetupTestOSContext(t)()
1148
+	controller := newController(t)
1149
+
1147 1150
 	_, err := controller.NewNetwork(bridgeNetType, "testnetworkinternal", "", libnetwork.NetworkOptionIpam(ipamapi.NullIPAM, "", nil, nil, nil))
1148 1151
 	if err == nil || err.Error() != "ipv4 pool is empty" {
1149 1152
 		t.Fatal("bridge network should complain empty pool")
... ...
@@ -28,8 +28,6 @@ import (
28 28
 	"github.com/sirupsen/logrus"
29 29
 )
30 30
 
31
-var controller libnetwork.NetworkController
32
-
33 31
 func TestMain(m *testing.M) {
34 32
 	if runtime.GOOS == "windows" {
35 33
 		logrus.Info("Test suite does not currently support windows")
... ...
@@ -39,35 +37,30 @@ func TestMain(m *testing.M) {
39 39
 		return
40 40
 	}
41 41
 
42
-	if err := createController(); err != nil {
43
-		logrus.Errorf("Error creating controller: %v", err)
44
-		os.Exit(1)
45
-	}
42
+	// Cleanup local datastore file
43
+	_ = os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
46 44
 
47
-	x := m.Run()
48
-	controller.Stop()
49
-	os.Exit(x)
45
+	os.Exit(m.Run())
50 46
 }
51 47
 
52
-func createController() error {
53
-	var err error
54
-
55
-	// Cleanup local datastore file
56
-	os.Remove(datastore.DefaultScopes("")[datastore.LocalScope].Client.Address)
57
-
58
-	option := options.Generic{
59
-		"EnableIPForwarding": true,
48
+func newController(t *testing.T) libnetwork.NetworkController {
49
+	t.Helper()
50
+	genericOption := map[string]interface{}{
51
+		netlabel.GenericData: options.Generic{
52
+			"EnableIPForwarding": true,
53
+		},
60 54
 	}
61 55
 
62
-	genericOption := make(map[string]interface{})
63
-	genericOption[netlabel.GenericData] = option
64
-
65 56
 	cfgOptions, err := libnetwork.OptionBoltdbWithRandomDBFile()
66 57
 	if err != nil {
67
-		return err
58
+		t.Fatal(err)
59
+	}
60
+	c, err := libnetwork.New(append(cfgOptions, config.OptionDriverConfig(bridgeNetType, genericOption))...)
61
+	if err != nil {
62
+		t.Fatal(err)
68 63
 	}
69
-	controller, err = libnetwork.New(append(cfgOptions, config.OptionDriverConfig(bridgeNetType, genericOption))...)
70
-	return err
64
+	t.Cleanup(c.Stop)
65
+	return c
71 66
 }
72 67
 
73 68
 func createTestNetwork(c libnetwork.NetworkController, networkType, networkName string, netOption options.Generic, ipamV4Configs, ipamV6Configs []*libnetwork.IpamConf) (libnetwork.Network, error) {
... ...
@@ -98,6 +91,9 @@ func isNotFound(err error) bool {
98 98
 }
99 99
 
100 100
 func TestNull(t *testing.T) {
101
+	defer testutils.SetupTestOSContext(t)()
102
+	controller := newController(t)
103
+
101 104
 	cnt, err := controller.NewSandbox("null_container",
102 105
 		libnetwork.OptionHostname("test"),
103 106
 		libnetwork.OptionDomainname("docker.io"),
... ...
@@ -146,6 +142,7 @@ func TestNull(t *testing.T) {
146 146
 
147 147
 func TestUnknownDriver(t *testing.T) {
148 148
 	defer testutils.SetupTestOSContext(t)()
149
+	controller := newController(t)
149 150
 
150 151
 	_, err := createTestNetwork(controller, "unknowndriver", "testnetwork", options.Generic{}, nil, nil)
151 152
 	if err == nil {
... ...
@@ -158,6 +155,9 @@ func TestUnknownDriver(t *testing.T) {
158 158
 }
159 159
 
160 160
 func TestNilRemoteDriver(t *testing.T) {
161
+	defer testutils.SetupTestOSContext(t)()
162
+	controller := newController(t)
163
+
161 164
 	_, err := controller.NewNetwork("framerelay", "dummy", "",
162 165
 		libnetwork.NetworkOptionGeneric(getEmptyGenericOption()))
163 166
 	if err == nil {
... ...
@@ -171,6 +171,7 @@ func TestNilRemoteDriver(t *testing.T) {
171 171
 
172 172
 func TestNetworkName(t *testing.T) {
173 173
 	defer testutils.SetupTestOSContext(t)()
174
+	controller := newController(t)
174 175
 
175 176
 	netOption := options.Generic{
176 177
 		netlabel.GenericData: options.Generic{
... ...
@@ -205,6 +206,7 @@ func TestNetworkName(t *testing.T) {
205 205
 
206 206
 func TestNetworkType(t *testing.T) {
207 207
 	defer testutils.SetupTestOSContext(t)()
208
+	controller := newController(t)
208 209
 
209 210
 	netOption := options.Generic{
210 211
 		netlabel.GenericData: options.Generic{
... ...
@@ -229,6 +231,7 @@ func TestNetworkType(t *testing.T) {
229 229
 
230 230
 func TestNetworkID(t *testing.T) {
231 231
 	defer testutils.SetupTestOSContext(t)()
232
+	controller := newController(t)
232 233
 
233 234
 	netOption := options.Generic{
234 235
 		netlabel.GenericData: options.Generic{
... ...
@@ -253,6 +256,7 @@ func TestNetworkID(t *testing.T) {
253 253
 
254 254
 func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
255 255
 	defer testutils.SetupTestOSContext(t)()
256
+	controller := newController(t)
256 257
 
257 258
 	netOption := options.Generic{
258 259
 		"BridgeName": "testnetwork",
... ...
@@ -292,6 +296,7 @@ func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
292 292
 
293 293
 func TestNetworkConfig(t *testing.T) {
294 294
 	defer testutils.SetupTestOSContext(t)()
295
+	controller := newController(t)
295 296
 
296 297
 	// Verify config network cannot inherit another config network
297 298
 	_, err := controller.NewNetwork("bridge", "config_network0", "",
... ...
@@ -392,6 +397,7 @@ func TestNetworkConfig(t *testing.T) {
392 392
 
393 393
 func TestUnknownNetwork(t *testing.T) {
394 394
 	defer testutils.SetupTestOSContext(t)()
395
+	controller := newController(t)
395 396
 
396 397
 	netOption := options.Generic{
397 398
 		"BridgeName": "testnetwork",
... ...
@@ -422,6 +428,7 @@ func TestUnknownNetwork(t *testing.T) {
422 422
 
423 423
 func TestUnknownEndpoint(t *testing.T) {
424 424
 	defer testutils.SetupTestOSContext(t)()
425
+	controller := newController(t)
425 426
 
426 427
 	netOption := options.Generic{
427 428
 		"BridgeName": "testnetwork",
... ...
@@ -462,6 +469,7 @@ func TestUnknownEndpoint(t *testing.T) {
462 462
 
463 463
 func TestNetworkEndpointsWalkers(t *testing.T) {
464 464
 	defer testutils.SetupTestOSContext(t)()
465
+	controller := newController(t)
465 466
 
466 467
 	// Create network 1 and add 2 endpoint: ep11, ep12
467 468
 	netOption := options.Generic{
... ...
@@ -590,6 +598,7 @@ func TestNetworkEndpointsWalkers(t *testing.T) {
590 590
 
591 591
 func TestDuplicateEndpoint(t *testing.T) {
592 592
 	defer testutils.SetupTestOSContext(t)()
593
+	controller := newController(t)
593 594
 
594 595
 	netOption := options.Generic{
595 596
 		netlabel.GenericData: options.Generic{
... ...
@@ -637,6 +646,7 @@ func TestDuplicateEndpoint(t *testing.T) {
637 637
 
638 638
 func TestControllerQuery(t *testing.T) {
639 639
 	defer testutils.SetupTestOSContext(t)()
640
+	controller := newController(t)
640 641
 
641 642
 	// Create network 1
642 643
 	netOption := options.Generic{
... ...
@@ -737,6 +747,7 @@ func TestControllerQuery(t *testing.T) {
737 737
 
738 738
 func TestNetworkQuery(t *testing.T) {
739 739
 	defer testutils.SetupTestOSContext(t)()
740
+	controller := newController(t)
740 741
 
741 742
 	// Create network 1 and add 2 endpoint: ep11, ep12
742 743
 	netOption := options.Generic{
... ...
@@ -884,6 +895,7 @@ func (f *fakeSandbox) DisableService() error {
884 884
 
885 885
 func TestEndpointDeleteWithActiveContainer(t *testing.T) {
886 886
 	defer testutils.SetupTestOSContext(t)()
887
+	controller := newController(t)
887 888
 
888 889
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
889 890
 		netlabel.GenericData: options.Generic{
... ...
@@ -957,6 +969,7 @@ func TestEndpointDeleteWithActiveContainer(t *testing.T) {
957 957
 
958 958
 func TestEndpointMultipleJoins(t *testing.T) {
959 959
 	defer testutils.SetupTestOSContext(t)()
960
+	controller := newController(t)
960 961
 
961 962
 	n, err := createTestNetwork(controller, bridgeNetType, "testmultiple", options.Generic{
962 963
 		netlabel.GenericData: options.Generic{
... ...
@@ -1029,6 +1042,7 @@ func TestEndpointMultipleJoins(t *testing.T) {
1029 1029
 
1030 1030
 func TestLeaveAll(t *testing.T) {
1031 1031
 	defer testutils.SetupTestOSContext(t)()
1032
+	controller := newController(t)
1032 1033
 
1033 1034
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
1034 1035
 		netlabel.GenericData: options.Generic{
... ...
@@ -1092,6 +1106,7 @@ func TestLeaveAll(t *testing.T) {
1092 1092
 
1093 1093
 func TestContainerInvalidLeave(t *testing.T) {
1094 1094
 	defer testutils.SetupTestOSContext(t)()
1095
+	controller := newController(t)
1095 1096
 
1096 1097
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
1097 1098
 		netlabel.GenericData: options.Generic{
... ...
@@ -1156,6 +1171,7 @@ func TestContainerInvalidLeave(t *testing.T) {
1156 1156
 
1157 1157
 func TestEndpointUpdateParent(t *testing.T) {
1158 1158
 	defer testutils.SetupTestOSContext(t)()
1159
+	controller := newController(t)
1159 1160
 
1160 1161
 	n, err := createTestNetwork(controller, bridgeNetType, "testnetwork", options.Generic{
1161 1162
 		netlabel.GenericData: options.Generic{
... ...
@@ -1300,6 +1316,7 @@ func TestValidRemoteDriver(t *testing.T) {
1300 1300
 		t.Fatal(err)
1301 1301
 	}
1302 1302
 
1303
+	controller := newController(t)
1303 1304
 	n, err := controller.NewNetwork("valid-network-driver", "dummy", "",
1304 1305
 		libnetwork.NetworkOptionGeneric(getEmptyGenericOption()))
1305 1306
 	if err != nil {
... ...
@@ -77,6 +77,7 @@ func checkDNSRRType(t *testing.T, actual, expected uint16) {
77 77
 func TestDNSIPQuery(t *testing.T) {
78 78
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
79 79
 
80
+	defer testutils.SetupTestOSContext(t)()
80 81
 	c, err := New()
81 82
 	if err != nil {
82 83
 		t.Fatal(err)
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"testing"
7 7
 
8 8
 	"github.com/docker/docker/libnetwork/resolvconf"
9
+	"github.com/docker/docker/libnetwork/testutils"
9 10
 	"gotest.tools/v3/assert"
10 11
 	is "gotest.tools/v3/assert/cmp"
11 12
 	"gotest.tools/v3/skip"
... ...
@@ -14,6 +15,7 @@ import (
14 14
 func TestCleanupServiceDiscovery(t *testing.T) {
15 15
 	skip.If(t, runtime.GOOS == "windows", "test only works on linux")
16 16
 
17
+	defer testutils.SetupTestOSContext(t)()
17 18
 	c, err := New()
18 19
 	assert.NilError(t, err)
19 20
 	defer c.Stop()