github.com/cloudwego/hertz@v0.9.3/pkg/route/routergroup_test.go (about) 1 /* 2 * Copyright 2022 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * The MIT License (MIT) 16 * 17 * Copyright (c) 2014 Manuel MartÃnez-Almeida 18 * 19 * Permission is hereby granted, free of charge, to any person obtaining a copy 20 * of this software and associated documentation files (the "Software"), to deal 21 * in the Software without restriction, including without limitation the rights 22 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 * copies of the Software, and to permit persons to whom the Software is 24 * furnished to do so, subject to the following conditions: 25 * 26 * The above copyright notice and this permission notice shall be included in 27 * all copies or substantial portions of the Software. 28 * 29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 * THE SOFTWARE. 36 * 37 * This file may have been modified by CloudWeGo authors. All CloudWeGo 38 * Modifications are Copyright 2022 CloudWeGo Authors 39 */ 40 41 package route 42 43 import ( 44 "context" 45 "io/ioutil" 46 "net/http" 47 "os" 48 "testing" 49 50 "github.com/cloudwego/hertz/pkg/app" 51 "github.com/cloudwego/hertz/pkg/common/config" 52 "github.com/cloudwego/hertz/pkg/common/test/assert" 53 ) 54 55 func TestRouterGroupBasic(t *testing.T) { 56 cfg := config.NewOptions(nil) 57 router := NewEngine(cfg) 58 group := router.Group("/hola", func(c context.Context, ctx *app.RequestContext) {}) 59 group.Use(func(c context.Context, ctx *app.RequestContext) {}) 60 61 assert.DeepEqual(t, len(group.Handlers), 2) 62 assert.DeepEqual(t, "/hola", group.BasePath()) 63 assert.DeepEqual(t, router, group.engine) 64 65 group2 := group.Group("manu") 66 group2.Use(func(c context.Context, ctx *app.RequestContext) {}, func(c context.Context, ctx *app.RequestContext) {}) 67 68 assert.DeepEqual(t, len(group2.Handlers), 4) 69 assert.DeepEqual(t, "/hola/manu", group2.BasePath()) 70 assert.DeepEqual(t, router, group2.engine) 71 } 72 73 func TestRouterGroupBasicHandle(t *testing.T) { 74 performRequestInGroup(t, http.MethodGet) 75 performRequestInGroup(t, http.MethodPost) 76 performRequestInGroup(t, http.MethodPut) 77 performRequestInGroup(t, http.MethodPatch) 78 performRequestInGroup(t, http.MethodDelete) 79 performRequestInGroup(t, http.MethodHead) 80 performRequestInGroup(t, http.MethodOptions) 81 } 82 83 func performRequestInGroup(t *testing.T, method string) { 84 router := NewEngine(config.NewOptions(nil)) 85 v1 := router.Group("v1", func(c context.Context, ctx *app.RequestContext) {}) 86 assert.DeepEqual(t, "/v1", v1.BasePath()) 87 88 login := v1.Group("/login/", func(c context.Context, ctx *app.RequestContext) {}, func(c context.Context, ctx *app.RequestContext) {}) 89 assert.DeepEqual(t, "/v1/login/", login.BasePath()) 90 91 handler := func(c context.Context, ctx *app.RequestContext) { 92 ctx.String(http.StatusBadRequest, "the method was %s and index %d", string(ctx.Request.Header.Method()), ctx.GetIndex()) 93 } 94 95 switch method { 96 case http.MethodGet: 97 v1.GET("/test", handler) 98 login.GET("/test", handler) 99 case http.MethodPost: 100 v1.POST("/test", handler) 101 login.POST("/test", handler) 102 case http.MethodPut: 103 v1.PUT("/test", handler) 104 login.PUT("/test", handler) 105 case http.MethodPatch: 106 v1.PATCH("/test", handler) 107 login.PATCH("/test", handler) 108 case http.MethodDelete: 109 v1.DELETE("/test", handler) 110 login.DELETE("/test", handler) 111 case http.MethodHead: 112 v1.HEAD("/test", handler) 113 login.HEAD("/test", handler) 114 case http.MethodOptions: 115 v1.OPTIONS("/test", handler) 116 login.OPTIONS("/test", handler) 117 default: 118 panic("unknown method") 119 } 120 121 w := performRequest(router, method, "/v1/login/test") 122 assert.DeepEqual(t, http.StatusBadRequest, w.Code) 123 assert.DeepEqual(t, "the method was "+method+" and index 3", w.Body.String()) 124 125 w = performRequest(router, method, "/v1/test") 126 assert.DeepEqual(t, http.StatusBadRequest, w.Code) 127 assert.DeepEqual(t, "the method was "+method+" and index 1", w.Body.String()) 128 } 129 130 func TestRouterGroupStatic(t *testing.T) { 131 router := NewEngine(config.NewOptions(nil)) 132 router.Static("/", ".") 133 w := performRequest(router, "GET", "/engine.go") 134 fd, err := os.Open("./engine.go") 135 if err != nil { 136 panic(err) 137 } 138 assert.DeepEqual(t, http.StatusOK, w.Code) 139 defer fd.Close() 140 content, err := ioutil.ReadAll(fd) 141 if err != nil { 142 panic(err) 143 } 144 assert.DeepEqual(t, string(content), w.Body.String()) 145 } 146 147 func TestRouterGroupStaticFile(t *testing.T) { 148 router := NewEngine(config.NewOptions(nil)) 149 router.StaticFile("file", "./engine.go") 150 w := performRequest(router, "GET", "/file") 151 assert.DeepEqual(t, http.StatusOK, w.Code) 152 fd, err := os.Open("./engine.go") 153 if err != nil { 154 panic(err) 155 } 156 defer fd.Close() 157 content, err := ioutil.ReadAll(fd) 158 if err != nil { 159 panic(err) 160 } 161 assert.DeepEqual(t, string(content), w.Body.String()) 162 } 163 164 func TestRouterGroupInvalidStatic(t *testing.T) { 165 router := &RouterGroup{ 166 Handlers: nil, 167 basePath: "/", 168 root: true, 169 } 170 assert.Panic(t, func() { 171 router.Static("/path/:param", "/") 172 }) 173 174 assert.Panic(t, func() { 175 router.Static("/path/*param", "/") 176 }) 177 } 178 179 func TestRouterGroupInvalidStaticFile(t *testing.T) { 180 router := &RouterGroup{ 181 Handlers: nil, 182 basePath: "/", 183 root: true, 184 } 185 assert.Panic(t, func() { 186 router.StaticFile("/path/:param", "favicon.ico") 187 }) 188 189 assert.Panic(t, func() { 190 router.StaticFile("/path/*param", "favicon.ico") 191 }) 192 } 193 194 func TestRouterGroupTooManyHandlers(t *testing.T) { 195 engine := NewEngine(config.NewOptions(nil)) 196 handlers1 := make([]app.HandlerFunc, 40) 197 engine.Use(handlers1...) 198 199 handlers2 := make([]app.HandlerFunc, 26) 200 assert.Panic(t, func() { 201 engine.Use(handlers2...) 202 }) 203 assert.Panic(t, func() { 204 engine.GET("/", handlers2...) 205 }) 206 } 207 208 func TestRouterGroupBadMethod(t *testing.T) { 209 router := &RouterGroup{ 210 Handlers: nil, 211 basePath: "/", 212 root: true, 213 } 214 assert.Panic(t, func() { 215 router.Handle(http.MethodGet, "/") 216 }) 217 assert.Panic(t, func() { 218 router.Handle(" GET", "/") 219 }) 220 assert.Panic(t, func() { 221 router.Handle("GET ", "/") 222 }) 223 assert.Panic(t, func() { 224 router.Handle("", "/") 225 }) 226 assert.Panic(t, func() { 227 router.Handle("PO ST", "/") 228 }) 229 assert.Panic(t, func() { 230 router.Handle("1GET", "/") 231 }) 232 assert.Panic(t, func() { 233 router.Handle("PATCh", "/") 234 }) 235 } 236 237 func TestRouterGroupPipeline(t *testing.T) { 238 opt := config.NewOptions([]config.Option{}) 239 router := NewEngine(opt) 240 testRoutesInterface(t, router) 241 242 v1 := router.Group("/v1") 243 testRoutesInterface(t, v1) 244 } 245 246 func testRoutesInterface(t *testing.T, r IRoutes) { 247 handler := func(c context.Context, ctx *app.RequestContext) {} 248 assert.DeepEqual(t, r, r.Use(handler)) 249 250 assert.DeepEqual(t, r, r.Handle(http.MethodGet, "/handler", handler)) 251 assert.DeepEqual(t, r, r.Any("/any", handler)) 252 assert.DeepEqual(t, r, r.GET("/", handler)) 253 assert.DeepEqual(t, r, r.POST("/", handler)) 254 assert.DeepEqual(t, r, r.DELETE("/", handler)) 255 assert.DeepEqual(t, r, r.PATCH("/", handler)) 256 assert.DeepEqual(t, r, r.PUT("/", handler)) 257 assert.DeepEqual(t, r, r.OPTIONS("/", handler)) 258 assert.DeepEqual(t, r, r.HEAD("/", handler)) 259 260 assert.DeepEqual(t, r, r.StaticFile("/file", ".")) 261 assert.DeepEqual(t, r, r.Static("/static", ".")) 262 assert.DeepEqual(t, r, r.StaticFS("/static2", &app.FS{})) 263 }