github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/znet/web_test.go (about) 1 package znet 2 3 import ( 4 "errors" 5 "fmt" 6 "html/template" 7 "io" 8 "io/ioutil" 9 "net/http" 10 "net/http/httptest" 11 "net/url" 12 "path/filepath" 13 "strings" 14 "sync" 15 "testing" 16 "time" 17 18 "github.com/sohaha/zlsgo" 19 "github.com/sohaha/zlsgo/zfile" 20 "github.com/sohaha/zlsgo/zjson" 21 "github.com/sohaha/zlsgo/zlog" 22 "github.com/sohaha/zlsgo/zstring" 23 // "go.uber.org/goleak" 24 ) 25 26 type GG struct { 27 Info string 28 P []AA `json:"p"` 29 } 30 31 type AA struct { 32 Name string 33 Gg GG `json:"g"` 34 ID int `json:"id"` 35 } 36 37 type SS struct { 38 Name string `json:"name"` 39 Gg GG `json:"g"` 40 To []string `json:"t"` 41 IDs []AA `json:"ids"` 42 Property struct { 43 Name string `json:"n"` 44 Key float64 45 } `json:"p"` 46 Abc int 47 ID int `json:"id"` 48 Pid uint 49 To2 int `json:"t2"` 50 } 51 52 var ( 53 expected = "hi" 54 host = "127.0.0.1" 55 ) 56 57 var ( 58 one sync.Once 59 engine *Engine 60 ) 61 62 // func TestMain(m *testing.M) { 63 // goleak.VerifyTestMain(m) 64 // } 65 66 func newServer() *Engine { 67 one.Do(func() { 68 engine = New("Web-test") 69 engine.AllowQuerySemicolons = true 70 engine.SetMode(DebugMode) 71 engine.AddAddr("3787") 72 engine.SetAddr("3788") 73 engine.SetTimeout(3 * time.Second) 74 CloseHotRestartFileMd5() 75 }) 76 return engine 77 } 78 79 func request(r *Engine, method, url string, body io.Reader, opt ...func(w *httptest.ResponseRecorder, req *http.Request)) *httptest.ResponseRecorder { 80 w := httptest.NewRecorder() 81 req, _ := http.NewRequest(method, url, body) 82 req.Host = host 83 for _, o := range opt { 84 o(w, req) 85 } 86 r.ServeHTTP(w, req) 87 return w 88 } 89 90 func newRequest(r *Engine, method string, urlAndBody interface{}, path string, handler ...Handler) *httptest.ResponseRecorder { 91 var ( 92 body io.Reader 93 _url string 94 contentType string 95 ) 96 method = strings.ToUpper(method) 97 if u, ok := urlAndBody.(string); ok { 98 _url = u 99 } else if u, ok := urlAndBody.([]string); ok { 100 _url = u[0] 101 body = strings.NewReader(u[1]) 102 contentType = u[2] 103 } 104 if len(handler) > 0 { 105 firstHandler := handler[0] 106 handlers := handler[1:] 107 if path == "" { 108 path = _url 109 } 110 switch method { 111 case "GET": 112 r.GET(path, firstHandler, handlers...) 113 case "POST": 114 r.POST(path, firstHandler, handlers...) 115 default: 116 r.Customize(method, path, firstHandler, handlers...) 117 } 118 } 119 return request(r, method, _url, body, func(w *httptest.ResponseRecorder, req *http.Request) { 120 if contentType != "" { 121 req.Header.Set("Content-Type", contentType) 122 } 123 }) 124 } 125 126 func TestMain(m *testing.M) { 127 m.Run() 128 Shutdown() 129 } 130 131 func TestWeb(t *testing.T) { 132 tt := zlsgo.NewTest(t) 133 r := newServer() 134 135 _, ok := Server("Web-test") 136 tt.EqualExit(true, ok) 137 138 // r.SetMode(ProdMode) 139 w := newRequest(r, "GET", "/", "/", func(c *Context) { 140 t.Log("TestWeb") 141 _, _ = c.GetDataRaw() 142 c.SetCookie("testCookie", "yes") 143 c.GetCookie("testCookie") 144 c.String(200, expected) 145 }) 146 tt.Equal(200, w.Code) 147 tt.Equal(expected, w.Body.String()) 148 // r.GetMiddleware() 149 150 w = newRequest(r, "PUT", "/", "/", func(c *Context) { 151 t.Log("run") 152 c.String(200, expected) 153 }, func(c *Context) { 154 t.Log(1) 155 }, func(c *Context) { 156 t.Log(2) 157 c.Next() 158 t.Log(3) 159 }) 160 tt.Equal(200, w.Code) 161 tt.Equal(expected, w.Body.String()) 162 } 163 164 func TestMoreMethod(t *testing.T) { 165 var w *httptest.ResponseRecorder 166 var req *http.Request 167 tt := zlsgo.NewTest(t) 168 r := newServer() 169 g := r.Group("/TestMore") 170 h := func(v string) func(c *Context) { 171 return func(c *Context) { 172 t.Log(c.Request.Method) 173 c.String(200, v) 174 } 175 } 176 177 g.CONNECT("/", h("CONNECT")) 178 g.OPTIONS("/", h("OPTIONS")) 179 g.DELETE("/", h("DELETE")) 180 g.TRACE("/", h("TRACE")) 181 g.POST("/", h("POST")) 182 g.PUT("/", h("PUT")) 183 184 for _, v := range []string{"CONNECT", "TRACE", "PUT", "DELETE", "POST", "OPTIONS"} { 185 w = httptest.NewRecorder() 186 req, _ = http.NewRequest(v, "/TestMore/", nil) 187 req.Host = host 188 r.ServeHTTP(w, req) 189 tt.Equal(200, w.Code) 190 tt.Equal(v, w.Body.String()) 191 } 192 } 193 194 func TestGroup(t *testing.T) { 195 tt := zlsgo.NewTest(t) 196 r := newServer() 197 g := r.Group("") 198 g.GET("isGroup", func(c *Context) { 199 c.String(200, "isGroup") 200 }) 201 w := httptest.NewRecorder() 202 req, _ := http.NewRequest("GET", "/isGroup", nil) 203 req.Host = host 204 r.ServeHTTP(w, req) 205 tt.Equal(200, w.Code) 206 tt.Equal("isGroup", w.Body.String()) 207 208 r = newServer() 209 g = r.Group("/") 210 g.GET("isGroup2", func(c *Context) { 211 c.String(200, "isGroup2") 212 }) 213 w = httptest.NewRecorder() 214 req, _ = http.NewRequest("GET", "/isGroup2", nil) 215 req.Host = host 216 r.ServeHTTP(w, req) 217 tt.Equal(200, w.Code) 218 tt.Equal("isGroup2", w.Body.String()) 219 220 r = newServer() 221 g = r.Group("/y/") 222 g.GET("//isGroup3", func(c *Context) { 223 c.String(200, "isGroup3") 224 }) 225 w = httptest.NewRecorder() 226 req, _ = http.NewRequest("GET", "/y/isGroup3", nil) 227 req.Host = host 228 r.ServeHTTP(w, req) 229 tt.Equal(200, w.Code) 230 tt.Equal("isGroup3", w.Body.String()) 231 } 232 233 func TestRedirect(t *testing.T) { 234 tt := zlsgo.NewTest(t) 235 r := newServer() 236 g := r.Group("/Redirect") 237 g.GET("", func(c *Context) { 238 c.Redirect("/", 301) 239 }) 240 w := httptest.NewRecorder() 241 req, _ := http.NewRequest("GET", "/Redirect", nil) 242 r.ServeHTTP(w, req) 243 tt.Equal(301, w.Code) 244 } 245 246 func TestGet(t *testing.T) { 247 tt := zlsgo.NewTest(t) 248 r := newServer() 249 _, ok := Server("Web-test") 250 tt.EqualExit(true, ok) 251 g := r.Group("/testGet") 252 g.GET("", func(c *Context) { 253 c.String(200, "empty") 254 }) 255 g.GET("/", func(c *Context) { 256 c.String(200, "/") 257 }) 258 g.GET("//ii", func(c *Context) { 259 c.String(200, "//ii") 260 }) 261 g.GET("ii", func(c *Context) { 262 c.String(200, "ii") 263 }) 264 g.GET("/ii", func(c *Context) { 265 c.String(200, "/ii") 266 }) 267 g.GET("/xxx/xxx/", func(c *Context) { 268 c.String(200, "xxx/xxx/") 269 }) 270 271 g.GET("/xxx/xxx", func(c *Context) { 272 c.String(200, "xxx/xxx") 273 }) 274 275 g.GET("/xxx/xxx/2", func(c *Context) { 276 c.String(200, "/ii") 277 }) 278 g.GET("/xxx/xxx/a3", func(c *Context) { 279 c.String(200, "/ii") 280 }) 281 282 var w *httptest.ResponseRecorder 283 var req *http.Request 284 285 w = httptest.NewRecorder() 286 req, _ = http.NewRequest("GET", "/testGet/ii", nil) 287 req.Host = host 288 r.ServeHTTP(w, req) 289 tt.Equal(200, w.Code) 290 tt.Equal("//ii", w.Body.String()) 291 292 w = httptest.NewRecorder() 293 req, _ = http.NewRequest("GET", "/testGet//ii", nil) 294 req.Host = host 295 r.ServeHTTP(w, req) 296 tt.Equal(404, w.Code) 297 298 w = httptest.NewRecorder() 299 req, _ = http.NewRequest("GET", "/testGet", nil) 300 req.Host = host 301 r.ServeHTTP(w, req) 302 tt.Equal(200, w.Code) 303 tt.Equal("empty", w.Body.String()) 304 305 w = httptest.NewRecorder() 306 req, _ = http.NewRequest("GET", "/testGet/", nil) 307 req.Host = host 308 r.ServeHTTP(w, req) 309 tt.Equal(200, w.Code) 310 tt.Equal("/", w.Body.String()) 311 312 w = httptest.NewRecorder() 313 req, _ = http.NewRequest("GET", "/testGet/xxx/xxx", nil) 314 req.Host = host 315 r.ServeHTTP(w, req) 316 tt.Equal(200, w.Code) 317 tt.Equal("xxx/xxx", w.Body.String()) 318 319 w = httptest.NewRecorder() 320 req, _ = http.NewRequest("GET", "/testGet/xxx/xxx/", nil) 321 req.Host = host 322 r.ServeHTTP(w, req) 323 tt.Equal(200, w.Code) 324 tt.Equal("xxx/xxx/", w.Body.String()) 325 } 326 327 func TestFile(tt *testing.T) { 328 T := zlsgo.NewTest(tt) 329 r := newServer() 330 w := newRequest(r, "GET", "/TestFile", "/TestFile", func(c *Context) { 331 tt.Log("TestFile") 332 lists, err := ioutil.ReadDir(zfile.RealPath(".")) 333 if err != nil { 334 tt.Fatal(err) 335 } 336 var path string 337 for _, list := range lists { 338 if filepath.Ext(list.Name()) != "" { 339 path = zfile.RealPath(list.Name()) 340 break 341 } 342 } 343 c.File(path) 344 }, func(c *Context) { 345 c.Next() 346 content := c.PrevContent() 347 tt.Log("PrevContent len", len(content.Content)) 348 }) 349 T.EqualExit(200, w.Code) 350 tt.Log(len(w.Body.String())) 351 352 w = newRequest(r, "GET", "/TestFile2", "/TestFile2", func(c *Context) { 353 tt.Log("TestFile") 354 c.File("doc_no.go") 355 }) 356 T.Equal(404, w.Code) 357 tt.Log(len(w.Body.String())) 358 359 w = newRequest(r, "GET", "/TestFile3", "/TestFile3", func(c *Context) { 360 tt.Log("TestFile") 361 c.File("doc_no.go") 362 }, func(c *Context) { 363 c.Next() 364 tt.Log("PrevContent", c.PrevContent()) 365 c.String(211, "file") 366 }) 367 T.Equal(211, w.Code) 368 tt.Log(len(w.Body.String())) 369 } 370 371 func TestPost(tt *testing.T) { 372 T := zlsgo.NewTest(tt) 373 r := newServer() 374 r.SetMode(DebugMode) 375 w := newRequest(r, "POST", "/Post", "/Post", func(c *Context) { 376 tt.Log("TestWeb") 377 c.WithValue("k3", "k3-data") 378 _, _ = c.GetDataRaw() 379 _, _ = c.MultipartForm() 380 c.JSON(201, ApiData{ 381 Code: 200, 382 Msg: expected, 383 Data: nil, 384 }) 385 }, func(c *Context) { 386 c.WithValue("k1", "k1-data") 387 tt.Log("==1==") 388 c.Next() 389 tt.Log("--1--") 390 tt.Log("PrevContent", zstring.Bytes2String(c.PrevContent().Content)) 391 T.Equal(expected, zjson.Get(zstring.Bytes2String(c.PrevContent().Content), "msg").String()) 392 tt.Log("PrevContent2", zstring.Bytes2String(c.PrevContent().Content)) 393 tt.Log("PrevStatus", c.PrevContent().Code) 394 c.SetStatus(211) 395 c.JSON(211, &ApiData{ 396 Code: 0, 397 Msg: "replace", 398 Data: nil, 399 }) 400 tt.Log("PrevContent3", zstring.Bytes2String(c.PrevContent().Content)) 401 tt.Log(c.Value("k1")) 402 tt.Log(c.Value("k2")) 403 tt.Log(c.Value("k2-2")) 404 tt.Log(c.Value("k3")) 405 tt.Log(c.Value("k4")) 406 }, func(c *Context) { 407 c.WithValue("k2", "k2-data") 408 tt.Log("==2==") 409 c.Next() 410 p := c.PrevContent() 411 ctype := p.Type 412 tt.Log("PrevContentType", ctype) 413 c.WithValue("k2-2", "k2-2-data") 414 }) 415 T.Equal(211, w.Code) 416 T.Equal("replace", zjson.Get(w.Body.String(), "msg").String()) 417 418 w = newRequest(r, "POST", "/Post2", "/Post2", func(c *Context) { 419 c.String(200, "ok") 420 }, func(c *Context) { 421 T.Equal(false, c.IsAbort()) 422 c.Next() 423 T.Equal(true, c.IsAbort()) 424 }, 425 func(c *Context) { 426 c.Abort(222) 427 }) 428 T.Equal(222, w.Code) 429 430 w = newRequest(r, "POST", "/Post3", "/Post3", 431 func(c *Context) { 432 c.Byte(200, []byte("ok")) 433 }) 434 T.Equal(200, w.Code) 435 T.Equal("ok", w.Body.String()) 436 } 437 438 func TestCustomMethod(t *testing.T) { 439 tt := zlsgo.NewTest(t) 440 r := newServer() 441 r.SetCustomMethodField("_m_") 442 443 var q []string 444 r.Use(func(c *Context) { 445 q = append(q, "1") 446 c.Next() 447 q = append(q, "1 done") 448 }) 449 r.Use(WrapFirstMiddleware(func() { 450 q = append(q, "second") 451 })) 452 r.Use(func() { 453 q = append(q, "third") 454 }) 455 r.PUT("/CustomMethod", func(c *Context) { 456 tt.EqualExit(true, c.IsAjax()) 457 c.String(200, `put`) 458 }, func() { 459 q = append(q, "2") 460 }, WrapFirstMiddleware(func() { 461 q = append(q, "first") 462 }), func() { 463 q = append(q, "3") 464 }) 465 466 w := httptest.NewRecorder() 467 req, _ := http.NewRequest("POST", "/CustomMethod", nil) 468 469 req.Header.Add("X-Requested-With", "XMLHttpRequest") 470 req.Header.Add("_m_", "put") 471 req.Host = host 472 473 r.ServeHTTP(w, req) 474 tt.Equal(200, w.Code) 475 tt.Equal("put", w.Body.String()) 476 tt.Equal("first second 1 third 2 3 1 done", strings.Join(q, " ")) 477 } 478 479 func TestPreHandler(tt *testing.T) { 480 t := zlsgo.NewTest(tt) 481 r := New("TestPreHandler") 482 r.PreHandler(func(c *Context) (stop bool) { 483 c.String(210, "stop") 484 return true 485 }) 486 w := request(r, "GET", "/", nil) 487 t.Equal(210, w.Code) 488 t.Equal("stop", w.Body.String()) 489 490 r.PreHandler(func(c *Context) error { 491 c.String(210, "stop") 492 return errors.New("stop handler") 493 }) 494 i := 0 495 w = newRequest(r, "GET", "/TestPreHandler", "/TestPreHandler", func(c *Context) { 496 c.String(200, "ok") 497 }, func() { 498 i++ 499 tt.Log("TestPreHandler") 500 }) 501 t.Equal(0, i) 502 t.Equal(500, w.Code) 503 t.Equal("stop handler", w.Body.String()) 504 } 505 506 func TestHTML(tt *testing.T) { 507 t := zlsgo.NewTest(tt) 508 r := newServer() 509 w := newRequest(r, "GET", "/TestHTML", "/TestHTML", func(c *Context) { 510 tt.Log("TestHTML") 511 c.HTML(202, `<html>123</html>`) 512 }) 513 t.Equal(202, w.Code) 514 t.EqualExit(`<html>123</html>`, w.Body.String()) 515 516 w = newRequest(r, "GET", "/TestHTML2", "/TestHTML2", func(c *Context) { 517 tt.Log("TestHTML2") 518 c.Template(202, `<html>{{.title}}</html>`, Data{"title": "ZlsGo"}) 519 }) 520 t.Equal(202, w.Code) 521 t.EqualExit(`<html>ZlsGo</html>`, w.Body.String()) 522 } 523 524 func TestMore(tt *testing.T) { 525 t := zlsgo.NewTest(tt) 526 r := newServer() 527 r.SetMode(DebugMode) 528 OnShutdown(func() { 529 fmt.Println("Shutdown") 530 }) 531 CloseHotRestart = true 532 w := newRequest(r, "delete", []string{"/", `{"Na":"is json","Name2":"222","U":{"name3":"333"},"N2":{"Name2":2002,"U.Name3":"333","S":[14.1,20]}}`, ContentTypeJSON}, "/", func(c *Context) { 533 _, _ = c.GetDataRaw() 534 c.String(200, expected) 535 c.GetAllQueryMaps() 536 c.GetAllQuery() 537 c.Log.Debug(c.GetJSON("Name")) 538 type U2 struct { 539 S []float64 540 N2 int `json:"U.Name3"` 541 Name2 int 542 } 543 type U3 struct { 544 Name3 string `json:"name3"` 545 } 546 var u struct { 547 Name string `json:"Na"` 548 U U3 549 U2 `json:"N2"` 550 } 551 err := c.Bind(&u) 552 t.EqualNil(err) 553 c.Log.Dump(u) 554 t.Equal("333", u.U.Name3) 555 t.Equal(333, u.N2) 556 t.Equal(2002, u.Name2) 557 }) 558 t.Equal(200, w.Code) 559 t.Equal(expected, w.Body.String()) 560 561 t.EqualTrue(getAddr("") != "") 562 t.EqualExit(":3120", getAddr("3120")) 563 t.EqualExit(":3120", getAddr(":3120")) 564 t.EqualExit("0.0.0.0:3120", getAddr("0.0.0.0:3120")) 565 566 t.EqualExit("http://127.0.0.1:3120", getHostname(":3120", false)) 567 t.EqualExit("https://127.0.0.1:3120", getHostname(":3120", true)) 568 } 569 570 func TestTemplate(t *testing.T) { 571 tt := zlsgo.NewTest(t) 572 r := newServer() 573 template := `<html>123</html>` 574 _ = zfile.WriteFile("template.html", []byte(template)) 575 defer zfile.Rmdir("template.html") 576 w := newRequest(r, "GET", "/Template", "/Template", func(c *Context) { 577 t.Log("TestHTML") 578 c.Template(200, "template.html", Data{}) 579 }) 580 tt.Equal(200, w.Code) 581 tt.EqualExit(template, w.Body.String()) 582 583 templates := `<html><title>{{.title}}</title><body>{{template "body".}}</body></html>` 584 _ = zfile.WriteFile("template2.html", []byte(templates)) 585 defer zfile.Rmdir("template2.html") 586 templatesBody := `{{define "body"}}This is body{{end}}` 587 _ = zfile.WriteFile("template2body.html", []byte(templatesBody)) 588 defer zfile.Rmdir("template2body.html") 589 w = newRequest(r, "GET", "/Templates", "/Templates", func(c *Context) { 590 t.Log("TestHTML2") 591 c.Templates(202, []string{"template2.html", "template2body.html"}, Data{"title": "ZlsGo"}) 592 }) 593 tt.Equal(202, w.Code) 594 tt.EqualExit(`<html><title>ZlsGo</title><body>This is body</body></html>`, w.Body.String()) 595 } 596 597 func TestTemplateLoad(t *testing.T) { 598 tt := zlsgo.NewTest(t) 599 r := newServer() 600 path := zfile.RealPathMkdir("tmpTemplate", true) 601 defer zfile.Rmdir(path) 602 603 _ = zfile.WriteFile(path+"tpl-define.html", []byte(`{{ define "user/index.html" }}{{.title}}{{test}}{{ end }}`)) 604 r.SetTemplateFuncMap(map[string]interface{}{ 605 "test": func() string { 606 return "-ok" 607 }, 608 }) 609 610 r.LoadHTMLGlob("tmpTemplate/*") 611 612 w := newRequest(r, "GET", "/Template-define-1", "/Template-define-1", 613 func(c *Context) { 614 c.Template(200, "user/index.html", Data{"title": "ZlsGo"}) 615 }) 616 tt.Equal(200, w.Code) 617 tt.EqualExit(`ZlsGo-ok`, w.Body.String()) 618 619 temple, _ := template.New("tmpTemplate/tpl-html.html").Parse(`{{.title}}`) 620 r.SetHTMLTemplate(temple) 621 622 w = newRequest(r, "GET", "/Template-define-2", "/Template-define-2", 623 func(c *Context) { 624 c.Template(200, "tmpTemplate/tpl-html.html", Data{"title": "ZlsGo"}) 625 }) 626 tt.Equal(200, w.Code) 627 tt.EqualExit(`ZlsGo`, w.Body.String()) 628 } 629 630 func TestTemplateNew(t *testing.T) { 631 tt := zlsgo.NewTest(t) 632 r := newServer() 633 path := zfile.RealPathMkdir("tmpTemplate", true) 634 defer zfile.Rmdir(path) 635 r.SetMode(DebugMode) 636 r.LoadHTMLGlob("tmpTemplate") 637 _ = zfile.WriteFile(path+"tpl-define.html", []byte(`{{ define "user/index.html" }}{{.title}}{{test}}{{ end }}`)) 638 r.SetTemplateFuncMap(map[string]interface{}{ 639 "test": func() string { 640 return "-ok" 641 }, 642 }) 643 644 w := newRequest(r, "GET", "/Template-new-define-1", "/Template-new-define-1", 645 func(c *Context) { 646 c.Template(200, "user/index.html", Data{"title": "ZlsGo"}) 647 }) 648 tt.Equal(200, w.Code) 649 tt.EqualExit(`ZlsGo-ok`, w.Body.String()) 650 } 651 652 func TestBind(t *testing.T) { 653 type AppInfo struct { 654 Label string `json:"label"` 655 Id string `json:"id"` 656 Appid string `json:"appid"` 657 HeadImg string `json:"head_img"` 658 } 659 tt := zlsgo.NewTest(t) 660 r := newServer() 661 w := newRequest(r, "POST", []string{"/TestBind", 662 `{"appid":"Aid","appids":[{"label":"isLabel","id":"333"}]}`, ContentTypeJSON}, "/TestBind", func(c *Context) { 663 json, _ := c.GetJSONs() 664 var appids []AppInfo 665 json.Get("appids").ForEach(func(key, value *zjson.Res) bool { 666 appinfo := AppInfo{} 667 err := value.Unmarshal(&appinfo) 668 if err != nil { 669 c.Log.Error(err) 670 return false 671 } 672 appids = append(appids, appinfo) 673 return true 674 }) 675 c.String(200, expected) 676 }) 677 tt.EqualExit(200, w.Code) 678 tt.EqualExit(expected, w.Body.String()) 679 } 680 681 func TestShouldBindStruct(tt *testing.T) { 682 t := zlsgo.NewTest(tt) 683 r := newServer() 684 685 _ = newRequest(r, "POST", []string{"/TestShouldBindStruct1", `{"id":666,"Pid":100,"name":"名字","g":{"Info":"基础"},"ids":[{"id":1,"Name":"用户1","g":{"Info":"详情"}}]}`, mimeJSON}, "/TestShouldBindStruct1", func(c *Context) { 686 var ss SS 687 err := c.Bind(&ss) 688 tt.Log(err, ss) 689 zlog.Dump(ss) 690 t.EqualExit(1, len(ss.IDs)) 691 t.EqualExit(666, ss.ID) 692 t.EqualExit("基础", ss.Gg.Info) 693 t.EqualExit("详情", ss.IDs[0].Gg.Info) 694 }) 695 696 _ = newRequest(r, "POST", []string{"/TestShouldBindStruct2", `id=666&&g[Info]=基础`, mimePOSTForm}, "/TestShouldBindStruct2", func(c *Context) { 697 var ss SS 698 err := c.Bind(&ss) 699 tt.Log(err, ss) 700 t.EqualExit(666, ss.ID) 701 t.EqualExit("基础", ss.Gg.Info) 702 t.Equal("666", c.DefaultPostForm("id", "")) 703 }) 704 } 705 706 func TestSetMode(T *testing.T) { 707 t := zlsgo.NewTest(T) 708 defer func() { 709 if r := recover(); r != nil { 710 t.Log("Recovered in f", r) 711 } 712 }() 713 r := newServer() 714 r.SetMode(DebugMode) 715 t.Equal(true, r.IsDebug()) 716 t.Equal(DebugMode, r.GetMode()) 717 r.SetMode(TestMode) 718 r.SetMode(ProdMode) 719 t.Equal(false, r.IsDebug()) 720 r.SetMode("") 721 r.SetMode("unknownMode") 722 } 723 724 func TestMoreMatchingRouter(t *testing.T) { 725 tt := zlsgo.NewTest(t) 726 r := newServer() 727 w := newRequest(r, "GET", "/MoreMatchingRouter/file-1-谁.txt", 728 `/MoreMatchingRouter/{name:[^\/.]+}.{ext:[\w]+}`, func(c *Context) { 729 tt.Log(c.GetAllParam()) 730 tt.Equal("file-1-谁", c.GetParam("name")) 731 tt.Equal("txt", c.GetParam("ext")) 732 }) 733 tt.Equal(200, w.Code) 734 735 w = newRequest(r, "GET", "/MoreMatchingRouter/bracket/file-text-谁.doc", 736 `/MoreMatchingRouter/bracket/file-(?P<name>[\w\p{Han}\-]+).(?P<ext>[a-zA-Z]+)`, func(c *Context) { 737 tt.Log(c.GetAllParam()) 738 tt.Equal("text-谁", c.GetParam("name")) 739 tt.Equal("doc", c.GetParam("ext")) 740 }) 741 tt.Equal(200, w.Code) 742 743 engine := r.GET("/MoreMatchingRouter/*", func(c *Context) string { 744 return c.GetParam("*") 745 }) 746 747 w = request(engine, "GET", "/MoreMatchingRouter/t1/x2/z3", nil) 748 tt.Equal(200, w.Code) 749 tt.Equal("t1/x2/z3", w.Body.String()) 750 751 w = request(engine, "GET", "/MoreMatchingRouter/t", nil) 752 tt.Equal(200, w.Code) 753 tt.Equal("t", w.Body.String()) 754 t.Log(w) 755 } 756 757 func TestWebRouter(T *testing.T) { 758 t := zlsgo.NewTest(T) 759 r := newServer() 760 761 testRouterNotFound(r, t) 762 testRouterCustomNotFound(r, t) 763 testRouterCustomPanicHandler(r, t) 764 testRouterGET(r, t) 765 } 766 767 func testRouterGET(r *Engine, t *zlsgo.TestUtil) { 768 randString := zstring.Rand(5) 769 770 w := newRequest(r, "GET", "/RouterGET?id="+randString+"&a;b", "/RouterGET", func(c *Context) { 771 id := c.DefaultQuery("id", "not") 772 host := c.Host() 773 u := c.Host(true) 774 t.Equal(true, host != u) 775 c.String(200, host+"|"+id) 776 }) 777 778 t.Equal(200, w.Code) 779 t.Equal("http://"+host+"|"+randString, w.Body.String()) 780 } 781 782 func testRouterNotFound(r *Engine, t *zlsgo.TestUtil) { 783 expectedText := "404 page not found" 784 w := newRequest(r, "GET", "/RouterNotFound", "") 785 t.Equal(404, w.Code) 786 t.Equal(expectedText, w.Body.String()) 787 } 788 789 func testRouterCustomNotFound(r *Engine, t *zlsgo.TestUtil) { 790 expectedText := "is 404" 791 r.NotFoundHandler(handleRes(expectedText)) 792 793 w := newRequest(r, "GET", "/404-2", "") 794 t.Equal(200, w.Code) 795 t.Equal(expectedText, w.Body.String()) 796 } 797 798 func testRouterCustomPanicHandler(r *Engine, t *zlsgo.TestUtil) { 799 expectedText := "panic" 800 w := newRequest(r, "GET", "/panic", "", handleRes(expectedText)) 801 t.Equal(200, w.Code) 802 t.Equal(expectedText, w.Body.String()) 803 } 804 805 func handleRes(expected string) func(c *Context) { 806 return func(c *Context) { 807 _, _ = fmt.Fprint(c.Writer, expected) 808 } 809 } 810 811 func TestGetInput(T *testing.T) { 812 t := zlsgo.NewTest(T) 813 r := newServer() 814 getA := "abc" 815 w := newRequest(r, "GET", "/"+getA+"?a="+getA, "/:name", func(c *Context) { 816 t.EqualExit(false, c.IsAjax()) 817 a, _ := c.GetQuery("a") 818 name := c.GetParam("name") 819 GetAllQueryst := c.GetAllQuery() 820 t.Log(GetAllQueryst) 821 t.Equal(getA, a) 822 t.Equal(getA, name) 823 t.Equal(url.Values{"a": []string{getA}}, GetAllQueryst) 824 c.String(200, expected) 825 }) 826 827 t.Equal(200, w.Code) 828 t.Equal(expected, w.Body.String()) 829 } 830 831 func TestRecovery(t *testing.T) { 832 tt := zlsgo.NewTest(t) 833 r := New("TestRecovery") 834 r.PanicHandler(func(c *Context, err error) { 835 c.String(200, "ok") 836 }) 837 r.GET("/", func(c *Context) { 838 panic("xxx") 839 }) 840 w := httptest.NewRecorder() 841 req, _ := http.NewRequest("GET", "/", nil) 842 r.ServeHTTP(w, req) 843 tt.Equal("ok", w.Body.String()) 844 tt.Equal(200, w.Code) 845 } 846 847 func TestSetContent(t *testing.T) { 848 tt := zlsgo.NewTest(t) 849 r := New("SetContent") 850 r.GET("/SetContent", func(c *Context) { 851 c.String(200, "ok") 852 }, func(c *Context) { 853 c.Next() 854 data := c.PrevContent() 855 tt.Equal([]byte("ok"), data.Content) 856 data.Content = []byte("yes") 857 }, func(c *Context) { 858 c.Next() 859 data := c.PrevContent() 860 data.Code.Store(404) 861 }) 862 w := httptest.NewRecorder() 863 req, _ := http.NewRequest("GET", "/SetContent", nil) 864 r.ServeHTTP(w, req) 865 tt.Equal("yes", w.Body.String()) 866 tt.Equal(404, w.Code) 867 } 868 869 func TestMethodAndName(t *testing.T) { 870 tt := zlsgo.NewTest(t) 871 r := New("TestMethodAndName") 872 r.SetMode(DebugMode) 873 g := r.Group("/TestMethodAndName") 874 h := func(s string) func(c *Context) { 875 return func(c *Context) { 876 c.String(200, c.GetParam("id")) 877 } 878 } 879 id := "456" 880 g.GETAndName("/:id", h("ok"), "isGet") 881 u, _ := r.GenerateURL("GET", "isGet", map[string]string{"id": id}) 882 w := httptest.NewRecorder() 883 req, _ := http.NewRequest("GET", u, nil) 884 r.ServeHTTP(w, req) 885 tt.Equal(id, w.Body.String()) 886 t.Log(u) 887 888 t.Log(r.GenerateURL(http.MethodPost, "non existent", nil)) 889 }