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 }