logger_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
  2. // is governed by an MIT-style license that can be found in the LICENSE file.
  3. package logger
  4. import (
  5. "bytes"
  6. "fmt"
  7. "io"
  8. "log"
  9. "strings"
  10. "testing"
  11. "time"
  12. )
  13. func TestAPI(t *testing.T) {
  14. l := New()
  15. l.SetFlags(0)
  16. l.SetPrefix("testing")
  17. debug := 0
  18. l.AddHandler(LevelDebug, checkFunc(t, LevelDebug, &debug))
  19. info := 0
  20. l.AddHandler(LevelInfo, checkFunc(t, LevelInfo, &info))
  21. warn := 0
  22. l.AddHandler(LevelWarn, checkFunc(t, LevelWarn, &warn))
  23. l.Debugf("test %d", 0)
  24. l.Debugln("test", 0)
  25. l.Infof("test %d", 1)
  26. l.Infoln("test", 1)
  27. l.Warnf("test %d", 3)
  28. l.Warnln("test", 3)
  29. if debug != 6 {
  30. t.Errorf("Debug handler called %d != 8 times", debug)
  31. }
  32. if info != 4 {
  33. t.Errorf("Info handler called %d != 6 times", info)
  34. }
  35. if warn != 2 {
  36. t.Errorf("Warn handler called %d != 2 times", warn)
  37. }
  38. }
  39. func checkFunc(t *testing.T, expectl LogLevel, counter *int) func(LogLevel, string) {
  40. return func(l LogLevel, msg string) {
  41. *counter++
  42. if l < expectl {
  43. t.Errorf("Incorrect message level %d < %d", l, expectl)
  44. }
  45. }
  46. }
  47. func TestFacilityDebugging(t *testing.T) {
  48. l := New()
  49. l.SetFlags(0)
  50. msgs := 0
  51. l.AddHandler(LevelDebug, func(l LogLevel, msg string) {
  52. msgs++
  53. if strings.Contains(msg, "f1") {
  54. t.Fatal("Should not get message for facility f1")
  55. }
  56. })
  57. f0 := l.NewFacility("f0", "foo#0")
  58. f1 := l.NewFacility("f1", "foo#1")
  59. l.SetDebug("f0", true)
  60. l.SetDebug("f1", false)
  61. f0.Debugln("Debug line from f0")
  62. f1.Debugln("Debug line from f1")
  63. if msgs != 1 {
  64. t.Fatalf("Incorrect number of messages, %d != 1", msgs)
  65. }
  66. }
  67. func TestRecorder(t *testing.T) {
  68. l := New()
  69. l.SetFlags(0)
  70. // Keep the last five warnings or higher, no special initial handling.
  71. r0 := NewRecorder(l, LevelWarn, 5, 0)
  72. // Keep the last ten infos or higher, with the first three being permanent.
  73. r1 := NewRecorder(l, LevelInfo, 10, 3)
  74. // Log a bunch of messages.
  75. for i := 0; i < 15; i++ {
  76. l.Debugf("Debug#%d", i)
  77. l.Infof("Info#%d", i)
  78. l.Warnf("Warn#%d", i)
  79. }
  80. // r0 should contain the last five warnings
  81. lines := r0.Since(time.Time{})
  82. if len(lines) != 5 {
  83. t.Fatalf("Incorrect length %d != 5", len(lines))
  84. }
  85. for i := 0; i < 5; i++ {
  86. expected := fmt.Sprintf("Warn#%d", i+10)
  87. if lines[i].Message != expected {
  88. t.Error("Incorrect warning in r0:", lines[i].Message, "!=", expected)
  89. }
  90. }
  91. // r0 should contain:
  92. // - The first three messages
  93. // - A "..." marker
  94. // - The last six messages
  95. // (totalling ten)
  96. lines = r1.Since(time.Time{})
  97. if len(lines) != 10 {
  98. t.Fatalf("Incorrect length %d != 10", len(lines))
  99. }
  100. expected := []string{
  101. "Info#0",
  102. "Warn#0",
  103. "Info#1",
  104. "...",
  105. "Info#12",
  106. "Warn#12",
  107. "Info#13",
  108. "Warn#13",
  109. "Info#14",
  110. "Warn#14",
  111. }
  112. for i := 0; i < 10; i++ {
  113. if lines[i].Message != expected[i] {
  114. t.Error("Incorrect warning in r0:", lines[i].Message, "!=", expected[i])
  115. }
  116. }
  117. // Check that since works
  118. now := time.Now()
  119. time.Sleep(time.Millisecond)
  120. lines = r1.Since(now)
  121. if len(lines) != 0 {
  122. t.Error("unexpected lines")
  123. }
  124. l.Infoln("hah")
  125. lines = r1.Since(now)
  126. if len(lines) != 1 {
  127. t.Fatalf("unexpected line count: %d", len(lines))
  128. }
  129. if lines[0].Message != "hah" {
  130. t.Errorf("incorrect line: %s", lines[0].Message)
  131. }
  132. }
  133. func TestStackLevel(t *testing.T) {
  134. b := new(bytes.Buffer)
  135. l := newLogger(b)
  136. l.SetFlags(log.Lshortfile)
  137. l.Infoln("testing")
  138. res := b.String()
  139. if !strings.Contains(res, "logger_test.go:") {
  140. t.Logf("%q", res)
  141. t.Error("Should identify this file as the source (bad level?)")
  142. }
  143. }
  144. func TestControlStripper(t *testing.T) {
  145. b := new(bytes.Buffer)
  146. l := newLogger(controlStripper{b})
  147. l.Infoln("testing\x07testing\ntesting")
  148. res := b.String()
  149. if !strings.Contains(res, "testing testing\ntesting") {
  150. t.Logf("%q", res)
  151. t.Error("Control character should become space")
  152. }
  153. if strings.Contains(res, "\x07") {
  154. t.Logf("%q", res)
  155. t.Error("Control character should be removed")
  156. }
  157. }
  158. func BenchmarkLog(b *testing.B) {
  159. l := newLogger(controlStripper{io.Discard})
  160. benchmarkLogger(b, l)
  161. }
  162. func BenchmarkLogNoStripper(b *testing.B) {
  163. l := newLogger(io.Discard)
  164. benchmarkLogger(b, l)
  165. }
  166. func benchmarkLogger(b *testing.B, l Logger) {
  167. l.SetFlags(log.Lshortfile | log.Lmicroseconds)
  168. l.SetPrefix("ABCDEFG")
  169. for i := 0; i < b.N; i++ {
  170. l.Infoln("This is a somewhat representative log line")
  171. l.Infof("This is a log line with a couple of formatted things: %d %q", 42, "a file name maybe, who knows?")
  172. }
  173. b.ReportAllocs()
  174. b.SetBytes(2) // log entries per iteration
  175. }