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
5package gin
6
7import (
8	"net/http"
9	"testing"
10
11	"github.com/stretchr/testify/assert"
12)
13
14func init() {
15	SetMode(TestMode)
16}
17
18func TestRouterGroupBasic(t *testing.T) {
19	router := New()
20	group := router.Group("/hola", func(c *Context) {})
21	group.Use(func(c *Context) {})
22
23	assert.Len(t, group.Handlers, 2)
24	assert.Equal(t, "/hola", group.BasePath())
25	assert.Equal(t, router, group.engine)
26
27	group2 := group.Group("manu")
28	group2.Use(func(c *Context) {}, func(c *Context) {})
29
30	assert.Len(t, group2.Handlers, 4)
31	assert.Equal(t, "/hola/manu", group2.BasePath())
32	assert.Equal(t, router, group2.engine)
33}
34
35func TestRouterGroupBasicHandle(t *testing.T) {
36	performRequestInGroup(t, http.MethodGet)
37	performRequestInGroup(t, http.MethodPost)
38	performRequestInGroup(t, http.MethodPut)
39	performRequestInGroup(t, http.MethodPatch)
40	performRequestInGroup(t, http.MethodDelete)
41	performRequestInGroup(t, http.MethodHead)
42	performRequestInGroup(t, http.MethodOptions)
43}
44
45func performRequestInGroup(t *testing.T, method string) {
46	router := New()
47	v1 := router.Group("v1", func(c *Context) {})
48	assert.Equal(t, "/v1", v1.BasePath())
49
50	login := v1.Group("/login/", func(c *Context) {}, func(c *Context) {})
51	assert.Equal(t, "/v1/login/", login.BasePath())
52
53	handler := func(c *Context) {
54		c.String(http.StatusBadRequest, "the method was %s and index %d", c.Request.Method, c.index)
55	}
56
57	switch method {
58	case http.MethodGet:
59		v1.GET("/test", handler)
60		login.GET("/test", handler)
61	case http.MethodPost:
62		v1.POST("/test", handler)
63		login.POST("/test", handler)
64	case http.MethodPut:
65		v1.PUT("/test", handler)
66		login.PUT("/test", handler)
67	case http.MethodPatch:
68		v1.PATCH("/test", handler)
69		login.PATCH("/test", handler)
70	case http.MethodDelete:
71		v1.DELETE("/test", handler)
72		login.DELETE("/test", handler)
73	case http.MethodHead:
74		v1.HEAD("/test", handler)
75		login.HEAD("/test", handler)
76	case http.MethodOptions:
77		v1.OPTIONS("/test", handler)
78		login.OPTIONS("/test", handler)
79	default:
80		panic("unknown method")
81	}
82
83	w := performRequest(router, method, "/v1/login/test")
84	assert.Equal(t, http.StatusBadRequest, w.Code)
85	assert.Equal(t, "the method was "+method+" and index 3", w.Body.String())
86
87	w = performRequest(router, method, "/v1/test")
88	assert.Equal(t, http.StatusBadRequest, w.Code)
89	assert.Equal(t, "the method was "+method+" and index 1", w.Body.String())
90}
91
92func TestRouterGroupInvalidStatic(t *testing.T) {
93	router := New()
94	assert.Panics(t, func() {
95		router.Static("/path/:param", "/")
96	})
97
98	assert.Panics(t, func() {
99		router.Static("/path/*param", "/")
100	})
101}
102
103func TestRouterGroupInvalidStaticFile(t *testing.T) {
104	router := New()
105	assert.Panics(t, func() {
106		router.StaticFile("/path/:param", "favicon.ico")
107	})
108
109	assert.Panics(t, func() {
110		router.StaticFile("/path/*param", "favicon.ico")
111	})
112}
113
114func TestRouterGroupTooManyHandlers(t *testing.T) {
115	router := New()
116	handlers1 := make([]HandlerFunc, 40)
117	router.Use(handlers1...)
118
119	handlers2 := make([]HandlerFunc, 26)
120	assert.Panics(t, func() {
121		router.Use(handlers2...)
122	})
123	assert.Panics(t, func() {
124		router.GET("/", handlers2...)
125	})
126}
127
128func TestRouterGroupBadMethod(t *testing.T) {
129	router := New()
130	assert.Panics(t, func() {
131		router.Handle(http.MethodGet, "/")
132	})
133	assert.Panics(t, func() {
134		router.Handle(" GET", "/")
135	})
136	assert.Panics(t, func() {
137		router.Handle("GET ", "/")
138	})
139	assert.Panics(t, func() {
140		router.Handle("", "/")
141	})
142	assert.Panics(t, func() {
143		router.Handle("PO ST", "/")
144	})
145	assert.Panics(t, func() {
146		router.Handle("1GET", "/")
147	})
148	assert.Panics(t, func() {
149		router.Handle("PATCh", "/")
150	})
151}
152
153func TestRouterGroupPipeline(t *testing.T) {
154	router := New()
155	testRoutesInterface(t, router)
156
157	v1 := router.Group("/v1")
158	testRoutesInterface(t, v1)
159}
160
161func testRoutesInterface(t *testing.T, r IRoutes) {
162	handler := func(c *Context) {}
163	assert.Equal(t, r, r.Use(handler))
164
165	assert.Equal(t, r, r.Handle(http.MethodGet, "/handler", handler))
166	assert.Equal(t, r, r.Any("/any", handler))
167	assert.Equal(t, r, r.GET("/", handler))
168	assert.Equal(t, r, r.POST("/", handler))
169	assert.Equal(t, r, r.DELETE("/", handler))
170	assert.Equal(t, r, r.PATCH("/", handler))
171	assert.Equal(t, r, r.PUT("/", handler))
172	assert.Equal(t, r, r.OPTIONS("/", handler))
173	assert.Equal(t, r, r.HEAD("/", handler))
174
175	assert.Equal(t, r, r.StaticFile("/file", "."))
176	assert.Equal(t, r, r.Static("/static", "."))
177	assert.Equal(t, r, r.StaticFS("/static2", Dir(".", false)))
178}
179