routes_test.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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. "errors"
  7. "io/ioutil"
  8. "net/http"
  9. "net/http/httptest"
  10. "os"
  11. "path"
  12. "strings"
  13. "testing"
  14. "github.com/stretchr/testify/assert"
  15. )
  16. func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
  17. req, _ := http.NewRequest(method, path, nil)
  18. w := httptest.NewRecorder()
  19. r.ServeHTTP(w, req)
  20. return w
  21. }
  22. func testRouteOK(method string, t *testing.T) {
  23. // SETUP
  24. passed := false
  25. r := New()
  26. r.Handle(method, "/test", []HandlerFunc{func(c *Context) {
  27. passed = true
  28. }})
  29. // RUN
  30. w := performRequest(r, method, "/test")
  31. // TEST
  32. assert.True(t, passed)
  33. assert.Equal(t, w.Code, http.StatusOK)
  34. }
  35. // TestSingleRouteOK tests that POST route is correctly invoked.
  36. func testRouteNotOK(method string, t *testing.T) {
  37. // SETUP
  38. passed := false
  39. router := New()
  40. router.Handle(method, "/test_2", []HandlerFunc{func(c *Context) {
  41. passed = true
  42. }})
  43. // RUN
  44. w := performRequest(router, method, "/test")
  45. // TEST
  46. assert.False(t, passed)
  47. assert.Equal(t, w.Code, http.StatusNotFound)
  48. }
  49. // TestSingleRouteOK tests that POST route is correctly invoked.
  50. func testRouteNotOK2(method string, t *testing.T) {
  51. // SETUP
  52. passed := false
  53. router := New()
  54. var methodRoute string
  55. if method == "POST" {
  56. methodRoute = "GET"
  57. } else {
  58. methodRoute = "POST"
  59. }
  60. router.Handle(methodRoute, "/test", []HandlerFunc{func(c *Context) {
  61. passed = true
  62. }})
  63. // RUN
  64. w := performRequest(router, method, "/test")
  65. // TEST
  66. assert.False(t, passed)
  67. assert.Equal(t, w.Code, http.StatusMethodNotAllowed)
  68. }
  69. func TestRouterGroupRouteOK(t *testing.T) {
  70. testRouteOK("POST", t)
  71. testRouteOK("DELETE", t)
  72. testRouteOK("PATCH", t)
  73. testRouteOK("PUT", t)
  74. testRouteOK("OPTIONS", t)
  75. testRouteOK("HEAD", t)
  76. }
  77. // TestSingleRouteOK tests that POST route is correctly invoked.
  78. func TestRouteNotOK(t *testing.T) {
  79. testRouteNotOK("POST", t)
  80. testRouteNotOK("DELETE", t)
  81. testRouteNotOK("PATCH", t)
  82. testRouteNotOK("PUT", t)
  83. testRouteNotOK("OPTIONS", t)
  84. testRouteNotOK("HEAD", t)
  85. }
  86. // TestSingleRouteOK tests that POST route is correctly invoked.
  87. func TestRouteNotOK2(t *testing.T) {
  88. testRouteNotOK2("POST", t)
  89. testRouteNotOK2("DELETE", t)
  90. testRouteNotOK2("PATCH", t)
  91. testRouteNotOK2("PUT", t)
  92. testRouteNotOK2("OPTIONS", t)
  93. testRouteNotOK2("HEAD", t)
  94. }
  95. // TestHandleStaticFile - ensure the static file handles properly
  96. func TestHandleStaticFile(t *testing.T) {
  97. // SETUP file
  98. testRoot, _ := os.Getwd()
  99. f, err := ioutil.TempFile(testRoot, "")
  100. if err != nil {
  101. t.Error(err)
  102. }
  103. defer os.Remove(f.Name())
  104. filePath := path.Join("/", path.Base(f.Name()))
  105. f.WriteString("Gin Web Framework")
  106. f.Close()
  107. // SETUP gin
  108. r := New()
  109. r.Static("./", testRoot)
  110. // RUN
  111. w := performRequest(r, "GET", filePath)
  112. // TEST
  113. if w.Code != 200 {
  114. t.Errorf("Response code should be 200, was: %d", w.Code)
  115. }
  116. if w.Body.String() != "Gin Web Framework" {
  117. t.Errorf("Response should be test, was: %s", w.Body.String())
  118. }
  119. if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
  120. t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
  121. }
  122. }
  123. // TestHandleStaticDir - ensure the root/sub dir handles properly
  124. func TestHandleStaticDir(t *testing.T) {
  125. // SETUP
  126. r := New()
  127. r.Static("/", "./")
  128. // RUN
  129. w := performRequest(r, "GET", "/")
  130. // TEST
  131. bodyAsString := w.Body.String()
  132. if w.Code != 200 {
  133. t.Errorf("Response code should be 200, was: %d", w.Code)
  134. }
  135. if len(bodyAsString) == 0 {
  136. t.Errorf("Got empty body instead of file tree")
  137. }
  138. if !strings.Contains(bodyAsString, "gin.go") {
  139. t.Errorf("Can't find:`gin.go` in file tree: %s", bodyAsString)
  140. }
  141. if w.HeaderMap.Get("Content-Type") != "text/html; charset=utf-8" {
  142. t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
  143. }
  144. }
  145. // TestHandleHeadToDir - ensure the root/sub dir handles properly
  146. func TestHandleHeadToDir(t *testing.T) {
  147. // SETUP
  148. router := New()
  149. router.Static("/", "./")
  150. // RUN
  151. w := performRequest(router, "HEAD", "/")
  152. // TEST
  153. bodyAsString := w.Body.String()
  154. assert.Equal(t, w.Code, 200)
  155. assert.NotEmpty(t, bodyAsString)
  156. assert.Contains(t, bodyAsString, "gin.go")
  157. assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
  158. }
  159. func TestContextGeneralCase(t *testing.T) {
  160. signature := ""
  161. router := New()
  162. router.Use(func(c *Context) {
  163. signature += "A"
  164. c.Next()
  165. signature += "B"
  166. })
  167. router.Use(func(c *Context) {
  168. signature += "C"
  169. })
  170. router.GET("/", func(c *Context) {
  171. signature += "D"
  172. })
  173. router.NoRoute(func(c *Context) {
  174. signature += "X"
  175. })
  176. router.NoMethod(func(c *Context) {
  177. signature += "X"
  178. })
  179. // RUN
  180. w := performRequest(router, "GET", "/")
  181. // TEST
  182. assert.Equal(t, w.Code, 200)
  183. assert.Equal(t, signature, "ACDB")
  184. }
  185. // TestBadAbortHandlersChain - ensure that Abort after switch context will not interrupt pending handlers
  186. func TestContextNextOrder(t *testing.T) {
  187. signature := ""
  188. router := New()
  189. router.Use(func(c *Context) {
  190. signature += "A"
  191. c.Next()
  192. signature += "B"
  193. })
  194. router.Use(func(c *Context) {
  195. signature += "C"
  196. c.Next()
  197. signature += "D"
  198. })
  199. router.NoRoute(func(c *Context) {
  200. signature += "E"
  201. c.Next()
  202. signature += "F"
  203. }, func(c *Context) {
  204. signature += "G"
  205. c.Next()
  206. signature += "H"
  207. })
  208. // RUN
  209. w := performRequest(router, "GET", "/")
  210. // TEST
  211. assert.Equal(t, w.Code, 404)
  212. assert.Equal(t, signature, "ACEGHFDB")
  213. }
  214. // TestAbortHandlersChain - ensure that Abort interrupt used middlewares in fifo order
  215. func TestAbortHandlersChain(t *testing.T) {
  216. signature := ""
  217. router := New()
  218. router.Use(func(c *Context) {
  219. signature += "A"
  220. })
  221. router.Use(func(c *Context) {
  222. signature += "C"
  223. c.AbortWithStatus(409)
  224. c.Next()
  225. signature += "D"
  226. })
  227. router.GET("/", func(c *Context) {
  228. signature += "D"
  229. c.Next()
  230. signature += "E"
  231. })
  232. // RUN
  233. w := performRequest(router, "GET", "/")
  234. // TEST
  235. assert.Equal(t, signature, "ACD")
  236. assert.Equal(t, w.Code, 409)
  237. }
  238. func TestAbortHandlersChainAndNext(t *testing.T) {
  239. signature := ""
  240. router := New()
  241. router.Use(func(c *Context) {
  242. signature += "A"
  243. c.AbortWithStatus(410)
  244. c.Next()
  245. signature += "B"
  246. })
  247. router.GET("/", func(c *Context) {
  248. signature += "C"
  249. c.Next()
  250. })
  251. // RUN
  252. w := performRequest(router, "GET", "/")
  253. // TEST
  254. assert.Equal(t, signature, "AB")
  255. assert.Equal(t, w.Code, 410)
  256. }
  257. // TestContextParamsGet tests that a parameter can be parsed from the URL.
  258. func TestContextParamsByName(t *testing.T) {
  259. name := ""
  260. lastName := ""
  261. router := New()
  262. router.GET("/test/:name/:last_name", func(c *Context) {
  263. name = c.Params.ByName("name")
  264. lastName = c.Params.ByName("last_name")
  265. })
  266. // RUN
  267. w := performRequest(router, "GET", "/test/john/smith")
  268. // TEST
  269. assert.Equal(t, w.Code, 200)
  270. assert.Equal(t, name, "john")
  271. assert.Equal(t, lastName, "smith")
  272. }
  273. // TestFailHandlersChain - ensure that Fail interrupt used middlewares in fifo order as
  274. // as well as Abort
  275. func TestFailHandlersChain(t *testing.T) {
  276. // SETUP
  277. var stepsPassed int = 0
  278. r := New()
  279. r.Use(func(context *Context) {
  280. stepsPassed += 1
  281. context.Fail(500, errors.New("foo"))
  282. })
  283. r.Use(func(context *Context) {
  284. stepsPassed += 1
  285. context.Next()
  286. stepsPassed += 1
  287. })
  288. // RUN
  289. w := performRequest(r, "GET", "/")
  290. // TEST
  291. assert.Equal(t, w.Code, 500, "Response code should be Server error, was: %d", w.Code)
  292. assert.Equal(t, stepsPassed, 1, "Falied to switch context in handler function: %d", stepsPassed)
  293. }