github.com/docker/engine@v22.0.0-20211208180946-d456264580cf+incompatible/libnetwork/drivers/overlay/overlay_test.go (about) 1 //go:build linux 2 // +build linux 3 4 package overlay 5 6 import ( 7 "context" 8 "fmt" 9 "net" 10 "os" 11 "syscall" 12 "testing" 13 "time" 14 15 "golang.org/x/sys/unix" 16 17 "github.com/docker/docker/libnetwork/datastore" 18 "github.com/docker/docker/libnetwork/discoverapi" 19 "github.com/docker/docker/libnetwork/driverapi" 20 "github.com/docker/docker/libnetwork/netlabel" 21 "github.com/docker/docker/pkg/plugingetter" 22 "github.com/docker/libkv/store/consul" 23 "github.com/vishvananda/netlink/nl" 24 ) 25 26 func init() { 27 consul.Register() 28 } 29 30 type driverTester struct { 31 t *testing.T 32 d *driver 33 } 34 35 const testNetworkType = "overlay" 36 37 func setupDriver(t *testing.T) *driverTester { 38 dt := &driverTester{t: t} 39 config := make(map[string]interface{}) 40 config[netlabel.GlobalKVClient] = discoverapi.DatastoreConfigData{ 41 Scope: datastore.GlobalScope, 42 Provider: "consul", 43 Address: "127.0.0.01:8500", 44 } 45 46 if err := Init(dt, config); err != nil { 47 t.Fatal(err) 48 } 49 50 iface, err := net.InterfaceByName("eth0") 51 if err != nil { 52 t.Fatal(err) 53 } 54 addrs, err := iface.Addrs() 55 if err != nil || len(addrs) == 0 { 56 t.Fatal(err) 57 } 58 data := discoverapi.NodeDiscoveryData{ 59 Address: addrs[0].String(), 60 Self: true, 61 } 62 dt.d.DiscoverNew(discoverapi.NodeDiscovery, data) 63 return dt 64 } 65 66 func cleanupDriver(t *testing.T, dt *driverTester) { 67 ch := make(chan struct{}) 68 go func() { 69 Fini(dt.d) 70 close(ch) 71 }() 72 73 select { 74 case <-ch: 75 case <-time.After(10 * time.Second): 76 t.Fatal("test timed out because Fini() did not return on time") 77 } 78 } 79 80 func (dt *driverTester) GetPluginGetter() plugingetter.PluginGetter { 81 return nil 82 } 83 84 func (dt *driverTester) RegisterDriver(name string, drv driverapi.Driver, 85 cap driverapi.Capability) error { 86 if name != testNetworkType { 87 dt.t.Fatalf("Expected driver register name to be %q. Instead got %q", 88 testNetworkType, name) 89 } 90 91 if _, ok := drv.(*driver); !ok { 92 dt.t.Fatalf("Expected driver type to be %T. Instead got %T", 93 &driver{}, drv) 94 } 95 96 dt.d = drv.(*driver) 97 return nil 98 } 99 100 func TestOverlayInit(t *testing.T) { 101 if err := Init(&driverTester{t: t}, nil); err != nil { 102 t.Fatal(err) 103 } 104 } 105 106 func TestOverlayFiniWithoutConfig(t *testing.T) { 107 dt := &driverTester{t: t} 108 if err := Init(dt, nil); err != nil { 109 t.Fatal(err) 110 } 111 112 cleanupDriver(t, dt) 113 } 114 115 func TestOverlayConfig(t *testing.T) { 116 dt := setupDriver(t) 117 118 time.Sleep(1 * time.Second) 119 120 d := dt.d 121 if d.notifyCh == nil { 122 t.Fatal("Driver notify channel wasn't initialized after Config method") 123 } 124 125 if d.exitCh == nil { 126 t.Fatal("Driver serfloop exit channel wasn't initialized after Config method") 127 } 128 129 if d.serfInstance == nil { 130 t.Fatal("Driver serfinstance hasn't been initialized after Config method") 131 } 132 133 cleanupDriver(t, dt) 134 } 135 136 func TestOverlayType(t *testing.T) { 137 dt := &driverTester{t: t} 138 if err := Init(dt, nil); err != nil { 139 t.Fatal(err) 140 } 141 142 if dt.d.Type() != testNetworkType { 143 t.Fatalf("Expected Type() to return %q. Instead got %q", testNetworkType, 144 dt.d.Type()) 145 } 146 } 147 148 // Test that the netlink socket close unblock the watchMiss to avoid deadlock 149 func TestNetlinkSocket(t *testing.T) { 150 // This is the same code used by the overlay driver to create the netlink interface 151 // for the watch miss 152 nlSock, err := nl.Subscribe(syscall.NETLINK_ROUTE, syscall.RTNLGRP_NEIGH) 153 if err != nil { 154 t.Fatal() 155 } 156 // set the receive timeout to not remain stuck on the RecvFrom if the fd gets closed 157 tv := unix.NsecToTimeval(soTimeout.Nanoseconds()) 158 err = nlSock.SetReceiveTimeout(&tv) 159 if err != nil { 160 t.Fatal() 161 } 162 n := &network{id: "testnetid"} 163 ch := make(chan error) 164 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 165 defer cancel() 166 go func() { 167 n.watchMiss(nlSock, fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())) 168 ch <- nil 169 }() 170 time.Sleep(5 * time.Second) 171 nlSock.Close() 172 select { 173 case <-ch: 174 case <-ctx.Done(): 175 { 176 t.Fatalf("Timeout expired") 177 } 178 } 179 }