github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/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/v2/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 }