Permalink
| package lion | |
| import ( | |
| "net/http" | |
| "testing" | |
| ) | |
| var githubLion http.Handler | |
| func init() { | |
| githubLion = loadLion(githubAPI) | |
| } | |
| func BenchmarkGithubAPI(b *testing.B) { | |
| benchRoutes(b, githubLion, githubAPI) | |
| } | |
| func BenchmarkLion_GithubParam(b *testing.B) { | |
| req, _ := http.NewRequest("GET", "/repos/julienschmidt/httprouter/stargazers", nil) | |
| benchRequest(b, githubLion, req) | |
| } | |
| func benchRequest(b *testing.B, router http.Handler, r *http.Request) { | |
| w := new(mockResponseWriter) | |
| u := r.URL | |
| rq := u.RawQuery | |
| r.RequestURI = u.RequestURI() | |
| b.ReportAllocs() | |
| b.ResetTimer() | |
| for i := 0; i < b.N; i++ { | |
| u.RawQuery = rq | |
| router.ServeHTTP(w, r) | |
| } | |
| } | |
| func benchRoutes(b *testing.B, router http.Handler, routes []route) { | |
| w := new(mockResponseWriter) | |
| r, _ := http.NewRequest("GET", "/", nil) | |
| u := r.URL | |
| rq := u.RawQuery | |
| b.ReportAllocs() | |
| b.ResetTimer() | |
| for i := 0; i < b.N; i++ { | |
| for _, route := range routes { | |
| r.Method = route.method | |
| r.RequestURI = route.path | |
| u.Path = route.path | |
| u.RawQuery = rq | |
| router.ServeHTTP(w, r) | |
| } | |
| } | |
| } | |
| type route struct { | |
| method string | |
| path string | |
| } | |
| type mockResponseWriter struct{} | |
| func (m *mockResponseWriter) Header() (h http.Header) { | |
| return http.Header{} | |
| } | |
| func (m *mockResponseWriter) Write(p []byte) (n int, err error) { | |
| return len(p), nil | |
| } | |
| func (m *mockResponseWriter) WriteString(s string) (n int, err error) { | |
| return len(s), nil | |
| } | |
| func (m *mockResponseWriter) WriteHeader(int) {} | |
| func loadLion(routes []route) http.Handler { | |
| hn := httpHandlerFunc | |
| h := Wrap(http.HandlerFunc(hn)) | |
| mux := New() | |
| for _, route := range routes { | |
| switch route.method { | |
| case "GET": | |
| mux.Get(route.path, h) | |
| case "POST": | |
| mux.Post(route.path, h) | |
| case "PUT": | |
| mux.Put(route.path, h) | |
| case "PATCH": | |
| mux.Patch(route.path, h) | |
| case "DELETE": | |
| mux.Delete(route.path, h) | |
| default: | |
| panic("Unknown HTTP method: " + route.method) | |
| } | |
| } | |
| // mux.Matcher.DisplayTree(0) | |
| return mux | |
| } | |
| func httpHandlerFunc(w http.ResponseWriter, r *http.Request) {} | |
| var githubAPI = []route{ | |
| // OAuth Authorizations | |
| {"GET", "/authorizations"}, | |
| {"GET", "/authorizations/:id"}, | |
| {"POST", "/authorizations"}, | |
| //{"PUT", "/authorizations/clients/:client_id"}, | |
| //{"PATCH", "/authorizations/:id"}, | |
| {"DELETE", "/authorizations/:id"}, | |
| {"GET", "/applications/:client_id/tokens/:access_token"}, | |
| {"DELETE", "/applications/:client_id/tokens"}, | |
| {"DELETE", "/applications/:client_id/tokens/:access_token"}, | |
| // Activity | |
| {"GET", "/events"}, | |
| {"GET", "/repos/:owner/:repo/events"}, | |
| {"GET", "/networks/:owner/:repo/events"}, | |
| {"GET", "/orgs/:org/events"}, | |
| {"GET", "/users/:user/received_events"}, | |
| {"GET", "/users/:user/received_events/public"}, | |
| {"GET", "/users/:user/events"}, | |
| {"GET", "/users/:user/events/public"}, | |
| {"GET", "/users/:user/events/orgs/:org"}, | |
| {"GET", "/feeds"}, | |
| {"GET", "/notifications"}, | |
| {"GET", "/repos/:owner/:repo/notifications"}, | |
| {"PUT", "/notifications"}, | |
| {"PUT", "/repos/:owner/:repo/notifications"}, | |
| {"GET", "/notifications/threads/:id"}, | |
| //{"PATCH", "/notifications/threads/:id"}, | |
| {"GET", "/notifications/threads/:id/subscription"}, | |
| {"PUT", "/notifications/threads/:id/subscription"}, | |
| {"DELETE", "/notifications/threads/:id/subscription"}, | |
| {"GET", "/repos/:owner/:repo/stargazers"}, | |
| {"GET", "/users/:user/starred"}, | |
| {"GET", "/user/starred"}, | |
| {"GET", "/user/starred/:owner/:repo"}, | |
| {"PUT", "/user/starred/:owner/:repo"}, | |
| {"DELETE", "/user/starred/:owner/:repo"}, | |
| {"GET", "/repos/:owner/:repo/subscribers"}, | |
| {"GET", "/users/:user/subscriptions"}, | |
| {"GET", "/user/subscriptions"}, | |
| {"GET", "/repos/:owner/:repo/subscription"}, | |
| {"PUT", "/repos/:owner/:repo/subscription"}, | |
| {"DELETE", "/repos/:owner/:repo/subscription"}, | |
| {"GET", "/user/subscriptions/:owner/:repo"}, | |
| {"PUT", "/user/subscriptions/:owner/:repo"}, | |
| {"DELETE", "/user/subscriptions/:owner/:repo"}, | |
| // Gists | |
| {"GET", "/users/:user/gists"}, | |
| {"GET", "/gists"}, | |
| //{"GET", "/gists/public"}, | |
| //{"GET", "/gists/starred"}, | |
| {"GET", "/gists/:id"}, | |
| {"POST", "/gists"}, | |
| //{"PATCH", "/gists/:id"}, | |
| {"PUT", "/gists/:id/star"}, | |
| {"DELETE", "/gists/:id/star"}, | |
| {"GET", "/gists/:id/star"}, | |
| {"POST", "/gists/:id/forks"}, | |
| {"DELETE", "/gists/:id"}, | |
| // Git Data | |
| {"GET", "/repos/:owner/:repo/git/blobs/:sha"}, | |
| {"POST", "/repos/:owner/:repo/git/blobs"}, | |
| {"GET", "/repos/:owner/:repo/git/commits/:sha"}, | |
| {"POST", "/repos/:owner/:repo/git/commits"}, | |
| //{"GET", "/repos/:owner/:repo/git/refs/*ref"}, | |
| {"GET", "/repos/:owner/:repo/git/refs"}, | |
| {"POST", "/repos/:owner/:repo/git/refs"}, | |
| //{"PATCH", "/repos/:owner/:repo/git/refs/*ref"}, | |
| //{"DELETE", "/repos/:owner/:repo/git/refs/*ref"}, | |
| {"GET", "/repos/:owner/:repo/git/tags/:sha"}, | |
| {"POST", "/repos/:owner/:repo/git/tags"}, | |
| {"GET", "/repos/:owner/:repo/git/trees/:sha"}, | |
| {"POST", "/repos/:owner/:repo/git/trees"}, | |
| // Issues | |
| {"GET", "/issues"}, | |
| {"GET", "/user/issues"}, | |
| {"GET", "/orgs/:org/issues"}, | |
| {"GET", "/repos/:owner/:repo/issues"}, | |
| {"GET", "/repos/:owner/:repo/issues/:number"}, | |
| {"POST", "/repos/:owner/:repo/issues"}, | |
| //{"PATCH", "/repos/:owner/:repo/issues/:number"}, | |
| {"GET", "/repos/:owner/:repo/assignees"}, | |
| {"GET", "/repos/:owner/:repo/assignees/:assignee"}, | |
| {"GET", "/repos/:owner/:repo/issues/:number/comments"}, | |
| //{"GET", "/repos/:owner/:repo/issues/comments"}, | |
| //{"GET", "/repos/:owner/:repo/issues/comments/:id"}, | |
| {"POST", "/repos/:owner/:repo/issues/:number/comments"}, | |
| //{"PATCH", "/repos/:owner/:repo/issues/comments/:id"}, | |
| //{"DELETE", "/repos/:owner/:repo/issues/comments/:id"}, | |
| {"GET", "/repos/:owner/:repo/issues/:number/events"}, | |
| //{"GET", "/repos/:owner/:repo/issues/events"}, | |
| //{"GET", "/repos/:owner/:repo/issues/events/:id"}, | |
| {"GET", "/repos/:owner/:repo/labels"}, | |
| {"GET", "/repos/:owner/:repo/labels/:name"}, | |
| {"POST", "/repos/:owner/:repo/labels"}, | |
| //{"PATCH", "/repos/:owner/:repo/labels/:name"}, | |
| {"DELETE", "/repos/:owner/:repo/labels/:name"}, | |
| {"GET", "/repos/:owner/:repo/issues/:number/labels"}, | |
| {"POST", "/repos/:owner/:repo/issues/:number/labels"}, | |
| {"DELETE", "/repos/:owner/:repo/issues/:number/labels/:name"}, | |
| {"PUT", "/repos/:owner/:repo/issues/:number/labels"}, | |
| {"DELETE", "/repos/:owner/:repo/issues/:number/labels"}, | |
| {"GET", "/repos/:owner/:repo/milestones/:number/labels"}, | |
| {"GET", "/repos/:owner/:repo/milestones"}, | |
| {"GET", "/repos/:owner/:repo/milestones/:number"}, | |
| {"POST", "/repos/:owner/:repo/milestones"}, | |
| //{"PATCH", "/repos/:owner/:repo/milestones/:number"}, | |
| {"DELETE", "/repos/:owner/:repo/milestones/:number"}, | |
| // Miscellaneous | |
| {"GET", "/emojis"}, | |
| {"GET", "/gitignore/templates"}, | |
| {"GET", "/gitignore/templates/:name"}, | |
| {"POST", "/markdown"}, | |
| {"POST", "/markdown/raw"}, | |
| {"GET", "/meta"}, | |
| {"GET", "/rate_limit"}, | |
| // Organizations | |
| {"GET", "/users/:user/orgs"}, | |
| {"GET", "/user/orgs"}, | |
| {"GET", "/orgs/:org"}, | |
| //{"PATCH", "/orgs/:org"}, | |
| {"GET", "/orgs/:org/members"}, | |
| {"GET", "/orgs/:org/members/:user"}, | |
| {"DELETE", "/orgs/:org/members/:user"}, | |
| {"GET", "/orgs/:org/public_members"}, | |
| {"GET", "/orgs/:org/public_members/:user"}, | |
| {"PUT", "/orgs/:org/public_members/:user"}, | |
| {"DELETE", "/orgs/:org/public_members/:user"}, | |
| {"GET", "/orgs/:org/teams"}, | |
| {"GET", "/teams/:id"}, | |
| {"POST", "/orgs/:org/teams"}, | |
| //{"PATCH", "/teams/:id"}, | |
| {"DELETE", "/teams/:id"}, | |
| {"GET", "/teams/:id/members"}, | |
| {"GET", "/teams/:id/members/:user"}, | |
| {"PUT", "/teams/:id/members/:user"}, | |
| {"DELETE", "/teams/:id/members/:user"}, | |
| {"GET", "/teams/:id/repos"}, | |
| {"GET", "/teams/:id/repos/:owner/:repo"}, | |
| {"PUT", "/teams/:id/repos/:owner/:repo"}, | |
| {"DELETE", "/teams/:id/repos/:owner/:repo"}, | |
| {"GET", "/user/teams"}, | |
| // Pull Requests | |
| {"GET", "/repos/:owner/:repo/pulls"}, | |
| {"GET", "/repos/:owner/:repo/pulls/:number"}, | |
| {"POST", "/repos/:owner/:repo/pulls"}, | |
| //{"PATCH", "/repos/:owner/:repo/pulls/:number"}, | |
| {"GET", "/repos/:owner/:repo/pulls/:number/commits"}, | |
| {"GET", "/repos/:owner/:repo/pulls/:number/files"}, | |
| {"GET", "/repos/:owner/:repo/pulls/:number/merge"}, | |
| {"PUT", "/repos/:owner/:repo/pulls/:number/merge"}, | |
| {"GET", "/repos/:owner/:repo/pulls/:number/comments"}, | |
| //{"GET", "/repos/:owner/:repo/pulls/comments"}, | |
| //{"GET", "/repos/:owner/:repo/pulls/comments/:number"}, | |
| {"PUT", "/repos/:owner/:repo/pulls/:number/comments"}, | |
| //{"PATCH", "/repos/:owner/:repo/pulls/comments/:number"}, | |
| //{"DELETE", "/repos/:owner/:repo/pulls/comments/:number"}, | |
| // Repositories | |
| {"GET", "/user/repos"}, | |
| {"GET", "/users/:user/repos"}, | |
| {"GET", "/orgs/:org/repos"}, | |
| {"GET", "/repositories"}, | |
| {"POST", "/user/repos"}, | |
| {"POST", "/orgs/:org/repos"}, | |
| {"GET", "/repos/:owner/:repo"}, | |
| //{"PATCH", "/repos/:owner/:repo"}, | |
| {"GET", "/repos/:owner/:repo/contributors"}, | |
| {"GET", "/repos/:owner/:repo/languages"}, | |
| {"GET", "/repos/:owner/:repo/teams"}, | |
| {"GET", "/repos/:owner/:repo/tags"}, | |
| {"GET", "/repos/:owner/:repo/branches"}, | |
| {"GET", "/repos/:owner/:repo/branches/:branch"}, | |
| {"DELETE", "/repos/:owner/:repo"}, | |
| {"GET", "/repos/:owner/:repo/collaborators"}, | |
| {"GET", "/repos/:owner/:repo/collaborators/:user"}, | |
| {"PUT", "/repos/:owner/:repo/collaborators/:user"}, | |
| {"DELETE", "/repos/:owner/:repo/collaborators/:user"}, | |
| {"GET", "/repos/:owner/:repo/comments"}, | |
| {"GET", "/repos/:owner/:repo/commits/:sha/comments"}, | |
| {"POST", "/repos/:owner/:repo/commits/:sha/comments"}, | |
| {"GET", "/repos/:owner/:repo/comments/:id"}, | |
| //{"PATCH", "/repos/:owner/:repo/comments/:id"}, | |
| {"DELETE", "/repos/:owner/:repo/comments/:id"}, | |
| {"GET", "/repos/:owner/:repo/commits"}, | |
| {"GET", "/repos/:owner/:repo/commits/:sha"}, | |
| {"GET", "/repos/:owner/:repo/readme"}, | |
| //{"GET", "/repos/:owner/:repo/contents/*path"}, | |
| //{"PUT", "/repos/:owner/:repo/contents/*path"}, | |
| //{"DELETE", "/repos/:owner/:repo/contents/*path"}, | |
| //{"GET", "/repos/:owner/:repo/:archive_format/:ref"}, | |
| {"GET", "/repos/:owner/:repo/keys"}, | |
| {"GET", "/repos/:owner/:repo/keys/:id"}, | |
| {"POST", "/repos/:owner/:repo/keys"}, | |
| //{"PATCH", "/repos/:owner/:repo/keys/:id"}, | |
| {"DELETE", "/repos/:owner/:repo/keys/:id"}, | |
| {"GET", "/repos/:owner/:repo/downloads"}, | |
| {"GET", "/repos/:owner/:repo/downloads/:id"}, | |
| {"DELETE", "/repos/:owner/:repo/downloads/:id"}, | |
| {"GET", "/repos/:owner/:repo/forks"}, | |
| {"POST", "/repos/:owner/:repo/forks"}, | |
| {"GET", "/repos/:owner/:repo/hooks"}, | |
| {"GET", "/repos/:owner/:repo/hooks/:id"}, | |
| {"POST", "/repos/:owner/:repo/hooks"}, | |
| //{"PATCH", "/repos/:owner/:repo/hooks/:id"}, | |
| {"POST", "/repos/:owner/:repo/hooks/:id/tests"}, | |
| {"DELETE", "/repos/:owner/:repo/hooks/:id"}, | |
| {"POST", "/repos/:owner/:repo/merges"}, | |
| {"GET", "/repos/:owner/:repo/releases"}, | |
| {"GET", "/repos/:owner/:repo/releases/:id"}, | |
| {"POST", "/repos/:owner/:repo/releases"}, | |
| //{"PATCH", "/repos/:owner/:repo/releases/:id"}, | |
| {"DELETE", "/repos/:owner/:repo/releases/:id"}, | |
| {"GET", "/repos/:owner/:repo/releases/:id/assets"}, | |
| {"GET", "/repos/:owner/:repo/stats/contributors"}, | |
| {"GET", "/repos/:owner/:repo/stats/commit_activity"}, | |
| {"GET", "/repos/:owner/:repo/stats/code_frequency"}, | |
| {"GET", "/repos/:owner/:repo/stats/participation"}, | |
| {"GET", "/repos/:owner/:repo/stats/punch_card"}, | |
| {"GET", "/repos/:owner/:repo/statuses/:ref"}, | |
| {"POST", "/repos/:owner/:repo/statuses/:ref"}, | |
| // Search | |
| {"GET", "/search/repositories"}, | |
| {"GET", "/search/code"}, | |
| {"GET", "/search/issues"}, | |
| {"GET", "/search/users"}, | |
| {"GET", "/legacy/issues/search/:owner/:repository/:state/:keyword"}, | |
| {"GET", "/legacy/repos/search/:keyword"}, | |
| {"GET", "/legacy/user/search/:keyword"}, | |
| {"GET", "/legacy/user/email/:email"}, | |
| // Users | |
| {"GET", "/users/:user"}, | |
| {"GET", "/user"}, | |
| //{"PATCH", "/user"}, | |
| {"GET", "/users"}, | |
| {"GET", "/user/emails"}, | |
| {"POST", "/user/emails"}, | |
| {"DELETE", "/user/emails"}, | |
| {"GET", "/users/:user/followers"}, | |
| {"GET", "/user/followers"}, | |
| {"GET", "/users/:user/following"}, | |
| {"GET", "/user/following"}, | |
| {"GET", "/user/following/:user"}, | |
| {"GET", "/users/:user/following/:target_user"}, | |
| {"PUT", "/user/following/:user"}, | |
| {"DELETE", "/user/following/:user"}, | |
| {"GET", "/users/:user/keys"}, | |
| {"GET", "/user/keys"}, | |
| {"GET", "/user/keys/:id"}, | |
| {"POST", "/user/keys"}, | |
| //{"PATCH", "/user/keys/:id"}, | |
| {"DELETE", "/user/keys/:id"}, | |
| } |