github.com/ethersphere/bee/v2@v2.2.0/pkg/log/registry_test.go (about) 1 // Copyright 2022 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package log 6 7 import ( 8 "bytes" 9 "fmt" 10 "sync" 11 "testing" 12 13 "github.com/google/go-cmp/cmp" 14 ) 15 16 // allVerbosityLevels enumerates all possible verbosity levels. 17 var allVerbosityLevels = []Level{ 18 VerbosityNone, 19 VerbosityError, 20 VerbosityWarning, 21 VerbosityInfo, 22 VerbosityDebug, 23 VerbosityAll, 24 } 25 26 // opts specifies different set options for testing. 27 var opts = []Option{ 28 WithSink(new(bytes.Buffer)), 29 WithVerbosity(1), 30 WithCaller(CategoryError), 31 WithCallerFunc(), 32 WithTimestamp(), 33 WithTimestampLayout("0123456789"), 34 WithMaxDepth(2), 35 WithJSONOutput(), 36 WithCallerDepth(3), 37 } 38 39 func TestModifyDefaults(t *testing.T) { 40 o := defaults.options 41 t.Cleanup(func() { 42 defaults.pin = sync.Once{} 43 defaults.options = o 44 }) 45 46 want := new(Options) 47 have := new(Options) 48 for _, o := range opts { 49 o(want) 50 } 51 defaults.options = have 52 ModifyDefaults(opts...) 53 54 diff := cmp.Diff(have, want, cmp.AllowUnexported( 55 Options{}, 56 fmtOptions{}, 57 bytes.Buffer{}, 58 )) 59 if diff != "" { 60 t.Errorf("ModifyDefaults(...) mismatch (-want +have):\n%s", diff) 61 } 62 } 63 64 func TestNewLogger(t *testing.T) { 65 l, o := loggers, defaults.options 66 t.Cleanup(func() { 67 loggers = l 68 defaults.pin = sync.Once{} 69 defaults.options = o 70 }) 71 72 loggers = new(sync.Map) 73 defaults.options = new(Options) 74 ModifyDefaults(opts...) 75 76 var ( 77 cnt int 78 val interface{} 79 ) 80 NewLogger("root").Register() 81 loggers.Range(func(k, v interface{}) bool { 82 cnt++ 83 val = v 84 return true 85 }) 86 if cnt != 1 { 87 t.Fatalf("NewLogger(...) instance(s) count mismatch: want: 1; have: %d", cnt) 88 } 89 want := val.(*logger) 90 have := NewLogger("root").Register() 91 92 diff := cmp.Diff(have, want, cmp.AllowUnexported( 93 builder{}, 94 logger{}, 95 caller{}, 96 formatter{}, 97 fmtOptions{}, 98 bytes.Buffer{}, 99 )) 100 if diff != "" { 101 t.Errorf("NewLogger(...) mismatch (-want +have):\n%s", diff) 102 } 103 } 104 105 func TestSetVerbosity(t *testing.T) { 106 l, o := loggers, defaults.options 107 t.Cleanup(func() { 108 loggers = l 109 defaults.pin = sync.Once{} 110 defaults.options = o 111 }) 112 113 loggers = new(sync.Map) 114 defaults.options = new(Options) 115 ModifyDefaults(opts...) 116 117 NewLogger("root").Register() 118 NewLogger("root").WithName("child1").Register() 119 NewLogger("root").WithName("child1").WithValues("abc", 123).Register() 120 121 registered := make(map[string]*logger) 122 loggers.Range(func(k, v interface{}) bool { 123 registered[k.(string)] = v.(*logger) 124 return true 125 }) 126 127 for _, verbosity := range allVerbosityLevels { 128 t.Run(fmt.Sprintf("to=%s/by logger", verbosity), func(t *testing.T) { 129 for _, logger := range registered { 130 if err := SetVerbosity(logger, verbosity); err != nil { 131 t.Errorf("SetVerbosity(...) unexpected error %v", err) 132 } 133 134 // On VerbosityAll, the maximum verbosity will 135 // be set instead (VerbosityDebug in our case). 136 if verbosity == VerbosityAll { 137 verbosity = VerbosityDebug 138 } 139 140 want, have := verbosity, registered[logger.id].verbosity.get() 141 if want != have { 142 t.Errorf("SetVerbosity(...) want verbosity: %q; have: %q", want, have) 143 } 144 145 } 146 }) 147 } 148 149 for _, verbosity := range allVerbosityLevels { 150 t.Run(fmt.Sprintf("to=%s/by exp", verbosity), func(t *testing.T) { 151 if err := SetVerbosityByExp("^root", verbosity); err != nil { 152 t.Errorf("SetVerbosityByExp(...) unexpected error %v", err) 153 } 154 155 // On VerbosityAll, the maximum verbosity will 156 // be set instead (VerbosityDebug in our case). 157 if verbosity == VerbosityAll { 158 verbosity = VerbosityDebug 159 } 160 161 for _, logger := range registered { 162 want, have := verbosity, logger.verbosity.get() 163 if want != have { 164 t.Errorf("SetVerbosityByExp(...) want verbosity: %q; have: %q", want, have) 165 } 166 } 167 }) 168 } 169 } 170 171 func TestRegistryRange(t *testing.T) { 172 l, o := loggers, defaults.options 173 t.Cleanup(func() { 174 loggers = l 175 defaults.pin = sync.Once{} 176 defaults.options = o 177 }) 178 179 loggers = new(sync.Map) 180 defaults.options = new(Options) 181 ModifyDefaults(opts...) 182 183 NewLogger("root").Register() 184 NewLogger("root").WithName("child1").Register() 185 NewLogger("root").WithName("child1").WithValues("abc", 123).Register() 186 187 registered := make(map[string]*logger) 188 loggers.Range(func(k, v interface{}) bool { 189 registered[k.(string)] = v.(*logger) 190 return true 191 }) 192 193 var cnt int 194 RegistryIterate(func(id, path string, verbosity Level, v uint) (next bool) { 195 cnt++ 196 197 have := registered[id] 198 if have.id != id { 199 t.Errorf("RegistryIterate(...) want id: %q; have: %q", id, have.id) 200 } 201 if have.namesStr != path { 202 t.Errorf("RegistryIterate(...) want namesStr: %q; have: %q", path, have.namesStr) 203 } 204 if have.verbosity.get() != verbosity { 205 t.Errorf("RegistryIterate(...) want verbosity: %q; have: %q", verbosity, have.verbosity) 206 } 207 if have.v != v { 208 t.Errorf("RegistryIterate(...) want: v %d; have: %d", v, have.v) 209 } 210 return true 211 }) 212 213 if have, want := cnt, len(registered); have != want { 214 t.Fatalf("RegistryIterate(...) instance(s) count mismatch: want: %d; have: %d", want, have) 215 } 216 }