githubapi_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
  2. // Use of this source code is governed by a MIT style
  3. // license that can be found in the LICENSE file.
  4. package gin
  5. import (
  6. "bytes"
  7. "fmt"
  8. "math/rand"
  9. "testing"
  10. "github.com/stretchr/testify/assert"
  11. )
  12. type route struct {
  13. method string
  14. path string
  15. }
  16. // http://developer.github.com/v3/
  17. var githubAPI = []route{
  18. // OAuth Authorizations
  19. {"GET", "/authorizations"},
  20. {"GET", "/authorizations/:id"},
  21. {"POST", "/authorizations"},
  22. //{"PUT", "/authorizations/clients/:client_id"},
  23. //{"PATCH", "/authorizations/:id"},
  24. {"DELETE", "/authorizations/:id"},
  25. {"GET", "/applications/:client_id/tokens/:access_token"},
  26. {"DELETE", "/applications/:client_id/tokens"},
  27. {"DELETE", "/applications/:client_id/tokens/:access_token"},
  28. // Activity
  29. {"GET", "/events"},
  30. {"GET", "/repos/:owner/:repo/events"},
  31. {"GET", "/networks/:owner/:repo/events"},
  32. {"GET", "/orgs/:org/events"},
  33. {"GET", "/users/:user/received_events"},
  34. {"GET", "/users/:user/received_events/public"},
  35. {"GET", "/users/:user/events"},
  36. {"GET", "/users/:user/events/public"},
  37. {"GET", "/users/:user/events/orgs/:org"},
  38. {"GET", "/feeds"},
  39. {"GET", "/notifications"},
  40. {"GET", "/repos/:owner/:repo/notifications"},
  41. {"PUT", "/notifications"},
  42. {"PUT", "/repos/:owner/:repo/notifications"},
  43. {"GET", "/notifications/threads/:id"},
  44. //{"PATCH", "/notifications/threads/:id"},
  45. {"GET", "/notifications/threads/:id/subscription"},
  46. {"PUT", "/notifications/threads/:id/subscription"},
  47. {"DELETE", "/notifications/threads/:id/subscription"},
  48. {"GET", "/repos/:owner/:repo/stargazers"},
  49. {"GET", "/users/:user/starred"},
  50. {"GET", "/user/starred"},
  51. {"GET", "/user/starred/:owner/:repo"},
  52. {"PUT", "/user/starred/:owner/:repo"},
  53. {"DELETE", "/user/starred/:owner/:repo"},
  54. {"GET", "/repos/:owner/:repo/subscribers"},
  55. {"GET", "/users/:user/subscriptions"},
  56. {"GET", "/user/subscriptions"},
  57. {"GET", "/repos/:owner/:repo/subscription"},
  58. {"PUT", "/repos/:owner/:repo/subscription"},
  59. {"DELETE", "/repos/:owner/:repo/subscription"},
  60. {"GET", "/user/subscriptions/:owner/:repo"},
  61. {"PUT", "/user/subscriptions/:owner/:repo"},
  62. {"DELETE", "/user/subscriptions/:owner/:repo"},
  63. // Gists
  64. {"GET", "/users/:user/gists"},
  65. {"GET", "/gists"},
  66. //{"GET", "/gists/public"},
  67. //{"GET", "/gists/starred"},
  68. {"GET", "/gists/:id"},
  69. {"POST", "/gists"},
  70. //{"PATCH", "/gists/:id"},
  71. {"PUT", "/gists/:id/star"},
  72. {"DELETE", "/gists/:id/star"},
  73. {"GET", "/gists/:id/star"},
  74. {"POST", "/gists/:id/forks"},
  75. {"DELETE", "/gists/:id"},
  76. // Git Data
  77. {"GET", "/repos/:owner/:repo/git/blobs/:sha"},
  78. {"POST", "/repos/:owner/:repo/git/blobs"},
  79. {"GET", "/repos/:owner/:repo/git/commits/:sha"},
  80. {"POST", "/repos/:owner/:repo/git/commits"},
  81. //{"GET", "/repos/:owner/:repo/git/refs/*ref"},
  82. {"GET", "/repos/:owner/:repo/git/refs"},
  83. {"POST", "/repos/:owner/:repo/git/refs"},
  84. //{"PATCH", "/repos/:owner/:repo/git/refs/*ref"},
  85. //{"DELETE", "/repos/:owner/:repo/git/refs/*ref"},
  86. {"GET", "/repos/:owner/:repo/git/tags/:sha"},
  87. {"POST", "/repos/:owner/:repo/git/tags"},
  88. {"GET", "/repos/:owner/:repo/git/trees/:sha"},
  89. {"POST", "/repos/:owner/:repo/git/trees"},
  90. // Issues
  91. {"GET", "/issues"},
  92. {"GET", "/user/issues"},
  93. {"GET", "/orgs/:org/issues"},
  94. {"GET", "/repos/:owner/:repo/issues"},
  95. {"GET", "/repos/:owner/:repo/issues/:number"},
  96. {"POST", "/repos/:owner/:repo/issues"},
  97. //{"PATCH", "/repos/:owner/:repo/issues/:number"},
  98. {"GET", "/repos/:owner/:repo/assignees"},
  99. {"GET", "/repos/:owner/:repo/assignees/:assignee"},
  100. {"GET", "/repos/:owner/:repo/issues/:number/comments"},
  101. //{"GET", "/repos/:owner/:repo/issues/comments"},
  102. //{"GET", "/repos/:owner/:repo/issues/comments/:id"},
  103. {"POST", "/repos/:owner/:repo/issues/:number/comments"},
  104. //{"PATCH", "/repos/:owner/:repo/issues/comments/:id"},
  105. //{"DELETE", "/repos/:owner/:repo/issues/comments/:id"},
  106. {"GET", "/repos/:owner/:repo/issues/:number/events"},
  107. //{"GET", "/repos/:owner/:repo/issues/events"},
  108. //{"GET", "/repos/:owner/:repo/issues/events/:id"},
  109. {"GET", "/repos/:owner/:repo/labels"},
  110. {"GET", "/repos/:owner/:repo/labels/:name"},
  111. {"POST", "/repos/:owner/:repo/labels"},
  112. //{"PATCH", "/repos/:owner/:repo/labels/:name"},
  113. {"DELETE", "/repos/:owner/:repo/labels/:name"},
  114. {"GET", "/repos/:owner/:repo/issues/:number/labels"},
  115. {"POST", "/repos/:owner/:repo/issues/:number/labels"},
  116. {"DELETE", "/repos/:owner/:repo/issues/:number/labels/:name"},
  117. {"PUT", "/repos/:owner/:repo/issues/:number/labels"},
  118. {"DELETE", "/repos/:owner/:repo/issues/:number/labels"},
  119. {"GET", "/repos/:owner/:repo/milestones/:number/labels"},
  120. {"GET", "/repos/:owner/:repo/milestones"},
  121. {"GET", "/repos/:owner/:repo/milestones/:number"},
  122. {"POST", "/repos/:owner/:repo/milestones"},
  123. //{"PATCH", "/repos/:owner/:repo/milestones/:number"},
  124. {"DELETE", "/repos/:owner/:repo/milestones/:number"},
  125. // Miscellaneous
  126. {"GET", "/emojis"},
  127. {"GET", "/gitignore/templates"},
  128. {"GET", "/gitignore/templates/:name"},
  129. {"POST", "/markdown"},
  130. {"POST", "/markdown/raw"},
  131. {"GET", "/meta"},
  132. {"GET", "/rate_limit"},
  133. // Organizations
  134. {"GET", "/users/:user/orgs"},
  135. {"GET", "/user/orgs"},
  136. {"GET", "/orgs/:org"},
  137. //{"PATCH", "/orgs/:org"},
  138. {"GET", "/orgs/:org/members"},
  139. {"GET", "/orgs/:org/members/:user"},
  140. {"DELETE", "/orgs/:org/members/:user"},
  141. {"GET", "/orgs/:org/public_members"},
  142. {"GET", "/orgs/:org/public_members/:user"},
  143. {"PUT", "/orgs/:org/public_members/:user"},
  144. {"DELETE", "/orgs/:org/public_members/:user"},
  145. {"GET", "/orgs/:org/teams"},
  146. {"GET", "/teams/:id"},
  147. {"POST", "/orgs/:org/teams"},
  148. //{"PATCH", "/teams/:id"},
  149. {"DELETE", "/teams/:id"},
  150. {"GET", "/teams/:id/members"},
  151. {"GET", "/teams/:id/members/:user"},
  152. {"PUT", "/teams/:id/members/:user"},
  153. {"DELETE", "/teams/:id/members/:user"},
  154. {"GET", "/teams/:id/repos"},
  155. {"GET", "/teams/:id/repos/:owner/:repo"},
  156. {"PUT", "/teams/:id/repos/:owner/:repo"},
  157. {"DELETE", "/teams/:id/repos/:owner/:repo"},
  158. {"GET", "/user/teams"},
  159. // Pull Requests
  160. {"GET", "/repos/:owner/:repo/pulls"},
  161. {"GET", "/repos/:owner/:repo/pulls/:number"},
  162. {"POST", "/repos/:owner/:repo/pulls"},
  163. //{"PATCH", "/repos/:owner/:repo/pulls/:number"},
  164. {"GET", "/repos/:owner/:repo/pulls/:number/commits"},
  165. {"GET", "/repos/:owner/:repo/pulls/:number/files"},
  166. {"GET", "/repos/:owner/:repo/pulls/:number/merge"},
  167. {"PUT", "/repos/:owner/:repo/pulls/:number/merge"},
  168. {"GET", "/repos/:owner/:repo/pulls/:number/comments"},
  169. //{"GET", "/repos/:owner/:repo/pulls/comments"},
  170. //{"GET", "/repos/:owner/:repo/pulls/comments/:number"},
  171. {"PUT", "/repos/:owner/:repo/pulls/:number/comments"},
  172. //{"PATCH", "/repos/:owner/:repo/pulls/comments/:number"},
  173. //{"DELETE", "/repos/:owner/:repo/pulls/comments/:number"},
  174. // Repositories
  175. {"GET", "/user/repos"},
  176. {"GET", "/users/:user/repos"},
  177. {"GET", "/orgs/:org/repos"},
  178. {"GET", "/repositories"},
  179. {"POST", "/user/repos"},
  180. {"POST", "/orgs/:org/repos"},
  181. {"GET", "/repos/:owner/:repo"},
  182. //{"PATCH", "/repos/:owner/:repo"},
  183. {"GET", "/repos/:owner/:repo/contributors"},
  184. {"GET", "/repos/:owner/:repo/languages"},
  185. {"GET", "/repos/:owner/:repo/teams"},
  186. {"GET", "/repos/:owner/:repo/tags"},
  187. {"GET", "/repos/:owner/:repo/branches"},
  188. {"GET", "/repos/:owner/:repo/branches/:branch"},
  189. {"DELETE", "/repos/:owner/:repo"},
  190. {"GET", "/repos/:owner/:repo/collaborators"},
  191. {"GET", "/repos/:owner/:repo/collaborators/:user"},
  192. {"PUT", "/repos/:owner/:repo/collaborators/:user"},
  193. {"DELETE", "/repos/:owner/:repo/collaborators/:user"},
  194. {"GET", "/repos/:owner/:repo/comments"},
  195. {"GET", "/repos/:owner/:repo/commits/:sha/comments"},
  196. {"POST", "/repos/:owner/:repo/commits/:sha/comments"},
  197. {"GET", "/repos/:owner/:repo/comments/:id"},
  198. //{"PATCH", "/repos/:owner/:repo/comments/:id"},
  199. {"DELETE", "/repos/:owner/:repo/comments/:id"},
  200. {"GET", "/repos/:owner/:repo/commits"},
  201. {"GET", "/repos/:owner/:repo/commits/:sha"},
  202. {"GET", "/repos/:owner/:repo/readme"},
  203. //{"GET", "/repos/:owner/:repo/contents/*path"},
  204. //{"PUT", "/repos/:owner/:repo/contents/*path"},
  205. //{"DELETE", "/repos/:owner/:repo/contents/*path"},
  206. //{"GET", "/repos/:owner/:repo/:archive_format/:ref"},
  207. {"GET", "/repos/:owner/:repo/keys"},
  208. {"GET", "/repos/:owner/:repo/keys/:id"},
  209. {"POST", "/repos/:owner/:repo/keys"},
  210. //{"PATCH", "/repos/:owner/:repo/keys/:id"},
  211. {"DELETE", "/repos/:owner/:repo/keys/:id"},
  212. {"GET", "/repos/:owner/:repo/downloads"},
  213. {"GET", "/repos/:owner/:repo/downloads/:id"},
  214. {"DELETE", "/repos/:owner/:repo/downloads/:id"},
  215. {"GET", "/repos/:owner/:repo/forks"},
  216. {"POST", "/repos/:owner/:repo/forks"},
  217. {"GET", "/repos/:owner/:repo/hooks"},
  218. {"GET", "/repos/:owner/:repo/hooks/:id"},
  219. {"POST", "/repos/:owner/:repo/hooks"},
  220. //{"PATCH", "/repos/:owner/:repo/hooks/:id"},
  221. {"POST", "/repos/:owner/:repo/hooks/:id/tests"},
  222. {"DELETE", "/repos/:owner/:repo/hooks/:id"},
  223. {"POST", "/repos/:owner/:repo/merges"},
  224. {"GET", "/repos/:owner/:repo/releases"},
  225. {"GET", "/repos/:owner/:repo/releases/:id"},
  226. {"POST", "/repos/:owner/:repo/releases"},
  227. //{"PATCH", "/repos/:owner/:repo/releases/:id"},
  228. {"DELETE", "/repos/:owner/:repo/releases/:id"},
  229. {"GET", "/repos/:owner/:repo/releases/:id/assets"},
  230. {"GET", "/repos/:owner/:repo/stats/contributors"},
  231. {"GET", "/repos/:owner/:repo/stats/commit_activity"},
  232. {"GET", "/repos/:owner/:repo/stats/code_frequency"},
  233. {"GET", "/repos/:owner/:repo/stats/participation"},
  234. {"GET", "/repos/:owner/:repo/stats/punch_card"},
  235. {"GET", "/repos/:owner/:repo/statuses/:ref"},
  236. {"POST", "/repos/:owner/:repo/statuses/:ref"},
  237. // Search
  238. {"GET", "/search/repositories"},
  239. {"GET", "/search/code"},
  240. {"GET", "/search/issues"},
  241. {"GET", "/search/users"},
  242. {"GET", "/legacy/issues/search/:owner/:repository/:state/:keyword"},
  243. {"GET", "/legacy/repos/search/:keyword"},
  244. {"GET", "/legacy/user/search/:keyword"},
  245. {"GET", "/legacy/user/email/:email"},
  246. // Users
  247. {"GET", "/users/:user"},
  248. {"GET", "/user"},
  249. //{"PATCH", "/user"},
  250. {"GET", "/users"},
  251. {"GET", "/user/emails"},
  252. {"POST", "/user/emails"},
  253. {"DELETE", "/user/emails"},
  254. {"GET", "/users/:user/followers"},
  255. {"GET", "/user/followers"},
  256. {"GET", "/users/:user/following"},
  257. {"GET", "/user/following"},
  258. {"GET", "/user/following/:user"},
  259. {"GET", "/users/:user/following/:target_user"},
  260. {"PUT", "/user/following/:user"},
  261. {"DELETE", "/user/following/:user"},
  262. {"GET", "/users/:user/keys"},
  263. {"GET", "/user/keys"},
  264. {"GET", "/user/keys/:id"},
  265. {"POST", "/user/keys"},
  266. //{"PATCH", "/user/keys/:id"},
  267. {"DELETE", "/user/keys/:id"},
  268. }
  269. func TestGithubAPI(t *testing.T) {
  270. router := New()
  271. for _, route := range githubAPI {
  272. router.Handle(route.method, route.path, HandlersChain{func(c *Context) {
  273. output := H{"status": "good"}
  274. for _, param := range c.Params {
  275. output[param.Key] = param.Value
  276. }
  277. c.JSON(200, output)
  278. }})
  279. }
  280. for _, route := range githubAPI {
  281. path, values := exampleFromPath(route.path)
  282. w := performRequest(router, route.method, path)
  283. // TEST
  284. assert.Contains(t, w.Body.String(), "\"status\":\"good\"")
  285. for _, value := range values {
  286. str := fmt.Sprintf("\"%s\":\"%s\"", value.Key, value.Value)
  287. assert.Contains(t, w.Body.String(), str)
  288. }
  289. }
  290. }
  291. func exampleFromPath(path string) (string, Params) {
  292. output := new(bytes.Buffer)
  293. params := make(Params, 0, 6)
  294. start := -1
  295. for i, c := range path {
  296. if c == ':' {
  297. start = i + 1
  298. }
  299. if start >= 0 {
  300. if c == '/' {
  301. value := fmt.Sprint(rand.Intn(100000))
  302. params = append(params, Param{
  303. Key: path[start:i],
  304. Value: value,
  305. })
  306. output.WriteString(value)
  307. output.WriteRune(c)
  308. start = -1
  309. }
  310. } else {
  311. output.WriteRune(c)
  312. }
  313. }
  314. if start >= 0 {
  315. value := fmt.Sprint(rand.Intn(100000))
  316. params = append(params, Param{
  317. Key: path[start:len(path)],
  318. Value: value,
  319. })
  320. output.WriteString(value)
  321. }
  322. return output.String(), params
  323. }