github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/common/flogging/fabenc/formatter_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package fabenc_test 8 9 import ( 10 "bytes" 11 "fmt" 12 "runtime" 13 "strconv" 14 "sync" 15 "testing" 16 "time" 17 18 "github.com/hyperledger/fabric/common/flogging/fabenc" 19 "github.com/stretchr/testify/assert" 20 "go.uber.org/zap" 21 "go.uber.org/zap/zapcore" 22 ) 23 24 func TestParseFormat(t *testing.T) { 25 var tests = []struct { 26 desc string 27 spec string 28 formatters []fabenc.Formatter 29 }{ 30 { 31 desc: "empty spec", 32 spec: "", 33 formatters: []fabenc.Formatter{}, 34 }, 35 { 36 desc: "simple verb", 37 spec: "%{color}", 38 formatters: []fabenc.Formatter{ 39 fabenc.ColorFormatter{}, 40 }, 41 }, 42 { 43 desc: "with prefix", 44 spec: "prefix %{color}", 45 formatters: []fabenc.Formatter{ 46 fabenc.StringFormatter{Value: "prefix "}, 47 fabenc.ColorFormatter{}, 48 }, 49 }, 50 { 51 desc: "with suffix", 52 spec: "%{color} suffix", 53 formatters: []fabenc.Formatter{ 54 fabenc.ColorFormatter{}, 55 fabenc.StringFormatter{Value: " suffix"}}, 56 }, 57 { 58 desc: "with prefix and suffix", 59 spec: "prefix %{color} suffix", 60 formatters: []fabenc.Formatter{ 61 fabenc.StringFormatter{Value: "prefix "}, 62 fabenc.ColorFormatter{}, 63 fabenc.StringFormatter{Value: " suffix"}, 64 }, 65 }, 66 { 67 desc: "with format", 68 spec: "%{level:.4s} suffix", 69 formatters: []fabenc.Formatter{ 70 fabenc.LevelFormatter{FormatVerb: "%.4s"}, 71 fabenc.StringFormatter{Value: " suffix"}, 72 }, 73 }, 74 } 75 76 for _, tc := range tests { 77 t.Run(fmt.Sprintf(tc.desc), func(t *testing.T) { 78 formatters, err := fabenc.ParseFormat(tc.spec) 79 assert.NoError(t, err) 80 assert.Equal(t, tc.formatters, formatters) 81 }) 82 } 83 } 84 85 func TestParseFormatError(t *testing.T) { 86 _, err := fabenc.ParseFormat("%{color:bad}") 87 assert.EqualError(t, err, "invalid color option: bad") 88 } 89 90 func TestNewFormatter(t *testing.T) { 91 var tests = []struct { 92 verb string 93 format string 94 formatter fabenc.Formatter 95 errorMsg string 96 }{ 97 {verb: "color", format: "", formatter: fabenc.ColorFormatter{}}, 98 {verb: "color", format: "bold", formatter: fabenc.ColorFormatter{Bold: true}}, 99 {verb: "color", format: "reset", formatter: fabenc.ColorFormatter{Reset: true}}, 100 {verb: "color", format: "unknown", errorMsg: "invalid color option: unknown"}, 101 {verb: "id", format: "", formatter: fabenc.SequenceFormatter{FormatVerb: "%d"}}, 102 {verb: "id", format: "04x", formatter: fabenc.SequenceFormatter{FormatVerb: "%04x"}}, 103 {verb: "level", format: "", formatter: fabenc.LevelFormatter{FormatVerb: "%s"}}, 104 {verb: "level", format: ".4s", formatter: fabenc.LevelFormatter{FormatVerb: "%.4s"}}, 105 {verb: "message", format: "", formatter: fabenc.MessageFormatter{FormatVerb: "%s"}}, 106 {verb: "message", format: "#30s", formatter: fabenc.MessageFormatter{FormatVerb: "%#30s"}}, 107 {verb: "module", format: "", formatter: fabenc.ModuleFormatter{FormatVerb: "%s"}}, 108 {verb: "module", format: "ok", formatter: fabenc.ModuleFormatter{FormatVerb: "%ok"}}, 109 {verb: "shortfunc", format: "", formatter: fabenc.ShortFuncFormatter{FormatVerb: "%s"}}, 110 {verb: "shortfunc", format: "U", formatter: fabenc.ShortFuncFormatter{FormatVerb: "%U"}}, 111 {verb: "time", format: "", formatter: fabenc.TimeFormatter{Layout: "2006-01-02T15:04:05.999Z07:00"}}, 112 {verb: "time", format: "04:05.999999Z05:00", formatter: fabenc.TimeFormatter{Layout: "04:05.999999Z05:00"}}, 113 {verb: "unknown", format: "", errorMsg: "unknown verb: unknown"}, 114 } 115 116 for i, tc := range tests { 117 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 118 f, err := fabenc.NewFormatter(tc.verb, tc.format) 119 if tc.errorMsg == "" { 120 assert.NoError(t, err) 121 assert.Equal(t, tc.formatter, f) 122 } else { 123 assert.EqualError(t, err, tc.errorMsg) 124 } 125 }) 126 } 127 } 128 129 func TestColorFormatter(t *testing.T) { 130 var tests = []struct { 131 f fabenc.ColorFormatter 132 level zapcore.Level 133 formatted string 134 }{ 135 {f: fabenc.ColorFormatter{Reset: true}, level: zapcore.DebugLevel, formatted: fabenc.ResetColor()}, 136 {f: fabenc.ColorFormatter{}, level: zapcore.DebugLevel, formatted: fabenc.ColorCyan.Normal()}, 137 {f: fabenc.ColorFormatter{Bold: true}, level: zapcore.DebugLevel, formatted: fabenc.ColorCyan.Bold()}, 138 {f: fabenc.ColorFormatter{}, level: zapcore.InfoLevel, formatted: fabenc.ColorBlue.Normal()}, 139 {f: fabenc.ColorFormatter{Bold: true}, level: zapcore.InfoLevel, formatted: fabenc.ColorBlue.Bold()}, 140 {f: fabenc.ColorFormatter{}, level: zapcore.WarnLevel, formatted: fabenc.ColorYellow.Normal()}, 141 {f: fabenc.ColorFormatter{Bold: true}, level: zapcore.WarnLevel, formatted: fabenc.ColorYellow.Bold()}, 142 {f: fabenc.ColorFormatter{}, level: zapcore.ErrorLevel, formatted: fabenc.ColorRed.Normal()}, 143 {f: fabenc.ColorFormatter{Bold: true}, level: zapcore.ErrorLevel, formatted: fabenc.ColorRed.Bold()}, 144 {f: fabenc.ColorFormatter{}, level: zapcore.DPanicLevel, formatted: fabenc.ColorMagenta.Normal()}, 145 {f: fabenc.ColorFormatter{Bold: true}, level: zapcore.DPanicLevel, formatted: fabenc.ColorMagenta.Bold()}, 146 {f: fabenc.ColorFormatter{}, level: zapcore.PanicLevel, formatted: fabenc.ColorMagenta.Normal()}, 147 {f: fabenc.ColorFormatter{Bold: true}, level: zapcore.PanicLevel, formatted: fabenc.ColorMagenta.Bold()}, 148 {f: fabenc.ColorFormatter{}, level: zapcore.FatalLevel, formatted: fabenc.ColorMagenta.Normal()}, 149 {f: fabenc.ColorFormatter{Bold: true}, level: zapcore.FatalLevel, formatted: fabenc.ColorMagenta.Bold()}, 150 {f: fabenc.ColorFormatter{}, level: zapcore.Level(99), formatted: fabenc.ColorNone.Normal()}, 151 {f: fabenc.ColorFormatter{Bold: true}, level: zapcore.Level(99), formatted: fabenc.ColorNone.Normal()}, 152 } 153 154 for i, tc := range tests { 155 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 156 buf := &bytes.Buffer{} 157 entry := zapcore.Entry{Level: tc.level} 158 tc.f.Format(buf, entry, nil) 159 assert.Equal(t, tc.formatted, buf.String()) 160 }) 161 } 162 } 163 164 func TestLevelFormatter(t *testing.T) { 165 var tests = []struct { 166 level zapcore.Level 167 formatted string 168 }{ 169 {level: zapcore.DebugLevel, formatted: "DEBUG"}, 170 {level: zapcore.InfoLevel, formatted: "INFO"}, 171 {level: zapcore.WarnLevel, formatted: "WARN"}, 172 {level: zapcore.ErrorLevel, formatted: "ERROR"}, 173 {level: zapcore.DPanicLevel, formatted: "DPANIC"}, 174 {level: zapcore.PanicLevel, formatted: "PANIC"}, 175 {level: zapcore.FatalLevel, formatted: "FATAL"}, 176 {level: zapcore.Level(99), formatted: "LEVEL(99)"}, 177 } 178 179 for i, tc := range tests { 180 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 181 buf := &bytes.Buffer{} 182 entry := zapcore.Entry{Level: tc.level} 183 fabenc.LevelFormatter{FormatVerb: "%s"}.Format(buf, entry, nil) 184 assert.Equal(t, tc.formatted, buf.String()) 185 }) 186 } 187 } 188 189 func TestMessageFormatter(t *testing.T) { 190 buf := &bytes.Buffer{} 191 entry := zapcore.Entry{Message: "some message text \n\n"} 192 f := fabenc.MessageFormatter{FormatVerb: "%s"} 193 f.Format(buf, entry, nil) 194 assert.Equal(t, "some message text ", buf.String()) 195 } 196 197 func TestModuleFormatter(t *testing.T) { 198 buf := &bytes.Buffer{} 199 entry := zapcore.Entry{LoggerName: "logger/name"} 200 f := fabenc.ModuleFormatter{FormatVerb: "%s"} 201 f.Format(buf, entry, nil) 202 assert.Equal(t, "logger/name", buf.String()) 203 } 204 205 func TestSequenceFormatter(t *testing.T) { 206 mutex := &sync.Mutex{} 207 results := map[string]struct{}{} 208 209 ready := &sync.WaitGroup{} 210 ready.Add(100) 211 212 finished := &sync.WaitGroup{} 213 finished.Add(100) 214 215 fabenc.SetSequence(0) 216 for i := 1; i <= 100; i++ { 217 go func(i int) { 218 buf := &bytes.Buffer{} 219 entry := zapcore.Entry{Level: zapcore.DebugLevel} 220 f := fabenc.SequenceFormatter{FormatVerb: "%d"} 221 ready.Done() // setup complete 222 ready.Wait() // wait for all go routines to be ready 223 224 f.Format(buf, entry, nil) // format concurrently 225 226 mutex.Lock() 227 results[buf.String()] = struct{}{} 228 mutex.Unlock() 229 230 finished.Done() 231 }(i) 232 } 233 234 finished.Wait() 235 for i := 1; i <= 100; i++ { 236 assert.Contains(t, results, strconv.Itoa(i)) 237 } 238 } 239 240 func TestShortFuncFormatter(t *testing.T) { 241 callerpc, _, _, ok := runtime.Caller(0) 242 assert.True(t, ok) 243 buf := &bytes.Buffer{} 244 entry := zapcore.Entry{Caller: zapcore.EntryCaller{PC: callerpc}} 245 fabenc.ShortFuncFormatter{FormatVerb: "%s"}.Format(buf, entry, nil) 246 assert.Equal(t, "TestShortFuncFormatter", buf.String()) 247 248 buf = &bytes.Buffer{} 249 entry = zapcore.Entry{Caller: zapcore.EntryCaller{PC: 0}} 250 fabenc.ShortFuncFormatter{FormatVerb: "%s"}.Format(buf, entry, nil) 251 assert.Equal(t, "(unknown)", buf.String()) 252 } 253 254 func TestTimeFormatter(t *testing.T) { 255 buf := &bytes.Buffer{} 256 entry := zapcore.Entry{Time: time.Date(1975, time.August, 15, 12, 0, 0, 333, time.UTC)} 257 f := fabenc.TimeFormatter{Layout: time.RFC3339Nano} 258 f.Format(buf, entry, nil) 259 assert.Equal(t, "1975-08-15T12:00:00.000000333Z", buf.String()) 260 } 261 262 func TestMultiFormatter(t *testing.T) { 263 entry := zapcore.Entry{ 264 Message: "message", 265 Level: zapcore.InfoLevel, 266 } 267 fields := []zapcore.Field{ 268 zap.String("name", "value"), 269 } 270 271 var tests = []struct { 272 desc string 273 initial []fabenc.Formatter 274 update []fabenc.Formatter 275 expected string 276 }{ 277 { 278 desc: "no formatters", 279 initial: nil, 280 update: nil, 281 expected: "", 282 }, 283 { 284 desc: "initial formatters", 285 initial: []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}}, 286 update: nil, 287 expected: "string1", 288 }, 289 { 290 desc: "set to formatters", 291 initial: []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}}, 292 update: []fabenc.Formatter{ 293 fabenc.StringFormatter{Value: "string1"}, 294 fabenc.StringFormatter{Value: "-"}, 295 fabenc.StringFormatter{Value: "string2"}, 296 }, 297 expected: "string1-string2", 298 }, 299 { 300 desc: "set to empty", 301 initial: []fabenc.Formatter{fabenc.StringFormatter{Value: "string1"}}, 302 update: []fabenc.Formatter{}, 303 expected: "", 304 }, 305 } 306 307 for _, tc := range tests { 308 mf := fabenc.NewMultiFormatter(tc.initial...) 309 if tc.update != nil { 310 mf.SetFormatters(tc.update) 311 } 312 313 buf := &bytes.Buffer{} 314 mf.Format(buf, entry, fields) 315 assert.Equal(t, tc.expected, buf.String()) 316 } 317 }