Browse code

pkg/plugins: make unit test less time sensitive

TestClientWithRequestTimeout has been observed to flake in CI. The
timing in the test is quite tight, only giving the client a 10ms window
to time out, which could potentially be missed if the host is under
load and the goroutine scheduling is unlucky. Give the client a full
five seconds of grace to time out before failing the test.

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

Cory Snider authored on 2023/07/06 01:09:37
Showing 1 changed files
... ...
@@ -3,6 +3,7 @@ package plugins // import "github.com/docker/docker/pkg/plugins"
3 3
 import (
4 4
 	"bytes"
5 5
 	"encoding/json"
6
+	"errors"
6 7
 	"io"
7 8
 	"net/http"
8 9
 	"net/http/httptest"
... ...
@@ -13,7 +14,6 @@ import (
13 13
 
14 14
 	"github.com/docker/docker/pkg/plugins/transport"
15 15
 	"github.com/docker/go-connections/tlsconfig"
16
-	"github.com/pkg/errors"
17 16
 	"gotest.tools/v3/assert"
18 17
 	is "gotest.tools/v3/assert/cmp"
19 18
 )
... ...
@@ -240,22 +240,39 @@ func TestClientWithRequestTimeout(t *testing.T) {
240 240
 		Timeout() bool
241 241
 	}
242 242
 
243
-	timeout := 1 * time.Millisecond
243
+	unblock := make(chan struct{})
244 244
 	testHandler := func(w http.ResponseWriter, r *http.Request) {
245
-		time.Sleep(timeout + 10*time.Millisecond)
245
+		select {
246
+		case <-unblock:
247
+		case <-r.Context().Done():
248
+		}
246 249
 		w.WriteHeader(http.StatusOK)
247 250
 	}
248 251
 
249 252
 	srv := httptest.NewServer(http.HandlerFunc(testHandler))
250
-	defer srv.Close()
253
+	defer func() {
254
+		close(unblock)
255
+		srv.Close()
256
+	}()
251 257
 
252 258
 	client := &Client{http: srv.Client(), requestFactory: &testRequestWrapper{srv}}
253
-	_, err := client.callWithRetry("/Plugin.Hello", nil, false, WithRequestTimeout(timeout))
254
-	assert.Assert(t, is.ErrorContains(err, ""), "expected error")
255
-
256
-	var tErr timeoutError
257
-	assert.Assert(t, errors.As(err, &tErr))
258
-	assert.Assert(t, tErr.Timeout())
259
+	errCh := make(chan error, 1)
260
+	go func() {
261
+		_, err := client.callWithRetry("/Plugin.Hello", nil, false, WithRequestTimeout(time.Millisecond))
262
+		errCh <- err
263
+	}()
264
+
265
+	timer := time.NewTimer(5 * time.Second)
266
+	defer timer.Stop()
267
+	select {
268
+	case err := <-errCh:
269
+		var tErr timeoutError
270
+		if assert.Check(t, errors.As(err, &tErr), "want timeout error, got %T", err) {
271
+			assert.Check(t, tErr.Timeout())
272
+		}
273
+	case <-timer.C:
274
+		t.Fatal("client request did not time out in time")
275
+	}
259 276
 }
260 277
 
261 278
 type testRequestWrapper struct {