logger_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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
  141. if expected != "" {
  142. expected = "[" + expected + "]"
  143. }
  144. expected += " \n"
  145. fun("")
  146. actual := buf.String()
  147. if actual != expected {
  148. t.Fatalf("Expected %#v but got %#v.", expected, actual)
  149. }
  150. },
  151. )
  152. }
  153. }
  154. /********************* Fatal tests ************************/
  155. func TestASilentLoggerDoesNotLogFatalMessages(t *testing.T) {
  156. expected := ""
  157. _, stderr, succ, err :=
  158. runFatal(aSilentLoggerDoesNotLogFatalMessages)
  159. if _, ok := err.(*exec.ExitError); ok && succ {
  160. t.Fatal("Expected exit but none observed.")
  161. }
  162. actual := string(stderr)
  163. if actual != expected {
  164. t.Fatalf("Expected %#v but got %#v.", expected, actual)
  165. }
  166. }
  167. func aSilentLoggerDoesNotLogFatalMessages() {
  168. logger := NewLogger()
  169. logger.SetFlags(0)
  170. logger.SetLevel(LogLevelSilent)
  171. logger.Fatal("fatal message")
  172. }
  173. func TestFatalAppliesCorrectPrefix(t *testing.T) {
  174. expected := "[FATAL] \n"
  175. _, stderr, succ, err :=
  176. runFatal(fatalAppliesCorrectPrefix)
  177. if _, ok := err.(*exec.ExitError); ok && succ {
  178. t.Fatal("Expected exit but none observed.")
  179. }
  180. actual := string(stderr)
  181. if actual != expected {
  182. t.Fatalf("Expected %#v but got %#v.", expected, actual)
  183. }
  184. }
  185. func fatalAppliesCorrectPrefix() {
  186. logger := NewLogger()
  187. logger.SetFlags(0)
  188. logger.Fatal("")
  189. }
  190. // fatal test helper
  191. func runFatal(
  192. fun func(),
  193. ) (stdout, stderr string, succ bool, err error) {
  194. // avoid infinite recursion
  195. if os.Getenv("CRASH") == "1" {
  196. fun()
  197. return
  198. }
  199. var caller string
  200. pc, _, _, ok := runtime.Caller(1)
  201. details := runtime.FuncForPC(pc)
  202. if ok && details != nil {
  203. caller = details.Name()
  204. tmp := strings.Split(details.Name(), ".")
  205. caller = tmp[len(tmp)-1]
  206. }
  207. if caller == "" {
  208. panic("Could not obtain caller")
  209. }
  210. cmd := exec.Command(
  211. os.Args[0],
  212. fmt.Sprintf("-test.run=%s", caller),
  213. )
  214. cmd.Env = append(os.Environ(), "CRASH=1")
  215. out, err := cmd.Output() // Output gives us stderr
  216. stdout = string(out)
  217. e, ok := err.(*exec.ExitError)
  218. if !ok {
  219. return
  220. }
  221. stderr = string(e.Stderr)
  222. succ = e.Success()
  223. return
  224. }