logger_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. This Source Code Form is subject to the terms of the Mozilla Public
  3. License, v. 2.0. If a copy of the MPL was not distributed with this
  4. file, You can obtain one at https://mozilla.org/MPL/2.0/.
  5. */
  6. package logger
  7. import (
  8. "bytes"
  9. "fmt"
  10. "os"
  11. "os/exec"
  12. "runtime"
  13. "strings"
  14. "testing"
  15. )
  16. func bufLogger() (*Logger, *bytes.Buffer) {
  17. logger := NewLogger()
  18. logger.SetFlags(0)
  19. b := bytes.NewBufferString("")
  20. logger.SetOutput(b)
  21. return logger, b
  22. }
  23. func TestLogging(t *testing.T) {
  24. t.Run(
  25. "The default level is warn.",
  26. func(t *testing.T) {
  27. expected := LogLevelWarn
  28. logger := NewLogger()
  29. actual := logger.Level()
  30. if actual != expected {
  31. t.Errorf("Expected %v but got %v.", expected, actual)
  32. }
  33. },
  34. )
  35. t.Run(
  36. "Changes to logging level persist.",
  37. func(t *testing.T) {
  38. expected := LogLevelSilent
  39. logger := NewLogger()
  40. logger.SetLevel(LogLevelSilent)
  41. actual := logger.Level()
  42. if actual != expected {
  43. t.Errorf("Expected %v but got %v.", expected, actual)
  44. }
  45. },
  46. )
  47. t.Run(
  48. "A new logger uses the declared default flags.",
  49. func(t *testing.T) {
  50. expected := FlagsDefault
  51. logger := NewLogger()
  52. actual := logger.Flags()
  53. if actual != expected {
  54. t.Errorf("Expected %v but got %v.", expected, actual)
  55. }
  56. },
  57. )
  58. t.Run(
  59. "The default flags are nonzero.",
  60. func(t *testing.T) {
  61. if FlagsDefault == 0 {
  62. t.Errorf("Expected default flags to be nonzero.")
  63. }
  64. },
  65. )
  66. t.Run(
  67. "Changes to flags persist.",
  68. func(t *testing.T) {
  69. expected := 0
  70. logger := NewLogger()
  71. logger.SetFlags(0)
  72. actual := logger.Flags()
  73. if actual != expected {
  74. t.Errorf("Expected %v but got %v.", expected, actual)
  75. }
  76. },
  77. )
  78. t.Run(
  79. "A new logger logs a warning.",
  80. func(t *testing.T) {
  81. expected := "[Warn] a message\n"
  82. logger, buf := bufLogger()
  83. logger.Warn("%s", "a message")
  84. actual := buf.String()
  85. if actual != expected {
  86. t.Errorf("Expected %#v but got %#v.", expected, actual)
  87. }
  88. },
  89. )
  90. t.Run(
  91. "A new logger does not log an informational message.",
  92. func(t *testing.T) {
  93. expected := ""
  94. logger, buf := bufLogger()
  95. logger.Info("%s", "an informational message")
  96. actual := buf.String()
  97. if actual != expected {
  98. t.Errorf("Expected %#v but got %#v.", expected, actual)
  99. }
  100. },
  101. )
  102. t.Run(
  103. "Pushed contexts persist.",
  104. func(t *testing.T) {
  105. expected := "[Warn] some context: a message\n"
  106. logger, buf := bufLogger()
  107. logger = logger.Push("some context")
  108. logger.Warn("%s", "a message")
  109. actual := buf.String()
  110. if actual != expected {
  111. t.Errorf("Expected %#v but got %#v.", expected, actual)
  112. }
  113. },
  114. )
  115. t.Run(
  116. "Logging methods apply expected prefixes.",
  117. testLoggingMethodsApplyExpectedPrefixes,
  118. )
  119. }
  120. func testLoggingMethodsApplyExpectedPrefixes(t *testing.T) {
  121. logger, buf := bufLogger()
  122. logger.SetLevel(LogLevelDebug)
  123. for i, fun := range []func(string, ...any){
  124. nil,
  125. nil, // We have to test Fatal elsewhere
  126. logger.Error,
  127. logger.Warn,
  128. logger.Info,
  129. logger.Debug,
  130. } {
  131. if fun == nil {
  132. continue
  133. }
  134. prefix := logLevelPrefix[i]
  135. buf.Truncate(0)
  136. t.Run(
  137. "Log level has correct prefix.",
  138. func(t *testing.T) {
  139. buf := buf
  140. expected := "[" + prefix + "] \n"
  141. fun("")
  142. actual := buf.String()
  143. if actual != expected {
  144. t.Fatalf("Expected %#v but got %#v.", expected, actual)
  145. }
  146. },
  147. )
  148. }
  149. }
  150. /********************* Fatal tests ************************/
  151. func TestASilentLoggerDoesNotLogFatalMessages(t *testing.T) {
  152. expected := ""
  153. _, stderr, succ, err :=
  154. runFatal(aSilentLoggerDoesNotLogFatalMessages)
  155. if _, ok := err.(*exec.ExitError); ok && succ {
  156. t.Fatal("Expected exit but none observed.")
  157. }
  158. actual := string(stderr)
  159. if actual != expected {
  160. t.Fatalf("Expected %#v but got %#v.", expected, actual)
  161. }
  162. }
  163. func aSilentLoggerDoesNotLogFatalMessages() {
  164. logger := NewLogger()
  165. logger.SetFlags(0)
  166. logger.SetLevel(LogLevelSilent)
  167. logger.Fatal("fatal message")
  168. }
  169. func TestFatalAppliesCorrectPrefix(t *testing.T) {
  170. expected := "[FATAL] \n"
  171. _, stderr, succ, err :=
  172. runFatal(fatalAppliesCorrectPrefix)
  173. if _, ok := err.(*exec.ExitError); ok && succ {
  174. t.Fatal("Expected exit but none observed.")
  175. }
  176. actual := string(stderr)
  177. if actual != expected {
  178. t.Fatalf("Expected %#v but got %#v.", expected, actual)
  179. }
  180. }
  181. func fatalAppliesCorrectPrefix() {
  182. logger := NewLogger()
  183. logger.SetFlags(0)
  184. logger.Fatal("")
  185. }
  186. // fatal test helper
  187. func runFatal(
  188. fun func(),
  189. ) (stdout, stderr string, succ bool, err error) {
  190. // avoid infinite recursion
  191. if os.Getenv("CRASH") == "1" {
  192. fun()
  193. return
  194. }
  195. var caller string
  196. pc, _, _, ok := runtime.Caller(1)
  197. details := runtime.FuncForPC(pc)
  198. if ok && details != nil {
  199. caller = details.Name()
  200. tmp := strings.Split(details.Name(), ".")
  201. caller = tmp[len(tmp)-1]
  202. }
  203. if caller == "" {
  204. panic("Could not obtain caller")
  205. }
  206. cmd := exec.Command(
  207. os.Args[0],
  208. fmt.Sprintf("-test.run=%s", caller),
  209. )
  210. cmd.Env = append(os.Environ(), "CRASH=1")
  211. out, err := cmd.Output() // Output gives us stderr
  212. stdout = string(out)
  213. e, ok := err.(*exec.ExitError)
  214. if !ok {
  215. return
  216. }
  217. stderr = string(e.Stderr)
  218. succ = e.Success()
  219. return
  220. }