package web import ( "net/http" "reflect" "regexp" "testing" ) func pt(url string, match bool, params map[string]string) patternTest { req, err := http.NewRequest("GET", url, nil) if err != nil { panic(err) } return patternTest{ r: req, match: match, c: &C{}, cout: &C{UrlParams: params}, } } type patternTest struct { r *http.Request match bool c *C cout *C } var patternTests = []struct { pat Pattern prefix string tests []patternTest }{ // Regexp tests {parseRegexpPattern(regexp.MustCompile("^/hello$")), "/hello", []patternTest{ pt("/hello", true, nil), pt("/hell", false, nil), pt("/hello/", false, nil), pt("/hello/world", false, nil), pt("/world", false, nil), }}, {parseRegexpPattern(regexp.MustCompile("^/hello/(?P[a-z]+)$")), "/hello/", []patternTest{ pt("/hello/world", true, map[string]string{ "name": "world", }), pt("/hello/", false, nil), pt("/hello/my/love", false, nil), }}, {parseRegexpPattern(regexp.MustCompile(`^/a(?P\d+)/b(?P\d+)/?$`)), "/a", []patternTest{ pt("/a1/b2", true, map[string]string{ "a": "1", "b": "2", }), pt("/a9001/b007/", true, map[string]string{ "a": "9001", "b": "007", }), pt("/a/b", false, nil), pt("/a", false, nil), pt("/squirrel", false, nil), }}, {parseRegexpPattern(regexp.MustCompile(`^/hello/([a-z]+)$`)), "/hello/", []patternTest{ pt("/hello/world", true, map[string]string{ "$1": "world", }), pt("/hello/", false, nil), }}, {parseRegexpPattern(regexp.MustCompile("/hello")), "/hello", []patternTest{ pt("/hello", true, nil), pt("/hell", false, nil), pt("/hello/", true, nil), pt("/hello/world", true, nil), pt("/world/hello", false, nil), }}, // String pattern tests {parseStringPattern("/hello", false), "/hello", []patternTest{ pt("/hello", true, nil), pt("/hell", false, nil), pt("/hello/", false, nil), pt("/hello/world", false, nil), }}, {parseStringPattern("/hello/:name", false), "/hello/", []patternTest{ pt("/hello/world", true, map[string]string{ "name": "world", }), pt("/hell", false, nil), pt("/hello/", false, nil), pt("/hello/my/love", false, nil), }}, {parseStringPattern("/a/:a/b/:b", false), "/a/", []patternTest{ pt("/a/1/b/2", true, map[string]string{ "a": "1", "b": "2", }), pt("/a", false, nil), pt("/a//b/", false, nil), pt("/a/1/b/2/3", false, nil), }}, // String sub-pattern tests {parseStringPattern("/user/:user", true), "/user/", []patternTest{ pt("/user/bob", true, map[string]string{ "user": "bob", }), pt("/user/bob/friends/123", true, map[string]string{ "user": "bob", }), pt("/user/", false, nil), pt("/user//", false, nil), }}, {parseStringPattern("/user/:user/friends", true), "/user/", []patternTest{ pt("/user/bob/friends", true, map[string]string{ "user": "bob", }), pt("/user/bob/friends/123", true, map[string]string{ "user": "bob", }), pt("/user/bob/enemies", false, nil), }}, } func TestPatterns(t *testing.T) { t.Parallel() for _, pt := range patternTests { p := pt.pat.Prefix() if p != pt.prefix { t.Errorf("Expected prefix %q for %v, got %q", pt.prefix, pt.pat, p) } else { for _, test := range pt.tests { runTest(t, pt.pat, test) } } } } func runTest(t *testing.T, p Pattern, test patternTest) { result := p.Match(test.r, test.c) if result != test.match { t.Errorf("Expected match(%v, %#v) to return %v", p, test.r.URL.Path, test.match) return } if !reflect.DeepEqual(test.c, test.cout) { t.Errorf("Expected a context of %v, instead got %v", test.cout, test.c) } }