logger_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
  2. // Use of this source code is governed by a MIT style
  3. // license that can be found in the LICENSE file.
  4. package gin
  5. import (
  6. "bytes"
  7. "errors"
  8. "fmt"
  9. "net/http"
  10. "testing"
  11. "time"
  12. "github.com/stretchr/testify/assert"
  13. )
  14. func init() {
  15. SetMode(TestMode)
  16. }
  17. func TestLogger(t *testing.T) {
  18. buffer := new(bytes.Buffer)
  19. router := New()
  20. router.Use(LoggerWithWriter(buffer))
  21. router.GET("/example", func(c *Context) {})
  22. router.POST("/example", func(c *Context) {})
  23. router.PUT("/example", func(c *Context) {})
  24. router.DELETE("/example", func(c *Context) {})
  25. router.PATCH("/example", func(c *Context) {})
  26. router.HEAD("/example", func(c *Context) {})
  27. router.OPTIONS("/example", func(c *Context) {})
  28. performRequest(router, "GET", "/example?a=100")
  29. assert.Contains(t, buffer.String(), "200")
  30. assert.Contains(t, buffer.String(), "GET")
  31. assert.Contains(t, buffer.String(), "/example")
  32. assert.Contains(t, buffer.String(), "a=100")
  33. // I wrote these first (extending the above) but then realized they are more
  34. // like integration tests because they test the whole logging process rather
  35. // than individual functions. Im not sure where these should go.
  36. buffer.Reset()
  37. performRequest(router, "POST", "/example")
  38. assert.Contains(t, buffer.String(), "200")
  39. assert.Contains(t, buffer.String(), "POST")
  40. assert.Contains(t, buffer.String(), "/example")
  41. buffer.Reset()
  42. performRequest(router, "PUT", "/example")
  43. assert.Contains(t, buffer.String(), "200")
  44. assert.Contains(t, buffer.String(), "PUT")
  45. assert.Contains(t, buffer.String(), "/example")
  46. buffer.Reset()
  47. performRequest(router, "DELETE", "/example")
  48. assert.Contains(t, buffer.String(), "200")
  49. assert.Contains(t, buffer.String(), "DELETE")
  50. assert.Contains(t, buffer.String(), "/example")
  51. buffer.Reset()
  52. performRequest(router, "PATCH", "/example")
  53. assert.Contains(t, buffer.String(), "200")
  54. assert.Contains(t, buffer.String(), "PATCH")
  55. assert.Contains(t, buffer.String(), "/example")
  56. buffer.Reset()
  57. performRequest(router, "HEAD", "/example")
  58. assert.Contains(t, buffer.String(), "200")
  59. assert.Contains(t, buffer.String(), "HEAD")
  60. assert.Contains(t, buffer.String(), "/example")
  61. buffer.Reset()
  62. performRequest(router, "OPTIONS", "/example")
  63. assert.Contains(t, buffer.String(), "200")
  64. assert.Contains(t, buffer.String(), "OPTIONS")
  65. assert.Contains(t, buffer.String(), "/example")
  66. buffer.Reset()
  67. performRequest(router, "GET", "/notfound")
  68. assert.Contains(t, buffer.String(), "404")
  69. assert.Contains(t, buffer.String(), "GET")
  70. assert.Contains(t, buffer.String(), "/notfound")
  71. }
  72. func TestLoggerWithConfig(t *testing.T) {
  73. buffer := new(bytes.Buffer)
  74. router := New()
  75. router.Use(LoggerWithConfig(LoggerConfig{Output: buffer}))
  76. router.GET("/example", func(c *Context) {})
  77. router.POST("/example", func(c *Context) {})
  78. router.PUT("/example", func(c *Context) {})
  79. router.DELETE("/example", func(c *Context) {})
  80. router.PATCH("/example", func(c *Context) {})
  81. router.HEAD("/example", func(c *Context) {})
  82. router.OPTIONS("/example", func(c *Context) {})
  83. performRequest(router, "GET", "/example?a=100")
  84. assert.Contains(t, buffer.String(), "200")
  85. assert.Contains(t, buffer.String(), "GET")
  86. assert.Contains(t, buffer.String(), "/example")
  87. assert.Contains(t, buffer.String(), "a=100")
  88. // I wrote these first (extending the above) but then realized they are more
  89. // like integration tests because they test the whole logging process rather
  90. // than individual functions. Im not sure where these should go.
  91. buffer.Reset()
  92. performRequest(router, "POST", "/example")
  93. assert.Contains(t, buffer.String(), "200")
  94. assert.Contains(t, buffer.String(), "POST")
  95. assert.Contains(t, buffer.String(), "/example")
  96. buffer.Reset()
  97. performRequest(router, "PUT", "/example")
  98. assert.Contains(t, buffer.String(), "200")
  99. assert.Contains(t, buffer.String(), "PUT")
  100. assert.Contains(t, buffer.String(), "/example")
  101. buffer.Reset()
  102. performRequest(router, "DELETE", "/example")
  103. assert.Contains(t, buffer.String(), "200")
  104. assert.Contains(t, buffer.String(), "DELETE")
  105. assert.Contains(t, buffer.String(), "/example")
  106. buffer.Reset()
  107. performRequest(router, "PATCH", "/example")
  108. assert.Contains(t, buffer.String(), "200")
  109. assert.Contains(t, buffer.String(), "PATCH")
  110. assert.Contains(t, buffer.String(), "/example")
  111. buffer.Reset()
  112. performRequest(router, "HEAD", "/example")
  113. assert.Contains(t, buffer.String(), "200")
  114. assert.Contains(t, buffer.String(), "HEAD")
  115. assert.Contains(t, buffer.String(), "/example")
  116. buffer.Reset()
  117. performRequest(router, "OPTIONS", "/example")
  118. assert.Contains(t, buffer.String(), "200")
  119. assert.Contains(t, buffer.String(), "OPTIONS")
  120. assert.Contains(t, buffer.String(), "/example")
  121. buffer.Reset()
  122. performRequest(router, "GET", "/notfound")
  123. assert.Contains(t, buffer.String(), "404")
  124. assert.Contains(t, buffer.String(), "GET")
  125. assert.Contains(t, buffer.String(), "/notfound")
  126. }
  127. func TestLoggerWithFormatter(t *testing.T) {
  128. buffer := new(bytes.Buffer)
  129. d := DefaultWriter
  130. DefaultWriter = buffer
  131. defer func() {
  132. DefaultWriter = d
  133. }()
  134. router := New()
  135. router.Use(LoggerWithFormatter(func(param LogFormatterParams) string {
  136. return fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s",
  137. param.TimeStamp.Format("2006/01/02 - 15:04:05"),
  138. param.StatusCode,
  139. param.Latency,
  140. param.ClientIP,
  141. param.Method,
  142. param.Path,
  143. param.ErrorMessage,
  144. )
  145. }))
  146. router.GET("/example", func(c *Context) {})
  147. performRequest(router, "GET", "/example?a=100")
  148. // output test
  149. assert.Contains(t, buffer.String(), "[FORMATTER TEST]")
  150. assert.Contains(t, buffer.String(), "200")
  151. assert.Contains(t, buffer.String(), "GET")
  152. assert.Contains(t, buffer.String(), "/example")
  153. assert.Contains(t, buffer.String(), "a=100")
  154. }
  155. func TestLoggerWithConfigFormatting(t *testing.T) {
  156. var gotParam LogFormatterParams
  157. buffer := new(bytes.Buffer)
  158. router := New()
  159. router.Use(LoggerWithConfig(LoggerConfig{
  160. Output: buffer,
  161. Formatter: func(param LogFormatterParams) string {
  162. // for assert test
  163. gotParam = param
  164. return fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s",
  165. param.TimeStamp.Format("2006/01/02 - 15:04:05"),
  166. param.StatusCode,
  167. param.Latency,
  168. param.ClientIP,
  169. param.Method,
  170. param.Path,
  171. param.ErrorMessage,
  172. )
  173. },
  174. }))
  175. router.GET("/example", func(c *Context) {
  176. // set dummy ClientIP
  177. c.Request.Header.Set("X-Forwarded-For", "20.20.20.20")
  178. })
  179. performRequest(router, "GET", "/example?a=100")
  180. // output test
  181. assert.Contains(t, buffer.String(), "[FORMATTER TEST]")
  182. assert.Contains(t, buffer.String(), "200")
  183. assert.Contains(t, buffer.String(), "GET")
  184. assert.Contains(t, buffer.String(), "/example")
  185. assert.Contains(t, buffer.String(), "a=100")
  186. // LogFormatterParams test
  187. assert.NotNil(t, gotParam.Request)
  188. assert.NotEmpty(t, gotParam.TimeStamp)
  189. assert.Equal(t, 200, gotParam.StatusCode)
  190. assert.NotEmpty(t, gotParam.Latency)
  191. assert.Equal(t, "20.20.20.20", gotParam.ClientIP)
  192. assert.Equal(t, "GET", gotParam.Method)
  193. assert.Equal(t, "/example?a=100", gotParam.Path)
  194. assert.Empty(t, gotParam.ErrorMessage)
  195. }
  196. func TestDefaultLogFormatter(t *testing.T) {
  197. timeStamp := time.Unix(1544173902, 0).UTC()
  198. termFalseParam := LogFormatterParams{
  199. TimeStamp: timeStamp,
  200. StatusCode: 200,
  201. Latency: time.Second * 5,
  202. ClientIP: "20.20.20.20",
  203. Method: "GET",
  204. Path: "/",
  205. ErrorMessage: "",
  206. IsTerm: false,
  207. }
  208. termTrueParam := LogFormatterParams{
  209. TimeStamp: timeStamp,
  210. StatusCode: 200,
  211. Latency: time.Second * 5,
  212. ClientIP: "20.20.20.20",
  213. Method: "GET",
  214. Path: "/",
  215. ErrorMessage: "",
  216. IsTerm: true,
  217. }
  218. assert.Equal(t, "[GIN] 2018/12/07 - 09:11:42 | 200 | 5s | 20.20.20.20 | GET /\n", defaultLogFormatter(termFalseParam))
  219. assert.Equal(t, "[GIN] 2018/12/07 - 09:11:42 |\x1b[97;42m 200 \x1b[0m| 5s | 20.20.20.20 |\x1b[97;44m GET \x1b[0m /\n", defaultLogFormatter(termTrueParam))
  220. }
  221. func TestColorForMethod(t *testing.T) {
  222. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 52, 109}), colorForMethod("GET"), "get should be blue")
  223. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 54, 109}), colorForMethod("POST"), "post should be cyan")
  224. assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 51, 109}), colorForMethod("PUT"), "put should be yellow")
  225. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 49, 109}), colorForMethod("DELETE"), "delete should be red")
  226. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 50, 109}), colorForMethod("PATCH"), "patch should be green")
  227. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 53, 109}), colorForMethod("HEAD"), "head should be magenta")
  228. assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 55, 109}), colorForMethod("OPTIONS"), "options should be white")
  229. assert.Equal(t, string([]byte{27, 91, 48, 109}), colorForMethod("TRACE"), "trace is not defined and should be the reset color")
  230. }
  231. func TestColorForStatus(t *testing.T) {
  232. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 50, 109}), colorForStatus(http.StatusOK), "2xx should be green")
  233. assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 55, 109}), colorForStatus(http.StatusMovedPermanently), "3xx should be white")
  234. assert.Equal(t, string([]byte{27, 91, 57, 48, 59, 52, 51, 109}), colorForStatus(http.StatusNotFound), "4xx should be yellow")
  235. assert.Equal(t, string([]byte{27, 91, 57, 55, 59, 52, 49, 109}), colorForStatus(2), "other things should be red")
  236. }
  237. func TestErrorLogger(t *testing.T) {
  238. router := New()
  239. router.Use(ErrorLogger())
  240. router.GET("/error", func(c *Context) {
  241. c.Error(errors.New("this is an error")) // nolint: errcheck
  242. })
  243. router.GET("/abort", func(c *Context) {
  244. c.AbortWithError(http.StatusUnauthorized, errors.New("no authorized")) // nolint: errcheck
  245. })
  246. router.GET("/print", func(c *Context) {
  247. c.Error(errors.New("this is an error")) // nolint: errcheck
  248. c.String(http.StatusInternalServerError, "hola!")
  249. })
  250. w := performRequest(router, "GET", "/error")
  251. assert.Equal(t, http.StatusOK, w.Code)
  252. assert.Equal(t, "{\"error\":\"this is an error\"}", w.Body.String())
  253. w = performRequest(router, "GET", "/abort")
  254. assert.Equal(t, http.StatusUnauthorized, w.Code)
  255. assert.Equal(t, "{\"error\":\"no authorized\"}", w.Body.String())
  256. w = performRequest(router, "GET", "/print")
  257. assert.Equal(t, http.StatusInternalServerError, w.Code)
  258. assert.Equal(t, "hola!{\"error\":\"this is an error\"}", w.Body.String())
  259. }
  260. func TestLoggerWithWriterSkippingPaths(t *testing.T) {
  261. buffer := new(bytes.Buffer)
  262. router := New()
  263. router.Use(LoggerWithWriter(buffer, "/skipped"))
  264. router.GET("/logged", func(c *Context) {})
  265. router.GET("/skipped", func(c *Context) {})
  266. performRequest(router, "GET", "/logged")
  267. assert.Contains(t, buffer.String(), "200")
  268. buffer.Reset()
  269. performRequest(router, "GET", "/skipped")
  270. assert.Contains(t, buffer.String(), "")
  271. }
  272. func TestLoggerWithConfigSkippingPaths(t *testing.T) {
  273. buffer := new(bytes.Buffer)
  274. router := New()
  275. router.Use(LoggerWithConfig(LoggerConfig{
  276. Output: buffer,
  277. SkipPaths: []string{"/skipped"},
  278. }))
  279. router.GET("/logged", func(c *Context) {})
  280. router.GET("/skipped", func(c *Context) {})
  281. performRequest(router, "GET", "/logged")
  282. assert.Contains(t, buffer.String(), "200")
  283. buffer.Reset()
  284. performRequest(router, "GET", "/skipped")
  285. assert.Contains(t, buffer.String(), "")
  286. }
  287. func TestDisableConsoleColor(t *testing.T) {
  288. New()
  289. assert.False(t, disableColor)
  290. DisableConsoleColor()
  291. assert.True(t, disableColor)
  292. }