github.com/gofiber/fiber/v2@v2.47.0/middleware/logger/logger_test.go (about) 1 //nolint:bodyclose // Much easier to just ignore memory leaks in tests 2 package logger 3 4 import ( 5 "bufio" 6 "bytes" 7 "errors" 8 "fmt" 9 "io" 10 "net/http" 11 "net/http/httptest" 12 "os" 13 "sync" 14 "testing" 15 "time" 16 17 "github.com/gofiber/fiber/v2" 18 "github.com/gofiber/fiber/v2/middleware/requestid" 19 "github.com/gofiber/fiber/v2/utils" 20 21 "github.com/valyala/bytebufferpool" 22 "github.com/valyala/fasthttp" 23 ) 24 25 // go test -run Test_Logger 26 func Test_Logger(t *testing.T) { 27 t.Parallel() 28 app := fiber.New() 29 30 buf := bytebufferpool.Get() 31 defer bytebufferpool.Put(buf) 32 33 app.Use(New(Config{ 34 Format: "${error}", 35 Output: buf, 36 })) 37 38 app.Get("/", func(c *fiber.Ctx) error { 39 return errors.New("some random error") 40 }) 41 42 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 43 utils.AssertEqual(t, nil, err) 44 utils.AssertEqual(t, fiber.StatusInternalServerError, resp.StatusCode) 45 utils.AssertEqual(t, "some random error", buf.String()) 46 } 47 48 // go test -run Test_Logger_locals 49 func Test_Logger_locals(t *testing.T) { 50 t.Parallel() 51 app := fiber.New() 52 53 buf := bytebufferpool.Get() 54 defer bytebufferpool.Put(buf) 55 56 app.Use(New(Config{ 57 Format: "${locals:demo}", 58 Output: buf, 59 })) 60 61 app.Get("/", func(c *fiber.Ctx) error { 62 c.Locals("demo", "johndoe") 63 return c.SendStatus(fiber.StatusOK) 64 }) 65 66 app.Get("/int", func(c *fiber.Ctx) error { 67 c.Locals("demo", 55) 68 return c.SendStatus(fiber.StatusOK) 69 }) 70 71 app.Get("/empty", func(c *fiber.Ctx) error { 72 return c.SendStatus(fiber.StatusOK) 73 }) 74 75 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 76 utils.AssertEqual(t, nil, err) 77 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 78 utils.AssertEqual(t, "johndoe", buf.String()) 79 80 buf.Reset() 81 82 resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/int", nil)) 83 utils.AssertEqual(t, nil, err) 84 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 85 utils.AssertEqual(t, "55", buf.String()) 86 87 buf.Reset() 88 89 resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/empty", nil)) 90 utils.AssertEqual(t, nil, err) 91 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 92 utils.AssertEqual(t, "", buf.String()) 93 } 94 95 // go test -run Test_Logger_Next 96 func Test_Logger_Next(t *testing.T) { 97 t.Parallel() 98 app := fiber.New() 99 app.Use(New(Config{ 100 Next: func(_ *fiber.Ctx) bool { 101 return true 102 }, 103 })) 104 105 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 106 utils.AssertEqual(t, nil, err) 107 utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) 108 } 109 110 // go test -run Test_Logger_Done 111 func Test_Logger_Done(t *testing.T) { 112 t.Parallel() 113 buf := bytes.NewBuffer(nil) 114 app := fiber.New() 115 app.Use(New(Config{ 116 Done: func(c *fiber.Ctx, logString []byte) { 117 if c.Response().StatusCode() == fiber.StatusOK { 118 _, err := buf.Write(logString) 119 utils.AssertEqual(t, nil, err) 120 } 121 }, 122 })).Get("/logging", func(ctx *fiber.Ctx) error { 123 return ctx.SendStatus(fiber.StatusOK) 124 }) 125 126 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/logging", nil)) 127 utils.AssertEqual(t, nil, err) 128 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 129 utils.AssertEqual(t, true, buf.Len() > 0) 130 } 131 132 // go test -run Test_Logger_ErrorTimeZone 133 func Test_Logger_ErrorTimeZone(t *testing.T) { 134 t.Parallel() 135 app := fiber.New() 136 app.Use(New(Config{ 137 TimeZone: "invalid", 138 })) 139 140 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 141 utils.AssertEqual(t, nil, err) 142 utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) 143 } 144 145 type fakeOutput int 146 147 func (o *fakeOutput) Write([]byte) (int, error) { 148 *o++ 149 return 0, errors.New("fake output") 150 } 151 152 // go test -run Test_Logger_ErrorOutput_WithoutColor 153 func Test_Logger_ErrorOutput_WithoutColor(t *testing.T) { 154 t.Parallel() 155 o := new(fakeOutput) 156 app := fiber.New() 157 app.Use(New(Config{ 158 Output: o, 159 DisableColors: true, 160 })) 161 162 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 163 utils.AssertEqual(t, nil, err) 164 utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) 165 166 utils.AssertEqual(t, 1, int(*o)) 167 } 168 169 // go test -run Test_Logger_ErrorOutput 170 func Test_Logger_ErrorOutput(t *testing.T) { 171 t.Parallel() 172 o := new(fakeOutput) 173 app := fiber.New() 174 app.Use(New(Config{ 175 Output: o, 176 })) 177 178 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 179 utils.AssertEqual(t, nil, err) 180 utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) 181 182 utils.AssertEqual(t, 1, int(*o)) 183 } 184 185 // go test -run Test_Logger_All 186 func Test_Logger_All(t *testing.T) { 187 t.Parallel() 188 buf := bytebufferpool.Get() 189 defer bytebufferpool.Put(buf) 190 191 app := fiber.New() 192 app.Use(New(Config{ 193 Format: "${pid}${reqHeaders}${referer}${protocol}${ip}${ips}${host}${url}${ua}${body}${route}${black}${red}${green}${yellow}${blue}${magenta}${cyan}${white}${reset}${error}${header:test}${query:test}${form:test}${cookie:test}${non}", 194 Output: buf, 195 })) 196 197 // Alias colors 198 colors := app.Config().ColorScheme 199 200 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/?foo=bar", nil)) 201 utils.AssertEqual(t, nil, err) 202 utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) 203 204 expected := fmt.Sprintf("%dHost=example.comhttp0.0.0.0example.com/?foo=bar/%s%s%s%s%s%s%s%s%sCannot GET /", os.Getpid(), colors.Black, colors.Red, colors.Green, colors.Yellow, colors.Blue, colors.Magenta, colors.Cyan, colors.White, colors.Reset) 205 utils.AssertEqual(t, expected, buf.String()) 206 } 207 208 // go test -run Test_Query_Params 209 func Test_Query_Params(t *testing.T) { 210 t.Parallel() 211 buf := bytebufferpool.Get() 212 defer bytebufferpool.Put(buf) 213 214 app := fiber.New() 215 app.Use(New(Config{ 216 Format: "${queryParams}", 217 Output: buf, 218 })) 219 220 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/?foo=bar&baz=moz", nil)) 221 utils.AssertEqual(t, nil, err) 222 utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) 223 224 expected := "foo=bar&baz=moz" 225 utils.AssertEqual(t, expected, buf.String()) 226 } 227 228 // go test -run Test_Response_Body 229 func Test_Response_Body(t *testing.T) { 230 t.Parallel() 231 buf := bytebufferpool.Get() 232 defer bytebufferpool.Put(buf) 233 234 app := fiber.New() 235 app.Use(New(Config{ 236 Format: "${resBody}", 237 Output: buf, 238 })) 239 240 app.Get("/", func(c *fiber.Ctx) error { 241 return c.SendString("Sample response body") 242 }) 243 244 app.Post("/test", func(c *fiber.Ctx) error { 245 return c.Send([]byte("Post in test")) 246 }) 247 248 _, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 249 utils.AssertEqual(t, nil, err) 250 251 expectedGetResponse := "Sample response body" 252 utils.AssertEqual(t, expectedGetResponse, buf.String()) 253 254 buf.Reset() // Reset buffer to test POST 255 256 _, err = app.Test(httptest.NewRequest(fiber.MethodPost, "/test", nil)) 257 utils.AssertEqual(t, nil, err) 258 259 expectedPostResponse := "Post in test" 260 utils.AssertEqual(t, expectedPostResponse, buf.String()) 261 } 262 263 // go test -run Test_Logger_AppendUint 264 func Test_Logger_AppendUint(t *testing.T) { 265 t.Parallel() 266 app := fiber.New() 267 268 buf := bytebufferpool.Get() 269 defer bytebufferpool.Put(buf) 270 271 app.Use(New(Config{ 272 Format: "${bytesReceived} ${bytesSent} ${status}", 273 Output: buf, 274 })) 275 276 app.Get("/", func(c *fiber.Ctx) error { 277 return c.SendString("hello") 278 }) 279 280 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 281 utils.AssertEqual(t, nil, err) 282 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 283 utils.AssertEqual(t, "0 5 200", buf.String()) 284 } 285 286 // go test -run Test_Logger_Data_Race -race 287 func Test_Logger_Data_Race(t *testing.T) { 288 t.Parallel() 289 app := fiber.New() 290 291 buf := bytebufferpool.Get() 292 defer bytebufferpool.Put(buf) 293 294 app.Use(New(ConfigDefault)) 295 app.Use(New(Config{ 296 Format: "${time} | ${pid} | ${locals:requestid} | ${status} | ${latency} | ${method} | ${path}\n", 297 })) 298 299 app.Get("/", func(c *fiber.Ctx) error { 300 return c.SendString("hello") 301 }) 302 303 var ( 304 resp1, resp2 *http.Response 305 err1, err2 error 306 ) 307 wg := &sync.WaitGroup{} 308 wg.Add(1) 309 go func() { 310 resp1, err1 = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 311 wg.Done() 312 }() 313 resp2, err2 = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 314 wg.Wait() 315 utils.AssertEqual(t, nil, err1) 316 utils.AssertEqual(t, fiber.StatusOK, resp1.StatusCode) 317 utils.AssertEqual(t, nil, err2) 318 utils.AssertEqual(t, fiber.StatusOK, resp2.StatusCode) 319 } 320 321 // go test -v -run=^$ -bench=Benchmark_Logger -benchmem -count=4 322 func Benchmark_Logger(b *testing.B) { 323 benchSetup := func(b *testing.B, app *fiber.App) { 324 b.Helper() 325 326 h := app.Handler() 327 328 fctx := &fasthttp.RequestCtx{} 329 fctx.Request.Header.SetMethod(fiber.MethodGet) 330 fctx.Request.SetRequestURI("/") 331 332 b.ReportAllocs() 333 b.ResetTimer() 334 335 for n := 0; n < b.N; n++ { 336 h(fctx) 337 } 338 339 utils.AssertEqual(b, 200, fctx.Response.Header.StatusCode()) 340 } 341 342 b.Run("Base", func(bb *testing.B) { 343 app := fiber.New() 344 app.Use(New(Config{ 345 Format: "${bytesReceived} ${bytesSent} ${status}", 346 Output: io.Discard, 347 })) 348 app.Get("/", func(c *fiber.Ctx) error { 349 c.Set("test", "test") 350 return c.SendString("Hello, World!") 351 }) 352 benchSetup(bb, app) 353 }) 354 355 b.Run("DefaultFormat", func(bb *testing.B) { 356 app := fiber.New() 357 app.Use(New(Config{ 358 Output: io.Discard, 359 })) 360 app.Get("/", func(c *fiber.Ctx) error { 361 return c.SendString("Hello, World!") 362 }) 363 benchSetup(bb, app) 364 }) 365 366 b.Run("WithTagParameter", func(bb *testing.B) { 367 app := fiber.New() 368 app.Use(New(Config{ 369 Format: "${bytesReceived} ${bytesSent} ${status} ${reqHeader:test}", 370 Output: io.Discard, 371 })) 372 app.Get("/", func(c *fiber.Ctx) error { 373 c.Set("test", "test") 374 return c.SendString("Hello, World!") 375 }) 376 benchSetup(bb, app) 377 }) 378 } 379 380 // go test -run Test_Response_Header 381 func Test_Response_Header(t *testing.T) { 382 t.Parallel() 383 buf := bytebufferpool.Get() 384 defer bytebufferpool.Put(buf) 385 386 app := fiber.New() 387 app.Use(requestid.New(requestid.Config{ 388 Next: nil, 389 Header: fiber.HeaderXRequestID, 390 Generator: func() string { return "Hello fiber!" }, 391 ContextKey: "requestid", 392 })) 393 app.Use(New(Config{ 394 Format: "${respHeader:X-Request-ID}", 395 Output: buf, 396 })) 397 app.Get("/", func(c *fiber.Ctx) error { 398 return c.SendString("Hello fiber!") 399 }) 400 401 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 402 utils.AssertEqual(t, nil, err) 403 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 404 utils.AssertEqual(t, "Hello fiber!", buf.String()) 405 } 406 407 // go test -run Test_Req_Header 408 func Test_Req_Header(t *testing.T) { 409 t.Parallel() 410 buf := bytebufferpool.Get() 411 defer bytebufferpool.Put(buf) 412 413 app := fiber.New() 414 app.Use(New(Config{ 415 Format: "${header:test}", 416 Output: buf, 417 })) 418 app.Get("/", func(c *fiber.Ctx) error { 419 return c.SendString("Hello fiber!") 420 }) 421 headerReq := httptest.NewRequest(fiber.MethodGet, "/", nil) 422 headerReq.Header.Add("test", "Hello fiber!") 423 424 resp, err := app.Test(headerReq) 425 utils.AssertEqual(t, nil, err) 426 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 427 utils.AssertEqual(t, "Hello fiber!", buf.String()) 428 } 429 430 // go test -run Test_ReqHeader_Header 431 func Test_ReqHeader_Header(t *testing.T) { 432 t.Parallel() 433 buf := bytebufferpool.Get() 434 defer bytebufferpool.Put(buf) 435 436 app := fiber.New() 437 app.Use(New(Config{ 438 Format: "${reqHeader:test}", 439 Output: buf, 440 })) 441 app.Get("/", func(c *fiber.Ctx) error { 442 return c.SendString("Hello fiber!") 443 }) 444 reqHeaderReq := httptest.NewRequest(fiber.MethodGet, "/", nil) 445 reqHeaderReq.Header.Add("test", "Hello fiber!") 446 447 resp, err := app.Test(reqHeaderReq) 448 utils.AssertEqual(t, nil, err) 449 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 450 utils.AssertEqual(t, "Hello fiber!", buf.String()) 451 } 452 453 // go test -run Test_CustomTags 454 func Test_CustomTags(t *testing.T) { 455 t.Parallel() 456 customTag := "it is a custom tag" 457 458 buf := bytebufferpool.Get() 459 defer bytebufferpool.Put(buf) 460 461 app := fiber.New() 462 app.Use(New(Config{ 463 Format: "${custom_tag}", 464 CustomTags: map[string]LogFunc{ 465 "custom_tag": func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) { 466 return output.WriteString(customTag) 467 }, 468 }, 469 Output: buf, 470 })) 471 app.Get("/", func(c *fiber.Ctx) error { 472 return c.SendString("Hello fiber!") 473 }) 474 reqHeaderReq := httptest.NewRequest(fiber.MethodGet, "/", nil) 475 reqHeaderReq.Header.Add("test", "Hello fiber!") 476 477 resp, err := app.Test(reqHeaderReq) 478 utils.AssertEqual(t, nil, err) 479 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 480 utils.AssertEqual(t, customTag, buf.String()) 481 } 482 483 // go test -run Test_Logger_ByteSent_Streaming 484 func Test_Logger_ByteSent_Streaming(t *testing.T) { 485 t.Parallel() 486 app := fiber.New() 487 488 buf := bytebufferpool.Get() 489 defer bytebufferpool.Put(buf) 490 491 app.Use(New(Config{ 492 Format: "${bytesReceived} ${bytesSent} ${status}", 493 Output: buf, 494 })) 495 496 app.Get("/", func(c *fiber.Ctx) error { 497 c.Set("Connection", "keep-alive") 498 c.Set("Transfer-Encoding", "chunked") 499 c.Context().SetBodyStreamWriter(func(w *bufio.Writer) { 500 var i int 501 for { 502 i++ 503 msg := fmt.Sprintf("%d - the time is %v", i, time.Now()) 504 fmt.Fprintf(w, "data: Message: %s\n\n", msg) 505 err := w.Flush() 506 if err != nil { 507 break 508 } 509 if i == 10 { 510 break 511 } 512 } 513 }) 514 return nil 515 }) 516 517 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 518 utils.AssertEqual(t, nil, err) 519 utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) 520 utils.AssertEqual(t, "0 0 200", buf.String()) 521 } 522 523 // go test -run Test_Logger_EnableColors 524 func Test_Logger_EnableColors(t *testing.T) { 525 t.Parallel() 526 o := new(fakeOutput) 527 app := fiber.New() 528 app.Use(New(Config{ 529 Output: o, 530 })) 531 532 resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) 533 utils.AssertEqual(t, nil, err) 534 utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) 535 536 utils.AssertEqual(t, 1, int(*o)) 537 }