github.com/gramework/gramework@v1.8.1-0.20231027140105-82555c9057f5/test/gramework_test.go (about) 1 // Copyright 2017-present Kirill Danshin and Gramework contributors 2 // Copyright 2019-present Highload LTD (UK CN: 11893420) 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 11 package test 12 13 import ( 14 "crypto/tls" 15 "fmt" 16 "io" 17 "net" 18 "net/http" 19 "reflect" 20 "testing" 21 "time" 22 23 "github.com/gramework/gramework" 24 "github.com/gramework/gramework/x/testutils" 25 ) 26 27 func TestGrameworkHTTP(t *testing.T) { 28 app := gramework.New() 29 const text = "test one two three" 30 var preCalled, mwCalled, postCalled, jsonOK bool 31 app.GET("/", text) 32 app.GET("/bytes", []byte(text)) 33 app.GET("/float32", float32(len(text))) 34 app.GET("/dumb", func() {}) 35 app.GET("/dumbWithErr", func() error { return nil }) 36 app.GET("/json", func(ctx *gramework.Context) { 37 m := map[string]map[string]map[string]map[string]int{ 38 "abc": { 39 "def": { 40 "ghk": { 41 "wtf": 42, 42 }, 43 }, 44 }, 45 } 46 jsonOK = true 47 48 if err := ctx.JSON(m); err != nil { 49 jsonOK = false 50 ctx.Logger.Errorf("can't JSON(): %s", err) 51 } 52 53 if b, err := ctx.ToJSON(m); err == nil { 54 var m2 map[string]map[string]map[string]map[string]int 55 if _, err := ctx.UnJSONBytes(b, &m2); err != nil { 56 ctx.Logger.Errorf("can't unjson: %s", err) 57 jsonOK = false 58 return 59 } 60 61 b2, err := ctx.ToJSON(m2) 62 if err != nil { 63 ctx.Logger.Errorf("ToJSON returns error: %s", err) 64 jsonOK = false 65 return 66 } 67 68 if len(b2) != len(b) { 69 ctx.Logger.Errorf("len is not equals, got len(b2) = [%v], len(b) = [%v]", len(b2), len(b)) 70 jsonOK = false 71 return 72 } 73 74 if !reflect.DeepEqual(b, b2) { 75 jsonOK = false 76 return 77 } 78 } 79 }) 80 81 var err error 82 app.ServeFile("/sf", "./nanotime.s") 83 app.SPAIndex("./nanotime.s") 84 app.GET("/sdnc_static/dist/*static", app.ServeDirNoCache("./")) 85 app.GET("/sdncc_static/dist/*static", app.ServeDirNoCacheCustom("./", 0, false, false, []string{})) 86 app.MethodNotAllowed(func(ctx *gramework.Context) { 87 _, err = ctx.WriteString("GTFO") 88 errCheck(t, err) 89 }) 90 91 err = app.UsePre(func() { 92 preCalled = true 93 }) 94 errCheck(t, err) 95 96 err = app.UsePre(func(ctx *gramework.Context) { 97 ctx.CORS() 98 }) 99 errCheck(t, err) 100 101 err = app.Use(func() { 102 mwCalled = true 103 }) 104 errCheck(t, err) 105 106 err = app.UseAfterRequest(func() { 107 postCalled = true 108 }) 109 errCheck(t, err) 110 111 port := 42069 112 bindAddr := fmt.Sprintf(":%d", port) 113 go func() { 114 var err error 115 for i := 0; i < 10; i++ { 116 err := app.ListenAndServe(bindAddr) 117 if err != nil { 118 port++ 119 bindAddr = fmt.Sprintf(":%d", port) 120 } 121 } 122 if err != nil { 123 t.Error("after 10 retries, consistently getting errors while trying to ListenAndServe. Last known error: " + err.Error()) 124 } 125 }() 126 127 time.Sleep(3 * time.Second) 128 129 resp, err := http.Get("http://127.0.0.1" + bindAddr) 130 if err != nil { 131 t.Fatalf("Gramework isn't working! Got error: %s", err) 132 t.FailNow() 133 } 134 135 body, err := io.ReadAll(resp.Body) 136 if err != nil { 137 t.Fatalf("Gramework isn't working! Can't read body: %s", err) 138 t.FailNow() 139 } 140 141 err = resp.Body.Close() 142 errCheck(t, err) 143 144 if string(body) != text { 145 t.Fatalf( 146 "Gramework returned unexpected body! Got %q, expected %q", 147 string(body), 148 text, 149 ) 150 t.FailNow() 151 } 152 153 resp, err = http.Get("http://127.0.0.1" + bindAddr + "/json") 154 if err != nil { 155 t.Fatalf("Gramework isn't working! Got error: %s", err) 156 t.FailNow() 157 } 158 159 _, err = io.ReadAll(resp.Body) 160 errCheck(t, err) 161 162 err = resp.Body.Close() 163 errCheck(t, err) 164 165 switch { 166 case !preCalled: 167 t.Fatalf("pre wasn't called") 168 t.FailNow() 169 case !mwCalled: 170 t.Fatalf("middleware wasn't called") 171 t.FailNow() 172 case !postCalled: 173 t.Fatalf("post middleware wasn't called") 174 t.FailNow() 175 case !jsonOK: 176 t.Fatalf("json response isn't OK") 177 t.FailNow() 178 } 179 } 180 181 func TestGrameworkDomainHTTP(t *testing.T) { 182 app := gramework.New() 183 const text = "test one two three" 184 185 ln, err := net.Listen("tcp", ":0") 186 if err != nil { 187 t.Fatal(err) 188 } 189 190 _, port, _ := net.SplitHostPort(ln.Addr().String()) 191 bindAddr := fmt.Sprintf(":%s", port) 192 193 app.Domain("127.0.0.1"+bindAddr).GET("/", text) 194 var preCalled, mwCalled, postCalled bool 195 196 err = app.UsePre(func() { 197 preCalled = true 198 }) 199 errCheck(t, err) 200 201 err = app.Use(func() { 202 mwCalled = true 203 }) 204 errCheck(t, err) 205 206 err = app.UseAfterRequest(func() { 207 postCalled = true 208 }) 209 errCheck(t, err) 210 211 go func() { 212 serveErr := app.Serve(ln) 213 errCheck(t, serveErr) 214 }() 215 216 time.Sleep(1 * time.Second) 217 218 resp, err := http.Get("http://127.0.0.1" + bindAddr) 219 if err != nil { 220 t.Fatalf("Gramework isn't working! Got error: %s", err) 221 } 222 223 body, err := io.ReadAll(resp.Body) 224 if err != nil { 225 t.Fatalf("Gramework isn't working! Can't read body: %s", err) 226 } 227 228 err = resp.Body.Close() 229 errCheck(t, err) 230 231 if string(body) != text { 232 t.Fatalf( 233 "Gramework returned unexpected body! Got %q, expected %q", 234 string(body), 235 text, 236 ) 237 } 238 239 if !preCalled { 240 t.Fatalf("pre wasn't called") 241 } 242 if !mwCalled { 243 t.Fatalf("middleware wasn't called") 244 } 245 if !postCalled { 246 t.Fatalf("post middleware wasn't called") 247 } 248 } 249 250 func TestGrameworkHTTPS(t *testing.T) { 251 app := gramework.New() 252 const text = "test one two three" 253 app.GET("/", text) 254 app.TLSEmails = []string{"k@guava.by"} 255 256 ln, err := net.Listen("tcp", ":0") 257 if err != nil { 258 t.Fatal(err) 259 } 260 261 _, port, _ := net.SplitHostPort(ln.Addr().String()) 262 bindAddr := fmt.Sprintf(":%s", port) 263 264 go func() { 265 err := app.ListenAndServeAutoTLS(bindAddr) 266 errCheck(t, err) 267 }() 268 269 time.Sleep(3 * time.Second) 270 271 tr := &http.Transport{ 272 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 273 } 274 client := &http.Client{Transport: tr} 275 276 resp, err := client.Get("https://127.0.0.1" + bindAddr) 277 if err != nil { 278 t.Fatalf("Gramework isn't working! Got error: %s", err) 279 } 280 281 body, err := io.ReadAll(resp.Body) 282 if err != nil { 283 t.Fatalf("Gramework isn't working! Can't read body: %s", err) 284 } 285 286 err = resp.Body.Close() 287 errCheck(t, err) 288 289 if string(body) != text { 290 t.Fatalf( 291 "Gramework returned unexpected body! Got %q, expected %q", 292 string(body), 293 text, 294 ) 295 } 296 } 297 298 func TestGrameworkListenAll(t *testing.T) { 299 app := gramework.New() 300 const text = "test one two three" 301 app.GET("/", text) 302 app.TLSEmails = []string{"k@guava.by"} 303 304 port := 65356 305 bindAddr := fmt.Sprintf(":%d", port) 306 tlsPort := 65357 307 tlsBindAddr := fmt.Sprintf(":%d", tlsPort) 308 app.TLSPort = uint16(tlsPort) 309 go func() { 310 app.ListenAndServeAll(bindAddr) 311 }() 312 313 time.Sleep(3 * time.Second) 314 315 tr := &http.Transport{ 316 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 317 } 318 client := &http.Client{Transport: tr} 319 320 resp, err := client.Get("http://127.0.0.1" + bindAddr) 321 if err != nil { 322 t.Fatalf("Gramework isn't working! Got error: %s", err) 323 } 324 325 body, err := io.ReadAll(resp.Body) 326 if err != nil { 327 t.Fatalf("Gramework isn't working! Can't read body: %s", err) 328 } 329 330 err = resp.Body.Close() 331 errCheck(t, err) 332 333 if string(body) != text { 334 t.Fatalf( 335 "Gramework returned unexpected body! Got %q, expected %q", 336 string(body), 337 text, 338 ) 339 } 340 341 resp, err = client.Get("https://127.0.0.1" + tlsBindAddr) 342 if err != nil { 343 t.Fatalf("Gramework isn't working! Got error: %s", err) 344 } 345 346 body, err = io.ReadAll(resp.Body) 347 if err != nil { 348 t.Fatalf("Gramework isn't working! Can't read body: %s", err) 349 } 350 351 err = resp.Body.Close() 352 errCheck(t, err) 353 354 if string(body) != text { 355 t.Fatalf( 356 "Gramework returned unexpected body! Got %q, expected %q", 357 string(body), 358 text, 359 ) 360 } 361 } 362 363 func TestSPAIndexHandler(t *testing.T) { 364 app := gramework.New() 365 const text = "My Template" 366 367 app.SPAIndex(func(ctx *gramework.Context) { 368 _, err := ctx.WriteString(text) 369 370 if err != nil { 371 t.Fatalf("WriteString error: %s", err) 372 t.FailNow() 373 } 374 }) 375 376 port := testutils.Port().NonRoot().Unused().Acquire() 377 bindAddr := fmt.Sprintf(":%d", port) 378 go func() { 379 listenErr := app.ListenAndServe(bindAddr) 380 errCheck(t, listenErr) 381 }() 382 383 time.Sleep(2 * time.Second) 384 385 resp, err := http.Get("http://127.0.0.1" + bindAddr) 386 if err != nil { 387 t.Fatalf("Gramework isn't working! Got error: %s", err) 388 t.FailNow() 389 } 390 391 body, err := io.ReadAll(resp.Body) 392 if err != nil { 393 t.Fatalf("Gramework isn't working! Can't read body: %s", err) 394 t.FailNow() 395 } 396 397 err = resp.Body.Close() 398 errCheck(t, err) 399 400 if string(body) != text { 401 t.Fatalf( 402 "Gramework returned unexpected body! Got %q, expected %q", 403 string(body), 404 text, 405 ) 406 t.FailNow() 407 } 408 409 err = resp.Body.Close() 410 errCheck(t, err) 411 }