123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 | package httpd
import (
"strings"
"testing"
)
// TestPatternMatch checks the port of patterns(7) against the cases the
// site's config depends on, and Lua's own semantics around them.
func TestPatternMatch(t *testing.T) {
for _, c := range []struct {
s, pat string
want []string // nil: no match
}{
{"/code/r/src/", "^/code/(.+)/$", []string{"/code/r/src/", "r/src"}},
{"/code/r/src", "^/code/(.+)/$", nil},
{"/x/code/r", "^/code/(.+)$", nil},
{"/code/r/src/", "^/code/(..-)/?$", []string{"/code/r/src/", "r/src"}},
{"/code/r/src", "^/code/(..-)/?$", []string{"/code/r/src", "r/src"}},
{"/code/r", "^/code/(..-)/?$", []string{"/code/r", "r"}},
{"/code/", "^/code/(..-)/?$", nil},
{"/CODE/r", "^/code/(..-)/?$", nil}, // case matters
{"/x/code/r", "/code/(.+)$", []string{"/code/r", "r"}},
{"/git/a.git/HEAD", "^/git/[^/]+%.git/HEAD$", []string{"/git/a.git/HEAD"}},
{"/git/aXgit/HEAD", "^/git/[^/]+%.git/HEAD$", nil},
{"/git/a/b.git/HEAD", "^/git/[^/]+%.git/HEAD$", nil},
{"/p/pack-0fA9.idx", "pack%-%x+%.idx$", []string{"pack-0fA9.idx"}},
{"/p/pack-0fg9.idx", "pack%-%x+%.idx$", nil},
{"aaab", "a-b", []string{"aaab"}},
{"ab", "^a?b$", []string{"ab"}},
{"b", "^a?b$", []string{"b"}},
{"a]", "^%a[]]$", []string{"a]"}}, // ] first in a set is literal
{"a^b", "a^b", []string{"a^b"}}, // ^ is literal past the start
{"a$b", "a$b", []string{"a$b"}}, // and $ before the end
{"x1-y", "^%w+[%d%-]+%l$", []string{"x1-y"}},
{"x!", "^%g%p$", []string{"x!"}},
{"((a)(b))", "^%((%a)%((%a)%)%)$", nil},
{"((a)(b))", "^%(%((%a)%)%((%a)%)%)$", []string{"((a)(b))", "a", "b"}},
{strings.Repeat("a", 300), "^" + strings.Repeat("a?", 300) + "$", nil}, // too complex
} {
got, ok := PatternLocation(c.pat).Match(c.s)
if ok != (c.want != nil) || strings.Join(got, "|") != strings.Join(c.want, "|") {
t.Errorf("match %q in %q = %q, %v; want %q", c.pat, c.s, got, ok, c.want)
}
}
}
func TestPatternCheck(t *testing.T) {
for pat, bad := range map[string]bool{
"^/code/(..-)/?$": false, "[]]": false, "%%": false, "[%]]": false,
"%": true, "[a": true, "[]": true, "[%": true, "(a": true, "a)": true,
"()": true, "%b()": true, "%f[a]": true, "(a)%1": true,
strings.Repeat("(a)", 33): true, `a\.b`: true, `a"b`: true,
} {
err := PatternLocation(pat).Check()
if (err != nil) != bad {
t.Errorf("Check(%q) = %v, want an error: %v", pat, err, bad)
}
if bad {
if _, ok := PatternLocation(pat).Match(pat); ok {
t.Errorf("%q: matched despite failing Check", pat)
}
}
}
}
func TestGlob(t *testing.T) {
for _, c := range []struct {
glob, s string
want bool
}{
{"/static/*", "/static/style.css", true},
{"/static/*", "/static/a/b", true}, // * matches / too
{"/static/*", "/STATIC/x", true}, // case is folded
{"/static/*", "/staticx", false},
{"/git/*/objects/pack/*", "/git/a.git/objects/pack/p.idx", true},
{"/git/*/objects/pack/*", "/git/a/b.git/objects/pack/p.idx", true},
{"/git/*/objects/pack/*", "/git/a.git/objects/p.idx", false},
{"/a", "/a", true},
{"/a", "/a/", false},
{"/a?", "/ab", false}, // refused: matches nothing
{"/[a]", "/a", false},
} {
if _, got := GlobLocation(c.glob).Match(c.s); got != c.want {
t.Errorf("glob %q on %q = %v, want %v", c.glob, c.s, got, c.want)
}
}
for _, g := range []string{"/a?", "/[a]", `/a\*`, `/a"`} {
if GlobLocation(g).Check() == nil {
t.Errorf("Check(%q): no error", g)
}
}
}
func TestRewrite(t *testing.T) {
caps := []string{"/code/r/src/", "r/src"}
for target, want := range map[string]string{
"/code/%1.html": "/code/r/src.html",
"%0": "/code/r/src/",
"/%2/%1": "/%2/r/src",
"100%": "100%",
"%%1": "%r/src",
} {
if got := Rewrite(target, caps); got != want {
t.Errorf("Rewrite(%q) = %q, want %q", target, got, want)
}
}
loc := PatternLocation("^/code/(..-)/?$")
if err := CheckRewrite(loc, "/code/%1.html"); err != nil {
t.Error(err)
}
if err := CheckRewrite(loc, "/code/%2.html"); err == nil {
t.Error("%2 of a pattern with one capture: no error")
}
if err := CheckRewrite(PatternLocation("^/code/%(x%)(.*)"), "/%1"); err != nil {
t.Error(err)
}
if err := CheckRewrite(GlobLocation("/code/*"), "/x/%1"); err == nil {
t.Error("%1 of a glob: no error")
}
}
func TestString(t *testing.T) {
if got := GlobLocation("/static/*").String(); got != `"/static/*"` {
t.Errorf("glob: %s", got)
}
if got := PatternLocation("^/a$").String(); got != `match "^/a$"` {
t.Errorf("pattern: %s", got)
}
}
|