Skip to content
Find file
5233dc7
348 lines (306 sloc) 9.23 KB
package lion
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
var (
emptyParams = map[string]string{}
)
func TestRouteMatching(t *testing.T) {
helloHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
helloNameHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
helloNameTweetsHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
helloNameGetTweetHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
cartsHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
getCartHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
helloContactHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
helloContactByPersonHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
extensionHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
usernameHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
wildcardHandler := HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {})
routes := []struct {
Method string
Pattern string
Handler Handler
}{
{
Method: "GET",
Pattern: "/hello",
Handler: helloHandler,
},
{
Method: "GET",
Pattern: "/hello/contact",
Handler: helloContactHandler,
},
{
Method: "GET",
Pattern: "/hello/:name",
Handler: helloNameHandler,
},
{
Method: "GET",
Pattern: "/hello/:name/tweets",
Handler: helloNameTweetsHandler,
},
{
Method: "GET",
Pattern: "/hello/:name/tweets/:id",
Handler: helloNameGetTweetHandler,
},
{
Method: "GET",
Pattern: "/carts",
Handler: cartsHandler,
},
{
Method: "GET",
Pattern: "/carts/:cartid",
Handler: getCartHandler,
},
{
Method: "GET",
Pattern: "/hello/contact/:dest",
Handler: helloContactByPersonHandler,
},
{
Method: "GET",
Pattern: "/extension/:file.:ext",
Handler: extensionHandler,
},
{
Method: "GET",
Pattern: "/@:username",
Handler: usernameHandler,
},
{
Method: "GET",
Pattern: "/*",
Handler: wildcardHandler,
},
}
tests := []struct {
Input string
ExpectedHandler Handler
ExpectedParams map[string]string
}{
{
Input: "/hello",
ExpectedHandler: helloHandler,
ExpectedParams: emptyParams,
},
{
Input: "/hello/batman",
ExpectedHandler: helloNameHandler,
ExpectedParams: map[string]string{"name": "batman"},
},
{
Input: "/hello/dot.inthemiddle",
ExpectedHandler: helloNameHandler,
ExpectedParams: map[string]string{"name": "dot.inthemiddle"},
},
{
Input: "/hello/batman/tweets",
ExpectedHandler: helloNameTweetsHandler,
ExpectedParams: map[string]string{"name": "batman"},
},
{
Input: "/hello/batman/tweets/123",
ExpectedHandler: helloNameGetTweetHandler,
ExpectedParams: map[string]string{"name": "batman", "id": "123"},
},
{
Input: "/carts",
ExpectedHandler: cartsHandler,
ExpectedParams: emptyParams,
},
{
Input: "/carts/123456",
ExpectedHandler: getCartHandler,
ExpectedParams: map[string]string{"cartid": "123456"},
},
{
Input: "/hello/contact",
ExpectedHandler: helloContactHandler,
ExpectedParams: emptyParams,
},
{
Input: "/hello/contact/batman",
ExpectedHandler: helloContactByPersonHandler,
ExpectedParams: map[string]string{"dest": "batman"},
},
{
Input: "/extension/batman.jpg",
ExpectedHandler: extensionHandler,
ExpectedParams: map[string]string{"file": "batman", "ext": "jpg"},
},
{
Input: "/@celrenheit",
ExpectedHandler: usernameHandler,
ExpectedParams: map[string]string{"username": "celrenheit"},
},
{
Input: "/unkownpath/subfolder",
ExpectedHandler: wildcardHandler,
ExpectedParams: map[string]string{"*": "unkownpath/subfolder"},
},
}
mux := New()
for _, r := range routes {
mux.Handle(r.Method, r.Pattern, r.Handler)
}
for _, test := range tests {
req, _ := http.NewRequest("GET", test.Input, nil)
c, h := mux.rm.Match(&Context{
parent: context.TODO(),
}, req)
// Compare params
for k, v := range test.ExpectedParams {
assert.NotNil(t, c.Value(k))
actual := c.Value(k).(string)
if actual != v {
t.Errorf("Expected %s but got %s for url: %s", green(v), red(actual), test.Input)
}
}
// Compare handlers
if fmt.Sprintf("%v", h) != fmt.Sprintf("%v", test.ExpectedHandler) {
t.Errorf("Handler not match for %s", test.Input)
}
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
// Compare response code
if w.Code != http.StatusOK {
t.Errorf("Response should be 200 OK for %s", test.Input)
}
}
}
type testmw struct{}
func (m testmw) ServeNext(next Handler) Handler {
return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Test-Key", "Test-Value")
next.ServeHTTPC(c, w, r)
})
}
func TestMiddleware(t *testing.T) {
mux := New()
mux.Use(testmw{})
mux.Get("/hi", HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hi!"))
}))
expectHeader(t, mux, "GET", "/hi", "Test-Key", "Test-Value")
}
func TestMiddlewareFunc(t *testing.T) {
mux := New()
mux.UseFunc(func(next Handler) Handler {
return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Test-Key", "Test-Value")
next.ServeHTTPC(c, w, r)
})
})
mux.Get("/hi", HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hi!"))
}))
expectHeader(t, mux, "GET", "/hi", "Test-Key", "Test-Value")
}
func TestMiddlewareChain(t *testing.T) {
mux := New()
mux.UseFunc(func(next Handler) Handler {
return nil
})
}
func TestMountingSubrouter(t *testing.T) {
mux := New()
adminrouter := New()
adminrouter.GetFunc("/:id", func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("admin", "id")
})
mux.Mount("/admin", adminrouter)
expectHeader(t, mux, "GET", "/admin/123", "admin", "id")
}
func TestGroupSubGroup(t *testing.T) {
s := New()
admin := s.Group("/admin")
sub := admin.Group("/")
sub.UseFunc(func(next Handler) Handler {
return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Test-Key", "Get")
next.ServeHTTPC(c, w, r)
})
})
sub.GetFunc("/", func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Get"))
})
sub2 := admin.Group("/")
sub2.UseFunc(func(next Handler) Handler {
return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Test-Key", "Put")
next.ServeHTTPC(c, w, r)
})
})
sub2.PutFunc("/", func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Put"))
})
expectHeader(t, s, "GET", "/admin", "Test-Key", "Get")
expectHeader(t, s, "PUT", "/admin", "Test-Key", "Put")
}
func TestNamedMiddlewares(t *testing.T) {
l := New()
l.DefineFunc("admin", func(next Handler) Handler {
return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Test-Key", "admin")
next.ServeHTTPC(c, w, r)
})
})
l.DefineFunc("public", func(next Handler) Handler {
return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Test-Key", "public")
next.ServeHTTPC(c, w, r)
})
})
g := l.Group("/admin")
g.UseNamed("admin")
g.GetFunc("/test", func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte("admintest"))
})
p := l.Group("/public")
p.UseNamed("public")
p.GetFunc("/test", func(c context.Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte("publictest"))
})
expectHeader(t, l, "GET", "/admin/test", "Test-Key", "admin")
expectHeader(t, l, "GET", "/public/test", "Test-Key", "public")
expectBody(t, l, "GET", "/admin/test", "admintest")
expectBody(t, l, "GET", "/public/test", "publictest")
}
func TestEmptyRouter(t *testing.T) {
l := New()
expectStatus(t, l, "GET", "/", http.StatusNotFound)
}
func expectStatus(t *testing.T, mux http.Handler, method, path string, status int) {
req, _ := http.NewRequest(method, path, nil)
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
if w.Code != status {
t.Errorf("Expected status code to be %d but got %d for request: %s %s", status, w.Code, method, path)
}
}
func expectHeader(t *testing.T, mux http.Handler, method, path, k, v string) {
req, _ := http.NewRequest(method, path, nil)
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
if w.Header().Get(k) != v {
t.Errorf("Expected header to be %s but got %s for request: %s %s", v, w.Header().Get(k), method, path)
}
}
func expectBody(t *testing.T, mux http.Handler, method, path, v string) {
req, _ := http.NewRequest(method, path, nil)
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
if w.Body.String() != v {
t.Errorf("Expected body to be %s but got %s for request: %s %s", v, w.Body.String(), method, path)
}
}
Something went wrong with that request. Please try again.