github.com/gofiber/fiber/v2@v2.47.0/router_test.go (about) 1 // ⚡️ Fiber is an Express inspired web framework written in Go with ☕️ 2 // 📃 Github Repository: https://github.com/gofiber/fiber 3 // 📌 API Documentation: https://docs.gofiber.io 4 5 //nolint:bodyclose // Much easier to just ignore memory leaks in tests 6 package fiber 7 8 import ( 9 "encoding/json" 10 "errors" 11 "fmt" 12 "io" 13 "net/http/httptest" 14 "os" 15 "strings" 16 "testing" 17 18 "github.com/gofiber/fiber/v2/utils" 19 20 "github.com/valyala/fasthttp" 21 ) 22 23 var routesFixture routeJSON 24 25 func init() { 26 dat, err := os.ReadFile("./.github/testdata/testRoutes.json") 27 if err != nil { 28 panic(err) 29 } 30 if err := json.Unmarshal(dat, &routesFixture); err != nil { 31 panic(err) 32 } 33 } 34 35 func Test_Route_Match_SameLength(t *testing.T) { 36 t.Parallel() 37 38 app := New() 39 40 app.Get("/:param", func(c *Ctx) error { 41 return c.SendString(c.Params("param")) 42 }) 43 44 resp, err := app.Test(httptest.NewRequest(MethodGet, "/:param", nil)) 45 utils.AssertEqual(t, nil, err, "app.Test(req)") 46 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 47 48 body, err := io.ReadAll(resp.Body) 49 utils.AssertEqual(t, nil, err, "app.Test(req)") 50 utils.AssertEqual(t, ":param", app.getString(body)) 51 52 // with param 53 resp, err = app.Test(httptest.NewRequest(MethodGet, "/test", nil)) 54 utils.AssertEqual(t, nil, err, "app.Test(req)") 55 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 56 57 body, err = io.ReadAll(resp.Body) 58 utils.AssertEqual(t, nil, err, "app.Test(req)") 59 utils.AssertEqual(t, "test", app.getString(body)) 60 } 61 62 func Test_Route_Match_Star(t *testing.T) { 63 t.Parallel() 64 65 app := New() 66 67 app.Get("/*", func(c *Ctx) error { 68 return c.SendString(c.Params("*")) 69 }) 70 71 resp, err := app.Test(httptest.NewRequest(MethodGet, "/*", nil)) 72 utils.AssertEqual(t, nil, err, "app.Test(req)") 73 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 74 75 body, err := io.ReadAll(resp.Body) 76 utils.AssertEqual(t, nil, err, "app.Test(req)") 77 utils.AssertEqual(t, "*", app.getString(body)) 78 79 // with param 80 resp, err = app.Test(httptest.NewRequest(MethodGet, "/test", nil)) 81 utils.AssertEqual(t, nil, err, "app.Test(req)") 82 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 83 84 body, err = io.ReadAll(resp.Body) 85 utils.AssertEqual(t, nil, err, "app.Test(req)") 86 utils.AssertEqual(t, "test", app.getString(body)) 87 88 // without parameter 89 route := Route{ 90 star: true, 91 path: "/*", 92 routeParser: routeParser{}, 93 } 94 params := [maxParams]string{} 95 match := route.match("", "", ¶ms) 96 utils.AssertEqual(t, true, match) 97 utils.AssertEqual(t, [maxParams]string{}, params) 98 99 // with parameter 100 match = route.match("/favicon.ico", "/favicon.ico", ¶ms) 101 utils.AssertEqual(t, true, match) 102 utils.AssertEqual(t, [maxParams]string{"favicon.ico"}, params) 103 104 // without parameter again 105 match = route.match("", "", ¶ms) 106 utils.AssertEqual(t, true, match) 107 utils.AssertEqual(t, [maxParams]string{}, params) 108 } 109 110 func Test_Route_Match_Root(t *testing.T) { 111 t.Parallel() 112 113 app := New() 114 115 app.Get("/", func(c *Ctx) error { 116 return c.SendString("root") 117 }) 118 119 resp, err := app.Test(httptest.NewRequest(MethodGet, "/", nil)) 120 utils.AssertEqual(t, nil, err, "app.Test(req)") 121 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 122 123 body, err := io.ReadAll(resp.Body) 124 utils.AssertEqual(t, nil, err, "app.Test(req)") 125 utils.AssertEqual(t, "root", app.getString(body)) 126 } 127 128 func Test_Route_Match_Parser(t *testing.T) { 129 t.Parallel() 130 131 app := New() 132 133 app.Get("/foo/:ParamName", func(c *Ctx) error { 134 return c.SendString(c.Params("ParamName")) 135 }) 136 app.Get("/Foobar/*", func(c *Ctx) error { 137 return c.SendString(c.Params("*")) 138 }) 139 resp, err := app.Test(httptest.NewRequest(MethodGet, "/foo/bar", nil)) 140 utils.AssertEqual(t, nil, err, "app.Test(req)") 141 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 142 143 body, err := io.ReadAll(resp.Body) 144 utils.AssertEqual(t, nil, err, "app.Test(req)") 145 utils.AssertEqual(t, "bar", app.getString(body)) 146 147 // with star 148 resp, err = app.Test(httptest.NewRequest(MethodGet, "/Foobar/test", nil)) 149 utils.AssertEqual(t, nil, err, "app.Test(req)") 150 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 151 152 body, err = io.ReadAll(resp.Body) 153 utils.AssertEqual(t, nil, err, "app.Test(req)") 154 utils.AssertEqual(t, "test", app.getString(body)) 155 } 156 157 func Test_Route_Match_Middleware(t *testing.T) { 158 t.Parallel() 159 160 app := New() 161 162 app.Use("/foo/*", func(c *Ctx) error { 163 return c.SendString(c.Params("*")) 164 }) 165 166 resp, err := app.Test(httptest.NewRequest(MethodGet, "/foo/*", nil)) 167 utils.AssertEqual(t, nil, err, "app.Test(req)") 168 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 169 170 body, err := io.ReadAll(resp.Body) 171 utils.AssertEqual(t, nil, err, "app.Test(req)") 172 utils.AssertEqual(t, "*", app.getString(body)) 173 174 // with param 175 resp, err = app.Test(httptest.NewRequest(MethodGet, "/foo/bar/fasel", nil)) 176 utils.AssertEqual(t, nil, err, "app.Test(req)") 177 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 178 179 body, err = io.ReadAll(resp.Body) 180 utils.AssertEqual(t, nil, err, "app.Test(req)") 181 utils.AssertEqual(t, "bar/fasel", app.getString(body)) 182 } 183 184 func Test_Route_Match_UnescapedPath(t *testing.T) { 185 t.Parallel() 186 187 app := New(Config{UnescapePath: true}) 188 189 app.Use("/créer", func(c *Ctx) error { 190 return c.SendString("test") 191 }) 192 193 resp, err := app.Test(httptest.NewRequest(MethodGet, "/cr%C3%A9er", nil)) 194 utils.AssertEqual(t, nil, err, "app.Test(req)") 195 utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") 196 197 body, err := io.ReadAll(resp.Body) 198 utils.AssertEqual(t, nil, err, "app.Test(req)") 199 utils.AssertEqual(t, "test", app.getString(body)) 200 // without special chars 201 resp, err = app.Test(httptest.NewRequest(MethodGet, "/créer", nil)) 202 utils.AssertEqual(t, nil, err, "app.Test(req)") 203 utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") 204 205 // check deactivated behavior 206 app.config.UnescapePath = false 207 resp, err = app.Test(httptest.NewRequest(MethodGet, "/cr%C3%A9er", nil)) 208 utils.AssertEqual(t, nil, err, "app.Test(req)") 209 utils.AssertEqual(t, StatusNotFound, resp.StatusCode, "Status code") 210 } 211 212 func Test_Route_Match_WithEscapeChar(t *testing.T) { 213 t.Parallel() 214 215 app := New() 216 // static route and escaped part 217 app.Get("/v1/some/resource/name\\:customVerb", func(c *Ctx) error { 218 return c.SendString("static") 219 }) 220 // group route 221 group := app.Group("/v2/\\:firstVerb") 222 group.Get("/\\:customVerb", func(c *Ctx) error { 223 return c.SendString("group") 224 }) 225 // route with resource param and escaped part 226 app.Get("/v3/:resource/name\\:customVerb", func(c *Ctx) error { 227 return c.SendString(c.Params("resource")) 228 }) 229 230 // check static route 231 resp, err := app.Test(httptest.NewRequest(MethodGet, "/v1/some/resource/name:customVerb", nil)) 232 utils.AssertEqual(t, nil, err, "app.Test(req)") 233 utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") 234 235 body, err := io.ReadAll(resp.Body) 236 utils.AssertEqual(t, nil, err, "app.Test(req)") 237 utils.AssertEqual(t, "static", app.getString(body)) 238 239 // check group route 240 resp, err = app.Test(httptest.NewRequest(MethodGet, "/v2/:firstVerb/:customVerb", nil)) 241 utils.AssertEqual(t, nil, err, "app.Test(req)") 242 utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") 243 244 body, err = io.ReadAll(resp.Body) 245 utils.AssertEqual(t, nil, err, "app.Test(req)") 246 utils.AssertEqual(t, "group", app.getString(body)) 247 248 // check param route 249 resp, err = app.Test(httptest.NewRequest(MethodGet, "/v3/awesome/name:customVerb", nil)) 250 utils.AssertEqual(t, nil, err, "app.Test(req)") 251 utils.AssertEqual(t, StatusOK, resp.StatusCode, "Status code") 252 253 body, err = io.ReadAll(resp.Body) 254 utils.AssertEqual(t, nil, err, "app.Test(req)") 255 utils.AssertEqual(t, "awesome", app.getString(body)) 256 } 257 258 func Test_Route_Match_Middleware_HasPrefix(t *testing.T) { 259 t.Parallel() 260 261 app := New() 262 263 app.Use("/foo", func(c *Ctx) error { 264 return c.SendString("middleware") 265 }) 266 267 resp, err := app.Test(httptest.NewRequest(MethodGet, "/foo/bar", nil)) 268 utils.AssertEqual(t, nil, err, "app.Test(req)") 269 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 270 271 body, err := io.ReadAll(resp.Body) 272 utils.AssertEqual(t, nil, err, "app.Test(req)") 273 utils.AssertEqual(t, "middleware", app.getString(body)) 274 } 275 276 func Test_Route_Match_Middleware_Root(t *testing.T) { 277 t.Parallel() 278 279 app := New() 280 281 app.Use("/", func(c *Ctx) error { 282 return c.SendString("middleware") 283 }) 284 285 resp, err := app.Test(httptest.NewRequest(MethodGet, "/everything", nil)) 286 utils.AssertEqual(t, nil, err, "app.Test(req)") 287 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 288 289 body, err := io.ReadAll(resp.Body) 290 utils.AssertEqual(t, nil, err, "app.Test(req)") 291 utils.AssertEqual(t, "middleware", app.getString(body)) 292 } 293 294 func Test_Router_Register_Missing_Handler(t *testing.T) { 295 t.Parallel() 296 297 app := New() 298 defer func() { 299 if err := recover(); err != nil { 300 utils.AssertEqual(t, "missing handler in route: /doe\n", fmt.Sprintf("%v", err)) 301 } 302 }() 303 app.register("USE", "/doe", nil) 304 } 305 306 func Test_Ensure_Router_Interface_Implementation(t *testing.T) { 307 t.Parallel() 308 309 var app interface{} = (*App)(nil) 310 _, ok := app.(Router) 311 utils.AssertEqual(t, true, ok) 312 313 var group interface{} = (*Group)(nil) 314 _, ok = group.(Router) 315 utils.AssertEqual(t, true, ok) 316 } 317 318 func Test_Router_Handler_SetETag(t *testing.T) { 319 t.Parallel() 320 321 app := New() 322 app.config.ETag = true 323 324 app.Get("/", func(c *Ctx) error { 325 return c.SendString("Hello, World!") 326 }) 327 328 c := &fasthttp.RequestCtx{} 329 330 app.Handler()(c) 331 332 utils.AssertEqual(t, `"13-1831710635"`, string(c.Response.Header.Peek(HeaderETag))) 333 } 334 335 func Test_Router_Handler_Catch_Error(t *testing.T) { 336 t.Parallel() 337 338 app := New() 339 app.config.ErrorHandler = func(ctx *Ctx, err error) error { 340 return errors.New("fake error") 341 } 342 343 app.Get("/", func(c *Ctx) error { 344 return ErrForbidden 345 }) 346 347 c := &fasthttp.RequestCtx{} 348 349 app.Handler()(c) 350 351 utils.AssertEqual(t, StatusInternalServerError, c.Response.Header.StatusCode()) 352 } 353 354 func Test_Route_Static_Root(t *testing.T) { 355 t.Parallel() 356 357 dir := "./.github/testdata/fs/css" 358 app := New() 359 app.Static("/", dir, Static{ 360 Browse: true, 361 }) 362 363 resp, err := app.Test(httptest.NewRequest(MethodGet, "/", nil)) 364 utils.AssertEqual(t, nil, err, "app.Test(req)") 365 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 366 367 resp, err = app.Test(httptest.NewRequest(MethodGet, "/style.css", nil)) 368 utils.AssertEqual(t, nil, err, "app.Test(req)") 369 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 370 371 body, err := io.ReadAll(resp.Body) 372 utils.AssertEqual(t, nil, err, "app.Test(req)") 373 utils.AssertEqual(t, true, strings.Contains(app.getString(body), "color")) 374 375 app = New() 376 app.Static("/", dir) 377 378 resp, err = app.Test(httptest.NewRequest(MethodGet, "/", nil)) 379 utils.AssertEqual(t, nil, err, "app.Test(req)") 380 utils.AssertEqual(t, 404, resp.StatusCode, "Status code") 381 382 resp, err = app.Test(httptest.NewRequest(MethodGet, "/style.css", nil)) 383 utils.AssertEqual(t, nil, err, "app.Test(req)") 384 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 385 386 body, err = io.ReadAll(resp.Body) 387 utils.AssertEqual(t, nil, err, "app.Test(req)") 388 utils.AssertEqual(t, true, strings.Contains(app.getString(body), "color")) 389 } 390 391 func Test_Route_Static_HasPrefix(t *testing.T) { 392 t.Parallel() 393 394 dir := "./.github/testdata/fs/css" 395 app := New() 396 app.Static("/static", dir, Static{ 397 Browse: true, 398 }) 399 400 resp, err := app.Test(httptest.NewRequest(MethodGet, "/static", nil)) 401 utils.AssertEqual(t, nil, err, "app.Test(req)") 402 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 403 404 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static/", nil)) 405 utils.AssertEqual(t, nil, err, "app.Test(req)") 406 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 407 408 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static/style.css", nil)) 409 utils.AssertEqual(t, nil, err, "app.Test(req)") 410 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 411 412 body, err := io.ReadAll(resp.Body) 413 utils.AssertEqual(t, nil, err, "app.Test(req)") 414 utils.AssertEqual(t, true, strings.Contains(app.getString(body), "color")) 415 416 app = New() 417 app.Static("/static/", dir, Static{ 418 Browse: true, 419 }) 420 421 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static", nil)) 422 utils.AssertEqual(t, nil, err, "app.Test(req)") 423 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 424 425 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static/", nil)) 426 utils.AssertEqual(t, nil, err, "app.Test(req)") 427 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 428 429 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static/style.css", nil)) 430 utils.AssertEqual(t, nil, err, "app.Test(req)") 431 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 432 433 body, err = io.ReadAll(resp.Body) 434 utils.AssertEqual(t, nil, err, "app.Test(req)") 435 utils.AssertEqual(t, true, strings.Contains(app.getString(body), "color")) 436 437 app = New() 438 app.Static("/static", dir) 439 440 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static", nil)) 441 utils.AssertEqual(t, nil, err, "app.Test(req)") 442 utils.AssertEqual(t, 404, resp.StatusCode, "Status code") 443 444 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static/", nil)) 445 utils.AssertEqual(t, nil, err, "app.Test(req)") 446 utils.AssertEqual(t, 404, resp.StatusCode, "Status code") 447 448 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static/style.css", nil)) 449 utils.AssertEqual(t, nil, err, "app.Test(req)") 450 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 451 452 body, err = io.ReadAll(resp.Body) 453 utils.AssertEqual(t, nil, err, "app.Test(req)") 454 utils.AssertEqual(t, true, strings.Contains(app.getString(body), "color")) 455 456 app = New() 457 app.Static("/static/", dir) 458 459 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static", nil)) 460 utils.AssertEqual(t, nil, err, "app.Test(req)") 461 utils.AssertEqual(t, 404, resp.StatusCode, "Status code") 462 463 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static/", nil)) 464 utils.AssertEqual(t, nil, err, "app.Test(req)") 465 utils.AssertEqual(t, 404, resp.StatusCode, "Status code") 466 467 resp, err = app.Test(httptest.NewRequest(MethodGet, "/static/style.css", nil)) 468 utils.AssertEqual(t, nil, err, "app.Test(req)") 469 utils.AssertEqual(t, 200, resp.StatusCode, "Status code") 470 471 body, err = io.ReadAll(resp.Body) 472 utils.AssertEqual(t, nil, err, "app.Test(req)") 473 utils.AssertEqual(t, true, strings.Contains(app.getString(body), "color")) 474 } 475 476 ////////////////////////////////////////////// 477 ///////////////// BENCHMARKS ///////////////// 478 ////////////////////////////////////////////// 479 480 func registerDummyRoutes(app *App) { 481 h := func(c *Ctx) error { 482 return nil 483 } 484 for _, r := range routesFixture.GithubAPI { 485 app.Add(r.Method, r.Path, h) 486 } 487 } 488 489 // go test -v -run=^$ -bench=Benchmark_App_MethodNotAllowed -benchmem -count=4 490 func Benchmark_App_MethodNotAllowed(b *testing.B) { 491 app := New() 492 h := func(c *Ctx) error { 493 return c.SendString("Hello World!") 494 } 495 app.All("/this/is/a/", h) 496 app.Get("/this/is/a/dummy/route/oke", h) 497 appHandler := app.Handler() 498 c := &fasthttp.RequestCtx{} 499 500 c.Request.Header.SetMethod("DELETE") 501 c.URI().SetPath("/this/is/a/dummy/route/oke") 502 503 b.ResetTimer() 504 for n := 0; n < b.N; n++ { 505 appHandler(c) 506 } 507 b.StopTimer() 508 utils.AssertEqual(b, 405, c.Response.StatusCode()) 509 utils.AssertEqual(b, "GET, HEAD", string(c.Response.Header.Peek("Allow"))) 510 utils.AssertEqual(b, utils.StatusMessage(StatusMethodNotAllowed), string(c.Response.Body())) 511 } 512 513 // go test -v ./... -run=^$ -bench=Benchmark_Router_NotFound -benchmem -count=4 514 func Benchmark_Router_NotFound(b *testing.B) { 515 app := New() 516 app.Use(func(c *Ctx) error { 517 return c.Next() 518 }) 519 registerDummyRoutes(app) 520 appHandler := app.Handler() 521 c := &fasthttp.RequestCtx{} 522 523 c.Request.Header.SetMethod("DELETE") 524 c.URI().SetPath("/this/route/does/not/exist") 525 526 b.ResetTimer() 527 for n := 0; n < b.N; n++ { 528 appHandler(c) 529 } 530 utils.AssertEqual(b, 404, c.Response.StatusCode()) 531 utils.AssertEqual(b, "Cannot DELETE /this/route/does/not/exist", string(c.Response.Body())) 532 } 533 534 // go test -v ./... -run=^$ -bench=Benchmark_Router_Handler -benchmem -count=4 535 func Benchmark_Router_Handler(b *testing.B) { 536 app := New() 537 registerDummyRoutes(app) 538 appHandler := app.Handler() 539 540 c := &fasthttp.RequestCtx{} 541 542 c.Request.Header.SetMethod("DELETE") 543 c.URI().SetPath("/user/keys/1337") 544 545 b.ResetTimer() 546 547 for n := 0; n < b.N; n++ { 548 appHandler(c) 549 } 550 } 551 552 func Benchmark_Router_Handler_Strict_Case(b *testing.B) { 553 app := New(Config{ 554 StrictRouting: true, 555 CaseSensitive: true, 556 }) 557 registerDummyRoutes(app) 558 appHandler := app.Handler() 559 560 c := &fasthttp.RequestCtx{} 561 562 c.Request.Header.SetMethod("DELETE") 563 c.URI().SetPath("/user/keys/1337") 564 565 b.ResetTimer() 566 567 for n := 0; n < b.N; n++ { 568 appHandler(c) 569 } 570 } 571 572 // go test -v ./... -run=^$ -bench=Benchmark_Router_Chain -benchmem -count=4 573 func Benchmark_Router_Chain(b *testing.B) { 574 app := New() 575 handler := func(c *Ctx) error { 576 return c.Next() 577 } 578 app.Get("/", handler, handler, handler, handler, handler, handler) 579 580 appHandler := app.Handler() 581 582 c := &fasthttp.RequestCtx{} 583 584 c.Request.Header.SetMethod(MethodGet) 585 c.URI().SetPath("/") 586 b.ResetTimer() 587 for n := 0; n < b.N; n++ { 588 appHandler(c) 589 } 590 } 591 592 // go test -v ./... -run=^$ -bench=Benchmark_Router_WithCompression -benchmem -count=4 593 func Benchmark_Router_WithCompression(b *testing.B) { 594 app := New() 595 handler := func(c *Ctx) error { 596 return c.Next() 597 } 598 app.Get("/", handler) 599 app.Get("/", handler) 600 app.Get("/", handler) 601 app.Get("/", handler) 602 app.Get("/", handler) 603 app.Get("/", handler) 604 605 appHandler := app.Handler() 606 c := &fasthttp.RequestCtx{} 607 608 c.Request.Header.SetMethod(MethodGet) 609 c.URI().SetPath("/") 610 b.ResetTimer() 611 for n := 0; n < b.N; n++ { 612 appHandler(c) 613 } 614 } 615 616 // go test -run=^$ -bench=Benchmark_Startup_Process -benchmem -count=9 617 func Benchmark_Startup_Process(b *testing.B) { 618 for n := 0; n < b.N; n++ { 619 app := New() 620 registerDummyRoutes(app) 621 app.startupProcess() 622 } 623 } 624 625 // go test -v ./... -run=^$ -bench=Benchmark_Router_Next -benchmem -count=4 626 func Benchmark_Router_Next(b *testing.B) { 627 app := New() 628 registerDummyRoutes(app) 629 app.startupProcess() 630 631 request := &fasthttp.RequestCtx{} 632 633 request.Request.Header.SetMethod("DELETE") 634 request.URI().SetPath("/user/keys/1337") 635 var res bool 636 var err error 637 638 c := app.AcquireCtx(request) 639 defer app.ReleaseCtx(c) 640 641 b.ResetTimer() 642 for n := 0; n < b.N; n++ { 643 c.indexRoute = -1 644 res, err = app.next(c) 645 } 646 utils.AssertEqual(b, nil, err) 647 utils.AssertEqual(b, true, res) 648 utils.AssertEqual(b, 4, c.indexRoute) 649 } 650 651 // go test -v ./... -run=^$ -bench=Benchmark_Route_Match -benchmem -count=4 652 func Benchmark_Route_Match(b *testing.B) { 653 var match bool 654 var params [maxParams]string 655 656 parsed := parseRoute("/user/keys/:id") 657 route := &Route{ 658 use: false, 659 root: false, 660 star: false, 661 routeParser: parsed, 662 Params: parsed.params, 663 path: "/user/keys/:id", 664 665 Path: "/user/keys/:id", 666 Method: "DELETE", 667 } 668 route.Handlers = append(route.Handlers, func(c *Ctx) error { 669 return nil 670 }) 671 b.ResetTimer() 672 for n := 0; n < b.N; n++ { 673 match = route.match("/user/keys/1337", "/user/keys/1337", ¶ms) 674 } 675 676 utils.AssertEqual(b, true, match) 677 utils.AssertEqual(b, []string{"1337"}, params[0:len(parsed.params)]) 678 } 679 680 // go test -v ./... -run=^$ -bench=Benchmark_Route_Match_Star -benchmem -count=4 681 func Benchmark_Route_Match_Star(b *testing.B) { 682 var match bool 683 var params [maxParams]string 684 685 parsed := parseRoute("/*") 686 route := &Route{ 687 use: false, 688 root: false, 689 star: true, 690 routeParser: parsed, 691 Params: parsed.params, 692 path: "/user/keys/bla", 693 694 Path: "/user/keys/bla", 695 Method: "DELETE", 696 } 697 route.Handlers = append(route.Handlers, func(c *Ctx) error { 698 return nil 699 }) 700 b.ResetTimer() 701 702 for n := 0; n < b.N; n++ { 703 match = route.match("/user/keys/bla", "/user/keys/bla", ¶ms) 704 } 705 706 utils.AssertEqual(b, true, match) 707 utils.AssertEqual(b, []string{"user/keys/bla"}, params[0:len(parsed.params)]) 708 } 709 710 // go test -v ./... -run=^$ -bench=Benchmark_Route_Match_Root -benchmem -count=4 711 func Benchmark_Route_Match_Root(b *testing.B) { 712 var match bool 713 var params [maxParams]string 714 715 parsed := parseRoute("/") 716 route := &Route{ 717 use: false, 718 root: true, 719 star: false, 720 path: "/", 721 routeParser: parsed, 722 Params: parsed.params, 723 724 Path: "/", 725 Method: "DELETE", 726 } 727 route.Handlers = append(route.Handlers, func(c *Ctx) error { 728 return nil 729 }) 730 731 b.ResetTimer() 732 733 for n := 0; n < b.N; n++ { 734 match = route.match("/", "/", ¶ms) 735 } 736 737 utils.AssertEqual(b, true, match) 738 utils.AssertEqual(b, []string{}, params[0:len(parsed.params)]) 739 } 740 741 // go test -v ./... -run=^$ -bench=Benchmark_Router_Handler_CaseSensitive -benchmem -count=4 742 func Benchmark_Router_Handler_CaseSensitive(b *testing.B) { 743 app := New() 744 app.config.CaseSensitive = true 745 registerDummyRoutes(app) 746 appHandler := app.Handler() 747 748 c := &fasthttp.RequestCtx{} 749 750 c.Request.Header.SetMethod("DELETE") 751 c.URI().SetPath("/user/keys/1337") 752 753 b.ResetTimer() 754 755 for n := 0; n < b.N; n++ { 756 appHandler(c) 757 } 758 } 759 760 // go test -v ./... -run=^$ -bench=Benchmark_Router_Handler_Unescape -benchmem -count=4 761 func Benchmark_Router_Handler_Unescape(b *testing.B) { 762 app := New() 763 app.config.UnescapePath = true 764 registerDummyRoutes(app) 765 app.Delete("/créer", func(c *Ctx) error { 766 return nil 767 }) 768 769 appHandler := app.Handler() 770 771 c := &fasthttp.RequestCtx{} 772 773 c.Request.Header.SetMethod(MethodDelete) 774 c.URI().SetPath("/cr%C3%A9er") 775 776 b.ResetTimer() 777 778 for n := 0; n < b.N; n++ { 779 c.URI().SetPath("/cr%C3%A9er") 780 appHandler(c) 781 } 782 } 783 784 // go test -run=^$ -bench=Benchmark_Router_Handler_StrictRouting -benchmem -count=4 785 func Benchmark_Router_Handler_StrictRouting(b *testing.B) { 786 app := New() 787 app.config.CaseSensitive = true 788 registerDummyRoutes(app) 789 appHandler := app.Handler() 790 791 c := &fasthttp.RequestCtx{} 792 793 c.Request.Header.SetMethod("DELETE") 794 c.URI().SetPath("/user/keys/1337") 795 796 b.ResetTimer() 797 798 for n := 0; n < b.N; n++ { 799 appHandler(c) 800 } 801 } 802 803 // go test -run=^$ -bench=Benchmark_Router_Github_API -benchmem -count=16 804 func Benchmark_Router_Github_API(b *testing.B) { 805 app := New() 806 registerDummyRoutes(app) 807 app.startupProcess() 808 809 c := &fasthttp.RequestCtx{} 810 var match bool 811 var err error 812 813 b.ResetTimer() 814 815 for i := range routesFixture.TestRoutes { 816 c.Request.Header.SetMethod(routesFixture.TestRoutes[i].Method) 817 for n := 0; n < b.N; n++ { 818 c.URI().SetPath(routesFixture.TestRoutes[i].Path) 819 ctx := app.AcquireCtx(c) 820 match, err = app.next(ctx) 821 app.ReleaseCtx(ctx) 822 } 823 utils.AssertEqual(b, nil, err) 824 utils.AssertEqual(b, true, match) 825 } 826 } 827 828 type testRoute struct { 829 Method string `json:"method"` 830 Path string `json:"path"` 831 } 832 833 type routeJSON struct { 834 TestRoutes []testRoute `json:"test_routes"` 835 GithubAPI []testRoute `json:"github_api"` 836 }