1package logrus_test 2 3import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "runtime" 11 "sync" 12 "testing" 13 "time" 14 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 18 . "github.com/sirupsen/logrus" 19 . "github.com/sirupsen/logrus/internal/testutils" 20) 21 22// TestReportCaller verifies that when ReportCaller is set, the 'func' field 23// is added, and when it is unset it is not set or modified 24// Verify that functions within the Logrus package aren't considered when 25// discovering the caller. 26func TestReportCallerWhenConfigured(t *testing.T) { 27 LogAndAssertJSON(t, func(log *Logger) { 28 log.ReportCaller = false 29 log.Print("testNoCaller") 30 }, func(fields Fields) { 31 assert.Equal(t, "testNoCaller", fields["msg"]) 32 assert.Equal(t, "info", fields["level"]) 33 assert.Equal(t, nil, fields["func"]) 34 }) 35 36 LogAndAssertJSON(t, func(log *Logger) { 37 log.ReportCaller = true 38 log.Print("testWithCaller") 39 }, func(fields Fields) { 40 assert.Equal(t, "testWithCaller", fields["msg"]) 41 assert.Equal(t, "info", fields["level"]) 42 assert.Equal(t, 43 "github.com/sirupsen/logrus_test.TestReportCallerWhenConfigured.func3", fields[FieldKeyFunc]) 44 }) 45 46 LogAndAssertJSON(t, func(log *Logger) { 47 log.ReportCaller = true 48 log.Formatter.(*JSONFormatter).CallerPrettyfier = func(f *runtime.Frame) (string, string) { 49 return "somekindoffunc", "thisisafilename" 50 } 51 log.Print("testWithCallerPrettyfier") 52 }, func(fields Fields) { 53 assert.Equal(t, "somekindoffunc", fields[FieldKeyFunc]) 54 assert.Equal(t, "thisisafilename", fields[FieldKeyFile]) 55 }) 56 57 LogAndAssertText(t, func(log *Logger) { 58 log.ReportCaller = true 59 log.Formatter.(*TextFormatter).CallerPrettyfier = func(f *runtime.Frame) (string, string) { 60 return "somekindoffunc", "thisisafilename" 61 } 62 log.Print("testWithCallerPrettyfier") 63 }, func(fields map[string]string) { 64 assert.Equal(t, "somekindoffunc", fields[FieldKeyFunc]) 65 assert.Equal(t, "thisisafilename", fields[FieldKeyFile]) 66 }) 67} 68 69func logSomething(t *testing.T, message string) Fields { 70 var buffer bytes.Buffer 71 var fields Fields 72 73 logger := New() 74 logger.Out = &buffer 75 logger.Formatter = new(JSONFormatter) 76 logger.ReportCaller = true 77 78 entry := logger.WithFields(Fields{ 79 "foo": "bar", 80 }) 81 82 entry.Info(message) 83 84 err := json.Unmarshal(buffer.Bytes(), &fields) 85 assert.Nil(t, err) 86 87 return fields 88} 89 90// TestReportCallerHelperDirect - verify reference when logging from a regular function 91func TestReportCallerHelperDirect(t *testing.T) { 92 fields := logSomething(t, "direct") 93 94 assert.Equal(t, "direct", fields["msg"]) 95 assert.Equal(t, "info", fields["level"]) 96 assert.Regexp(t, "github.com/.*/logrus_test.logSomething", fields["func"]) 97} 98 99// TestReportCallerHelperDirect - verify reference when logging from a function called via pointer 100func TestReportCallerHelperViaPointer(t *testing.T) { 101 fptr := logSomething 102 fields := fptr(t, "via pointer") 103 104 assert.Equal(t, "via pointer", fields["msg"]) 105 assert.Equal(t, "info", fields["level"]) 106 assert.Regexp(t, "github.com/.*/logrus_test.logSomething", fields["func"]) 107} 108 109func TestPrint(t *testing.T) { 110 LogAndAssertJSON(t, func(log *Logger) { 111 log.Print("test") 112 }, func(fields Fields) { 113 assert.Equal(t, "test", fields["msg"]) 114 assert.Equal(t, "info", fields["level"]) 115 }) 116} 117 118func TestInfo(t *testing.T) { 119 LogAndAssertJSON(t, func(log *Logger) { 120 log.Info("test") 121 }, func(fields Fields) { 122 assert.Equal(t, "test", fields["msg"]) 123 assert.Equal(t, "info", fields["level"]) 124 }) 125} 126 127func TestWarn(t *testing.T) { 128 LogAndAssertJSON(t, func(log *Logger) { 129 log.Warn("test") 130 }, func(fields Fields) { 131 assert.Equal(t, "test", fields["msg"]) 132 assert.Equal(t, "warning", fields["level"]) 133 }) 134} 135 136func TestLog(t *testing.T) { 137 LogAndAssertJSON(t, func(log *Logger) { 138 log.Log(WarnLevel, "test") 139 }, func(fields Fields) { 140 assert.Equal(t, "test", fields["msg"]) 141 assert.Equal(t, "warning", fields["level"]) 142 }) 143} 144 145func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) { 146 LogAndAssertJSON(t, func(log *Logger) { 147 log.Infoln("test", "test") 148 }, func(fields Fields) { 149 assert.Equal(t, "test test", fields["msg"]) 150 }) 151} 152 153func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) { 154 LogAndAssertJSON(t, func(log *Logger) { 155 log.Infoln("test", 10) 156 }, func(fields Fields) { 157 assert.Equal(t, "test 10", fields["msg"]) 158 }) 159} 160 161func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) { 162 LogAndAssertJSON(t, func(log *Logger) { 163 log.Infoln(10, 10) 164 }, func(fields Fields) { 165 assert.Equal(t, "10 10", fields["msg"]) 166 }) 167} 168 169func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) { 170 LogAndAssertJSON(t, func(log *Logger) { 171 log.Infoln(10, 10) 172 }, func(fields Fields) { 173 assert.Equal(t, "10 10", fields["msg"]) 174 }) 175} 176 177func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) { 178 LogAndAssertJSON(t, func(log *Logger) { 179 log.Info("test", 10) 180 }, func(fields Fields) { 181 assert.Equal(t, "test10", fields["msg"]) 182 }) 183} 184 185func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) { 186 LogAndAssertJSON(t, func(log *Logger) { 187 log.Info("test", "test") 188 }, func(fields Fields) { 189 assert.Equal(t, "testtest", fields["msg"]) 190 }) 191} 192 193func TestWithFieldsShouldAllowAssignments(t *testing.T) { 194 var buffer bytes.Buffer 195 var fields Fields 196 197 logger := New() 198 logger.Out = &buffer 199 logger.Formatter = new(JSONFormatter) 200 201 localLog := logger.WithFields(Fields{ 202 "key1": "value1", 203 }) 204 205 localLog.WithField("key2", "value2").Info("test") 206 err := json.Unmarshal(buffer.Bytes(), &fields) 207 assert.Nil(t, err) 208 209 assert.Equal(t, "value2", fields["key2"]) 210 assert.Equal(t, "value1", fields["key1"]) 211 212 buffer = bytes.Buffer{} 213 fields = Fields{} 214 localLog.Info("test") 215 err = json.Unmarshal(buffer.Bytes(), &fields) 216 assert.Nil(t, err) 217 218 _, ok := fields["key2"] 219 assert.Equal(t, false, ok) 220 assert.Equal(t, "value1", fields["key1"]) 221} 222 223func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) { 224 LogAndAssertJSON(t, func(log *Logger) { 225 log.WithField("msg", "hello").Info("test") 226 }, func(fields Fields) { 227 assert.Equal(t, "test", fields["msg"]) 228 }) 229} 230 231func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) { 232 LogAndAssertJSON(t, func(log *Logger) { 233 log.WithField("msg", "hello").Info("test") 234 }, func(fields Fields) { 235 assert.Equal(t, "test", fields["msg"]) 236 assert.Equal(t, "hello", fields["fields.msg"]) 237 }) 238} 239 240func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) { 241 LogAndAssertJSON(t, func(log *Logger) { 242 log.WithField("time", "hello").Info("test") 243 }, func(fields Fields) { 244 assert.Equal(t, "hello", fields["fields.time"]) 245 }) 246} 247 248func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) { 249 LogAndAssertJSON(t, func(log *Logger) { 250 log.WithField("level", 1).Info("test") 251 }, func(fields Fields) { 252 assert.Equal(t, "info", fields["level"]) 253 assert.Equal(t, 1.0, fields["fields.level"]) // JSON has floats only 254 }) 255} 256 257func TestDefaultFieldsAreNotPrefixed(t *testing.T) { 258 LogAndAssertText(t, func(log *Logger) { 259 ll := log.WithField("herp", "derp") 260 ll.Info("hello") 261 ll.Info("bye") 262 }, func(fields map[string]string) { 263 for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} { 264 if _, ok := fields[fieldName]; ok { 265 t.Fatalf("should not have prefixed %q: %v", fieldName, fields) 266 } 267 } 268 }) 269} 270 271func TestWithTimeShouldOverrideTime(t *testing.T) { 272 now := time.Now().Add(24 * time.Hour) 273 274 LogAndAssertJSON(t, func(log *Logger) { 275 log.WithTime(now).Info("foobar") 276 }, func(fields Fields) { 277 assert.Equal(t, fields["time"], now.Format(time.RFC3339)) 278 }) 279} 280 281func TestWithTimeShouldNotOverrideFields(t *testing.T) { 282 now := time.Now().Add(24 * time.Hour) 283 284 LogAndAssertJSON(t, func(log *Logger) { 285 log.WithField("herp", "derp").WithTime(now).Info("blah") 286 }, func(fields Fields) { 287 assert.Equal(t, fields["time"], now.Format(time.RFC3339)) 288 assert.Equal(t, fields["herp"], "derp") 289 }) 290} 291 292func TestWithFieldShouldNotOverrideTime(t *testing.T) { 293 now := time.Now().Add(24 * time.Hour) 294 295 LogAndAssertJSON(t, func(log *Logger) { 296 log.WithTime(now).WithField("herp", "derp").Info("blah") 297 }, func(fields Fields) { 298 assert.Equal(t, fields["time"], now.Format(time.RFC3339)) 299 assert.Equal(t, fields["herp"], "derp") 300 }) 301} 302 303func TestTimeOverrideMultipleLogs(t *testing.T) { 304 var buffer bytes.Buffer 305 var firstFields, secondFields Fields 306 307 logger := New() 308 logger.Out = &buffer 309 formatter := new(JSONFormatter) 310 formatter.TimestampFormat = time.StampMilli 311 logger.Formatter = formatter 312 313 llog := logger.WithField("herp", "derp") 314 llog.Info("foo") 315 316 err := json.Unmarshal(buffer.Bytes(), &firstFields) 317 assert.NoError(t, err, "should have decoded first message") 318 319 buffer.Reset() 320 321 time.Sleep(10 * time.Millisecond) 322 llog.Info("bar") 323 324 err = json.Unmarshal(buffer.Bytes(), &secondFields) 325 assert.NoError(t, err, "should have decoded second message") 326 327 assert.NotEqual(t, firstFields["time"], secondFields["time"], "timestamps should not be equal") 328} 329 330func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) { 331 332 var buffer bytes.Buffer 333 var fields Fields 334 335 logger := New() 336 logger.Out = &buffer 337 logger.Formatter = new(JSONFormatter) 338 339 llog := logger.WithField("context", "eating raw fish") 340 341 llog.Info("looks delicious") 342 343 err := json.Unmarshal(buffer.Bytes(), &fields) 344 assert.NoError(t, err, "should have decoded first message") 345 assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields") 346 assert.Equal(t, fields["msg"], "looks delicious") 347 assert.Equal(t, fields["context"], "eating raw fish") 348 349 buffer.Reset() 350 351 llog.Warn("omg it is!") 352 353 err = json.Unmarshal(buffer.Bytes(), &fields) 354 assert.NoError(t, err, "should have decoded second message") 355 assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields") 356 assert.Equal(t, "omg it is!", fields["msg"]) 357 assert.Equal(t, "eating raw fish", fields["context"]) 358 assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry") 359 360} 361 362func TestNestedLoggingReportsCorrectCaller(t *testing.T) { 363 var buffer bytes.Buffer 364 var fields Fields 365 366 logger := New() 367 logger.Out = &buffer 368 logger.Formatter = new(JSONFormatter) 369 logger.ReportCaller = true 370 371 llog := logger.WithField("context", "eating raw fish") 372 373 llog.Info("looks delicious") 374 _, _, line, _ := runtime.Caller(0) 375 376 err := json.Unmarshal(buffer.Bytes(), &fields) 377 require.NoError(t, err, "should have decoded first message") 378 assert.Equal(t, 6, len(fields), "should have msg/time/level/func/context fields") 379 assert.Equal(t, "looks delicious", fields["msg"]) 380 assert.Equal(t, "eating raw fish", fields["context"]) 381 assert.Equal(t, 382 "github.com/sirupsen/logrus_test.TestNestedLoggingReportsCorrectCaller", fields["func"]) 383 cwd, err := os.Getwd() 384 require.NoError(t, err) 385 assert.Equal(t, filepath.ToSlash(fmt.Sprintf("%s/logrus_test.go:%d", cwd, line-1)), filepath.ToSlash(fields["file"].(string))) 386 387 buffer.Reset() 388 389 logger.WithFields(Fields{ 390 "Clyde": "Stubblefield", 391 }).WithFields(Fields{ 392 "Jab'o": "Starks", 393 }).WithFields(Fields{ 394 "uri": "https://www.youtube.com/watch?v=V5DTznu-9v0", 395 }).WithFields(Fields{ 396 "func": "y drummer", 397 }).WithFields(Fields{ 398 "James": "Brown", 399 }).Print("The hardest workin' man in show business") 400 _, _, line, _ = runtime.Caller(0) 401 402 err = json.Unmarshal(buffer.Bytes(), &fields) 403 assert.NoError(t, err, "should have decoded second message") 404 assert.Equal(t, 11, len(fields), "should have all builtin fields plus foo,bar,baz,...") 405 assert.Equal(t, "Stubblefield", fields["Clyde"]) 406 assert.Equal(t, "Starks", fields["Jab'o"]) 407 assert.Equal(t, "https://www.youtube.com/watch?v=V5DTznu-9v0", fields["uri"]) 408 assert.Equal(t, "y drummer", fields["fields.func"]) 409 assert.Equal(t, "Brown", fields["James"]) 410 assert.Equal(t, "The hardest workin' man in show business", fields["msg"]) 411 assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry") 412 assert.Equal(t, 413 "github.com/sirupsen/logrus_test.TestNestedLoggingReportsCorrectCaller", fields["func"]) 414 require.NoError(t, err) 415 assert.Equal(t, filepath.ToSlash(fmt.Sprintf("%s/logrus_test.go:%d", cwd, line-1)), filepath.ToSlash(fields["file"].(string))) 416 417 logger.ReportCaller = false // return to default value 418} 419 420func logLoop(iterations int, reportCaller bool) { 421 var buffer bytes.Buffer 422 423 logger := New() 424 logger.Out = &buffer 425 logger.Formatter = new(JSONFormatter) 426 logger.ReportCaller = reportCaller 427 428 for i := 0; i < iterations; i++ { 429 logger.Infof("round %d of %d", i, iterations) 430 } 431} 432 433// Assertions for upper bounds to reporting overhead 434func TestCallerReportingOverhead(t *testing.T) { 435 iterations := 5000 436 before := time.Now() 437 logLoop(iterations, false) 438 during := time.Now() 439 logLoop(iterations, true) 440 after := time.Now() 441 442 elapsedNotReporting := during.Sub(before).Nanoseconds() 443 elapsedReporting := after.Sub(during).Nanoseconds() 444 445 maxDelta := 1 * time.Second 446 assert.WithinDuration(t, during, before, maxDelta, 447 "%d log calls without caller name lookup takes less than %d second(s) (was %d nanoseconds)", 448 iterations, maxDelta.Seconds(), elapsedNotReporting) 449 assert.WithinDuration(t, after, during, maxDelta, 450 "%d log calls without caller name lookup takes less than %d second(s) (was %d nanoseconds)", 451 iterations, maxDelta.Seconds(), elapsedReporting) 452} 453 454// benchmarks for both with and without caller-function reporting 455func BenchmarkWithoutCallerTracing(b *testing.B) { 456 for i := 0; i < b.N; i++ { 457 logLoop(1000, false) 458 } 459} 460 461func BenchmarkWithCallerTracing(b *testing.B) { 462 for i := 0; i < b.N; i++ { 463 logLoop(1000, true) 464 } 465} 466 467func TestConvertLevelToString(t *testing.T) { 468 assert.Equal(t, "trace", TraceLevel.String()) 469 assert.Equal(t, "debug", DebugLevel.String()) 470 assert.Equal(t, "info", InfoLevel.String()) 471 assert.Equal(t, "warning", WarnLevel.String()) 472 assert.Equal(t, "error", ErrorLevel.String()) 473 assert.Equal(t, "fatal", FatalLevel.String()) 474 assert.Equal(t, "panic", PanicLevel.String()) 475} 476 477func TestParseLevel(t *testing.T) { 478 l, err := ParseLevel("panic") 479 assert.Nil(t, err) 480 assert.Equal(t, PanicLevel, l) 481 482 l, err = ParseLevel("PANIC") 483 assert.Nil(t, err) 484 assert.Equal(t, PanicLevel, l) 485 486 l, err = ParseLevel("fatal") 487 assert.Nil(t, err) 488 assert.Equal(t, FatalLevel, l) 489 490 l, err = ParseLevel("FATAL") 491 assert.Nil(t, err) 492 assert.Equal(t, FatalLevel, l) 493 494 l, err = ParseLevel("error") 495 assert.Nil(t, err) 496 assert.Equal(t, ErrorLevel, l) 497 498 l, err = ParseLevel("ERROR") 499 assert.Nil(t, err) 500 assert.Equal(t, ErrorLevel, l) 501 502 l, err = ParseLevel("warn") 503 assert.Nil(t, err) 504 assert.Equal(t, WarnLevel, l) 505 506 l, err = ParseLevel("WARN") 507 assert.Nil(t, err) 508 assert.Equal(t, WarnLevel, l) 509 510 l, err = ParseLevel("warning") 511 assert.Nil(t, err) 512 assert.Equal(t, WarnLevel, l) 513 514 l, err = ParseLevel("WARNING") 515 assert.Nil(t, err) 516 assert.Equal(t, WarnLevel, l) 517 518 l, err = ParseLevel("info") 519 assert.Nil(t, err) 520 assert.Equal(t, InfoLevel, l) 521 522 l, err = ParseLevel("INFO") 523 assert.Nil(t, err) 524 assert.Equal(t, InfoLevel, l) 525 526 l, err = ParseLevel("debug") 527 assert.Nil(t, err) 528 assert.Equal(t, DebugLevel, l) 529 530 l, err = ParseLevel("DEBUG") 531 assert.Nil(t, err) 532 assert.Equal(t, DebugLevel, l) 533 534 l, err = ParseLevel("trace") 535 assert.Nil(t, err) 536 assert.Equal(t, TraceLevel, l) 537 538 l, err = ParseLevel("TRACE") 539 assert.Nil(t, err) 540 assert.Equal(t, TraceLevel, l) 541 542 _, err = ParseLevel("invalid") 543 assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error()) 544} 545 546func TestLevelString(t *testing.T) { 547 var loggerlevel Level 548 loggerlevel = 32000 549 550 _ = loggerlevel.String() 551} 552 553func TestGetSetLevelRace(t *testing.T) { 554 wg := sync.WaitGroup{} 555 for i := 0; i < 100; i++ { 556 wg.Add(1) 557 go func(i int) { 558 defer wg.Done() 559 if i%2 == 0 { 560 SetLevel(InfoLevel) 561 } else { 562 GetLevel() 563 } 564 }(i) 565 566 } 567 wg.Wait() 568} 569 570func TestLoggingRace(t *testing.T) { 571 logger := New() 572 573 var wg sync.WaitGroup 574 wg.Add(100) 575 576 for i := 0; i < 100; i++ { 577 go func() { 578 logger.Info("info") 579 wg.Done() 580 }() 581 } 582 wg.Wait() 583} 584 585func TestLoggingRaceWithHooksOnEntry(t *testing.T) { 586 logger := New() 587 hook := new(ModifyHook) 588 logger.AddHook(hook) 589 entry := logger.WithField("context", "clue") 590 591 var ( 592 wg sync.WaitGroup 593 mtx sync.Mutex 594 start bool 595 ) 596 597 cond := sync.NewCond(&mtx) 598 599 wg.Add(100) 600 601 for i := 0; i < 50; i++ { 602 go func() { 603 cond.L.Lock() 604 for !start { 605 cond.Wait() 606 } 607 cond.L.Unlock() 608 for j := 0; j < 100; j++ { 609 entry.Info("info") 610 } 611 wg.Done() 612 }() 613 } 614 615 for i := 0; i < 50; i++ { 616 go func() { 617 cond.L.Lock() 618 for !start { 619 cond.Wait() 620 } 621 cond.L.Unlock() 622 for j := 0; j < 100; j++ { 623 entry.WithField("another field", "with some data").Info("info") 624 } 625 wg.Done() 626 }() 627 } 628 629 cond.L.Lock() 630 start = true 631 cond.L.Unlock() 632 cond.Broadcast() 633 wg.Wait() 634} 635 636func TestReplaceHooks(t *testing.T) { 637 old, cur := &TestHook{}, &TestHook{} 638 639 logger := New() 640 logger.SetOutput(ioutil.Discard) 641 logger.AddHook(old) 642 643 hooks := make(LevelHooks) 644 hooks.Add(cur) 645 replaced := logger.ReplaceHooks(hooks) 646 647 logger.Info("test") 648 649 assert.Equal(t, old.Fired, false) 650 assert.Equal(t, cur.Fired, true) 651 652 logger.ReplaceHooks(replaced) 653 logger.Info("test") 654 assert.Equal(t, old.Fired, true) 655} 656 657// Compile test 658func TestLogrusInterfaces(t *testing.T) { 659 var buffer bytes.Buffer 660 // This verifies FieldLogger and Ext1FieldLogger work as designed. 661 // Please don't use them. Use Logger and Entry directly. 662 fn := func(xl Ext1FieldLogger) { 663 var l FieldLogger = xl 664 b := l.WithField("key", "value") 665 b.Debug("Test") 666 } 667 // test logger 668 logger := New() 669 logger.Out = &buffer 670 fn(logger) 671 672 // test Entry 673 e := logger.WithField("another", "value") 674 fn(e) 675} 676 677// Implements io.Writer using channels for synchronization, so we can wait on 678// the Entry.Writer goroutine to write in a non-racey way. This does assume that 679// there is a single call to Logger.Out for each message. 680type channelWriter chan []byte 681 682func (cw channelWriter) Write(p []byte) (int, error) { 683 cw <- p 684 return len(p), nil 685} 686 687func TestEntryWriter(t *testing.T) { 688 cw := channelWriter(make(chan []byte, 1)) 689 log := New() 690 log.Out = cw 691 log.Formatter = new(JSONFormatter) 692 _, err := log.WithField("foo", "bar").WriterLevel(WarnLevel).Write([]byte("hello\n")) 693 if err != nil { 694 t.Error("unexecpted error", err) 695 } 696 697 bs := <-cw 698 var fields Fields 699 err = json.Unmarshal(bs, &fields) 700 assert.Nil(t, err) 701 assert.Equal(t, fields["foo"], "bar") 702 assert.Equal(t, fields["level"], "warning") 703} 704 705func TestLogLevelEnabled(t *testing.T) { 706 log := New() 707 log.SetLevel(PanicLevel) 708 assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) 709 assert.Equal(t, false, log.IsLevelEnabled(FatalLevel)) 710 assert.Equal(t, false, log.IsLevelEnabled(ErrorLevel)) 711 assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) 712 assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) 713 assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) 714 assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) 715 716 log.SetLevel(FatalLevel) 717 assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) 718 assert.Equal(t, true, log.IsLevelEnabled(FatalLevel)) 719 assert.Equal(t, false, log.IsLevelEnabled(ErrorLevel)) 720 assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) 721 assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) 722 assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) 723 assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) 724 725 log.SetLevel(ErrorLevel) 726 assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) 727 assert.Equal(t, true, log.IsLevelEnabled(FatalLevel)) 728 assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel)) 729 assert.Equal(t, false, log.IsLevelEnabled(WarnLevel)) 730 assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) 731 assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) 732 assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) 733 734 log.SetLevel(WarnLevel) 735 assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) 736 assert.Equal(t, true, log.IsLevelEnabled(FatalLevel)) 737 assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel)) 738 assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) 739 assert.Equal(t, false, log.IsLevelEnabled(InfoLevel)) 740 assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) 741 assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) 742 743 log.SetLevel(InfoLevel) 744 assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) 745 assert.Equal(t, true, log.IsLevelEnabled(FatalLevel)) 746 assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel)) 747 assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) 748 assert.Equal(t, true, log.IsLevelEnabled(InfoLevel)) 749 assert.Equal(t, false, log.IsLevelEnabled(DebugLevel)) 750 assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) 751 752 log.SetLevel(DebugLevel) 753 assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) 754 assert.Equal(t, true, log.IsLevelEnabled(FatalLevel)) 755 assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel)) 756 assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) 757 assert.Equal(t, true, log.IsLevelEnabled(InfoLevel)) 758 assert.Equal(t, true, log.IsLevelEnabled(DebugLevel)) 759 assert.Equal(t, false, log.IsLevelEnabled(TraceLevel)) 760 761 log.SetLevel(TraceLevel) 762 assert.Equal(t, true, log.IsLevelEnabled(PanicLevel)) 763 assert.Equal(t, true, log.IsLevelEnabled(FatalLevel)) 764 assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel)) 765 assert.Equal(t, true, log.IsLevelEnabled(WarnLevel)) 766 assert.Equal(t, true, log.IsLevelEnabled(InfoLevel)) 767 assert.Equal(t, true, log.IsLevelEnabled(DebugLevel)) 768 assert.Equal(t, true, log.IsLevelEnabled(TraceLevel)) 769} 770 771func TestReportCallerOnTextFormatter(t *testing.T) { 772 l := New() 773 774 l.Formatter.(*TextFormatter).ForceColors = true 775 l.Formatter.(*TextFormatter).DisableColors = false 776 l.WithFields(Fields{"func": "func", "file": "file"}).Info("test") 777 778 l.Formatter.(*TextFormatter).ForceColors = false 779 l.Formatter.(*TextFormatter).DisableColors = true 780 l.WithFields(Fields{"func": "func", "file": "file"}).Info("test") 781} 782 783func TestSetReportCallerRace(t *testing.T) { 784 l := New() 785 l.Out = ioutil.Discard 786 l.SetReportCaller(true) 787 788 var wg sync.WaitGroup 789 wg.Add(100) 790 791 for i := 0; i < 100; i++ { 792 go func() { 793 l.Error("Some Error") 794 wg.Done() 795 }() 796 } 797 wg.Wait() 798} 799