...

Source file src/github.com/gorilla/mux/old_test.go

Documentation: github.com/gorilla/mux

     1  // Old tests ported to Go1. This is a mess. Want to drop it one day.
     2  
     3  // Copyright 2011 Gorilla Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package mux
     8  
     9  import (
    10  	"bytes"
    11  	"net/http"
    12  	"testing"
    13  )
    14  
    15  // ----------------------------------------------------------------------------
    16  // ResponseRecorder
    17  // ----------------------------------------------------------------------------
    18  // Copyright 2009 The Go Authors. All rights reserved.
    19  // Use of this source code is governed by a BSD-style
    20  // license that can be found in the LICENSE file.
    21  
    22  // ResponseRecorder is an implementation of http.ResponseWriter that
    23  // records its mutations for later inspection in tests.
    24  type ResponseRecorder struct {
    25  	Code      int           // the HTTP response code from WriteHeader
    26  	HeaderMap http.Header   // the HTTP response headers
    27  	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
    28  	Flushed   bool
    29  }
    30  
    31  // NewRecorder returns an initialized ResponseRecorder.
    32  func NewRecorder() *ResponseRecorder {
    33  	return &ResponseRecorder{
    34  		HeaderMap: make(http.Header),
    35  		Body:      new(bytes.Buffer),
    36  	}
    37  }
    38  
    39  // Header returns the response headers.
    40  func (rw *ResponseRecorder) Header() http.Header {
    41  	return rw.HeaderMap
    42  }
    43  
    44  // Write always succeeds and writes to rw.Body, if not nil.
    45  func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
    46  	if rw.Body != nil {
    47  		rw.Body.Write(buf)
    48  	}
    49  	if rw.Code == 0 {
    50  		rw.Code = http.StatusOK
    51  	}
    52  	return len(buf), nil
    53  }
    54  
    55  // WriteHeader sets rw.Code.
    56  func (rw *ResponseRecorder) WriteHeader(code int) {
    57  	rw.Code = code
    58  }
    59  
    60  // Flush sets rw.Flushed to true.
    61  func (rw *ResponseRecorder) Flush() {
    62  	rw.Flushed = true
    63  }
    64  
    65  // ----------------------------------------------------------------------------
    66  
    67  func TestRouteMatchers(t *testing.T) {
    68  	var scheme, host, path, query, method string
    69  	var headers map[string]string
    70  	var resultVars map[bool]map[string]string
    71  
    72  	router := NewRouter()
    73  	router.NewRoute().Host("{var1}.google.com").
    74  		Path("/{var2:[a-z]+}/{var3:[0-9]+}").
    75  		Queries("foo", "bar").
    76  		Methods("GET").
    77  		Schemes("https").
    78  		Headers("x-requested-with", "XMLHttpRequest")
    79  	router.NewRoute().Host("www.{var4}.com").
    80  		PathPrefix("/foo/{var5:[a-z]+}/{var6:[0-9]+}").
    81  		Queries("baz", "ding").
    82  		Methods("POST").
    83  		Schemes("http").
    84  		Headers("Content-Type", "application/json")
    85  
    86  	reset := func() {
    87  		// Everything match.
    88  		scheme = "https"
    89  		host = "www.google.com"
    90  		path = "/product/42"
    91  		query = "?foo=bar"
    92  		method = "GET"
    93  		headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
    94  		resultVars = map[bool]map[string]string{
    95  			true:  {"var1": "www", "var2": "product", "var3": "42"},
    96  			false: {},
    97  		}
    98  	}
    99  
   100  	reset2 := func() {
   101  		// Everything match.
   102  		scheme = "http"
   103  		host = "www.google.com"
   104  		path = "/foo/product/42/path/that/is/ignored"
   105  		query = "?baz=ding"
   106  		method = "POST"
   107  		headers = map[string]string{"Content-Type": "application/json"}
   108  		resultVars = map[bool]map[string]string{
   109  			true:  {"var4": "google", "var5": "product", "var6": "42"},
   110  			false: {},
   111  		}
   112  	}
   113  
   114  	match := func(shouldMatch bool) {
   115  		url := scheme + "://" + host + path + query
   116  		request, _ := http.NewRequest(method, url, nil)
   117  		for key, value := range headers {
   118  			request.Header.Add(key, value)
   119  		}
   120  
   121  		var routeMatch RouteMatch
   122  		matched := router.Match(request, &routeMatch)
   123  		if matched != shouldMatch {
   124  			t.Errorf("Expected: %v\nGot: %v\nRequest: %v %v", shouldMatch, matched, request.Method, url)
   125  		}
   126  
   127  		if matched {
   128  			currentRoute := routeMatch.Route
   129  			if currentRoute == nil {
   130  				t.Errorf("Expected a current route.")
   131  			}
   132  			vars := routeMatch.Vars
   133  			expectedVars := resultVars[shouldMatch]
   134  			if len(vars) != len(expectedVars) {
   135  				t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
   136  			}
   137  			for name, value := range vars {
   138  				if expectedVars[name] != value {
   139  					t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
   140  				}
   141  			}
   142  		}
   143  	}
   144  
   145  	// 1st route --------------------------------------------------------------
   146  
   147  	// Everything match.
   148  	reset()
   149  	match(true)
   150  
   151  	// Scheme doesn't match.
   152  	reset()
   153  	scheme = "http"
   154  	match(false)
   155  
   156  	// Host doesn't match.
   157  	reset()
   158  	host = "www.mygoogle.com"
   159  	match(false)
   160  
   161  	// Path doesn't match.
   162  	reset()
   163  	path = "/product/notdigits"
   164  	match(false)
   165  
   166  	// Query doesn't match.
   167  	reset()
   168  	query = "?foo=baz"
   169  	match(false)
   170  
   171  	// Method doesn't match.
   172  	reset()
   173  	method = "POST"
   174  	match(false)
   175  
   176  	// Header doesn't match.
   177  	reset()
   178  	headers = map[string]string{}
   179  	match(false)
   180  
   181  	// Everything match, again.
   182  	reset()
   183  	match(true)
   184  
   185  	// 2nd route --------------------------------------------------------------
   186  	// Everything match.
   187  	reset2()
   188  	match(true)
   189  
   190  	// Scheme doesn't match.
   191  	reset2()
   192  	scheme = "https"
   193  	match(false)
   194  
   195  	// Host doesn't match.
   196  	reset2()
   197  	host = "sub.google.com"
   198  	match(false)
   199  
   200  	// Path doesn't match.
   201  	reset2()
   202  	path = "/bar/product/42"
   203  	match(false)
   204  
   205  	// Query doesn't match.
   206  	reset2()
   207  	query = "?foo=baz"
   208  	match(false)
   209  
   210  	// Method doesn't match.
   211  	reset2()
   212  	method = "GET"
   213  	match(false)
   214  
   215  	// Header doesn't match.
   216  	reset2()
   217  	headers = map[string]string{}
   218  	match(false)
   219  
   220  	// Everything match, again.
   221  	reset2()
   222  	match(true)
   223  }
   224  
   225  type headerMatcherTest struct {
   226  	matcher headerMatcher
   227  	headers map[string]string
   228  	result  bool
   229  }
   230  
   231  var headerMatcherTests = []headerMatcherTest{
   232  	{
   233  		matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
   234  		headers: map[string]string{"X-Requested-With": "XMLHttpRequest"},
   235  		result:  true,
   236  	},
   237  	{
   238  		matcher: headerMatcher(map[string]string{"x-requested-with": ""}),
   239  		headers: map[string]string{"X-Requested-With": "anything"},
   240  		result:  true,
   241  	},
   242  	{
   243  		matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
   244  		headers: map[string]string{},
   245  		result:  false,
   246  	},
   247  }
   248  
   249  type hostMatcherTest struct {
   250  	matcher *Route
   251  	url     string
   252  	vars    map[string]string
   253  	result  bool
   254  }
   255  
   256  var hostMatcherTests = []hostMatcherTest{
   257  	{
   258  		matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
   259  		url:     "http://abc.def.ghi/",
   260  		vars:    map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
   261  		result:  true,
   262  	},
   263  	{
   264  		matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}:{port:.*}"),
   265  		url:     "http://abc.def.ghi:65535/",
   266  		vars:    map[string]string{"foo": "abc", "bar": "def", "baz": "ghi", "port": "65535"},
   267  		result:  true,
   268  	},
   269  	{
   270  		matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
   271  		url:     "http://abc.def.ghi:65535/",
   272  		vars:    map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
   273  		result:  true,
   274  	},
   275  	{
   276  		matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
   277  		url:     "http://a.b.c/",
   278  		vars:    map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
   279  		result:  false,
   280  	},
   281  }
   282  
   283  type methodMatcherTest struct {
   284  	matcher methodMatcher
   285  	method  string
   286  	result  bool
   287  }
   288  
   289  var methodMatcherTests = []methodMatcherTest{
   290  	{
   291  		matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
   292  		method:  "GET",
   293  		result:  true,
   294  	},
   295  	{
   296  		matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
   297  		method:  "POST",
   298  		result:  true,
   299  	},
   300  	{
   301  		matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
   302  		method:  "PUT",
   303  		result:  true,
   304  	},
   305  	{
   306  		matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
   307  		method:  "DELETE",
   308  		result:  false,
   309  	},
   310  }
   311  
   312  type pathMatcherTest struct {
   313  	matcher *Route
   314  	url     string
   315  	vars    map[string]string
   316  	result  bool
   317  }
   318  
   319  var pathMatcherTests = []pathMatcherTest{
   320  	{
   321  		matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
   322  		url:     "http://localhost:8080/123/456/789",
   323  		vars:    map[string]string{"foo": "123", "bar": "456", "baz": "789"},
   324  		result:  true,
   325  	},
   326  	{
   327  		matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
   328  		url:     "http://localhost:8080/1/2/3",
   329  		vars:    map[string]string{"foo": "123", "bar": "456", "baz": "789"},
   330  		result:  false,
   331  	},
   332  }
   333  
   334  type schemeMatcherTest struct {
   335  	matcher schemeMatcher
   336  	url     string
   337  	result  bool
   338  }
   339  
   340  var schemeMatcherTests = []schemeMatcherTest{
   341  	{
   342  		matcher: schemeMatcher([]string{"http", "https"}),
   343  		url:     "http://localhost:8080/",
   344  		result:  true,
   345  	},
   346  	{
   347  		matcher: schemeMatcher([]string{"http", "https"}),
   348  		url:     "https://localhost:8080/",
   349  		result:  true,
   350  	},
   351  	{
   352  		matcher: schemeMatcher([]string{"https"}),
   353  		url:     "http://localhost:8080/",
   354  		result:  false,
   355  	},
   356  	{
   357  		matcher: schemeMatcher([]string{"http"}),
   358  		url:     "https://localhost:8080/",
   359  		result:  false,
   360  	},
   361  }
   362  
   363  type urlBuildingTest struct {
   364  	route *Route
   365  	vars  []string
   366  	url   string
   367  }
   368  
   369  var urlBuildingTests = []urlBuildingTest{
   370  	{
   371  		route: new(Route).Host("foo.domain.com"),
   372  		vars:  []string{},
   373  		url:   "http://foo.domain.com",
   374  	},
   375  	{
   376  		route: new(Route).Host("{subdomain}.domain.com"),
   377  		vars:  []string{"subdomain", "bar"},
   378  		url:   "http://bar.domain.com",
   379  	},
   380  	{
   381  		route: new(Route).Host("{subdomain}.domain.com:{port:.*}"),
   382  		vars:  []string{"subdomain", "bar", "port", "65535"},
   383  		url:   "http://bar.domain.com:65535",
   384  	},
   385  	{
   386  		route: new(Route).Host("foo.domain.com").Path("/articles"),
   387  		vars:  []string{},
   388  		url:   "http://foo.domain.com/articles",
   389  	},
   390  	{
   391  		route: new(Route).Path("/articles"),
   392  		vars:  []string{},
   393  		url:   "/articles",
   394  	},
   395  	{
   396  		route: new(Route).Path("/articles/{category}/{id:[0-9]+}"),
   397  		vars:  []string{"category", "technology", "id", "42"},
   398  		url:   "/articles/technology/42",
   399  	},
   400  	{
   401  		route: new(Route).Host("{subdomain}.domain.com").Path("/articles/{category}/{id:[0-9]+}"),
   402  		vars:  []string{"subdomain", "foo", "category", "technology", "id", "42"},
   403  		url:   "http://foo.domain.com/articles/technology/42",
   404  	},
   405  	{
   406  		route: new(Route).Host("example.com").Schemes("https", "http"),
   407  		vars:  []string{},
   408  		url:   "https://example.com",
   409  	},
   410  }
   411  
   412  func TestHeaderMatcher(t *testing.T) {
   413  	for _, v := range headerMatcherTests {
   414  		request, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
   415  		for key, value := range v.headers {
   416  			request.Header.Add(key, value)
   417  		}
   418  		var routeMatch RouteMatch
   419  		result := v.matcher.Match(request, &routeMatch)
   420  		if result != v.result {
   421  			if v.result {
   422  				t.Errorf("%#v: should match %v.", v.matcher, request.Header)
   423  			} else {
   424  				t.Errorf("%#v: should not match %v.", v.matcher, request.Header)
   425  			}
   426  		}
   427  	}
   428  }
   429  
   430  func TestHostMatcher(t *testing.T) {
   431  	for _, v := range hostMatcherTests {
   432  		request, err := http.NewRequest("GET", v.url, nil)
   433  		if err != nil {
   434  			t.Errorf("http.NewRequest failed %#v", err)
   435  			continue
   436  		}
   437  		var routeMatch RouteMatch
   438  		result := v.matcher.Match(request, &routeMatch)
   439  		vars := routeMatch.Vars
   440  		if result != v.result {
   441  			if v.result {
   442  				t.Errorf("%#v: should match %v.", v.matcher, v.url)
   443  			} else {
   444  				t.Errorf("%#v: should not match %v.", v.matcher, v.url)
   445  			}
   446  		}
   447  		if result {
   448  			if len(vars) != len(v.vars) {
   449  				t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
   450  			}
   451  			for name, value := range vars {
   452  				if v.vars[name] != value {
   453  					t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
   454  				}
   455  			}
   456  		} else {
   457  			if len(vars) != 0 {
   458  				t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
   459  			}
   460  		}
   461  	}
   462  }
   463  
   464  func TestMethodMatcher(t *testing.T) {
   465  	for _, v := range methodMatcherTests {
   466  		request, _ := http.NewRequest(v.method, "http://localhost:8080/", nil)
   467  		var routeMatch RouteMatch
   468  		result := v.matcher.Match(request, &routeMatch)
   469  		if result != v.result {
   470  			if v.result {
   471  				t.Errorf("%#v: should match %v.", v.matcher, v.method)
   472  			} else {
   473  				t.Errorf("%#v: should not match %v.", v.matcher, v.method)
   474  			}
   475  		}
   476  	}
   477  }
   478  
   479  func TestPathMatcher(t *testing.T) {
   480  	for _, v := range pathMatcherTests {
   481  		request, _ := http.NewRequest("GET", v.url, nil)
   482  		var routeMatch RouteMatch
   483  		result := v.matcher.Match(request, &routeMatch)
   484  		vars := routeMatch.Vars
   485  		if result != v.result {
   486  			if v.result {
   487  				t.Errorf("%#v: should match %v.", v.matcher, v.url)
   488  			} else {
   489  				t.Errorf("%#v: should not match %v.", v.matcher, v.url)
   490  			}
   491  		}
   492  		if result {
   493  			if len(vars) != len(v.vars) {
   494  				t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
   495  			}
   496  			for name, value := range vars {
   497  				if v.vars[name] != value {
   498  					t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
   499  				}
   500  			}
   501  		} else {
   502  			if len(vars) != 0 {
   503  				t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
   504  			}
   505  		}
   506  	}
   507  }
   508  
   509  func TestSchemeMatcher(t *testing.T) {
   510  	for _, v := range schemeMatcherTests {
   511  		request, _ := http.NewRequest("GET", v.url, nil)
   512  		var routeMatch RouteMatch
   513  		result := v.matcher.Match(request, &routeMatch)
   514  		if result != v.result {
   515  			if v.result {
   516  				t.Errorf("%#v: should match %v.", v.matcher, v.url)
   517  			} else {
   518  				t.Errorf("%#v: should not match %v.", v.matcher, v.url)
   519  			}
   520  		}
   521  	}
   522  }
   523  
   524  func TestUrlBuilding(t *testing.T) {
   525  
   526  	for _, v := range urlBuildingTests {
   527  		u, _ := v.route.URL(v.vars...)
   528  		url := u.String()
   529  		if url != v.url {
   530  			t.Errorf("expected %v, got %v", v.url, url)
   531  		}
   532  	}
   533  
   534  	ArticleHandler := func(w http.ResponseWriter, r *http.Request) {
   535  	}
   536  
   537  	router := NewRouter()
   538  	router.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article")
   539  
   540  	url, _ := router.Get("article").URL("category", "technology", "id", "42")
   541  	expected := "/articles/technology/42"
   542  	if url.String() != expected {
   543  		t.Errorf("Expected %v, got %v", expected, url.String())
   544  	}
   545  }
   546  
   547  func TestMatchedRouteName(t *testing.T) {
   548  	routeName := "stock"
   549  	router := NewRouter()
   550  	route := router.NewRoute().Path("/products/").Name(routeName)
   551  
   552  	url := "http://www.example.com/products/"
   553  	request, _ := http.NewRequest("GET", url, nil)
   554  	var rv RouteMatch
   555  	ok := router.Match(request, &rv)
   556  
   557  	if !ok || rv.Route != route {
   558  		t.Errorf("Expected same route, got %+v.", rv.Route)
   559  	}
   560  
   561  	retName := rv.Route.GetName()
   562  	if retName != routeName {
   563  		t.Errorf("Expected %q, got %q.", routeName, retName)
   564  	}
   565  }
   566  
   567  func TestSubRouting(t *testing.T) {
   568  	// Example from docs.
   569  	router := NewRouter()
   570  	subrouter := router.NewRoute().Host("www.example.com").Subrouter()
   571  	route := subrouter.NewRoute().Path("/products/").Name("products")
   572  
   573  	url := "http://www.example.com/products/"
   574  	request, _ := http.NewRequest("GET", url, nil)
   575  	var rv RouteMatch
   576  	ok := router.Match(request, &rv)
   577  
   578  	if !ok || rv.Route != route {
   579  		t.Errorf("Expected same route, got %+v.", rv.Route)
   580  	}
   581  
   582  	u, _ := router.Get("products").URL()
   583  	builtURL := u.String()
   584  	// Yay, subroute aware of the domain when building!
   585  	if builtURL != url {
   586  		t.Errorf("Expected %q, got %q.", url, builtURL)
   587  	}
   588  }
   589  
   590  func TestVariableNames(t *testing.T) {
   591  	route := new(Route).Host("{arg1}.domain.com").Path("/{arg1}/{arg2:[0-9]+}")
   592  	if route.err == nil {
   593  		t.Errorf("Expected error for duplicated variable names")
   594  	}
   595  }
   596  
   597  func TestRedirectSlash(t *testing.T) {
   598  	var route *Route
   599  	var routeMatch RouteMatch
   600  	r := NewRouter()
   601  
   602  	r.StrictSlash(false)
   603  	route = r.NewRoute()
   604  	if route.strictSlash != false {
   605  		t.Errorf("Expected false redirectSlash.")
   606  	}
   607  
   608  	r.StrictSlash(true)
   609  	route = r.NewRoute()
   610  	if route.strictSlash != true {
   611  		t.Errorf("Expected true redirectSlash.")
   612  	}
   613  
   614  	route = new(Route)
   615  	route.strictSlash = true
   616  	route.Path("/{arg1}/{arg2:[0-9]+}/")
   617  	request, _ := http.NewRequest("GET", "http://localhost/foo/123", nil)
   618  	routeMatch = RouteMatch{}
   619  	_ = route.Match(request, &routeMatch)
   620  	vars := routeMatch.Vars
   621  	if vars["arg1"] != "foo" {
   622  		t.Errorf("Expected foo.")
   623  	}
   624  	if vars["arg2"] != "123" {
   625  		t.Errorf("Expected 123.")
   626  	}
   627  	rsp := NewRecorder()
   628  	routeMatch.Handler.ServeHTTP(rsp, request)
   629  	if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123/" {
   630  		t.Errorf("Expected redirect header.")
   631  	}
   632  
   633  	route = new(Route)
   634  	route.strictSlash = true
   635  	route.Path("/{arg1}/{arg2:[0-9]+}")
   636  	request, _ = http.NewRequest("GET", "http://localhost/foo/123/", nil)
   637  	routeMatch = RouteMatch{}
   638  	_ = route.Match(request, &routeMatch)
   639  	vars = routeMatch.Vars
   640  	if vars["arg1"] != "foo" {
   641  		t.Errorf("Expected foo.")
   642  	}
   643  	if vars["arg2"] != "123" {
   644  		t.Errorf("Expected 123.")
   645  	}
   646  	rsp = NewRecorder()
   647  	routeMatch.Handler.ServeHTTP(rsp, request)
   648  	if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123" {
   649  		t.Errorf("Expected redirect header.")
   650  	}
   651  }
   652  
   653  // Test for the new regexp library, still not available in stable Go.
   654  func TestNewRegexp(t *testing.T) {
   655  	var p *routeRegexp
   656  	var matches []string
   657  
   658  	tests := map[string]map[string][]string{
   659  		"/{foo:a{2}}": {
   660  			"/a":    nil,
   661  			"/aa":   {"aa"},
   662  			"/aaa":  nil,
   663  			"/aaaa": nil,
   664  		},
   665  		"/{foo:a{2,}}": {
   666  			"/a":    nil,
   667  			"/aa":   {"aa"},
   668  			"/aaa":  {"aaa"},
   669  			"/aaaa": {"aaaa"},
   670  		},
   671  		"/{foo:a{2,3}}": {
   672  			"/a":    nil,
   673  			"/aa":   {"aa"},
   674  			"/aaa":  {"aaa"},
   675  			"/aaaa": nil,
   676  		},
   677  		"/{foo:[a-z]{3}}/{bar:[a-z]{2}}": {
   678  			"/a":       nil,
   679  			"/ab":      nil,
   680  			"/abc":     nil,
   681  			"/abcd":    nil,
   682  			"/abc/ab":  {"abc", "ab"},
   683  			"/abc/abc": nil,
   684  			"/abcd/ab": nil,
   685  		},
   686  		`/{foo:\w{3,}}/{bar:\d{2,}}`: {
   687  			"/a":        nil,
   688  			"/ab":       nil,
   689  			"/abc":      nil,
   690  			"/abc/1":    nil,
   691  			"/abc/12":   {"abc", "12"},
   692  			"/abcd/12":  {"abcd", "12"},
   693  			"/abcd/123": {"abcd", "123"},
   694  		},
   695  	}
   696  
   697  	for pattern, paths := range tests {
   698  		p, _ = newRouteRegexp(pattern, regexpTypePath, routeRegexpOptions{})
   699  		for path, result := range paths {
   700  			matches = p.regexp.FindStringSubmatch(path)
   701  			if result == nil {
   702  				if matches != nil {
   703  					t.Errorf("%v should not match %v.", pattern, path)
   704  				}
   705  			} else {
   706  				if len(matches) != len(result)+1 {
   707  					t.Errorf("Expected %v matches, got %v.", len(result)+1, len(matches))
   708  				} else {
   709  					for k, v := range result {
   710  						if matches[k+1] != v {
   711  							t.Errorf("Expected %v, got %v.", v, matches[k+1])
   712  						}
   713  					}
   714  				}
   715  			}
   716  		}
   717  	}
   718  }
   719  

View as plain text