Skip to content

Commit

Permalink
0 alloc
Browse files Browse the repository at this point in the history
  • Loading branch information
nbari committed Oct 5, 2017
1 parent 5605872 commit 72cf83a
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 72 deletions.
10 changes: 7 additions & 3 deletions .travis.yml
@@ -1,9 +1,13 @@
language: go

os:
- linux
- osx

go:
- 1.9
- 1.8
- 1.7
- 1.9.x
- 1.8.x
- 1.7.x
- tip

before_install:
Expand Down
7 changes: 3 additions & 4 deletions bench_test.go
@@ -1,16 +1,15 @@
// go test -run=BenchmarkRouter -bench=.
// go test -bench=.
// go test -bench=BenchmarkRouter
// go test -run=^$ -bench=BenchmarkRouterStatic

package violetear

import (
"net/http"
"net/http/httptest"
"testing"
)

func benchRequest(b *testing.B, router http.Handler, r *http.Request) {
w := &ResponseWriter{}
w := httptest.NewRecorder()
u := r.URL
rq := u.RawQuery
r.RequestURI = u.RequestURI()
Expand Down
6 changes: 3 additions & 3 deletions trie.go
Expand Up @@ -92,10 +92,13 @@ func (t *Trie) Get(path, version string) (*Trie, string, string, bool) {
return t, key, path, false
}

// SplitPath returns first element of path and remaining path
func (t *Trie) SplitPath(path string) (string, string) {
var key string
if path == "" {
return key, path
} else if path == "/" {
return path, ""
}
for i := 0; i < len(path); i++ {
if path[i] == '/' {
Expand All @@ -105,9 +108,6 @@ func (t *Trie) SplitPath(path string) (string, string) {
if i > 0 {
key = path[:i]
path = path[i:]
if key == "" && path != "" {
return t.SplitPath(path)
}
if path == "/" {
return key, ""
}
Expand Down
156 changes: 96 additions & 60 deletions trie_test.go
@@ -1,6 +1,9 @@
package violetear

/*
import (
"testing"
)

func TestTrieSetEmpty(t *testing.T) {
trie := &Trie{}
err := trie.Set([]string{}, nil, "ALL", "")
Expand Down Expand Up @@ -98,116 +101,149 @@ func TestTrieGet(t *testing.T) {
err = trie.Set([]string{"alpha", "*"}, nil, "ALL", "")
expect(t, err, nil)

_, _, _, err = trie.Get([]string{}, "")
if err == nil {
t.Error(err)
}
_, k, p, l := trie.Get("", "")
expect(t, k, "")
expect(t, p, "")
expect(t, l, false)

n, p, l, err := trie.Get([]string{"*"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"*"})
_, k, p, l = trie.Get("*", "")
expect(t, k, "*")
expect(t, p, "")
expect(t, l, true)
n, p, l, err = trie.Get([]string{"*"}, "v5")
expect(t, err, nil)
n, p, l, err = trie.Get([]string{"*"}, "v4")
expect(t, err, nil)
n, p, l, err = trie.Get([]string{"*"}, "v3")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"*"})

_, k, p, l = trie.Get("*", "v5")
expect(t, k, "*")
expect(t, p, "")
expect(t, l, false)

_, k, p, l = trie.Get("*", "v4")
expect(t, k, "*")
expect(t, p, "")
expect(t, l, false)

_, k, p, l = trie.Get("*", "v3")
expect(t, k, "*")
expect(t, p, "")
expect(t, l, true)

n, p, l, err = trie.Get([]string{"not_found"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"not_found"})
n, k, p, l := trie.Get("not_found", "")
expect(t, k, "not_found")
expect(t, p, "")
expect(t, l, false)
expect(t, n.HasRegex, true)

n, p, l, err = trie.Get([]string{":dynamic"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{":dynamic"})
n, k, p, l = trie.Get(":dynamic", "")
expect(t, k, ":dynamic")
expect(t, p, "")
expect(t, l, true)
n, p, l, err = trie.Get([]string{":dynamic"}, "v3")
expect(t, err, nil)
expectDeepEqual(t, p, []string{":dynamic"})

n, k, p, l = trie.Get(":dynamic", "v3")
expect(t, k, ":dynamic")
expect(t, p, "")
expect(t, l, true)

n, p, l, err = trie.Get([]string{"root"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"root"})
n, k, p, l = trie.Get("root", "")
expect(t, k, "root")
expect(t, p, "")
expect(t, l, true)
expect(t, len(n.Node), 4)

n, p, l, err = trie.Get([]string{"root", "v3"}, "v3")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"v3"})
n, k, p, l = trie.Get("root/v3", "v3")
expect(t, k, "v3")
expect(t, p, "")
expect(t, l, false)
expect(t, len(n.Node), 1)

n, p, l, err = trie.Get([]string{"root", "alpha"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"alpha"})
n, k, p, l = trie.Get("root/alpha", "")
expect(t, k, "alpha")
expect(t, p, "")
expect(t, l, true)
expect(t, len(n.Node), 2)

n, p, l, err = trie.Get([]string{"root", "not_found"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"not_found"})
n, k, p, l = trie.Get("root/not_found", "")
expect(t, k, "not_found")
expect(t, p, "")
expect(t, l, false)
expect(t, len(n.Node), 4)

n, p, l, err = trie.Get([]string{"root", "alpha1"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"alpha1"})
n, k, p, l = trie.Get("root/alpha1", "")
expect(t, k, "alpha1")
expect(t, p, "")
expect(t, l, true)
expect(t, len(n.Node), 1)

n, p, l, err = trie.Get([]string{"root", "alpha1", "any"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"any"})
n, k, p, l = trie.Get("root/alpha1/any", "")
expect(t, k, "any")
expect(t, p, "")
expect(t, l, false)
expect(t, len(n.Node), 1)
expect(t, n.HasRegex, false)

n, p, l, err = trie.Get([]string{"root", "alpha2", "any"}, "")
n, k, p, l = trie.Get("root/alpha2/any", "")
expect(t, k, "any")
expect(t, p, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"any"})
expect(t, l, false)
expect(t, len(n.Node), 1)
expect(t, n.HasRegex, true)

n, p, l, err = trie.Get([]string{"root", "alpha", "beta"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"beta"})
n, k, p, l = trie.Get("root/alpha/beta", "")
expect(t, k, "beta")
expect(t, p, "")
expect(t, l, true)
expect(t, len(n.Node), 1)
expect(t, n.HasRegex, false)

n, p, l, err = trie.Get([]string{"root", "alpha", "beta", "gamma"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"gamma"})
n, k, p, l = trie.Get("root/alpha/beta/gamma", "")
expect(t, k, "gamma")
expect(t, p, "")
expect(t, l, true)
expect(t, len(n.Node), 0)
expect(t, n.HasRegex, false)

n, p, l, err = trie.Get([]string{"root", "alphaA", "betaB", "gammaC"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"alphaA", "betaB", "gammaC"})
n, k, p, l = trie.Get("root/alphaA/betaB/gammaC", "")
expect(t, k, "alphaA")
expect(t, p, "/betaB/gammaC")
expect(t, l, false)
expect(t, len(n.Node), 4)
expect(t, n.HasRegex, false)

n, p, l, err = trie.Get([]string{"root", "alpha", "betaB", "gammaC"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"betaB", "gammaC"})
n, k, p, l = trie.Get("root/alpha/betaB/gammaC", "")
expect(t, k, "betaB")
expect(t, p, "/gammaC")
expect(t, l, false)
expect(t, len(n.Node), 2)
expect(t, n.HasRegex, false)

n, p, l, err = trie.Get([]string{"root", "alpha", "betaB", "gamma", "delta"}, "")
expect(t, err, nil)
expectDeepEqual(t, p, []string{"betaB", "gamma", "delta"})
n, k, p, l = trie.Get("root/alpha/betaB/gamma/delta", "")
expect(t, k, "betaB")
expect(t, p, "/gamma/delta")
expect(t, l, false)
expect(t, len(n.Node), 2)
expect(t, n.HasRegex, false)
}
*/

func TestSplitPath(t *testing.T) {
var testPaths = []struct {
in string
out []string
}{
{"/", []string{"/", ""}},
{"//", []string{"/", ""}},
{"///", []string{"/", ""}},
{"////", []string{"/", ""}},
{"/////", []string{"/", ""}},
{"/hello", []string{"hello", ""}},
{"/hello/world", []string{"hello", "/world"}},
{"/hello/:world", []string{"hello", "/:world"}},
{"*", []string{"*", ""}},
{"/?foo=bar", []string{"?foo=bar", ""}},
}

trie := &Trie{}
for _, tt := range testPaths {
k, p := trie.SplitPath(tt.in)
expect(t, k, tt.out[0])
expect(t, p, tt.out[1])
}
}
5 changes: 3 additions & 2 deletions violetear.go
Expand Up @@ -172,7 +172,7 @@ func (r *Router) checkMethod(node *Trie, method string) http.Handler {
func (r *Router) dispatch(node *Trie, key, path, method, version string, leaf bool, params Params) (http.Handler, Params) {
catchall := false
if len(node.Handler) > 0 && leaf {
return r.checkMethod(node, method), nil
return r.checkMethod(node, method), params
} else if node.HasRegex {
for _, n := range node.Node {
if strings.HasPrefix(n.path, ":") {
Expand Down Expand Up @@ -248,9 +248,10 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
version = ""
}

// query the path from left to right
node, key, path, leaf := r.routes.Get(req.URL.Path, version)

// h http.Handler
// dispatch the request
h, p := r.dispatch(node, key, path, req.Method, version, leaf, nil)

// dispatch request
Expand Down

0 comments on commit 72cf83a

Please sign in to comment.