github.com/ttys3/engine@v17.12.1-ce-rc2+incompatible/pkg/plugins/client_test.go (about) 1 package plugins 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 "net/http" 8 "net/http/httptest" 9 "net/url" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/docker/docker/pkg/plugins/transport" 15 "github.com/docker/go-connections/tlsconfig" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 var ( 20 mux *http.ServeMux 21 server *httptest.Server 22 ) 23 24 func setupRemotePluginServer() string { 25 mux = http.NewServeMux() 26 server = httptest.NewServer(mux) 27 return server.URL 28 } 29 30 func teardownRemotePluginServer() { 31 if server != nil { 32 server.Close() 33 } 34 } 35 36 func TestFailedConnection(t *testing.T) { 37 c, _ := NewClient("tcp://127.0.0.1:1", &tlsconfig.Options{InsecureSkipVerify: true}) 38 _, err := c.callWithRetry("Service.Method", nil, false) 39 if err == nil { 40 t.Fatal("Unexpected successful connection") 41 } 42 } 43 44 func TestFailOnce(t *testing.T) { 45 addr := setupRemotePluginServer() 46 defer teardownRemotePluginServer() 47 48 failed := false 49 mux.HandleFunc("/Test.FailOnce", func(w http.ResponseWriter, r *http.Request) { 50 if !failed { 51 failed = true 52 panic("Plugin not ready") 53 } 54 }) 55 56 c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true}) 57 b := strings.NewReader("body") 58 _, err := c.callWithRetry("Test.FailOnce", b, true) 59 if err != nil { 60 t.Fatal(err) 61 } 62 } 63 64 func TestEchoInputOutput(t *testing.T) { 65 addr := setupRemotePluginServer() 66 defer teardownRemotePluginServer() 67 68 m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}} 69 70 mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) { 71 if r.Method != "POST" { 72 t.Fatalf("Expected POST, got %s\n", r.Method) 73 } 74 75 header := w.Header() 76 header.Set("Content-Type", transport.VersionMimetype) 77 78 io.Copy(w, r.Body) 79 }) 80 81 c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true}) 82 var output Manifest 83 err := c.Call("Test.Echo", m, &output) 84 if err != nil { 85 t.Fatal(err) 86 } 87 88 assert.Equal(t, m, output) 89 err = c.Call("Test.Echo", nil, nil) 90 if err != nil { 91 t.Fatal(err) 92 } 93 } 94 95 func TestBackoff(t *testing.T) { 96 cases := []struct { 97 retries int 98 expTimeOff time.Duration 99 }{ 100 {0, time.Duration(1)}, 101 {1, time.Duration(2)}, 102 {2, time.Duration(4)}, 103 {4, time.Duration(16)}, 104 {6, time.Duration(30)}, 105 {10, time.Duration(30)}, 106 } 107 108 for _, c := range cases { 109 s := c.expTimeOff * time.Second 110 if d := backoff(c.retries); d != s { 111 t.Fatalf("Retry %v, expected %v, was %v\n", c.retries, s, d) 112 } 113 } 114 } 115 116 func TestAbortRetry(t *testing.T) { 117 cases := []struct { 118 timeOff time.Duration 119 expAbort bool 120 }{ 121 {time.Duration(1), false}, 122 {time.Duration(2), false}, 123 {time.Duration(10), false}, 124 {time.Duration(30), true}, 125 {time.Duration(40), true}, 126 } 127 128 for _, c := range cases { 129 s := c.timeOff * time.Second 130 if a := abort(time.Now(), s); a != c.expAbort { 131 t.Fatalf("Duration %v, expected %v, was %v\n", c.timeOff, s, a) 132 } 133 } 134 } 135 136 func TestClientScheme(t *testing.T) { 137 cases := map[string]string{ 138 "tcp://127.0.0.1:8080": "http", 139 "unix:///usr/local/plugins/foo": "http", 140 "http://127.0.0.1:8080": "http", 141 "https://127.0.0.1:8080": "https", 142 } 143 144 for addr, scheme := range cases { 145 u, err := url.Parse(addr) 146 if err != nil { 147 t.Fatal(err) 148 } 149 s := httpScheme(u) 150 151 if s != scheme { 152 t.Fatalf("URL scheme mismatch, expected %s, got %s", scheme, s) 153 } 154 } 155 } 156 157 func TestNewClientWithTimeout(t *testing.T) { 158 addr := setupRemotePluginServer() 159 defer teardownRemotePluginServer() 160 161 m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}} 162 163 mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) { 164 time.Sleep(time.Duration(600) * time.Millisecond) 165 io.Copy(w, r.Body) 166 }) 167 168 // setting timeout of 500ms 169 timeout := time.Duration(500) * time.Millisecond 170 c, _ := NewClientWithTimeout(addr, &tlsconfig.Options{InsecureSkipVerify: true}, timeout) 171 var output Manifest 172 err := c.Call("Test.Echo", m, &output) 173 if err == nil { 174 t.Fatal("Expected timeout error") 175 } 176 } 177 178 func TestClientStream(t *testing.T) { 179 addr := setupRemotePluginServer() 180 defer teardownRemotePluginServer() 181 182 m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}} 183 var output Manifest 184 185 mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) { 186 if r.Method != "POST" { 187 t.Fatalf("Expected POST, got %s", r.Method) 188 } 189 190 header := w.Header() 191 header.Set("Content-Type", transport.VersionMimetype) 192 193 io.Copy(w, r.Body) 194 }) 195 196 c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true}) 197 body, err := c.Stream("Test.Echo", m) 198 if err != nil { 199 t.Fatal(err) 200 } 201 defer body.Close() 202 if err := json.NewDecoder(body).Decode(&output); err != nil { 203 t.Fatalf("Test.Echo: error reading plugin resp: %v", err) 204 } 205 assert.Equal(t, m, output) 206 } 207 208 func TestClientSendFile(t *testing.T) { 209 addr := setupRemotePluginServer() 210 defer teardownRemotePluginServer() 211 212 m := Manifest{[]string{"VolumeDriver", "NetworkDriver"}} 213 var output Manifest 214 var buf bytes.Buffer 215 if err := json.NewEncoder(&buf).Encode(m); err != nil { 216 t.Fatal(err) 217 } 218 mux.HandleFunc("/Test.Echo", func(w http.ResponseWriter, r *http.Request) { 219 if r.Method != "POST" { 220 t.Fatalf("Expected POST, got %s\n", r.Method) 221 } 222 223 header := w.Header() 224 header.Set("Content-Type", transport.VersionMimetype) 225 226 io.Copy(w, r.Body) 227 }) 228 229 c, _ := NewClient(addr, &tlsconfig.Options{InsecureSkipVerify: true}) 230 if err := c.SendFile("Test.Echo", &buf, &output); err != nil { 231 t.Fatal(err) 232 } 233 assert.Equal(t, m, output) 234 }