gin_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  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. "crypto/tls"
  7. "fmt"
  8. "html/template"
  9. "io/ioutil"
  10. "net/http"
  11. "net/http/httptest"
  12. "reflect"
  13. "strconv"
  14. "sync/atomic"
  15. "testing"
  16. "time"
  17. "github.com/stretchr/testify/assert"
  18. )
  19. func formatAsDate(t time.Time) string {
  20. year, month, day := t.Date()
  21. return fmt.Sprintf("%d/%02d/%02d", year, month, day)
  22. }
  23. func setupHTMLFiles(t *testing.T, mode string, tls bool, loadMethod func(*Engine)) *httptest.Server {
  24. SetMode(mode)
  25. router := New()
  26. router.Delims("{[{", "}]}")
  27. router.SetFuncMap(template.FuncMap{
  28. "formatAsDate": formatAsDate,
  29. })
  30. loadMethod(router)
  31. router.GET("/test", func(c *Context) {
  32. c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"})
  33. })
  34. router.GET("/raw", func(c *Context) {
  35. c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{
  36. "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
  37. })
  38. })
  39. var ts *httptest.Server
  40. if tls {
  41. ts = httptest.NewTLSServer(router)
  42. } else {
  43. ts = httptest.NewServer(router)
  44. }
  45. return ts
  46. }
  47. func TestLoadHTMLGlobDebugMode(t *testing.T) {
  48. ts := setupHTMLFiles(
  49. t,
  50. DebugMode,
  51. false,
  52. func(router *Engine) {
  53. router.LoadHTMLGlob("./testdata/template/*")
  54. },
  55. )
  56. defer ts.Close()
  57. res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
  58. if err != nil {
  59. fmt.Println(err)
  60. }
  61. resp, _ := ioutil.ReadAll(res.Body)
  62. assert.Equal(t, "<h1>Hello world</h1>", string(resp))
  63. }
  64. func TestLoadHTMLGlobTestMode(t *testing.T) {
  65. ts := setupHTMLFiles(
  66. t,
  67. TestMode,
  68. false,
  69. func(router *Engine) {
  70. router.LoadHTMLGlob("./testdata/template/*")
  71. },
  72. )
  73. defer ts.Close()
  74. res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
  75. if err != nil {
  76. fmt.Println(err)
  77. }
  78. resp, _ := ioutil.ReadAll(res.Body)
  79. assert.Equal(t, "<h1>Hello world</h1>", string(resp))
  80. }
  81. func TestLoadHTMLGlobReleaseMode(t *testing.T) {
  82. ts := setupHTMLFiles(
  83. t,
  84. ReleaseMode,
  85. false,
  86. func(router *Engine) {
  87. router.LoadHTMLGlob("./testdata/template/*")
  88. },
  89. )
  90. defer ts.Close()
  91. res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
  92. if err != nil {
  93. fmt.Println(err)
  94. }
  95. resp, _ := ioutil.ReadAll(res.Body)
  96. assert.Equal(t, "<h1>Hello world</h1>", string(resp))
  97. }
  98. func TestLoadHTMLGlobUsingTLS(t *testing.T) {
  99. ts := setupHTMLFiles(
  100. t,
  101. DebugMode,
  102. true,
  103. func(router *Engine) {
  104. router.LoadHTMLGlob("./testdata/template/*")
  105. },
  106. )
  107. defer ts.Close()
  108. // Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error
  109. tr := &http.Transport{
  110. TLSClientConfig: &tls.Config{
  111. InsecureSkipVerify: true,
  112. },
  113. }
  114. client := &http.Client{Transport: tr}
  115. res, err := client.Get(fmt.Sprintf("%s/test", ts.URL))
  116. if err != nil {
  117. fmt.Println(err)
  118. }
  119. resp, _ := ioutil.ReadAll(res.Body)
  120. assert.Equal(t, "<h1>Hello world</h1>", string(resp))
  121. }
  122. func TestLoadHTMLGlobFromFuncMap(t *testing.T) {
  123. ts := setupHTMLFiles(
  124. t,
  125. DebugMode,
  126. false,
  127. func(router *Engine) {
  128. router.LoadHTMLGlob("./testdata/template/*")
  129. },
  130. )
  131. defer ts.Close()
  132. res, err := http.Get(fmt.Sprintf("%s/raw", ts.URL))
  133. if err != nil {
  134. fmt.Println(err)
  135. }
  136. resp, _ := ioutil.ReadAll(res.Body)
  137. assert.Equal(t, "Date: 2017/07/01\n", string(resp))
  138. }
  139. func init() {
  140. SetMode(TestMode)
  141. }
  142. func TestCreateEngine(t *testing.T) {
  143. router := New()
  144. assert.Equal(t, "/", router.basePath)
  145. assert.Equal(t, router.engine, router)
  146. assert.Empty(t, router.Handlers)
  147. }
  148. func TestLoadHTMLFilesTestMode(t *testing.T) {
  149. ts := setupHTMLFiles(
  150. t,
  151. TestMode,
  152. false,
  153. func(router *Engine) {
  154. router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
  155. },
  156. )
  157. defer ts.Close()
  158. res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
  159. if err != nil {
  160. fmt.Println(err)
  161. }
  162. resp, _ := ioutil.ReadAll(res.Body)
  163. assert.Equal(t, "<h1>Hello world</h1>", string(resp))
  164. }
  165. func TestLoadHTMLFilesDebugMode(t *testing.T) {
  166. ts := setupHTMLFiles(
  167. t,
  168. DebugMode,
  169. false,
  170. func(router *Engine) {
  171. router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
  172. },
  173. )
  174. defer ts.Close()
  175. res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
  176. if err != nil {
  177. fmt.Println(err)
  178. }
  179. resp, _ := ioutil.ReadAll(res.Body)
  180. assert.Equal(t, "<h1>Hello world</h1>", string(resp))
  181. }
  182. func TestLoadHTMLFilesReleaseMode(t *testing.T) {
  183. ts := setupHTMLFiles(
  184. t,
  185. ReleaseMode,
  186. false,
  187. func(router *Engine) {
  188. router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
  189. },
  190. )
  191. defer ts.Close()
  192. res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
  193. if err != nil {
  194. fmt.Println(err)
  195. }
  196. resp, _ := ioutil.ReadAll(res.Body)
  197. assert.Equal(t, "<h1>Hello world</h1>", string(resp))
  198. }
  199. func TestLoadHTMLFilesUsingTLS(t *testing.T) {
  200. ts := setupHTMLFiles(
  201. t,
  202. TestMode,
  203. true,
  204. func(router *Engine) {
  205. router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
  206. },
  207. )
  208. defer ts.Close()
  209. // Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error
  210. tr := &http.Transport{
  211. TLSClientConfig: &tls.Config{
  212. InsecureSkipVerify: true,
  213. },
  214. }
  215. client := &http.Client{Transport: tr}
  216. res, err := client.Get(fmt.Sprintf("%s/test", ts.URL))
  217. if err != nil {
  218. fmt.Println(err)
  219. }
  220. resp, _ := ioutil.ReadAll(res.Body)
  221. assert.Equal(t, "<h1>Hello world</h1>", string(resp))
  222. }
  223. func TestLoadHTMLFilesFuncMap(t *testing.T) {
  224. ts := setupHTMLFiles(
  225. t,
  226. TestMode,
  227. false,
  228. func(router *Engine) {
  229. router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
  230. },
  231. )
  232. defer ts.Close()
  233. res, err := http.Get(fmt.Sprintf("%s/raw", ts.URL))
  234. if err != nil {
  235. fmt.Println(err)
  236. }
  237. resp, _ := ioutil.ReadAll(res.Body)
  238. assert.Equal(t, "Date: 2017/07/01\n", string(resp))
  239. }
  240. func TestAddRoute(t *testing.T) {
  241. router := New()
  242. router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
  243. assert.Len(t, router.trees, 1)
  244. assert.NotNil(t, router.trees.get("GET"))
  245. assert.Nil(t, router.trees.get("POST"))
  246. router.addRoute("POST", "/", HandlersChain{func(_ *Context) {}})
  247. assert.Len(t, router.trees, 2)
  248. assert.NotNil(t, router.trees.get("GET"))
  249. assert.NotNil(t, router.trees.get("POST"))
  250. router.addRoute("POST", "/post", HandlersChain{func(_ *Context) {}})
  251. assert.Len(t, router.trees, 2)
  252. }
  253. func TestAddRouteFails(t *testing.T) {
  254. router := New()
  255. assert.Panics(t, func() { router.addRoute("", "/", HandlersChain{func(_ *Context) {}}) })
  256. assert.Panics(t, func() { router.addRoute("GET", "a", HandlersChain{func(_ *Context) {}}) })
  257. assert.Panics(t, func() { router.addRoute("GET", "/", HandlersChain{}) })
  258. router.addRoute("POST", "/post", HandlersChain{func(_ *Context) {}})
  259. assert.Panics(t, func() {
  260. router.addRoute("POST", "/post", HandlersChain{func(_ *Context) {}})
  261. })
  262. }
  263. func TestCreateDefaultRouter(t *testing.T) {
  264. router := Default()
  265. assert.Len(t, router.Handlers, 2)
  266. }
  267. func TestNoRouteWithoutGlobalHandlers(t *testing.T) {
  268. var middleware0 HandlerFunc = func(c *Context) {}
  269. var middleware1 HandlerFunc = func(c *Context) {}
  270. router := New()
  271. router.NoRoute(middleware0)
  272. assert.Nil(t, router.Handlers)
  273. assert.Len(t, router.noRoute, 1)
  274. assert.Len(t, router.allNoRoute, 1)
  275. compareFunc(t, router.noRoute[0], middleware0)
  276. compareFunc(t, router.allNoRoute[0], middleware0)
  277. router.NoRoute(middleware1, middleware0)
  278. assert.Len(t, router.noRoute, 2)
  279. assert.Len(t, router.allNoRoute, 2)
  280. compareFunc(t, router.noRoute[0], middleware1)
  281. compareFunc(t, router.allNoRoute[0], middleware1)
  282. compareFunc(t, router.noRoute[1], middleware0)
  283. compareFunc(t, router.allNoRoute[1], middleware0)
  284. }
  285. func TestNoRouteWithGlobalHandlers(t *testing.T) {
  286. var middleware0 HandlerFunc = func(c *Context) {}
  287. var middleware1 HandlerFunc = func(c *Context) {}
  288. var middleware2 HandlerFunc = func(c *Context) {}
  289. router := New()
  290. router.Use(middleware2)
  291. router.NoRoute(middleware0)
  292. assert.Len(t, router.allNoRoute, 2)
  293. assert.Len(t, router.Handlers, 1)
  294. assert.Len(t, router.noRoute, 1)
  295. compareFunc(t, router.Handlers[0], middleware2)
  296. compareFunc(t, router.noRoute[0], middleware0)
  297. compareFunc(t, router.allNoRoute[0], middleware2)
  298. compareFunc(t, router.allNoRoute[1], middleware0)
  299. router.Use(middleware1)
  300. assert.Len(t, router.allNoRoute, 3)
  301. assert.Len(t, router.Handlers, 2)
  302. assert.Len(t, router.noRoute, 1)
  303. compareFunc(t, router.Handlers[0], middleware2)
  304. compareFunc(t, router.Handlers[1], middleware1)
  305. compareFunc(t, router.noRoute[0], middleware0)
  306. compareFunc(t, router.allNoRoute[0], middleware2)
  307. compareFunc(t, router.allNoRoute[1], middleware1)
  308. compareFunc(t, router.allNoRoute[2], middleware0)
  309. }
  310. func TestNoMethodWithoutGlobalHandlers(t *testing.T) {
  311. var middleware0 HandlerFunc = func(c *Context) {}
  312. var middleware1 HandlerFunc = func(c *Context) {}
  313. router := New()
  314. router.NoMethod(middleware0)
  315. assert.Empty(t, router.Handlers)
  316. assert.Len(t, router.noMethod, 1)
  317. assert.Len(t, router.allNoMethod, 1)
  318. compareFunc(t, router.noMethod[0], middleware0)
  319. compareFunc(t, router.allNoMethod[0], middleware0)
  320. router.NoMethod(middleware1, middleware0)
  321. assert.Len(t, router.noMethod, 2)
  322. assert.Len(t, router.allNoMethod, 2)
  323. compareFunc(t, router.noMethod[0], middleware1)
  324. compareFunc(t, router.allNoMethod[0], middleware1)
  325. compareFunc(t, router.noMethod[1], middleware0)
  326. compareFunc(t, router.allNoMethod[1], middleware0)
  327. }
  328. func TestRebuild404Handlers(t *testing.T) {
  329. }
  330. func TestNoMethodWithGlobalHandlers(t *testing.T) {
  331. var middleware0 HandlerFunc = func(c *Context) {}
  332. var middleware1 HandlerFunc = func(c *Context) {}
  333. var middleware2 HandlerFunc = func(c *Context) {}
  334. router := New()
  335. router.Use(middleware2)
  336. router.NoMethod(middleware0)
  337. assert.Len(t, router.allNoMethod, 2)
  338. assert.Len(t, router.Handlers, 1)
  339. assert.Len(t, router.noMethod, 1)
  340. compareFunc(t, router.Handlers[0], middleware2)
  341. compareFunc(t, router.noMethod[0], middleware0)
  342. compareFunc(t, router.allNoMethod[0], middleware2)
  343. compareFunc(t, router.allNoMethod[1], middleware0)
  344. router.Use(middleware1)
  345. assert.Len(t, router.allNoMethod, 3)
  346. assert.Len(t, router.Handlers, 2)
  347. assert.Len(t, router.noMethod, 1)
  348. compareFunc(t, router.Handlers[0], middleware2)
  349. compareFunc(t, router.Handlers[1], middleware1)
  350. compareFunc(t, router.noMethod[0], middleware0)
  351. compareFunc(t, router.allNoMethod[0], middleware2)
  352. compareFunc(t, router.allNoMethod[1], middleware1)
  353. compareFunc(t, router.allNoMethod[2], middleware0)
  354. }
  355. func compareFunc(t *testing.T, a, b interface{}) {
  356. sf1 := reflect.ValueOf(a)
  357. sf2 := reflect.ValueOf(b)
  358. if sf1.Pointer() != sf2.Pointer() {
  359. t.Error("different functions")
  360. }
  361. }
  362. func TestListOfRoutes(t *testing.T) {
  363. router := New()
  364. router.GET("/favicon.ico", handlerTest1)
  365. router.GET("/", handlerTest1)
  366. group := router.Group("/users")
  367. {
  368. group.GET("/", handlerTest2)
  369. group.GET("/:id", handlerTest1)
  370. group.POST("/:id", handlerTest2)
  371. }
  372. router.Static("/static", ".")
  373. list := router.Routes()
  374. assert.Len(t, list, 7)
  375. assertRoutePresent(t, list, RouteInfo{
  376. Method: "GET",
  377. Path: "/favicon.ico",
  378. Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
  379. })
  380. assertRoutePresent(t, list, RouteInfo{
  381. Method: "GET",
  382. Path: "/",
  383. Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
  384. })
  385. assertRoutePresent(t, list, RouteInfo{
  386. Method: "GET",
  387. Path: "/users/",
  388. Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest2$",
  389. })
  390. assertRoutePresent(t, list, RouteInfo{
  391. Method: "GET",
  392. Path: "/users/:id",
  393. Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
  394. })
  395. assertRoutePresent(t, list, RouteInfo{
  396. Method: "POST",
  397. Path: "/users/:id",
  398. Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest2$",
  399. })
  400. }
  401. func TestEngineHandleContext(t *testing.T) {
  402. r := New()
  403. r.GET("/", func(c *Context) {
  404. c.Request.URL.Path = "/v2"
  405. r.HandleContext(c)
  406. })
  407. v2 := r.Group("/v2")
  408. {
  409. v2.GET("/", func(c *Context) {})
  410. }
  411. assert.NotPanics(t, func() {
  412. w := performRequest(r, "GET", "/")
  413. assert.Equal(t, 301, w.Code)
  414. })
  415. }
  416. func TestEngineHandleContextManyReEntries(t *testing.T) {
  417. expectValue := 10000
  418. var handlerCounter, middlewareCounter int64
  419. r := New()
  420. r.Use(func(c *Context) {
  421. atomic.AddInt64(&middlewareCounter, 1)
  422. })
  423. r.GET("/:count", func(c *Context) {
  424. countStr := c.Param("count")
  425. count, err := strconv.Atoi(countStr)
  426. assert.NoError(t, err)
  427. n, err := c.Writer.Write([]byte("."))
  428. assert.NoError(t, err)
  429. assert.Equal(t, 1, n)
  430. switch {
  431. case count > 0:
  432. c.Request.URL.Path = "/" + strconv.Itoa(count-1)
  433. r.HandleContext(c)
  434. }
  435. }, func(c *Context) {
  436. atomic.AddInt64(&handlerCounter, 1)
  437. })
  438. assert.NotPanics(t, func() {
  439. w := performRequest(r, "GET", "/"+strconv.Itoa(expectValue-1)) // include 0 value
  440. assert.Equal(t, 200, w.Code)
  441. assert.Equal(t, expectValue, w.Body.Len())
  442. })
  443. assert.Equal(t, int64(expectValue), handlerCounter)
  444. assert.Equal(t, int64(expectValue), middlewareCounter)
  445. }
  446. func assertRoutePresent(t *testing.T, gotRoutes RoutesInfo, wantRoute RouteInfo) {
  447. for _, gotRoute := range gotRoutes {
  448. if gotRoute.Path == wantRoute.Path && gotRoute.Method == wantRoute.Method {
  449. assert.Regexp(t, wantRoute.Handler, gotRoute.Handler)
  450. return
  451. }
  452. }
  453. t.Errorf("route not found: %v", wantRoute)
  454. }
  455. func handlerTest1(c *Context) {}
  456. func handlerTest2(c *Context) {}