github.com/System-Glitch/goyave/v3@v3.6.1-0.20210226143142-ac2fe42ee80e/router_bench_test.go (about)

     1  package goyave
     2  
     3  import (
     4  	"net/http"
     5  	"net/http/httptest"
     6  	"runtime"
     7  	"testing"
     8  
     9  	"github.com/System-Glitch/goyave/v3/validation"
    10  )
    11  
    12  type routerDefinition struct {
    13  	prefix     string // Empty for main router
    14  	middleware []Middleware
    15  	routes     []*routeDefinition
    16  	subrouters []*routerDefinition
    17  }
    18  
    19  type routeDefinition struct {
    20  	uri     string
    21  	methods string
    22  	name    string
    23  	handler Handler
    24  	rules   validation.RuleSet
    25  }
    26  
    27  var handler Handler = func(response *Response, request *Request) {
    28  	response.Status(200)
    29  }
    30  
    31  var sampleRouteDefinition *routerDefinition = &routerDefinition{
    32  	prefix:     "",
    33  	middleware: []Middleware{},
    34  	routes: []*routeDefinition{
    35  		{
    36  			uri:     "/hello",
    37  			methods: "GET",
    38  			name:    "hello",
    39  			handler: handler,
    40  			rules:   nil,
    41  		},
    42  		{
    43  			uri:     "/world",
    44  			methods: "POST",
    45  			name:    "post",
    46  			handler: handler,
    47  			rules:   nil,
    48  		},
    49  		{
    50  			uri:     "/{param}",
    51  			methods: "POST",
    52  			name:    "param",
    53  			handler: handler,
    54  			rules:   nil,
    55  		},
    56  	},
    57  	subrouters: []*routerDefinition{
    58  		{
    59  			prefix:     "/product",
    60  			middleware: []Middleware{},
    61  			routes: []*routeDefinition{
    62  				{
    63  					uri:     "/",
    64  					methods: "GET",
    65  					name:    "product.index",
    66  					handler: handler,
    67  					rules:   nil,
    68  				},
    69  				{
    70  					uri:     "/",
    71  					methods: "POST",
    72  					name:    "product.store",
    73  					handler: handler,
    74  					rules:   nil,
    75  				},
    76  				{
    77  					uri:     "/{id:[0-9]+}",
    78  					methods: "GET",
    79  					name:    "product.show",
    80  					handler: handler,
    81  					rules:   nil,
    82  				},
    83  				{
    84  					uri:     "/{id:[0-9]+}",
    85  					methods: "PUT|PATCH",
    86  					name:    "product.update",
    87  					handler: handler,
    88  					rules:   nil,
    89  				},
    90  				{
    91  					uri:     "/{id:[0-9]+}",
    92  					methods: "DELETE",
    93  					name:    "product.destroy",
    94  					handler: handler,
    95  					rules:   nil,
    96  				},
    97  			},
    98  			subrouters: []*routerDefinition{},
    99  		},
   100  	},
   101  }
   102  
   103  var sampleRequests []*http.Request = []*http.Request{
   104  	httptest.NewRequest("GET", "/", nil), // 404
   105  	httptest.NewRequest("GET", "/hello", nil),
   106  	httptest.NewRequest("POST", "/world", nil),
   107  	httptest.NewRequest("POST", "/param", nil),
   108  	httptest.NewRequest("GET", "/product", nil),
   109  	httptest.NewRequest("POST", "/product", nil),
   110  	httptest.NewRequest("GET", "/product/test", nil), // 404
   111  	httptest.NewRequest("GET", "/product/1", nil),
   112  	httptest.NewRequest("PUT", "/product/1", nil),
   113  	httptest.NewRequest("DELETE", "/product/1", nil),
   114  }
   115  
   116  func registerAll(def *routerDefinition) *Router {
   117  	main := newRouter()
   118  	registerRouter(main, def)
   119  	return main
   120  }
   121  
   122  func registerRouter(router *Router, def *routerDefinition) {
   123  	for _, subdef := range def.subrouters {
   124  		subrouter := router.Subrouter(subdef.prefix)
   125  		registerRouter(subrouter, subdef)
   126  	}
   127  	for _, routeDef := range def.routes {
   128  		router.registerRoute(routeDef.methods, routeDef.uri, routeDef.handler).Validate(routeDef.rules).Name(routeDef.name)
   129  	}
   130  }
   131  
   132  func BenchmarkRouteRegistration(b *testing.B) {
   133  	b.ReportAllocs()
   134  	for n := 0; n < b.N; n++ {
   135  		registerAll(sampleRouteDefinition)
   136  		regexCache = nil
   137  	}
   138  }
   139  
   140  func BenchmarkRootLevelNotFound(b *testing.B) {
   141  	router := setupRouteBench(b)
   142  
   143  	for n := 0; n < b.N; n++ {
   144  		router.match(sampleRequests[0], &routeMatch{currentPath: sampleRequests[0].URL.Path})
   145  	}
   146  }
   147  
   148  func BenchmarkRootLevelMatch(b *testing.B) {
   149  	router := setupRouteBench(b)
   150  
   151  	for n := 0; n < b.N; n++ {
   152  		router.match(sampleRequests[1], &routeMatch{currentPath: sampleRequests[1].URL.Path})
   153  	}
   154  }
   155  
   156  func BenchmarkRootLevelPostMatch(b *testing.B) {
   157  	router := setupRouteBench(b)
   158  
   159  	for n := 0; n < b.N; n++ {
   160  		router.match(sampleRequests[2], &routeMatch{currentPath: sampleRequests[2].URL.Path})
   161  	}
   162  }
   163  
   164  func BenchmarkRootLevelPostParamMatch(b *testing.B) {
   165  	router := setupRouteBench(b)
   166  
   167  	for n := 0; n < b.N; n++ {
   168  		router.match(sampleRequests[3], &routeMatch{currentPath: sampleRequests[3].URL.Path})
   169  	}
   170  }
   171  
   172  func BenchmarkSubrouterMatch(b *testing.B) {
   173  	router := setupRouteBench(b)
   174  
   175  	for n := 0; n < b.N; n++ {
   176  		router.match(sampleRequests[4], &routeMatch{currentPath: sampleRequests[4].URL.Path})
   177  	}
   178  }
   179  
   180  func BenchmarkSubrouterPostMatch(b *testing.B) {
   181  	router := setupRouteBench(b)
   182  
   183  	for n := 0; n < b.N; n++ {
   184  		router.match(sampleRequests[5], &routeMatch{currentPath: sampleRequests[5].URL.Path})
   185  	}
   186  }
   187  
   188  func BenchmarkSubrouterNotFound(b *testing.B) {
   189  	router := setupRouteBench(b)
   190  
   191  	for n := 0; n < b.N; n++ {
   192  		router.match(sampleRequests[6], &routeMatch{currentPath: sampleRequests[6].URL.Path})
   193  	}
   194  }
   195  
   196  func BenchmarkParamMatch(b *testing.B) {
   197  	router := setupRouteBench(b)
   198  
   199  	for n := 0; n < b.N; n++ {
   200  		router.match(sampleRequests[7], &routeMatch{currentPath: sampleRequests[7].URL.Path})
   201  	}
   202  }
   203  
   204  func BenchmarkParamPutMatch(b *testing.B) {
   205  	router := setupRouteBench(b)
   206  
   207  	for n := 0; n < b.N; n++ {
   208  		router.match(sampleRequests[8], &routeMatch{currentPath: sampleRequests[8].URL.Path})
   209  	}
   210  }
   211  
   212  func BenchmarkParamDeleteMatch(b *testing.B) {
   213  	router := setupRouteBench(b)
   214  
   215  	for n := 0; n < b.N; n++ {
   216  		router.match(sampleRequests[9], &routeMatch{currentPath: sampleRequests[9].URL.Path})
   217  	}
   218  }
   219  
   220  func BenchmarkMatchAll(b *testing.B) {
   221  	router := setupRouteBench(b)
   222  
   223  	for n := 0; n < b.N; n++ {
   224  		for _, r := range sampleRequests {
   225  			router.match(r, &routeMatch{currentPath: r.URL.Path})
   226  		}
   227  	}
   228  }
   229  
   230  func setupRouteBench(b *testing.B) *Router {
   231  	router := registerAll(sampleRouteDefinition)
   232  	regexCache = nil
   233  	b.ReportAllocs()
   234  	runtime.GC()
   235  	defer b.ResetTimer()
   236  	return router
   237  }