github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/log/logger_test.go (about) 1 package log 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "io" 8 "log/slog" 9 "math/big" 10 "os" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/holiman/uint256" 16 ) 17 18 // TestLoggingWithVmodule checks that vmodule works. 19 func TestLoggingWithVmodule(t *testing.T) { 20 out := new(bytes.Buffer) 21 glog := NewGlogHandler(NewTerminalHandlerWithLevel(out, LevelTrace, false)) 22 glog.Verbosity(LevelCrit) 23 logger := NewLogger(glog) 24 logger.Warn("This should not be seen", "ignored", "true") 25 glog.Vmodule("logger_test.go=5") 26 logger.Trace("a message", "foo", "bar") 27 have := out.String() 28 // The timestamp is locale-dependent, so we want to trim that off 29 // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..." 30 have = strings.Split(have, "]")[1] 31 want := " a message foo=bar\n" 32 if have != want { 33 t.Errorf("\nhave: %q\nwant: %q\n", have, want) 34 } 35 } 36 37 func TestTerminalHandlerWithAttrs(t *testing.T) { 38 out := new(bytes.Buffer) 39 glog := NewGlogHandler(NewTerminalHandlerWithLevel(out, LevelTrace, false).WithAttrs([]slog.Attr{slog.String("baz", "bat")})) 40 glog.Verbosity(LevelTrace) 41 logger := NewLogger(glog) 42 logger.Trace("a message", "foo", "bar") 43 have := out.String() 44 // The timestamp is locale-dependent, so we want to trim that off 45 // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..." 46 have = strings.Split(have, "]")[1] 47 want := " a message baz=bat foo=bar\n" 48 if have != want { 49 t.Errorf("\nhave: %q\nwant: %q\n", have, want) 50 } 51 } 52 53 // Make sure the default json handler outputs debug log lines 54 func TestJSONHandler(t *testing.T) { 55 out := new(bytes.Buffer) 56 handler := JSONHandler(out) 57 logger := slog.New(handler) 58 logger.Debug("hi there") 59 if len(out.String()) == 0 { 60 t.Error("expected non-empty debug log output from default JSON Handler") 61 } 62 63 out.Reset() 64 handler = JSONHandlerWithLevel(out, slog.LevelInfo) 65 logger = slog.New(handler) 66 logger.Debug("hi there") 67 if len(out.String()) != 0 { 68 t.Errorf("expected empty debug log output, but got: %v", out.String()) 69 } 70 } 71 72 func BenchmarkTraceLogging(b *testing.B) { 73 SetDefault(NewLogger(NewTerminalHandler(os.Stderr, true))) 74 b.ResetTimer() 75 for i := 0; i < b.N; i++ { 76 Trace("a message", "v", i) 77 } 78 } 79 80 func BenchmarkTerminalHandler(b *testing.B) { 81 l := NewLogger(NewTerminalHandler(io.Discard, false)) 82 benchmarkLogger(b, l) 83 } 84 func BenchmarkLogfmtHandler(b *testing.B) { 85 l := NewLogger(LogfmtHandler(io.Discard)) 86 benchmarkLogger(b, l) 87 } 88 89 func BenchmarkJSONHandler(b *testing.B) { 90 l := NewLogger(JSONHandler(io.Discard)) 91 benchmarkLogger(b, l) 92 } 93 94 func benchmarkLogger(b *testing.B, l Logger) { 95 var ( 96 bb = make([]byte, 10) 97 tt = time.Now() 98 bigint = big.NewInt(100) 99 nilbig *big.Int 100 err = errors.New("Oh nooes it's crap") 101 ) 102 b.ReportAllocs() 103 b.ResetTimer() 104 for i := 0; i < b.N; i++ { 105 l.Info("This is a message", 106 "foo", int16(i), 107 "bytes", bb, 108 "bonk", "a string with text", 109 "time", tt, 110 "bigint", bigint, 111 "nilbig", nilbig, 112 "err", err) 113 } 114 b.StopTimer() 115 } 116 117 func TestLoggerOutput(t *testing.T) { 118 type custom struct { 119 A string 120 B int8 121 } 122 var ( 123 customA = custom{"Foo", 12} 124 customB = custom{"Foo\nLinebreak", 122} 125 bb = make([]byte, 10) 126 tt = time.Time{} 127 bigint = big.NewInt(100) 128 nilbig *big.Int 129 err = errors.New("Oh nooes it's crap") 130 smallUint = uint256.NewInt(500_000) 131 bigUint = &uint256.Int{0xff, 0xff, 0xff, 0xff} 132 ) 133 134 out := new(bytes.Buffer) 135 glogHandler := NewGlogHandler(NewTerminalHandler(out, false)) 136 glogHandler.Verbosity(LevelInfo) 137 NewLogger(glogHandler).Info("This is a message", 138 "foo", int16(123), 139 "bytes", bb, 140 "bonk", "a string with text", 141 "time", tt, 142 "bigint", bigint, 143 "nilbig", nilbig, 144 "err", err, 145 "struct", customA, 146 "struct", customB, 147 "ptrstruct", &customA, 148 "smalluint", smallUint, 149 "bigUint", bigUint) 150 151 have := out.String() 152 t.Logf("output %v", out.String()) 153 want := `INFO [11-07|19:14:33.821] This is a message foo=123 bytes="[0 0 0 0 0 0 0 0 0 0]" bonk="a string with text" time=0001-01-01T00:00:00+0000 bigint=100 nilbig=<nil> err="Oh nooes it's crap" struct="{A:Foo B:12}" struct="{A:Foo\nLinebreak B:122}" ptrstruct="&{A:Foo B:12}" smalluint=500,000 bigUint=1,600,660,942,523,603,594,864,898,306,482,794,244,293,965,082,972,225,630,372,095 154 ` 155 if !bytes.Equal([]byte(have)[25:], []byte(want)[25:]) { 156 t.Errorf("Error\nhave: %q\nwant: %q", have, want) 157 } 158 } 159 160 const termTimeFormat = "01-02|15:04:05.000" 161 162 func BenchmarkAppendFormat(b *testing.B) { 163 var now = time.Now() 164 b.Run("fmt time.Format", func(b *testing.B) { 165 for i := 0; i < b.N; i++ { 166 fmt.Fprintf(io.Discard, "%s", now.Format(termTimeFormat)) 167 } 168 }) 169 b.Run("time.AppendFormat", func(b *testing.B) { 170 for i := 0; i < b.N; i++ { 171 now.AppendFormat(nil, termTimeFormat) 172 } 173 }) 174 var buf = new(bytes.Buffer) 175 b.Run("time.Custom", func(b *testing.B) { 176 for i := 0; i < b.N; i++ { 177 writeTimeTermFormat(buf, now) 178 buf.Reset() 179 } 180 }) 181 } 182 183 func TestTermTimeFormat(t *testing.T) { 184 var now = time.Now() 185 want := now.AppendFormat(nil, termTimeFormat) 186 var b = new(bytes.Buffer) 187 writeTimeTermFormat(b, now) 188 have := b.Bytes() 189 if !bytes.Equal(have, want) { 190 t.Errorf("have != want\nhave: %q\nwant: %q\n", have, want) 191 } 192 }