You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
714 lines
17 KiB
714 lines
17 KiB
// Old tests ported to Go1. This is a mess. Want to drop it one day.
|
|
|
|
// Copyright 2011 Gorilla Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package mux
|
|
|
|
import (
|
|
"bytes"
|
|
"net/http"
|
|
"testing"
|
|
)
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ResponseRecorder
|
|
// ----------------------------------------------------------------------------
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// ResponseRecorder is an implementation of http.ResponseWriter that
|
|
// records its mutations for later inspection in tests.
|
|
type ResponseRecorder struct {
|
|
Code int // the HTTP response code from WriteHeader
|
|
HeaderMap http.Header // the HTTP response headers
|
|
Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
|
|
Flushed bool
|
|
}
|
|
|
|
// NewRecorder returns an initialized ResponseRecorder.
|
|
func NewRecorder() *ResponseRecorder {
|
|
return &ResponseRecorder{
|
|
HeaderMap: make(http.Header),
|
|
Body: new(bytes.Buffer),
|
|
}
|
|
}
|
|
|
|
// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
|
|
// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
|
|
const DefaultRemoteAddr = "1.2.3.4"
|
|
|
|
// Header returns the response headers.
|
|
func (rw *ResponseRecorder) Header() http.Header {
|
|
return rw.HeaderMap
|
|
}
|
|
|
|
// Write always succeeds and writes to rw.Body, if not nil.
|
|
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
|
|
if rw.Body != nil {
|
|
rw.Body.Write(buf)
|
|
}
|
|
if rw.Code == 0 {
|
|
rw.Code = http.StatusOK
|
|
}
|
|
return len(buf), nil
|
|
}
|
|
|
|
// WriteHeader sets rw.Code.
|
|
func (rw *ResponseRecorder) WriteHeader(code int) {
|
|
rw.Code = code
|
|
}
|
|
|
|
// Flush sets rw.Flushed to true.
|
|
func (rw *ResponseRecorder) Flush() {
|
|
rw.Flushed = true
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func TestRouteMatchers(t *testing.T) {
|
|
var scheme, host, path, query, method string
|
|
var headers map[string]string
|
|
var resultVars map[bool]map[string]string
|
|
|
|
router := NewRouter()
|
|
router.NewRoute().Host("{var1}.google.com").
|
|
Path("/{var2:[a-z]+}/{var3:[0-9]+}").
|
|
Queries("foo", "bar").
|
|
Methods("GET").
|
|
Schemes("https").
|
|
Headers("x-requested-with", "XMLHttpRequest")
|
|
router.NewRoute().Host("www.{var4}.com").
|
|
PathPrefix("/foo/{var5:[a-z]+}/{var6:[0-9]+}").
|
|
Queries("baz", "ding").
|
|
Methods("POST").
|
|
Schemes("http").
|
|
Headers("Content-Type", "application/json")
|
|
|
|
reset := func() {
|
|
// Everything match.
|
|
scheme = "https"
|
|
host = "www.google.com"
|
|
path = "/product/42"
|
|
query = "?foo=bar"
|
|
method = "GET"
|
|
headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
|
|
resultVars = map[bool]map[string]string{
|
|
true: {"var1": "www", "var2": "product", "var3": "42"},
|
|
false: {},
|
|
}
|
|
}
|
|
|
|
reset2 := func() {
|
|
// Everything match.
|
|
scheme = "http"
|
|
host = "www.google.com"
|
|
path = "/foo/product/42/path/that/is/ignored"
|
|
query = "?baz=ding"
|
|
method = "POST"
|
|
headers = map[string]string{"Content-Type": "application/json"}
|
|
resultVars = map[bool]map[string]string{
|
|
true: {"var4": "google", "var5": "product", "var6": "42"},
|
|
false: {},
|
|
}
|
|
}
|
|
|
|
match := func(shouldMatch bool) {
|
|
url := scheme + "://" + host + path + query
|
|
request, _ := http.NewRequest(method, url, nil)
|
|
for key, value := range headers {
|
|
request.Header.Add(key, value)
|
|
}
|
|
|
|
var routeMatch RouteMatch
|
|
matched := router.Match(request, &routeMatch)
|
|
if matched != shouldMatch {
|
|
// Need better messages. :)
|
|
if matched {
|
|
t.Errorf("Should match.")
|
|
} else {
|
|
t.Errorf("Should not match.")
|
|
}
|
|
}
|
|
|
|
if matched {
|
|
currentRoute := routeMatch.Route
|
|
if currentRoute == nil {
|
|
t.Errorf("Expected a current route.")
|
|
}
|
|
vars := routeMatch.Vars
|
|
expectedVars := resultVars[shouldMatch]
|
|
if len(vars) != len(expectedVars) {
|
|
t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
|
|
}
|
|
for name, value := range vars {
|
|
if expectedVars[name] != value {
|
|
t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1st route --------------------------------------------------------------
|
|
|
|
// Everything match.
|
|
reset()
|
|
match(true)
|
|
|
|
// Scheme doesn't match.
|
|
reset()
|
|
scheme = "http"
|
|
match(false)
|
|
|
|
// Host doesn't match.
|
|
reset()
|
|
host = "www.mygoogle.com"
|
|
match(false)
|
|
|
|
// Path doesn't match.
|
|
reset()
|
|
path = "/product/notdigits"
|
|
match(false)
|
|
|
|
// Query doesn't match.
|
|
reset()
|
|
query = "?foo=baz"
|
|
match(false)
|
|
|
|
// Method doesn't match.
|
|
reset()
|
|
method = "POST"
|
|
match(false)
|
|
|
|
// Header doesn't match.
|
|
reset()
|
|
headers = map[string]string{}
|
|
match(false)
|
|
|
|
// Everything match, again.
|
|
reset()
|
|
match(true)
|
|
|
|
// 2nd route --------------------------------------------------------------
|
|
|
|
// Everything match.
|
|
reset2()
|
|
match(true)
|
|
|
|
// Scheme doesn't match.
|
|
reset2()
|
|
scheme = "https"
|
|
match(false)
|
|
|
|
// Host doesn't match.
|
|
reset2()
|
|
host = "sub.google.com"
|
|
match(false)
|
|
|
|
// Path doesn't match.
|
|
reset2()
|
|
path = "/bar/product/42"
|
|
match(false)
|
|
|
|
// Query doesn't match.
|
|
reset2()
|
|
query = "?foo=baz"
|
|
match(false)
|
|
|
|
// Method doesn't match.
|
|
reset2()
|
|
method = "GET"
|
|
match(false)
|
|
|
|
// Header doesn't match.
|
|
reset2()
|
|
headers = map[string]string{}
|
|
match(false)
|
|
|
|
// Everything match, again.
|
|
reset2()
|
|
match(true)
|
|
}
|
|
|
|
type headerMatcherTest struct {
|
|
matcher headerMatcher
|
|
headers map[string]string
|
|
result bool
|
|
}
|
|
|
|
var headerMatcherTests = []headerMatcherTest{
|
|
{
|
|
matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
|
|
headers: map[string]string{"X-Requested-With": "XMLHttpRequest"},
|
|
result: true,
|
|
},
|
|
{
|
|
matcher: headerMatcher(map[string]string{"x-requested-with": ""}),
|
|
headers: map[string]string{"X-Requested-With": "anything"},
|
|
result: true,
|
|
},
|
|
{
|
|
matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
|
|
headers: map[string]string{},
|
|
result: false,
|
|
},
|
|
}
|
|
|
|
type hostMatcherTest struct {
|
|
matcher *Route
|
|
url string
|
|
vars map[string]string
|
|
result bool
|
|
}
|
|
|
|
var hostMatcherTests = []hostMatcherTest{
|
|
{
|
|
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]}"),
|
|
url: "http://abc.def.ghi/",
|
|
vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
|
|
result: true,
|
|
},
|
|
{
|
|
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]}"),
|
|
url: "http://a.b.c/",
|
|
vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
|
|
result: false,
|
|
},
|
|
}
|
|
|
|
type methodMatcherTest struct {
|
|
matcher methodMatcher
|
|
method string
|
|
result bool
|
|
}
|
|
|
|
var methodMatcherTests = []methodMatcherTest{
|
|
{
|
|
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
|
method: "GET",
|
|
result: true,
|
|
},
|
|
{
|
|
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
|
method: "POST",
|
|
result: true,
|
|
},
|
|
{
|
|
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
|
method: "PUT",
|
|
result: true,
|
|
},
|
|
{
|
|
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
|
method: "DELETE",
|
|
result: false,
|
|
},
|
|
}
|
|
|
|
type pathMatcherTest struct {
|
|
matcher *Route
|
|
url string
|
|
vars map[string]string
|
|
result bool
|
|
}
|
|
|
|
var pathMatcherTests = []pathMatcherTest{
|
|
{
|
|
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]}"),
|
|
url: "http://localhost:8080/123/456/789",
|
|
vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"},
|
|
result: true,
|
|
},
|
|
{
|
|
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]}"),
|
|
url: "http://localhost:8080/1/2/3",
|
|
vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"},
|
|
result: false,
|
|
},
|
|
}
|
|
|
|
type schemeMatcherTest struct {
|
|
matcher schemeMatcher
|
|
url string
|
|
result bool
|
|
}
|
|
|
|
var schemeMatcherTests = []schemeMatcherTest{
|
|
{
|
|
matcher: schemeMatcher([]string{"http", "https"}),
|
|
url: "http://localhost:8080/",
|
|
result: true,
|
|
},
|
|
{
|
|
matcher: schemeMatcher([]string{"http", "https"}),
|
|
url: "https://localhost:8080/",
|
|
result: true,
|
|
},
|
|
{
|
|
matcher: schemeMatcher([]string{"https"}),
|
|
url: "http://localhost:8080/",
|
|
result: false,
|
|
},
|
|
{
|
|
matcher: schemeMatcher([]string{"http"}),
|
|
url: "https://localhost:8080/",
|
|
result: false,
|
|
},
|
|
}
|
|
|
|
type urlBuildingTest struct {
|
|
route *Route
|
|
vars []string
|
|
url string
|
|
}
|
|
|
|
var urlBuildingTests = []urlBuildingTest{
|
|
{
|
|
route: new(Route).Host("foo.domain.com"),
|
|
vars: []string{},
|
|
url: "http://foo.domain.com",
|
|
},
|
|
{
|
|
route: new(Route).Host("{subdomain}.domain.com"),
|
|
vars: []string{"subdomain", "bar"},
|
|
url: "http://bar.domain.com",
|
|
},
|
|
{
|
|
route: new(Route).Host("foo.domain.com").Path("/articles"),
|
|
vars: []string{},
|
|
url: "http://foo.domain.com/articles",
|
|
},
|
|
{
|
|
route: new(Route).Path("/articles"),
|
|
vars: []string{},
|
|
url: "/articles",
|
|
},
|
|
{
|
|
route: new(Route).Path("/articles/{category}/{id:[0-9]+}"),
|
|
vars: []string{"category", "technology", "id", "42"},
|
|
url: "/articles/technology/42",
|
|
},
|
|
{
|
|
route: new(Route).Host("{subdomain}.domain.com").Path("/articles/{category}/{id:[0-9]+}"),
|
|
vars: []string{"subdomain", "foo", "category", "technology", "id", "42"},
|
|
url: "http://foo.domain.com/articles/technology/42",
|
|
},
|
|
}
|
|
|
|
func TestHeaderMatcher(t *testing.T) {
|
|
for _, v := range headerMatcherTests {
|
|
request, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
|
for key, value := range v.headers {
|
|
request.Header.Add(key, value)
|
|
}
|
|
var routeMatch RouteMatch
|
|
result := v.matcher.Match(request, &routeMatch)
|
|
if result != v.result {
|
|
if v.result {
|
|
t.Errorf("%#v: should match %v.", v.matcher, request.Header)
|
|
} else {
|
|
t.Errorf("%#v: should not match %v.", v.matcher, request.Header)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHostMatcher(t *testing.T) {
|
|
for _, v := range hostMatcherTests {
|
|
request, _ := http.NewRequest("GET", v.url, nil)
|
|
var routeMatch RouteMatch
|
|
result := v.matcher.Match(request, &routeMatch)
|
|
vars := routeMatch.Vars
|
|
if result != v.result {
|
|
if v.result {
|
|
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
|
} else {
|
|
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
|
}
|
|
}
|
|
if result {
|
|
if len(vars) != len(v.vars) {
|
|
t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
|
|
}
|
|
for name, value := range vars {
|
|
if v.vars[name] != value {
|
|
t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
|
|
}
|
|
}
|
|
} else {
|
|
if len(vars) != 0 {
|
|
t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMethodMatcher(t *testing.T) {
|
|
for _, v := range methodMatcherTests {
|
|
request, _ := http.NewRequest(v.method, "http://localhost:8080/", nil)
|
|
var routeMatch RouteMatch
|
|
result := v.matcher.Match(request, &routeMatch)
|
|
if result != v.result {
|
|
if v.result {
|
|
t.Errorf("%#v: should match %v.", v.matcher, v.method)
|
|
} else {
|
|
t.Errorf("%#v: should not match %v.", v.matcher, v.method)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPathMatcher(t *testing.T) {
|
|
for _, v := range pathMatcherTests {
|
|
request, _ := http.NewRequest("GET", v.url, nil)
|
|
var routeMatch RouteMatch
|
|
result := v.matcher.Match(request, &routeMatch)
|
|
vars := routeMatch.Vars
|
|
if result != v.result {
|
|
if v.result {
|
|
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
|
} else {
|
|
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
|
}
|
|
}
|
|
if result {
|
|
if len(vars) != len(v.vars) {
|
|
t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
|
|
}
|
|
for name, value := range vars {
|
|
if v.vars[name] != value {
|
|
t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
|
|
}
|
|
}
|
|
} else {
|
|
if len(vars) != 0 {
|
|
t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSchemeMatcher(t *testing.T) {
|
|
for _, v := range schemeMatcherTests {
|
|
request, _ := http.NewRequest("GET", v.url, nil)
|
|
var routeMatch RouteMatch
|
|
result := v.matcher.Match(request, &routeMatch)
|
|
if result != v.result {
|
|
if v.result {
|
|
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
|
} else {
|
|
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUrlBuilding(t *testing.T) {
|
|
|
|
for _, v := range urlBuildingTests {
|
|
u, _ := v.route.URL(v.vars...)
|
|
url := u.String()
|
|
if url != v.url {
|
|
t.Errorf("expected %v, got %v", v.url, url)
|
|
/*
|
|
reversePath := ""
|
|
reverseHost := ""
|
|
if v.route.pathTemplate != nil {
|
|
reversePath = v.route.pathTemplate.Reverse
|
|
}
|
|
if v.route.hostTemplate != nil {
|
|
reverseHost = v.route.hostTemplate.Reverse
|
|
}
|
|
|
|
t.Errorf("%#v:\nexpected: %q\ngot: %q\nreverse path: %q\nreverse host: %q", v.route, v.url, url, reversePath, reverseHost)
|
|
*/
|
|
}
|
|
}
|
|
|
|
ArticleHandler := func(w http.ResponseWriter, r *http.Request) {
|
|
}
|
|
|
|
router := NewRouter()
|
|
router.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article")
|
|
|
|
url, _ := router.Get("article").URL("category", "technology", "id", "42")
|
|
expected := "/articles/technology/42"
|
|
if url.String() != expected {
|
|
t.Errorf("Expected %v, got %v", expected, url.String())
|
|
}
|
|
}
|
|
|
|
func TestMatchedRouteName(t *testing.T) {
|
|
routeName := "stock"
|
|
router := NewRouter()
|
|
route := router.NewRoute().Path("/products/").Name(routeName)
|
|
|
|
url := "http://www.domain.com/products/"
|
|
request, _ := http.NewRequest("GET", url, nil)
|
|
var rv RouteMatch
|
|
ok := router.Match(request, &rv)
|
|
|
|
if !ok || rv.Route != route {
|
|
t.Errorf("Expected same route, got %+v.", rv.Route)
|
|
}
|
|
|
|
retName := rv.Route.GetName()
|
|
if retName != routeName {
|
|
t.Errorf("Expected %q, got %q.", routeName, retName)
|
|
}
|
|
}
|
|
|
|
func TestSubRouting(t *testing.T) {
|
|
// Example from docs.
|
|
router := NewRouter()
|
|
subrouter := router.NewRoute().Host("www.domain.com").Subrouter()
|
|
route := subrouter.NewRoute().Path("/products/").Name("products")
|
|
|
|
url := "http://www.domain.com/products/"
|
|
request, _ := http.NewRequest("GET", url, nil)
|
|
var rv RouteMatch
|
|
ok := router.Match(request, &rv)
|
|
|
|
if !ok || rv.Route != route {
|
|
t.Errorf("Expected same route, got %+v.", rv.Route)
|
|
}
|
|
|
|
u, _ := router.Get("products").URL()
|
|
builtUrl := u.String()
|
|
// Yay, subroute aware of the domain when building!
|
|
if builtUrl != url {
|
|
t.Errorf("Expected %q, got %q.", url, builtUrl)
|
|
}
|
|
}
|
|
|
|
func TestVariableNames(t *testing.T) {
|
|
route := new(Route).Host("{arg1}.domain.com").Path("/{arg1}/{arg2:[0-9]+}")
|
|
if route.err == nil {
|
|
t.Errorf("Expected error for duplicated variable names")
|
|
}
|
|
}
|
|
|
|
func TestRedirectSlash(t *testing.T) {
|
|
var route *Route
|
|
var routeMatch RouteMatch
|
|
r := NewRouter()
|
|
|
|
r.StrictSlash(false)
|
|
route = r.NewRoute()
|
|
if route.strictSlash != false {
|
|
t.Errorf("Expected false redirectSlash.")
|
|
}
|
|
|
|
r.StrictSlash(true)
|
|
route = r.NewRoute()
|
|
if route.strictSlash != true {
|
|
t.Errorf("Expected true redirectSlash.")
|
|
}
|
|
|
|
route = new(Route)
|
|
route.strictSlash = true
|
|
route.Path("/{arg1}/{arg2:[0-9]+}/")
|
|
request, _ := http.NewRequest("GET", "http://localhost/foo/123", nil)
|
|
routeMatch = RouteMatch{}
|
|
_ = route.Match(request, &routeMatch)
|
|
vars := routeMatch.Vars
|
|
if vars["arg1"] != "foo" {
|
|
t.Errorf("Expected foo.")
|
|
}
|
|
if vars["arg2"] != "123" {
|
|
t.Errorf("Expected 123.")
|
|
}
|
|
rsp := NewRecorder()
|
|
routeMatch.Handler.ServeHTTP(rsp, request)
|
|
if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123/" {
|
|
t.Errorf("Expected redirect header.")
|
|
}
|
|
|
|
route = new(Route)
|
|
route.strictSlash = true
|
|
route.Path("/{arg1}/{arg2:[0-9]+}")
|
|
request, _ = http.NewRequest("GET", "http://localhost/foo/123/", nil)
|
|
routeMatch = RouteMatch{}
|
|
_ = route.Match(request, &routeMatch)
|
|
vars = routeMatch.Vars
|
|
if vars["arg1"] != "foo" {
|
|
t.Errorf("Expected foo.")
|
|
}
|
|
if vars["arg2"] != "123" {
|
|
t.Errorf("Expected 123.")
|
|
}
|
|
rsp = NewRecorder()
|
|
routeMatch.Handler.ServeHTTP(rsp, request)
|
|
if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123" {
|
|
t.Errorf("Expected redirect header.")
|
|
}
|
|
}
|
|
|
|
// Test for the new regexp library, still not available in stable Go.
|
|
func TestNewRegexp(t *testing.T) {
|
|
var p *routeRegexp
|
|
var matches []string
|
|
|
|
tests := map[string]map[string][]string{
|
|
"/{foo:a{2}}": {
|
|
"/a": nil,
|
|
"/aa": {"aa"},
|
|
"/aaa": nil,
|
|
"/aaaa": nil,
|
|
},
|
|
"/{foo:a{2,}}": {
|
|
"/a": nil,
|
|
"/aa": {"aa"},
|
|
"/aaa": {"aaa"},
|
|
"/aaaa": {"aaaa"},
|
|
},
|
|
"/{foo:a{2,3}}": {
|
|
"/a": nil,
|
|
"/aa": {"aa"},
|
|
"/aaa": {"aaa"},
|
|
"/aaaa": nil,
|
|
},
|
|
"/{foo:[a-z]{3}}/{bar:[a-z]{2}}": {
|
|
"/a": nil,
|
|
"/ab": nil,
|
|
"/abc": nil,
|
|
"/abcd": nil,
|
|
"/abc/ab": {"abc", "ab"},
|
|
"/abc/abc": nil,
|
|
"/abcd/ab": nil,
|
|
},
|
|
`/{foo:\w{3,}}/{bar:\d{2,}}`: {
|
|
"/a": nil,
|
|
"/ab": nil,
|
|
"/abc": nil,
|
|
"/abc/1": nil,
|
|
"/abc/12": {"abc", "12"},
|
|
"/abcd/12": {"abcd", "12"},
|
|
"/abcd/123": {"abcd", "123"},
|
|
},
|
|
}
|
|
|
|
for pattern, paths := range tests {
|
|
p, _ = newRouteRegexp(pattern, false, false, false, false)
|
|
for path, result := range paths {
|
|
matches = p.regexp.FindStringSubmatch(path)
|
|
if result == nil {
|
|
if matches != nil {
|
|
t.Errorf("%v should not match %v.", pattern, path)
|
|
}
|
|
} else {
|
|
if len(matches) != len(result)+1 {
|
|
t.Errorf("Expected %v matches, got %v.", len(result)+1, len(matches))
|
|
} else {
|
|
for k, v := range result {
|
|
if matches[k+1] != v {
|
|
t.Errorf("Expected %v, got %v.", v, matches[k+1])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|