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  }