go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/logging/teelogger/teelogger_test.go (about) 1 // Copyright 2015 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package teelogger 16 17 import ( 18 "context" 19 "fmt" 20 "testing" 21 22 . "github.com/smartystreets/goconvey/convey" 23 "go.chromium.org/luci/common/logging" 24 "go.chromium.org/luci/common/logging/memlogger" 25 ) 26 27 func TestTeeLogger(t *testing.T) { 28 Convey(`A new TeeLogger instance`, t, func() { 29 l1 := logging.Get( 30 memlogger.Use(context.Background())).(*memlogger.MemLogger) 31 l2 := logging.Get( 32 memlogger.Use(context.Background())).(*memlogger.MemLogger) 33 l3 := logging.Get( 34 memlogger.Use(context.Background())).(*memlogger.MemLogger) 35 factories := []logging.Factory{ 36 func(_ context.Context) logging.Logger { return l1 }, 37 func(_ context.Context) logging.Logger { return l2 }, 38 func(_ context.Context) logging.Logger { return l3 }, 39 } 40 Convey("Set level Debug", func() { 41 ctx := Use(context.Background(), factories...) 42 ctx = logging.SetLevel(ctx, logging.Debug) 43 teeLog := logging.Get(ctx) 44 for _, entry := range []struct { 45 L logging.Level 46 F func(string, ...any) 47 T string 48 }{ 49 {logging.Debug, teeLog.Debugf, "DEBU"}, 50 {logging.Info, teeLog.Infof, "INFO"}, 51 {logging.Warning, teeLog.Warningf, "WARN"}, 52 {logging.Error, teeLog.Errorf, "ERRO"}, 53 } { 54 Convey(fmt.Sprintf("Can log to %s", entry.L), func() { 55 entry.F("%s", entry.T) 56 for _, logger := range []*memlogger.MemLogger{l1, l2, l3} { 57 So(len(logger.Messages()), ShouldEqual, 1) 58 msg := logger.Get(entry.L, entry.T, map[string]any(nil)) 59 So(msg, ShouldNotBeNil) 60 So(msg.CallDepth, ShouldEqual, 3) 61 } 62 }) 63 } 64 }) 65 Convey("Set level as Warning", func() { 66 ctx := Use(context.Background(), factories...) 67 ctx = logging.SetLevel(ctx, logging.Warning) 68 teeLog := logging.Get(ctx) 69 for _, entry := range []struct { 70 L logging.Level 71 F func(string, ...any) 72 T string 73 E bool 74 }{ 75 {logging.Debug, teeLog.Debugf, "DEBU", false}, 76 {logging.Info, teeLog.Infof, "INFO", false}, 77 {logging.Warning, teeLog.Warningf, "WARN", true}, 78 {logging.Error, teeLog.Errorf, "ERRO", true}, 79 } { 80 Convey(fmt.Sprintf("Can log to %s", entry.L), func() { 81 entry.F("%s", entry.T) 82 for _, logger := range []*memlogger.MemLogger{l1, l2, l3} { 83 if entry.E { 84 So(len(logger.Messages()), ShouldEqual, 1) 85 msg := logger.Get(entry.L, entry.T, map[string]any(nil)) 86 So(msg, ShouldNotBeNil) 87 So(msg.CallDepth, ShouldEqual, 3) 88 } else { 89 So(len(logger.Messages()), ShouldEqual, 0) 90 } 91 } 92 }) 93 } 94 }) 95 Convey("Uses context logger", func() { 96 ctx := memlogger.Use(context.Background()) 97 logger := logging.Get(ctx).(*memlogger.MemLogger) 98 99 teeCtx := Use(ctx) 100 logging.Get(teeCtx).Infof("Testing 1 2") 101 messages := logger.Messages() 102 103 // Make sure context logger doesn't get called 104 So(len(messages), ShouldEqual, 1) 105 msg := messages[0] 106 So(msg.CallDepth, ShouldEqual, 3) 107 So(msg.Msg, ShouldEqual, "Testing 1 2") 108 }) 109 }) 110 } 111 112 func TestTeeFilteredLogger(t *testing.T) { 113 Convey(`A new TeeLogger instance`, t, func() { 114 lD := logging.Get(memlogger.Use(context.Background())).(*memlogger.MemLogger) 115 lI := logging.Get(memlogger.Use(context.Background())).(*memlogger.MemLogger) 116 lW := logging.Get(memlogger.Use(context.Background())).(*memlogger.MemLogger) 117 lE := logging.Get(memlogger.Use(context.Background())).(*memlogger.MemLogger) 118 makeFactory := func(l logging.Logger) logging.Factory { 119 return func(_ context.Context) logging.Logger { return l } 120 } 121 filtereds := []Filtered{ 122 {makeFactory(lD), logging.Debug}, 123 {makeFactory(lI), logging.Info}, 124 {makeFactory(lW), logging.Warning}, 125 {makeFactory(lE), logging.Error}, 126 } 127 ctx := UseFiltered(context.Background(), filtereds...) 128 // The context level is ignored, even we set it. 129 ctx = logging.SetLevel(ctx, logging.Error) 130 teeLog := logging.Get(ctx) 131 132 for _, entry := range []struct { 133 L logging.Level 134 F func(string, ...any) 135 T string 136 // Loggers which have messages. 137 GoodLogger []*memlogger.MemLogger 138 // Loggers which do not have messages. 139 BadLogger []*memlogger.MemLogger 140 }{ 141 {logging.Debug, teeLog.Debugf, "DEBU", 142 []*memlogger.MemLogger{lD}, 143 []*memlogger.MemLogger{lI, lW, lE}}, 144 {logging.Info, teeLog.Infof, "INFO", 145 []*memlogger.MemLogger{lD, lI}, 146 []*memlogger.MemLogger{lW, lE}}, 147 {logging.Warning, teeLog.Warningf, "WARN", 148 []*memlogger.MemLogger{lD, lI, lW}, 149 []*memlogger.MemLogger{lE}}, 150 {logging.Error, teeLog.Errorf, "ERRO", 151 []*memlogger.MemLogger{lD, lI, lW, lE}, 152 []*memlogger.MemLogger{}}, 153 } { 154 Convey(fmt.Sprintf("Can log to %s", entry.L), func() { 155 entry.F("%s", entry.T) 156 for _, l := range entry.GoodLogger { 157 So(len(l.Messages()), ShouldEqual, 1) 158 msg := l.Get(entry.L, entry.T, map[string]any(nil)) 159 So(msg, ShouldNotBeNil) 160 So(msg.CallDepth, ShouldEqual, 3) 161 } 162 for _, l := range entry.BadLogger { 163 So(len(l.Messages()), ShouldEqual, 0) 164 } 165 }) 166 } 167 Convey("Use context logger with context level Debug", func() { 168 ctx := memlogger.Use(context.Background()) 169 logger := logging.Get(ctx).(*memlogger.MemLogger) 170 171 teeCtx := UseFiltered(ctx) 172 teeCtx = logging.SetLevel(teeCtx, logging.Debug) 173 l := logging.Get(teeCtx) 174 So(l, ShouldNotBeNil) 175 l.Infof("Info testing 1 2") 176 messages := logger.Messages() 177 178 // Make sure context logger doesn't get called 179 So(len(messages), ShouldEqual, 1) 180 msg := messages[0] 181 So(msg.CallDepth, ShouldEqual, 3) 182 So(msg.Msg, ShouldEqual, "Info testing 1 2") 183 }) 184 Convey("Use context logger with context level Warning", func() { 185 ctx := memlogger.Use(context.Background()) 186 logger := logging.Get(ctx).(*memlogger.MemLogger) 187 188 teeCtx := UseFiltered(ctx) 189 teeCtx = logging.SetLevel(teeCtx, logging.Warning) 190 logging.Get(teeCtx).Infof("Info testing 1 2") 191 messages := logger.Messages() 192 193 // Make sure context logger doesn't have messages 194 So(len(messages), ShouldEqual, 0) 195 }) 196 }) 197 }