codeberg.org/gruf/go-log@v1.0.6-0.20231202001801-031c3d3d089b/log_test.go (about) 1 package log_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "net/http" 7 "strings" 8 "sync" 9 "testing" 10 11 "codeberg.org/gruf/go-kv" 12 "codeberg.org/gruf/go-log" 13 ) 14 15 var ( 16 testArgs = [][]interface{}{ 17 {0, 1, 2, 3, 4}, 18 {"hello", "world!"}, 19 {"random", 0, 1, 2.2, 3.3, "arguments"}, 20 {[]int{0, 1, 2, 3}, []string{"hello", "world"}, map[string]string{"hello": "world"}}, 21 {http.Client{}, sync.Mutex{}}, 22 {nil, nil, nil, nil}, 23 } 24 25 testFmts = []struct { 26 fmt string 27 arg []interface{} 28 }{ 29 { 30 fmt: "hello world: %q", 31 arg: []interface{}{"hello world"}, 32 }, 33 { 34 fmt: "no operators here", 35 arg: []interface{}{"oh no unexpected!"}, 36 }, 37 { 38 fmt: "0, 1, %d, %f, %s", 39 arg: []interface{}{2, 3.0, "4"}, 40 }, 41 { 42 fmt: "%d %d %d %d", 43 arg: []interface{}{"oh no bad and missing operators"}, 44 }, 45 { 46 fmt: "%#v", 47 arg: []interface{}{http.Client{}}, 48 }, 49 { 50 fmt: "%+v", 51 arg: []interface{}{map[string]interface{}{"key": "value", "hello": "world"}}, 52 }, 53 } 54 55 testFields = []kv.Fields{ 56 { 57 kv.Field{K: "hello", V: "world!"}, 58 kv.Field{K: "client", V: http.Client{}}, 59 }, 60 { 61 kv.Field{K: "map", V: map[string]string{"map": "of values"}}, 62 kv.Field{K: "slice", V: []string{"slice", "of", "values"}}, 63 }, 64 { 65 kv.Field{K: "nil", V: nil}, 66 kv.Field{K: "hmmm", V: "watcha sayyyy"}, 67 }, 68 { 69 kv.Field{K: "int", V: 420}, 70 kv.Field{K: "float", V: 6.9}, 71 }, 72 { 73 kv.Field{K: "complex", V: complex(120, 120)}, 74 kv.Field{K: "shrug", V: "\n\n\n\n\n\n\n\n\n\n\n\n"}, 75 }, 76 } 77 ) 78 79 func TestLoggingLevels(t *testing.T) { 80 // Special case of no log flags 81 log.Default().Logger().SetFlags(0) 82 83 // Output to buffer 84 buf := bytes.Buffer{} 85 log.SetOutput(&buf) 86 87 testLog := func(do func(), expect bool) { 88 do() 89 if !expect && buf.Len() > 0 { 90 t.Error("log should not have produced output") 91 } else if expect && buf.Len() == 0 { 92 t.Error("log should have produced output") 93 } 94 buf.Reset() 95 } 96 97 for _, lvl := range []log.LEVEL{ 98 log.ALL, 99 log.DEBUG, 100 log.INFO, 101 log.WARN, 102 log.ERROR, 103 log.PANIC, 104 log.NONE, 105 } { 106 // Update log level 107 log.SetLevel(lvl) 108 109 // DEBUG level 110 testLog(func() { 111 log.Debug("test log") 112 }, lvl >= log.DEBUG) 113 testLog(func() { 114 log.Debugf("test log") 115 }, lvl >= log.DEBUG) 116 testLog(func() { 117 log.DebugFields(kv.Field{K: "test", V: "log"}) 118 }, lvl >= log.DEBUG) 119 120 // INFO level 121 testLog(func() { 122 log.Info("test log") 123 }, lvl >= log.INFO) 124 testLog(func() { 125 log.Infof("test log") 126 }, lvl >= log.INFO) 127 testLog(func() { 128 log.InfoFields(kv.Field{K: "test", V: "log"}) 129 }, lvl >= log.INFO) 130 131 // WARN level 132 testLog(func() { 133 log.Warn("test log") 134 }, lvl >= log.WARN) 135 testLog(func() { 136 log.Warnf("test log") 137 }, lvl >= log.WARN) 138 testLog(func() { 139 log.WarnFields(kv.Field{K: "test", V: "log"}) 140 }, lvl >= log.WARN) 141 142 // ERROR level 143 testLog(func() { 144 log.Error("test log") 145 }, lvl >= log.ERROR) 146 testLog(func() { 147 log.Errorf("test log") 148 }, lvl >= log.ERROR) 149 testLog(func() { 150 log.ErrorFields(kv.Field{K: "test", V: "log"}) 151 }, lvl >= log.ERROR) 152 153 // PANIC level 154 testLog(func() { 155 defer func() { _ = recover() }() 156 log.Panic("test log") 157 }, lvl >= log.PANIC) 158 testLog(func() { 159 defer func() { _ = recover() }() 160 log.Panicf("test log") 161 }, lvl >= log.PANIC) 162 testLog(func() { 163 defer func() { _ = recover() }() 164 log.PanicFields(kv.Field{K: "test", V: "log"}) 165 }, lvl >= log.PANIC) 166 } 167 } 168 169 func TestLoggerOutput(t *testing.T) { 170 // Special case of no log flags 171 log.Default().Logger().SetFlags(0) 172 173 // Output to buffer 174 buf := bytes.Buffer{} 175 log.SetOutput(&buf) 176 177 // Reset log level 178 log.SetLevel(log.ALL) 179 180 testLog := func(do func(), match func(string) bool) { 181 do() 182 if str := buf.String(); !match(strings.TrimSpace(str)) { 183 t.Errorf("unexpected log output: %s", str) 184 } 185 buf.Reset() 186 } 187 188 for _, arg := range testArgs { 189 expect := fmt.Sprint(arg...) 190 191 testLog(func() { 192 log.Debug(arg...) 193 }, func(out string) bool { 194 return strings.HasPrefix(out, "[DEBUG] ") && 195 (strings.TrimPrefix(out, "[DEBUG] ") == expect) 196 }) 197 198 testLog(func() { 199 log.Info(arg...) 200 }, func(out string) bool { 201 return strings.HasPrefix(out, "[INFO] ") && 202 (strings.TrimPrefix(out, "[INFO] ") == expect) 203 }) 204 205 testLog(func() { 206 log.Warn(arg...) 207 }, func(out string) bool { 208 return strings.HasPrefix(out, "[WARN] ") && 209 (strings.TrimPrefix(out, "[WARN] ") == expect) 210 }) 211 212 testLog(func() { 213 log.Error(arg...) 214 }, func(out string) bool { 215 return strings.HasPrefix(out, "[ERROR] ") && 216 (strings.TrimPrefix(out, "[ERROR] ") == expect) 217 }) 218 219 testLog(func() { 220 defer func() { 221 if recover() != expect { 222 t.Error("unexpected panic result") 223 } 224 }() 225 log.Panic(arg...) 226 }, func(out string) bool { 227 return strings.HasPrefix(out, "[PANIC] ") && 228 (strings.TrimPrefix(out, "[PANIC] ") == expect) 229 }) 230 } 231 232 for _, format := range testFmts { 233 expect := fmt.Sprintf(format.fmt, format.arg...) 234 235 testLog(func() { 236 log.Debugf(format.fmt, format.arg...) 237 }, func(out string) bool { 238 return strings.HasPrefix(out, "[DEBUG] ") && 239 (strings.TrimPrefix(out, "[DEBUG] ") == expect) 240 }) 241 242 testLog(func() { 243 log.Infof(format.fmt, format.arg...) 244 }, func(out string) bool { 245 return strings.HasPrefix(out, "[INFO] ") && 246 (strings.TrimPrefix(out, "[INFO] ") == expect) 247 }) 248 249 testLog(func() { 250 log.Warnf(format.fmt, format.arg...) 251 }, func(out string) bool { 252 return strings.HasPrefix(out, "[WARN] ") && 253 (strings.TrimPrefix(out, "[WARN] ") == expect) 254 }) 255 256 testLog(func() { 257 log.Errorf(format.fmt, format.arg...) 258 }, func(out string) bool { 259 return strings.HasPrefix(out, "[ERROR] ") && 260 (strings.TrimPrefix(out, "[ERROR] ") == expect) 261 }) 262 263 testLog(func() { 264 defer func() { 265 if recover() != expect { 266 t.Error("unexpected panic result") 267 } 268 }() 269 log.Panicf(format.fmt, format.arg...) 270 }, func(out string) bool { 271 return strings.HasPrefix(out, "[PANIC] ") && 272 (strings.TrimPrefix(out, "[PANIC] ") == expect) 273 }) 274 } 275 276 for _, fields := range testFields { 277 expect := fields.String() 278 279 testLog(func() { 280 log.DebugFields(fields...) 281 }, func(out string) bool { 282 return strings.HasPrefix(out, "[DEBUG] ") && 283 (strings.TrimPrefix(out, "[DEBUG] ") == expect) 284 }) 285 286 testLog(func() { 287 log.InfoFields(fields...) 288 }, func(out string) bool { 289 return strings.HasPrefix(out, "[INFO] ") && 290 (strings.TrimPrefix(out, "[INFO] ") == expect) 291 }) 292 293 testLog(func() { 294 log.WarnFields(fields...) 295 }, func(out string) bool { 296 return strings.HasPrefix(out, "[WARN] ") && 297 (strings.TrimPrefix(out, "[WARN] ") == expect) 298 }) 299 300 testLog(func() { 301 log.ErrorFields(fields...) 302 }, func(out string) bool { 303 return strings.HasPrefix(out, "[ERROR] ") && 304 (strings.TrimPrefix(out, "[ERROR] ") == expect) 305 }) 306 307 testLog(func() { 308 defer func() { 309 if recover() != expect { 310 t.Error("unexpected panic result") 311 } 312 }() 313 log.PanicFields(fields...) 314 }, func(out string) bool { 315 return strings.HasPrefix(out, "[PANIC] ") && 316 (strings.TrimPrefix(out, "[PANIC] ") == expect) 317 }) 318 } 319 }