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