Skip to content

Commit a041c43

Browse files
refactor: add tests
1 parent c3ab0a3 commit a041c43

3 files changed

Lines changed: 130 additions & 1 deletion

File tree

mux_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,45 @@ func TestMuxRegexp3(t *testing.T) {
16501650
}
16511651
}
16521652

1653+
func TestMuxNamedPathParam(t *testing.T) {
1654+
r := NewRouter()
1655+
r.Get("/foo/bar/{other-stuff:*}/fizz/buzz", func(w http.ResponseWriter, r *http.Request) {
1656+
w.Write([]byte(URLParam(r, "other-stuff")))
1657+
})
1658+
1659+
ts := httptest.NewServer(r)
1660+
defer ts.Close()
1661+
1662+
if _, body := testRequest(t, ts, "GET", "/foo/bar/one/two/three/fizz/buzz", nil); body != "one/two/three" {
1663+
t.Fatalf("expecting %q, got %q", "one/two/three", body)
1664+
}
1665+
if _, body := testRequest(t, ts, "GET", "/foo/bar/fizz/buzz", nil); body != "" {
1666+
t.Fatalf("expecting empty body, got %q", body)
1667+
}
1668+
}
1669+
1670+
func TestMuxNamedPathParamInNestedRoute(t *testing.T) {
1671+
r := NewRouter()
1672+
r.Route("/stuff", func(r Router) {
1673+
r.Route("/{owner}/{group:*}/{repo}", func(r Router) {
1674+
r.Route("/src", func(r Router) {
1675+
r.Route("/branch/{branch:*}", func(r Router) {
1676+
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
1677+
fmt.Fprintf(w, "%s:%s:%s:%s", URLParam(r, "owner"), URLParam(r, "group"), URLParam(r, "repo"), URLParam(r, "branch"))
1678+
})
1679+
})
1680+
})
1681+
})
1682+
})
1683+
1684+
ts := httptest.NewServer(r)
1685+
defer ts.Close()
1686+
1687+
if _, body := testRequest(t, ts, "GET", "/stuff/owner/foo/repo/src/branch/feature", nil); body != "owner:foo:repo:feature" {
1688+
t.Fatalf("expecting %q, got %q", "owner:foo:repo:feature", body)
1689+
}
1690+
}
1691+
16531692
func TestMuxSubrouterWildcardParam(t *testing.T) {
16541693
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
16551694
fmt.Fprintf(w, "param:%v *:%v", URLParam(r, "param"), URLParam(r, "*"))

path_value_test.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func TestPathValue(t *testing.T) {
1515
requestPath string
1616
expectedBody string
1717
pathKeys []string
18+
allowEmpty bool
1819
}{
1920
{
2021
name: "Basic path value",
@@ -40,6 +41,23 @@ func TestPathValue(t *testing.T) {
4041
requestPath: "/users/Gojo/friends/all-of-them/and/more",
4142
expectedBody: "Gojo all-of-them/and/more",
4243
},
44+
{
45+
name: "Named path value with slashes",
46+
pattern: "/foo/bar/{other-stuff:*}/fizz/buzz",
47+
method: "GET",
48+
pathKeys: []string{"other-stuff"},
49+
requestPath: "/foo/bar/one/two/three/fizz/buzz",
50+
expectedBody: "one/two/three",
51+
},
52+
{
53+
name: "Empty named path value",
54+
pattern: "/foo/bar/{other-stuff:*}/fizz/buzz",
55+
method: "GET",
56+
pathKeys: []string{"other-stuff"},
57+
requestPath: "/foo/bar/fizz/buzz",
58+
expectedBody: "",
59+
allowEmpty: true,
60+
},
4361
}
4462

4563
for _, tc := range testCases {
@@ -50,7 +68,7 @@ func TestPathValue(t *testing.T) {
5068
pathValues := []string{}
5169
for _, pathKey := range tc.pathKeys {
5270
pathValue := r.PathValue(pathKey)
53-
if pathValue == "" {
71+
if pathValue == "" && !tc.allowEmpty {
5472
pathValue = "NOT_FOUND:" + pathKey
5573
}
5674

tree_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,70 @@ func TestTreeRegexMatchWholeParam(t *testing.T) {
414414
}
415415
}
416416

417+
func TestTreePathParam(t *testing.T) {
418+
hPath := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
419+
hPathNonGreedy := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
420+
hPathOne := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
421+
hPathOneNonGreedy := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
422+
hSingle := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
423+
hFiles := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
424+
425+
tr := &node{}
426+
tr.InsertRoute(mGET, "/foo/bar/{other-stuff:*}/fizz/buzz", hPath)
427+
tr.InsertRoute(mGET, "/foo/bar/{other-stuff}/fizz/buzz", hSingle)
428+
tr.InsertRoute(mGET, "/files/{path:*}", hFiles)
429+
tr.InsertRoute(mGET, "/plus/{path:+}/tail", hPathOne)
430+
tr.InsertRoute(mGET, "/greedy/{path:*}/x/*", hPath)
431+
tr.InsertRoute(mGET, "/nongreedy/{path:*?}/x/*", hPathNonGreedy)
432+
tr.InsertRoute(mGET, "/plusgreedy/{path:+}/x/*", hPathOne)
433+
tr.InsertRoute(mGET, "/plusnongreedy/{path:+?}/x/*", hPathOneNonGreedy)
434+
435+
tests := []struct {
436+
r string
437+
h http.Handler
438+
k []string
439+
v []string
440+
}{
441+
{r: "/foo/bar/one/two/three/fizz/buzz", h: hPath, k: []string{"other-stuff"}, v: []string{"one/two/three"}},
442+
{r: "/foo/bar/one/fizz/buzz", h: hSingle, k: []string{"other-stuff"}, v: []string{"one"}},
443+
{r: "/foo/bar/fizz/buzz", h: hPath, k: []string{"other-stuff"}, v: []string{""}},
444+
{r: "/files/a/b/c", h: hFiles, k: []string{"path"}, v: []string{"a/b/c"}},
445+
{r: "/files/", h: hFiles, k: []string{"path"}, v: []string{""}},
446+
{r: "/plus/a/tail", h: hPathOne, k: []string{"path"}, v: []string{"a"}},
447+
{r: "/plus/a/b/tail", h: hPathOne, k: []string{"path"}, v: []string{"a/b"}},
448+
{r: "/plus/tail", h: nil, k: []string{}, v: []string{}},
449+
{r: "/plus//tail", h: nil, k: []string{}, v: []string{}},
450+
{r: "/greedy/a/x/b/x/c", h: hPath, k: []string{"path", "*"}, v: []string{"a/x/b", "c"}},
451+
{r: "/nongreedy/a/x/b/x/c", h: hPathNonGreedy, k: []string{"path", "*"}, v: []string{"a", "b/x/c"}},
452+
{r: "/plusgreedy/a/x/b/x/c", h: hPathOne, k: []string{"path", "*"}, v: []string{"a/x/b", "c"}},
453+
{r: "/plusnongreedy/a/x/b/x/c", h: hPathOneNonGreedy, k: []string{"path", "*"}, v: []string{"a", "b/x/c"}},
454+
}
455+
456+
for i, tt := range tests {
457+
rctx := NewRouteContext()
458+
459+
_, handlers, _ := tr.FindRoute(rctx, mGET, tt.r)
460+
461+
var handler http.Handler
462+
if methodHandler, ok := handlers[mGET]; ok {
463+
handler = methodHandler.handler
464+
}
465+
466+
paramKeys := rctx.routeParams.Keys
467+
paramValues := rctx.routeParams.Values
468+
469+
if fmt.Sprintf("%v", tt.h) != fmt.Sprintf("%v", handler) {
470+
t.Errorf("input [%d]: find '%s' expecting handler:%v , got:%v", i, tt.r, tt.h, handler)
471+
}
472+
if !stringSliceEqual(tt.k, paramKeys) {
473+
t.Errorf("input [%d]: find '%s' expecting paramKeys:(%d)%v , got:(%d)%v", i, tt.r, len(tt.k), tt.k, len(paramKeys), paramKeys)
474+
}
475+
if !stringSliceEqual(tt.v, paramValues) {
476+
t.Errorf("input [%d]: find '%s' expecting paramValues:(%d)%v , got:(%d)%v", i, tt.r, len(tt.v), tt.v, len(paramValues), paramValues)
477+
}
478+
}
479+
}
480+
417481
func TestTreeFindPattern(t *testing.T) {
418482
hStub1 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
419483
hStub2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
@@ -423,6 +487,8 @@ func TestTreeFindPattern(t *testing.T) {
423487
tr.InsertRoute(mGET, "/pages/*", hStub1)
424488
tr.InsertRoute(mGET, "/articles/{id}/*", hStub2)
425489
tr.InsertRoute(mGET, "/articles/{slug}/{uid}/*", hStub3)
490+
tr.InsertRoute(mGET, "/files/{path:*}/info", hStub1)
491+
tr.InsertRoute(mGET, "/assets/{path:+?}/info", hStub1)
426492

427493
if tr.findPattern("/pages") != false {
428494
t.Errorf("find /pages failed")
@@ -442,6 +508,12 @@ func TestTreeFindPattern(t *testing.T) {
442508
if tr.findPattern("/articles/{slug}/{uid}/*") == false {
443509
t.Errorf("find /articles/{slug}/{uid}/* failed")
444510
}
511+
if tr.findPattern("/files/{name:*}/info") == false {
512+
t.Errorf("find /files/{name:*}/info failed")
513+
}
514+
if tr.findPattern("/assets/{name:+?}/info") == false {
515+
t.Errorf("find /assets/{name:+?}/info failed")
516+
}
445517
}
446518

447519
func debugPrintTree(parent int, i int, n *node, label byte) bool {

0 commit comments

Comments
 (0)