github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/xlog/tee_core_test.go (about)

     1  package xlog
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"path/filepath"
     7  	"strconv"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/require"
    13  	"go.uber.org/zap"
    14  	"go.uber.org/zap/zapcore"
    15  
    16  	"github.com/benz9527/xboot/lib/id"
    17  )
    18  
    19  func TestConsoleAndFileMultiCores_DataRace(t *testing.T) {
    20  	tee := make(xLogMultiCore, 0, 2)
    21  	require.Nil(t, tee.context())
    22  	require.Nil(t, tee.writeSyncer())
    23  	require.Nil(t, tee.levelEncoder())
    24  	require.Nil(t, tee.timeEncoder())
    25  	require.Nil(t, tee.outEncoder())
    26  
    27  	lvlEnabler := zap.NewAtomicLevelAt(LogLevelDebug.zapLevel())
    28  	ctx, cancel := context.WithCancel(context.TODO())
    29  	cc := newConsoleCore(
    30  		ctx,
    31  		&lvlEnabler,
    32  		JSON,
    33  		zapcore.CapitalLevelEncoder,
    34  		zapcore.ISO8601TimeEncoder,
    35  	)
    36  
    37  	nano, err := id.ClassicNanoID(6)
    38  	require.NoError(t, err)
    39  	rngLogSuffix := "_" + nano() + "_xlog"
    40  
    41  	cfg := &FileCoreConfig{
    42  		FilePath: os.TempDir(),
    43  		Filename: filepath.Base(os.Args[0]) + rngLogSuffix + ".log",
    44  	}
    45  	fc := newFileCore(cfg)(
    46  		ctx,
    47  		&lvlEnabler,
    48  		JSON,
    49  		zapcore.CapitalLevelEncoder,
    50  		zapcore.ISO8601TimeEncoder,
    51  	)
    52  	tee1, err := WrapCores(nil, defaultCoreEncoderCfg())
    53  	require.Error(t, err)
    54  	require.Nil(t, tee1)
    55  
    56  	tee1, err = WrapCores([]xLogCore{nil}, defaultCoreEncoderCfg())
    57  	require.Error(t, err)
    58  	require.Nil(t, tee1)
    59  
    60  	tee1 = XLogTeeCore(cc, fc)
    61  	require.Equal(t, zapcore.DebugLevel, tee1.(xLogMultiCore).Level())
    62  
    63  	tee2, err := WrapCores(tee1.(xLogMultiCore), defaultCoreEncoderCfg())
    64  	require.NoError(t, err)
    65  
    66  	lvlEnabler2 := zap.NewAtomicLevelAt(LogLevelDebug.zapLevel())
    67  	tee3, err := WrapCoresNewLevelEnabler(nil, &lvlEnabler2, defaultCoreEncoderCfg())
    68  	require.Error(t, err)
    69  	require.Nil(t, tee3)
    70  
    71  	tee3, err = WrapCoresNewLevelEnabler([]xLogCore{nil}, &lvlEnabler2, defaultCoreEncoderCfg())
    72  	require.Error(t, err)
    73  	require.Nil(t, tee3)
    74  
    75  	tee3, err = WrapCoresNewLevelEnabler(tee2.(xLogMultiCore), &lvlEnabler2, defaultCoreEncoderCfg())
    76  	require.NoError(t, err)
    77  
    78  	tee4 := tee3.(xLogMultiCore).With([]zap.Field{zap.String("fields", "tee4")})
    79  
    80  	var ws sync.WaitGroup
    81  	ws.Add(4)
    82  	go func() {
    83  		ent := tee1.Check(zapcore.Entry{Level: zapcore.DebugLevel}, nil)
    84  		for i := 0; i < 100; i++ {
    85  			time.Sleep(10 * time.Millisecond)
    86  			if tee.Enabled(ent.Entry.Level) {
    87  				err := tee1.Write(ent.Entry, []zap.Field{zap.String("tee1", strconv.Itoa(i)+" "+time.Now().UTC().Format(backupDateTimeFormat)+" xlog tee write test!")})
    88  				require.NoError(t, err)
    89  			}
    90  		}
    91  		ws.Done()
    92  	}()
    93  	go func() {
    94  		ent := tee2.Check(zapcore.Entry{Level: zapcore.InfoLevel}, nil)
    95  		for i := 0; i < 100; i++ {
    96  			time.Sleep(10 * time.Millisecond)
    97  			if tee2.Enabled(ent.Entry.Level) {
    98  				err := tee2.Write(ent.Entry, []zap.Field{zap.String("tee2", strconv.Itoa(i)+" "+time.Now().UTC().Format(backupDateTimeFormat)+" xlog tee write test!")})
    99  				require.NoError(t, err)
   100  			}
   101  		}
   102  		ws.Done()
   103  	}()
   104  	go func() {
   105  		ent := tee3.Check(zapcore.Entry{Level: zapcore.InfoLevel}, nil)
   106  		for i := 0; i < 100; i++ {
   107  			time.Sleep(10 * time.Millisecond)
   108  			if tee3.Enabled(ent.Entry.Level) {
   109  				err := tee3.Write(ent.Entry, []zap.Field{zap.String("tee3", strconv.Itoa(i)+" "+time.Now().UTC().Format(backupDateTimeFormat)+" xlog tee write test!")})
   110  				require.NoError(t, err)
   111  			}
   112  		}
   113  		ws.Done()
   114  	}()
   115  	go func() {
   116  		ent := tee4.Check(zapcore.Entry{Level: zapcore.WarnLevel}, nil)
   117  		for i := 0; i < 100; i++ {
   118  			time.Sleep(10 * time.Millisecond)
   119  			if tee4.Enabled(ent.Entry.Level) {
   120  				err := tee4.Write(ent.Entry, []zap.Field{zap.String("tee4", strconv.Itoa(i)+" "+time.Now().UTC().Format(backupDateTimeFormat)+" xlog tee write test!")})
   121  				require.NoError(t, err)
   122  			}
   123  		}
   124  		ws.Done()
   125  	}()
   126  	go func() {
   127  		time.Sleep(200 * time.Millisecond)
   128  		_ = tee1.Sync()
   129  		_ = tee2.Sync()
   130  		_ = tee3.Sync()
   131  		_ = tee4.Sync()
   132  		t.Log("info level change")
   133  		lvlEnabler.SetLevel(LogLevelInfo.zapLevel())
   134  
   135  		time.Sleep(200 * time.Millisecond)
   136  		_ = tee1.Sync()
   137  		_ = tee2.Sync()
   138  		_ = tee3.Sync()
   139  		_ = tee4.Sync()
   140  		t.Log("debug level change")
   141  		lvlEnabler.SetLevel(LogLevelDebug.zapLevel())
   142  
   143  		time.Sleep(300 * time.Millisecond)
   144  		_ = tee1.Sync()
   145  		_ = tee2.Sync()
   146  		_ = tee3.Sync()
   147  		_ = tee4.Sync()
   148  		t.Log("warn level no other tee1 and tee2 logs")
   149  		lvlEnabler.SetLevel(LogLevelWarn.zapLevel())
   150  
   151  		time.Sleep(50 * time.Millisecond)
   152  		_ = tee1.Sync()
   153  		_ = tee2.Sync()
   154  		_ = tee3.Sync()
   155  		_ = tee4.Sync()
   156  		t.Log("error level no other tee1, tee2 and tee3 logs")
   157  		lvlEnabler2.SetLevel(LogLevelWarn.zapLevel())
   158  	}()
   159  	ws.Wait()
   160  
   161  	_ = tee1.Sync()
   162  	_ = tee2.Sync()
   163  	_ = tee3.Sync()
   164  	_ = tee4.Sync()
   165  	cancel()
   166  
   167  	removed := testCleanLogFiles(t, cfg.FilePath, filepath.Base(os.Args[0])+rngLogSuffix, ".log")
   168  	require.Equal(t, 1, removed)
   169  }