Browse Source

awslogs: fix flaky TestLogBlocking unit test

TestLogBlocking is intended to test that the Log method blocks by
default.  It does this by mocking out the internals of the
awslogs.logStream and replacing one of its internal channels with one
that is controlled by the test.  The call to Log occurs inside a
goroutine.  Go may or may not schedule the goroutine immediately and the
blocking may or may not be observed outside the goroutine immediately
due to decisions made by the Go runtime.  This change adds a small
timeout for test failure so that the Go runtime has the opportunity to
run the goroutine before the test fails.

Signed-off-by: Samuel Karp <skarp@amazon.com>
Samuel Karp 5 years ago
parent
commit
fd94bae0b8
1 changed files with 9 additions and 6 deletions
  1. 9 6
      daemon/logger/awslogs/cloudwatchlogs_test.go

+ 9 - 6
daemon/logger/awslogs/cloudwatchlogs_test.go

@@ -24,7 +24,6 @@ import (
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/dockerversion"
 	"gotest.tools/assert"
 	"gotest.tools/assert"
 	is "gotest.tools/assert/cmp"
 	is "gotest.tools/assert/cmp"
-	"gotest.tools/skip"
 )
 )
 
 
 const (
 const (
@@ -286,8 +285,10 @@ func TestLogClosed(t *testing.T) {
 	}
 	}
 }
 }
 
 
+// TestLogBlocking tests that the Log method blocks appropriately when
+// non-blocking behavior is not enabled.  Blocking is achieved through an
+// internal channel that must be drained for Log to return.
 func TestLogBlocking(t *testing.T) {
 func TestLogBlocking(t *testing.T) {
-	skip.If(t, runtime.GOOS == "windows", "FIXME: test is flaky on Windows. See #39857")
 	mockClient := newMockClient()
 	mockClient := newMockClient()
 	stream := &logStream{
 	stream := &logStream{
 		client:   mockClient,
 		client:   mockClient,
@@ -301,18 +302,20 @@ func TestLogBlocking(t *testing.T) {
 		err := stream.Log(&logger.Message{})
 		err := stream.Log(&logger.Message{})
 		errorCh <- err
 		errorCh <- err
 	}()
 	}()
+	// block until the goroutine above has started
 	<-started
 	<-started
 	select {
 	select {
 	case err := <-errorCh:
 	case err := <-errorCh:
 		t.Fatal("Expected stream.Log to block: ", err)
 		t.Fatal("Expected stream.Log to block: ", err)
 	default:
 	default:
-		break
 	}
 	}
+	// assuming it is blocked, we can now try to drain the internal channel and
+	// unblock it
 	select {
 	select {
-	case <-stream.messages:
-		break
-	default:
+	case <-time.After(10 * time.Millisecond):
+		// if we're unable to drain the channel within 10ms, something seems broken
 		t.Fatal("Expected to be able to read from stream.messages but was unable to")
 		t.Fatal("Expected to be able to read from stream.messages but was unable to")
+	case <-stream.messages:
 	}
 	}
 	select {
 	select {
 	case err := <-errorCh:
 	case err := <-errorCh: