github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/daemon/logger/loggerutils/logfile_race_test.go (about)

     1  //go:build race
     2  
     3  package loggerutils // import "github.com/Prakhar-Agarwal-byte/moby/daemon/logger/loggerutils"
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"io"
     9  	"path/filepath"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/Prakhar-Agarwal-byte/moby/api/types/backend"
    14  	"github.com/Prakhar-Agarwal-byte/moby/daemon/logger"
    15  	"github.com/Prakhar-Agarwal-byte/moby/pkg/tailfile"
    16  	"golang.org/x/sync/errgroup"
    17  	"gotest.tools/v3/assert"
    18  )
    19  
    20  func TestConcurrentLogging(t *testing.T) {
    21  	const (
    22  		containers = 5
    23  		loggers    = 3  // loggers per container
    24  		messages   = 50 // messages per logger
    25  
    26  		capacity = 256
    27  		maxFiles = 3
    28  		compress = true
    29  	)
    30  	getTailReader := func(ctx context.Context, r SizeReaderAt, lines int) (io.Reader, int, error) {
    31  		return tailfile.NewTailReader(ctx, r, lines)
    32  	}
    33  	createDecoder := func(io.Reader) Decoder {
    34  		return dummyDecoder{}
    35  	}
    36  	marshal := func(msg *logger.Message) []byte {
    37  		return []byte(fmt.Sprintf(
    38  			"Line=%q Source=%q Timestamp=%v Attrs=%v PLogMetaData=%#v Err=%v",
    39  			msg.Line, msg.Source, msg.Timestamp, msg.Attrs, msg.PLogMetaData, msg.Err,
    40  		))
    41  	}
    42  	g, ctx := errgroup.WithContext(context.Background())
    43  	for ct := 0; ct < containers; ct++ {
    44  		ct := ct
    45  		dir := t.TempDir()
    46  		g.Go(func() (err error) {
    47  			logfile, err := NewLogFile(filepath.Join(dir, "log.log"), capacity, maxFiles, compress, createDecoder, 0o644, getTailReader)
    48  			if err != nil {
    49  				return err
    50  			}
    51  			defer func() {
    52  				if cErr := logfile.Close(); cErr != nil && err == nil {
    53  					err = cErr
    54  				}
    55  			}()
    56  			lg, ctx := errgroup.WithContext(ctx)
    57  			for ln := 0; ln < loggers; ln++ {
    58  				ln := ln
    59  				lg.Go(func() error {
    60  					for m := 0; m < messages; m++ {
    61  						select {
    62  						case <-ctx.Done():
    63  							return ctx.Err()
    64  						default:
    65  						}
    66  						timestamp := time.Now()
    67  						msg := logger.NewMessage()
    68  						msg.Line = append(msg.Line, fmt.Sprintf("container=%v logger=%v msg=%v", ct, ln, m)...)
    69  						msg.Source = "stdout"
    70  						msg.Timestamp = timestamp
    71  						msg.Attrs = append(msg.Attrs, backend.LogAttr{Key: "foo", Value: "bar"})
    72  						msg.PLogMetaData = &backend.PartialLogMetaData{ID: fmt.Sprintf("%v %v %v", ct, ln, m), Ordinal: 1, Last: true}
    73  						marshalled := marshal(msg)
    74  						logger.PutMessage(msg)
    75  						if err := logfile.WriteLogEntry(timestamp, marshalled); err != nil {
    76  							return err
    77  						}
    78  					}
    79  					return nil
    80  				})
    81  			}
    82  			return lg.Wait()
    83  		})
    84  	}
    85  	assert.NilError(t, g.Wait())
    86  }