Browse Source

daemon/logger: add test to detect data races

Signed-off-by: Cory Snider <csnider@mirantis.com>
Cory Snider 3 years ago
parent
commit
9080e5a1f7
1 changed files with 84 additions and 0 deletions
  1. 84 0
      daemon/logger/loggerutils/logfile_race_test.go

+ 84 - 0
daemon/logger/loggerutils/logfile_race_test.go

@@ -0,0 +1,84 @@
+//go:build race
+// +build race
+
+package loggerutils // import "github.com/docker/docker/daemon/logger/loggerutils"
+
+import (
+	"context"
+	"fmt"
+	"io"
+	"path/filepath"
+	"testing"
+	"time"
+
+	"github.com/docker/docker/api/types/backend"
+	"github.com/docker/docker/daemon/logger"
+	"github.com/docker/docker/pkg/tailfile"
+	"golang.org/x/sync/errgroup"
+	"gotest.tools/v3/assert"
+)
+
+func TestConcurrentLogging(t *testing.T) {
+	const (
+		containers = 5
+		loggers    = 3  // loggers per container
+		messages   = 50 // messages per logger
+
+		capacity = 256
+		maxFiles = 3
+		compress = true
+	)
+	getTailReader := func(ctx context.Context, r SizeReaderAt, lines int) (io.Reader, int, error) {
+		return tailfile.NewTailReader(ctx, r, lines)
+	}
+	createDecoder := func(io.Reader) Decoder {
+		return dummyDecoder{}
+	}
+	marshal := func(msg *logger.Message) ([]byte, error) {
+		return []byte(fmt.Sprintf(
+			"Line=%q Source=%q Timestamp=%v Attrs=%v PLogMetaData=%#v Err=%v",
+			msg.Line, msg.Source, msg.Timestamp, msg.Attrs, msg.PLogMetaData, msg.Err,
+		)), nil
+	}
+	g, ctx := errgroup.WithContext(context.Background())
+	for ct := 0; ct < containers; ct++ {
+		ct := ct
+		dir := t.TempDir()
+		g.Go(func() (err error) {
+			logfile, err := NewLogFile(filepath.Join(dir, "log.log"), capacity, maxFiles, compress, marshal, createDecoder, 0644, getTailReader)
+			if err != nil {
+				return err
+			}
+			defer func() {
+				if cErr := logfile.Close(); cErr != nil && err == nil {
+					err = cErr
+				}
+			}()
+			lg, ctx := errgroup.WithContext(ctx)
+			for ln := 0; ln < loggers; ln++ {
+				ln := ln
+				lg.Go(func() error {
+					for m := 0; m < messages; m++ {
+						select {
+						case <-ctx.Done():
+							return ctx.Err()
+						default:
+						}
+						msg := logger.NewMessage()
+						msg.Line = append(msg.Line, fmt.Sprintf("container=%v logger=%v msg=%v", ct, ln, m)...)
+						msg.Source = "stdout"
+						msg.Timestamp = time.Now()
+						msg.Attrs = append(msg.Attrs, backend.LogAttr{Key: "foo", Value: "bar"})
+						msg.PLogMetaData = &backend.PartialLogMetaData{ID: fmt.Sprintf("%v %v %v", ct, ln, m), Ordinal: 1, Last: true}
+						if err := logfile.WriteLogEntry(msg); err != nil {
+							return err
+						}
+					}
+					return nil
+				})
+			}
+			return lg.Wait()
+		})
+	}
+	assert.NilError(t, g.Wait())
+}