github.com/astaxie/beego@v1.12.3/tree_test.go (about)

     1  // Copyright 2014 beego Author. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package beego
    16  
    17  import (
    18  	"strings"
    19  	"testing"
    20  
    21  	"github.com/astaxie/beego/context"
    22  )
    23  
    24  type testinfo struct {
    25  	url        string
    26  	requesturl string
    27  	params     map[string]string
    28  }
    29  
    30  var routers []testinfo
    31  
    32  func init() {
    33  	routers = make([]testinfo, 0)
    34  	routers = append(routers, testinfo{"/topic/?:auth:int", "/topic", nil})
    35  	routers = append(routers, testinfo{"/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}})
    36  	routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1", map[string]string{":id": "1"}})
    37  	routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1/2", map[string]string{":id": "1", ":auth": "2"}})
    38  	routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1", map[string]string{":id": "1"}})
    39  	routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1", ":auth": "123"}})
    40  	routers = append(routers, testinfo{"/:id", "/123", map[string]string{":id": "123"}})
    41  	routers = append(routers, testinfo{"/hello/?:id", "/hello", map[string]string{":id": ""}})
    42  	routers = append(routers, testinfo{"/", "/", nil})
    43  	routers = append(routers, testinfo{"/customer/login", "/customer/login", nil})
    44  	routers = append(routers, testinfo{"/customer/login", "/customer/login.json", map[string]string{":ext": "json"}})
    45  	routers = append(routers, testinfo{"/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}})
    46  	routers = append(routers, testinfo{"/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}})
    47  	routers = append(routers, testinfo{"/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}})
    48  	routers = append(routers, testinfo{"/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}})
    49  	routers = append(routers, testinfo{"/cc/:id/*", "/cc/2009/11/dd", map[string]string{":id": "2009", ":splat": "11/dd"}})
    50  	routers = append(routers, testinfo{"/ee/:year/*/ff", "/ee/2009/11/ff", map[string]string{":year": "2009", ":splat": "11"}})
    51  	routers = append(routers, testinfo{"/thumbnail/:size/uploads/*",
    52  		"/thumbnail/100x100/uploads/items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg",
    53  		map[string]string{":size": "100x100", ":splat": "items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg"}})
    54  	routers = append(routers, testinfo{"/*.*", "/nice/api.json", map[string]string{":path": "nice/api", ":ext": "json"}})
    55  	routers = append(routers, testinfo{"/:name/*.*", "/nice/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}})
    56  	routers = append(routers, testinfo{"/:name/test/*.*", "/nice/test/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}})
    57  	routers = append(routers, testinfo{"/dl/:width:int/:height:int/*.*",
    58  		"/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg",
    59  		map[string]string{":width": "48", ":height": "48", ":ext": "jpg", ":path": "05ac66d9bda00a3acf948c43e306fc9a"}})
    60  	routers = append(routers, testinfo{"/v1/shop/:id:int", "/v1/shop/123", map[string]string{":id": "123"}})
    61  	routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(a)", map[string]string{":id": "123"}})
    62  	routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(b)", map[string]string{":id": "123"}})
    63  	routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(c)", map[string]string{":id": "123"}})
    64  	routers = append(routers, testinfo{"/:year:int/:month:int/:id/:endid", "/1111/111/aaa/aaa", map[string]string{":year": "1111", ":month": "111", ":id": "aaa", ":endid": "aaa"}})
    65  	routers = append(routers, testinfo{"/v1/shop/:id/:name", "/v1/shop/123/nike", map[string]string{":id": "123", ":name": "nike"}})
    66  	routers = append(routers, testinfo{"/v1/shop/:id/account", "/v1/shop/123/account", map[string]string{":id": "123"}})
    67  	routers = append(routers, testinfo{"/v1/shop/:name:string", "/v1/shop/nike", map[string]string{":name": "nike"}})
    68  	routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)", "/v1/shop//123", map[string]string{":id": "123"}})
    69  	routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)_:name", "/v1/shop/123_nike", map[string]string{":id": "123", ":name": "nike"}})
    70  	routers = append(routers, testinfo{"/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", map[string]string{":id": "123"}})
    71  	routers = append(routers, testinfo{"/v1/shop/cms_:id(.+)_:page(.+).html", "/v1/shop/cms_123_1.html", map[string]string{":id": "123", ":page": "1"}})
    72  	routers = append(routers, testinfo{"/v1/:v/cms/aaa_:id(.+)_:page(.+).html", "/v1/2/cms/aaa_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
    73  	routers = append(routers, testinfo{"/v1/:v/cms_:id(.+)_:page(.+).html", "/v1/2/cms_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
    74  	routers = append(routers, testinfo{"/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", "/v1/2_cms/ttt_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
    75  	routers = append(routers, testinfo{"/api/projects/:pid/members/?:mid", "/api/projects/1/members", map[string]string{":pid": "1"}})
    76  	routers = append(routers, testinfo{"/api/projects/:pid/members/?:mid", "/api/projects/1/members/2", map[string]string{":pid": "1", ":mid": "2"}})
    77  }
    78  
    79  func TestTreeRouters(t *testing.T) {
    80  	for _, r := range routers {
    81  		tr := NewTree()
    82  		tr.AddRouter(r.url, "astaxie")
    83  		ctx := context.NewContext()
    84  		obj := tr.Match(r.requesturl, ctx)
    85  		if obj == nil || obj.(string) != "astaxie" {
    86  			t.Fatal(r.url+" can't get obj, Expect ", r.requesturl)
    87  		}
    88  		if r.params != nil {
    89  			for k, v := range r.params {
    90  				if vv := ctx.Input.Param(k); vv != v {
    91  					t.Fatal("The Rule: " + r.url + "\nThe RequestURL:" + r.requesturl + "\nThe Key is " + k + ", The Value should be: " + v + ", but get: " + vv)
    92  				} else if vv == "" && v != "" {
    93  					t.Fatal(r.url + "    " + r.requesturl + " get param empty:" + k)
    94  				}
    95  			}
    96  		}
    97  	}
    98  }
    99  
   100  func TestStaticPath(t *testing.T) {
   101  	tr := NewTree()
   102  	tr.AddRouter("/topic/:id", "wildcard")
   103  	tr.AddRouter("/topic", "static")
   104  	ctx := context.NewContext()
   105  	obj := tr.Match("/topic", ctx)
   106  	if obj == nil || obj.(string) != "static" {
   107  		t.Fatal("/topic is  a static route")
   108  	}
   109  	obj = tr.Match("/topic/1", ctx)
   110  	if obj == nil || obj.(string) != "wildcard" {
   111  		t.Fatal("/topic/1 is a wildcard route")
   112  	}
   113  }
   114  
   115  func TestAddTree(t *testing.T) {
   116  	tr := NewTree()
   117  	tr.AddRouter("/shop/:id/account", "astaxie")
   118  	tr.AddRouter("/shop/:sd/ttt_:id(.+)_:page(.+).html", "astaxie")
   119  	t1 := NewTree()
   120  	t1.AddTree("/v1/zl", tr)
   121  	ctx := context.NewContext()
   122  	obj := t1.Match("/v1/zl/shop/123/account", ctx)
   123  	if obj == nil || obj.(string) != "astaxie" {
   124  		t.Fatal("/v1/zl/shop/:id/account can't get obj ")
   125  	}
   126  	if ctx.Input.ParamsLen() == 0 {
   127  		t.Fatal("get param error")
   128  	}
   129  	if ctx.Input.Param(":id") != "123" {
   130  		t.Fatal("get :id param error")
   131  	}
   132  	ctx.Input.Reset(ctx)
   133  	obj = t1.Match("/v1/zl/shop/123/ttt_1_12.html", ctx)
   134  	if obj == nil || obj.(string) != "astaxie" {
   135  		t.Fatal("/v1/zl//shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ")
   136  	}
   137  	if ctx.Input.ParamsLen() == 0 {
   138  		t.Fatal("get param error")
   139  	}
   140  	if ctx.Input.Param(":sd") != "123" || ctx.Input.Param(":id") != "1" || ctx.Input.Param(":page") != "12" {
   141  		t.Fatal("get :sd :id :page param error")
   142  	}
   143  
   144  	t2 := NewTree()
   145  	t2.AddTree("/v1/:shopid", tr)
   146  	ctx.Input.Reset(ctx)
   147  	obj = t2.Match("/v1/zl/shop/123/account", ctx)
   148  	if obj == nil || obj.(string) != "astaxie" {
   149  		t.Fatal("/v1/:shopid/shop/:id/account can't get obj ")
   150  	}
   151  	if ctx.Input.ParamsLen() == 0 {
   152  		t.Fatal("get param error")
   153  	}
   154  	if ctx.Input.Param(":id") != "123" || ctx.Input.Param(":shopid") != "zl" {
   155  		t.Fatal("get :id :shopid param error")
   156  	}
   157  	ctx.Input.Reset(ctx)
   158  	obj = t2.Match("/v1/zl/shop/123/ttt_1_12.html", ctx)
   159  	if obj == nil || obj.(string) != "astaxie" {
   160  		t.Fatal("/v1/:shopid/shop/:sd/ttt_:id(.+)_:page(.+).html can't get obj ")
   161  	}
   162  	if ctx.Input.ParamsLen() == 0 {
   163  		t.Fatal("get :shopid param error")
   164  	}
   165  	if ctx.Input.Param(":sd") != "123" || ctx.Input.Param(":id") != "1" || ctx.Input.Param(":page") != "12" || ctx.Input.Param(":shopid") != "zl" {
   166  		t.Fatal("get :sd :id :page :shopid param error")
   167  	}
   168  }
   169  
   170  func TestAddTree2(t *testing.T) {
   171  	tr := NewTree()
   172  	tr.AddRouter("/shop/:id/account", "astaxie")
   173  	tr.AddRouter("/shop/:sd/ttt_:id(.+)_:page(.+).html", "astaxie")
   174  	t3 := NewTree()
   175  	t3.AddTree("/:version(v1|v2)/:prefix", tr)
   176  	ctx := context.NewContext()
   177  	obj := t3.Match("/v1/zl/shop/123/account", ctx)
   178  	if obj == nil || obj.(string) != "astaxie" {
   179  		t.Fatal("/:version(v1|v2)/:prefix/shop/:id/account can't get obj ")
   180  	}
   181  	if ctx.Input.ParamsLen() == 0 {
   182  		t.Fatal("get param error")
   183  	}
   184  	if ctx.Input.Param(":id") != "123" || ctx.Input.Param(":prefix") != "zl" || ctx.Input.Param(":version") != "v1" {
   185  		t.Fatal("get :id :prefix :version param error")
   186  	}
   187  }
   188  
   189  func TestAddTree3(t *testing.T) {
   190  	tr := NewTree()
   191  	tr.AddRouter("/create", "astaxie")
   192  	tr.AddRouter("/shop/:sd/account", "astaxie")
   193  	t3 := NewTree()
   194  	t3.AddTree("/table/:num", tr)
   195  	ctx := context.NewContext()
   196  	obj := t3.Match("/table/123/shop/123/account", ctx)
   197  	if obj == nil || obj.(string) != "astaxie" {
   198  		t.Fatal("/table/:num/shop/:sd/account can't get obj ")
   199  	}
   200  	if ctx.Input.ParamsLen() == 0 {
   201  		t.Fatal("get param error")
   202  	}
   203  	if ctx.Input.Param(":num") != "123" || ctx.Input.Param(":sd") != "123" {
   204  		t.Fatal("get :num :sd param error")
   205  	}
   206  	ctx.Input.Reset(ctx)
   207  	obj = t3.Match("/table/123/create", ctx)
   208  	if obj == nil || obj.(string) != "astaxie" {
   209  		t.Fatal("/table/:num/create can't get obj ")
   210  	}
   211  }
   212  
   213  func TestAddTree4(t *testing.T) {
   214  	tr := NewTree()
   215  	tr.AddRouter("/create", "astaxie")
   216  	tr.AddRouter("/shop/:sd/:account", "astaxie")
   217  	t4 := NewTree()
   218  	t4.AddTree("/:info:int/:num/:id", tr)
   219  	ctx := context.NewContext()
   220  	obj := t4.Match("/12/123/456/shop/123/account", ctx)
   221  	if obj == nil || obj.(string) != "astaxie" {
   222  		t.Fatal("/:info:int/:num/:id/shop/:sd/:account can't get obj ")
   223  	}
   224  	if ctx.Input.ParamsLen() == 0 {
   225  		t.Fatal("get param error")
   226  	}
   227  	if ctx.Input.Param(":info") != "12" || ctx.Input.Param(":num") != "123" ||
   228  		ctx.Input.Param(":id") != "456" || ctx.Input.Param(":sd") != "123" ||
   229  		ctx.Input.Param(":account") != "account" {
   230  		t.Fatal("get :info :num :id :sd :account param error")
   231  	}
   232  	ctx.Input.Reset(ctx)
   233  	obj = t4.Match("/12/123/456/create", ctx)
   234  	if obj == nil || obj.(string) != "astaxie" {
   235  		t.Fatal("/:info:int/:num/:id/create can't get obj ")
   236  	}
   237  }
   238  
   239  // Test for issue #1595
   240  func TestAddTree5(t *testing.T) {
   241  	tr := NewTree()
   242  	tr.AddRouter("/v1/shop/:id", "shopdetail")
   243  	tr.AddRouter("/v1/shop/", "shophome")
   244  	ctx := context.NewContext()
   245  	obj := tr.Match("/v1/shop/", ctx)
   246  	if obj == nil || obj.(string) != "shophome" {
   247  		t.Fatal("url /v1/shop/ need match router /v1/shop/ ")
   248  	}
   249  }
   250  
   251  func TestSplitPath(t *testing.T) {
   252  	a := splitPath("")
   253  	if len(a) != 0 {
   254  		t.Fatal("/ should retrun []")
   255  	}
   256  	a = splitPath("/")
   257  	if len(a) != 0 {
   258  		t.Fatal("/ should retrun []")
   259  	}
   260  	a = splitPath("/admin")
   261  	if len(a) != 1 || a[0] != "admin" {
   262  		t.Fatal("/admin should retrun [admin]")
   263  	}
   264  	a = splitPath("/admin/")
   265  	if len(a) != 1 || a[0] != "admin" {
   266  		t.Fatal("/admin/ should retrun [admin]")
   267  	}
   268  	a = splitPath("/admin/users")
   269  	if len(a) != 2 || a[0] != "admin" || a[1] != "users" {
   270  		t.Fatal("/admin should retrun [admin users]")
   271  	}
   272  	a = splitPath("/admin/:id:int")
   273  	if len(a) != 2 || a[0] != "admin" || a[1] != ":id:int" {
   274  		t.Fatal("/admin should retrun [admin :id:int]")
   275  	}
   276  }
   277  
   278  func TestSplitSegment(t *testing.T) {
   279  
   280  	items := map[string]struct {
   281  		isReg  bool
   282  		params []string
   283  		regStr string
   284  	}{
   285  		"admin":                      {false, nil, ""},
   286  		"*":                          {true, []string{":splat"}, ""},
   287  		"*.*":                        {true, []string{".", ":path", ":ext"}, ""},
   288  		":id":                        {true, []string{":id"}, ""},
   289  		"?:id":                       {true, []string{":", ":id"}, ""},
   290  		":id:int":                    {true, []string{":id"}, "([0-9]+)"},
   291  		":name:string":               {true, []string{":name"}, `([\w]+)`},
   292  		":id([0-9]+)":                {true, []string{":id"}, `([0-9]+)`},
   293  		":id([0-9]+)_:name":          {true, []string{":id", ":name"}, `([0-9]+)_(.+)`},
   294  		":id(.+)_cms.html":           {true, []string{":id"}, `(.+)_cms.html`},
   295  		"cms_:id(.+)_:page(.+).html": {true, []string{":id", ":page"}, `cms_(.+)_(.+).html`},
   296  		`:app(a|b|c)`:                {true, []string{":app"}, `(a|b|c)`},
   297  		`:app\((a|b|c)\)`:            {true, []string{":app"}, `(.+)\((a|b|c)\)`},
   298  	}
   299  
   300  	for pattern, v := range items {
   301  		b, w, r := splitSegment(pattern)
   302  		if b != v.isReg || r != v.regStr || strings.Join(w, ",") != strings.Join(v.params, ",") {
   303  			t.Fatalf("%s should return %t,%s,%q, got %t,%s,%q", pattern, v.isReg, v.params, v.regStr, b, w, r)
   304  		}
   305  	}
   306  }