func TestRouterMatchAny(t *testing.T) { e := New() r := e.router // Routes r.Add(GET, "/", func(*Context) error { return nil }, e) r.Add(GET, "/*", func(*Context) error { return nil }, e) r.Add(GET, "/users/*", func(*Context) error { return nil }, e) c := NewContext(nil, nil, e) h, _ := r.Find(GET, "/", c) if assert.NotNil(t, h) { assert.Equal(t, "", c.P(0)) } h, _ = r.Find(GET, "/download", c) if assert.NotNil(t, h) { assert.Equal(t, "download", c.P(0)) } h, _ = r.Find(GET, "/users/joe", c) if assert.NotNil(t, h) { assert.Equal(t, "joe", c.P(0)) } }
func TestGzip(t *testing.T) { req, _ := http.NewRequest(vodka.GET, "/", nil) rec := httptest.NewRecorder() c := vodka.NewContext(req, vodka.NewResponse(rec), vodka.New()) h := func(c *vodka.Context) error { c.Response().Write([]byte("test")) // For Content-Type sniffing return nil } // Skip if no Accept-Encoding header Gzip()(h)(c) assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, "test", rec.Body.String()) req, _ = http.NewRequest(vodka.GET, "/", nil) req.Header.Set(vodka.AcceptEncoding, "gzip") rec = httptest.NewRecorder() c = vodka.NewContext(req, vodka.NewResponse(rec), vodka.New()) // Gzip Gzip()(h)(c) assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, "gzip", rec.Header().Get(vodka.ContentEncoding)) assert.Contains(t, rec.Header().Get(vodka.ContentType), vodka.TextPlain) r, err := gzip.NewReader(rec.Body) defer r.Close() if assert.NoError(t, err) { buf := new(bytes.Buffer) buf.ReadFrom(r) assert.Equal(t, "test", buf.String()) } }
func TestVodkaHandler(t *testing.T) { e := New() // HandlerFunc e.Get("/1", HandlerFunc(func(c *Context) error { return c.String(http.StatusOK, "1") })) // func(*vodka.Context) error e.Get("/2", func(c *Context) error { return c.String(http.StatusOK, "2") }) // http.Handler/http.HandlerFunc e.Get("/3", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("3")) })) // func(http.ResponseWriter, *http.Request) e.Get("/4", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("4")) }) for _, p := range []string{"1", "2", "3", "4"} { c, b := request(GET, "/"+p, e) assert.Equal(t, http.StatusOK, c) assert.Equal(t, p, b) } // Unknown assert.Panics(t, func() { e.Get("/5", nil) }) }
func TestResponse(t *testing.T) { w := httptest.NewRecorder() r := NewResponse(w) // SetWriter r.SetWriter(w) // Writer assert.Equal(t, w, r.Writer()) // Header assert.NotNil(t, r.Header()) // WriteHeader r.WriteHeader(http.StatusOK) assert.Equal(t, http.StatusOK, r.status) // Committed assert.True(t, r.committed) // Already committed r.WriteHeader(http.StatusTeapot) assert.NotEqual(t, http.StatusTeapot, r.Status()) // Status r.status = http.StatusOK assert.Equal(t, http.StatusOK, r.Status()) // Write s := "vodka" _, err := r.Write([]byte(s)) assert.NoError(t, err) // Flush r.Flush() // Size assert.EqualValues(t, len(s), r.Size()) // Committed assert.Equal(t, true, r.Committed()) // Hijack assert.Panics(t, func() { r.Hijack() }) // CloseNotify assert.Panics(t, func() { r.CloseNotify() }) // reset r.reset(httptest.NewRecorder()) }
func testBind(t *testing.T, c *Context, ct string) { c.request.Header.Set(ContentType, ct) u := new(user) err := c.Bind(u) if ct == "" { assert.Error(t, UnsupportedMediaType) } else if assert.NoError(t, err) { assert.Equal(t, "1", u.ID) assert.Equal(t, "Joe", u.Name) } }
func TestVodkaGroup(t *testing.T) { e := New() buf := new(bytes.Buffer) e.Use(func(*Context) error { buf.WriteString("0") return nil }) h := func(*Context) error { return nil } //-------- // Routes //-------- e.Get("/users", h) // Group g1 := e.Group("/group1") g1.Use(func(*Context) error { buf.WriteString("1") return nil }) g1.Get("/", h) // Group with no parent middleware g2 := e.Group("/group2", func(*Context) error { buf.WriteString("2") return nil }) g2.Get("/", h) // Nested groups g3 := e.Group("/group3") g4 := g3.Group("/group4") g4.Get("/", func(c *Context) error { return c.Status(http.StatusOK) }) request(GET, "/users", e) // println(len(e.middleware)) assert.Equal(t, "0", buf.String()) buf.Reset() request(GET, "/group1/", e) // println(len(g1.vodka.middleware)) assert.Equal(t, "01", buf.String()) buf.Reset() request(GET, "/group2/", e) assert.Equal(t, "2", buf.String()) buf.Reset() c, _ := request(GET, "/group3/group4/", e) assert.Equal(t, http.StatusOK, c) }
func TestContextForm(t *testing.T) { f := make(url.Values) f.Set("name", "joe") f.Set("email", "*****@*****.**") req, err := http.NewRequest(POST, "/", strings.NewReader(f.Encode())) assert.NoError(t, err) req.Header.Add(ContentType, ApplicationForm) c := NewContext(req, nil, New()) assert.Equal(t, "joe", c.Form("name")) assert.Equal(t, "*****@*****.**", c.Form("email")) }
func TestContextQuery(t *testing.T) { q := make(url.Values) q.Set("name", "joe") q.Set("email", "*****@*****.**") req, err := http.NewRequest(GET, "/", nil) assert.NoError(t, err) req.URL.RawQuery = q.Encode() c := NewContext(req, nil, New()) assert.Equal(t, "joe", c.Query("name")) assert.Equal(t, "*****@*****.**", c.Query("email")) }
func TestRouterTwoParam(t *testing.T) { e := New() r := e.router r.Add(GET, "/users/:uid/files/:fid", func(*Context) error { return nil }, e) c := NewContext(nil, nil, e) h, _ := r.Find(GET, "/users/1/files/1", c) if assert.NotNil(t, h) { assert.Equal(t, "1", c.P(0)) assert.Equal(t, "1", c.P(1)) } }
func TestRouterMicroParam(t *testing.T) { e := New() r := e.router r.Add(GET, "/:a/:b/:c", func(c *Context) error { return nil }, e) c := NewContext(nil, nil, e) h, _ := r.Find(GET, "/1/2/3", c) if assert.NotNil(t, h) { assert.Equal(t, "1", c.P(0)) assert.Equal(t, "2", c.P(1)) assert.Equal(t, "3", c.P(2)) } }
func TestVodkaFavicon(t *testing.T) { e := New() e.Favicon("examples/website/public/favicon.ico") c, b := request(GET, "/favicon.ico", e) assert.Equal(t, http.StatusOK, c) assert.NotEmpty(t, b) }
func TestVodkaIndex(t *testing.T) { e := New() e.Index("examples/website/public/index.html") c, b := request(GET, "/", e) assert.Equal(t, http.StatusOK, c) assert.NotEmpty(t, b) }
func TestVodkaBadRequest(t *testing.T) { e := New() r, _ := http.NewRequest("INVALID", "/files", nil) w := httptest.NewRecorder() e.ServeHTTP(w, r) assert.Equal(t, http.StatusBadRequest, w.Code) }
func TestVodkaNotFound(t *testing.T) { e := New() r, _ := http.NewRequest(GET, "/files", nil) w := httptest.NewRecorder() e.ServeHTTP(w, r) assert.Equal(t, http.StatusNotFound, w.Code) }
func TestVodkaWebSocket(t *testing.T) { fmt.Println("TestVodkaWebSocket start") e := New() e.WebSocket("/ws", func(c *Context) error { fmt.Println("Got WebSocket Request!") c.socket.Write([]byte("test")) return nil }) srv := httptest.NewServer(e) defer srv.Close() addr := srv.Listener.Addr().String() origin := "http://localhost" url := fmt.Sprintf("ws://%s/ws", addr) ws, err := websocket.Dial(url, "", origin) if assert.NoError(t, err) { ws.Write([]byte("test")) defer ws.Close() buf := new(bytes.Buffer) buf.ReadFrom(ws) assert.Equal(t, "test", buf.String()) fmt.Println("Return buf.String():", buf.String()) } fmt.Println("TestVodkaWebSocket end") }
func TestRouterAPI(t *testing.T) { e := New() r := e.router for _, route := range api { r.Add(route.Method, route.Path, func(c *Context) error { return nil }, e) } response := NewResponse(httptest.NewRecorder()) c := NewContext(nil, response, e) for _, route := range api { h, _ := r.Find(route.Method, route.Path, c) if assert.NotNil(t, h) { for i, n := range c.pnames { if assert.NotEmpty(t, n) { assert.Equal(t, ":"+n, c.P(i)) } } h(c) } } }
func TestStripTrailingSlash(t *testing.T) { e := New() e.StripTrailingSlash() r, _ := http.NewRequest(GET, "/users/", nil) w := httptest.NewRecorder() e.ServeHTTP(w, r) assert.Equal(t, http.StatusNotFound, w.Code) }
func TestVodkaStatic(t *testing.T) { e := New() // OK e.Static("/scripts", "examples/website/public/scripts") c, b := request(GET, "/scripts/main.js", e) assert.Equal(t, http.StatusOK, c) assert.NotEmpty(t, b) // No file e.Static("/scripts", "examples/website/public/scripts") c, _ = request(GET, "/scripts/index.js", e) assert.Equal(t, http.StatusNotFound, c) // Directory e.Static("/scripts", "examples/website/public/scripts") c, _ = request(GET, "/scripts", e) assert.Equal(t, http.StatusForbidden, c) // Directory with index.html e.Static("/", "examples/website/public") c, r := request(GET, "/", e) assert.Equal(t, http.StatusOK, c) assert.Equal(t, true, strings.HasPrefix(r, "<!doctype html>")) // Sub-directory with index.html c, r = request(GET, "/folder", e) assert.Equal(t, http.StatusOK, c) assert.Equal(t, "sub directory", r) }
func TestVodkaRoutes(t *testing.T) { e := New() h := func(*Context) error { return nil } routes := []Route{ {GET, "/users/:user/events", h}, {GET, "/users/:user/events/public", h}, {POST, "/repos/:owner/:repo/git/refs", h}, {POST, "/repos/:owner/:repo/git/tags", h}, } for _, r := range routes { e.add(r.Method, r.Path, h) } for i, r := range e.Routes() { assert.Equal(t, routes[i].Method, r.Method) assert.Equal(t, routes[i].Path, r.Path) } }
func TestVodkaURL(t *testing.T) { e := New() static := func(*Context) error { return nil } getUser := func(*Context) error { return nil } getFile := func(*Context) error { return nil } e.Get("/static/file", static) e.Get("/users/:id", getUser) g := e.Group("/group") g.Get("/users/:uid/files/:fid", getFile) assert.Equal(t, "/static/file", e.URL(static)) assert.Equal(t, "/users/:id", e.URL(getUser)) assert.Equal(t, "/users/1", e.URL(getUser, "1")) assert.Equal(t, "/group/users/1/files/:fid", e.URL(getFile, "1")) assert.Equal(t, "/group/users/1/files/1", e.URL(getFile, "1", "1")) }
func TestRouterMultiRoute(t *testing.T) { e := New() r := e.router // Routes r.Add(GET, "/users", func(c *Context) error { c.Set("path", "/users") return nil }, e) r.Add(GET, "/users/:id", func(c *Context) error { return nil }, e) c := NewContext(nil, new(Response), e) // Route > /users h, _ := r.Find(GET, "/users", c) if assert.NotNil(t, h) { h(c) assert.Equal(t, "/users", c.Get("path")) } // Route > /users/:id h, _ = r.Find(GET, "/users/1", c) if assert.NotNil(t, h) { assert.Equal(t, "1", c.P(0)) } // Route > /user h, _ = r.Find(GET, "/user", c) if assert.IsType(t, new(HTTPError), h(c)) { he := h(c).(*HTTPError) assert.Equal(t, http.StatusNotFound, he.code) } // Invalid Method for Resource c.response.writer = httptest.NewRecorder() h, _ = r.Find("INVALID", "/users", c) if assert.IsType(t, new(HTTPError), h(c)) { he := h(c).(*HTTPError) assert.Equal(t, http.StatusBadRequest, he.code) } }
func TestRouterServeHTTP(t *testing.T) { e := New() r := e.router r.Add(GET, "/users", func(*Context) error { return nil }, e) // OK req, _ := http.NewRequest(GET, "/users", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) // Not found req, _ = http.NewRequest(GET, "/files", nil) w = httptest.NewRecorder() r.ServeHTTP(w, req) assert.Equal(t, http.StatusNotFound, w.Code) }
func TestRecover(t *testing.T) { e := vodka.New() e.SetDebug(true) req, _ := http.NewRequest(vodka.GET, "/", nil) rec := httptest.NewRecorder() c := vodka.NewContext(req, vodka.NewResponse(rec), e) h := func(c *vodka.Context) error { panic("test") } Recover()(h)(c) assert.Equal(t, http.StatusInternalServerError, rec.Code) assert.Contains(t, rec.Body.String(), "panic recover") }
func TestRouterStatic(t *testing.T) { e := New() r := e.router path := "/folders/a/files/vodka.gif" r.Add(GET, path, func(c *Context) error { c.Set("path", path) return nil }, e) c := NewContext(nil, nil, e) h, _ := r.Find(GET, path, c) if assert.NotNil(t, h) { h(c) assert.Equal(t, path, c.Get("path")) } }
func TestRouterMixParamMatchAny(t *testing.T) { e := New() r := e.router // Route r.Add(GET, "/users/:id/*", func(c *Context) error { return nil }, e) c := NewContext(nil, nil, e) h, _ := r.Find(GET, "/users/joe/comments", c) if assert.NotNil(t, h) { h(c) assert.Equal(t, "joe", c.P(0)) } }
func TestGzipCloseNotify(t *testing.T) { rec := newCloseNotifyingRecorder() buf := new(bytes.Buffer) w := gzip.NewWriter(buf) gw := gzipWriter{Writer: w, ResponseWriter: rec} closed := false notifier := gw.CloseNotify() rec.close() select { case <-notifier: closed = true case <-time.After(time.Second): } assert.Equal(t, closed, true) }
func TestVodka(t *testing.T) { e := New() req, _ := http.NewRequest(GET, "/", nil) rec := httptest.NewRecorder() c := NewContext(req, NewResponse(rec), e) // Router assert.NotNil(t, e.Router()) // Debug e.SetDebug(true) assert.True(t, e.debug) // DefaultHTTPErrorHandler e.DefaultHTTPErrorHandler(errors.New("error"), c) assert.Equal(t, http.StatusInternalServerError, rec.Code) }
func TestBasicAuth(t *testing.T) { req, _ := http.NewRequest(vodka.GET, "/", nil) rec := httptest.NewRecorder() c := vodka.NewContext(req, vodka.NewResponse(rec), vodka.New()) fn := func(u, p string) bool { if u == "joe" && p == "secret" { return true } return false } ba := BasicAuth(fn) // Valid credentials auth := Basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret")) req.Header.Set(vodka.Authorization, auth) assert.NoError(t, ba(c)) //--------------------- // Invalid credentials //--------------------- // Incorrect password auth = Basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:password")) req.Header.Set(vodka.Authorization, auth) he := ba(c).(*vodka.HTTPError) assert.Equal(t, http.StatusUnauthorized, he.Code()) assert.Equal(t, Basic+" realm=Restricted", rec.Header().Get(vodka.WWWAuthenticate)) // Empty Authorization header req.Header.Set(vodka.Authorization, "") he = ba(c).(*vodka.HTTPError) assert.Equal(t, http.StatusUnauthorized, he.Code()) assert.Equal(t, Basic+" realm=Restricted", rec.Header().Get(vodka.WWWAuthenticate)) // Invalid Authorization header auth = base64.StdEncoding.EncodeToString([]byte("invalid")) req.Header.Set(vodka.Authorization, auth) he = ba(c).(*vodka.HTTPError) assert.Equal(t, http.StatusUnauthorized, he.Code()) assert.Equal(t, Basic+" realm=Restricted", rec.Header().Get(vodka.WWWAuthenticate)) // WebSocket c.Request().Header.Set(vodka.Upgrade, vodka.WebSocket) assert.NoError(t, ba(c)) }
func TestRouterParamNames(t *testing.T) { e := New() r := e.router // Routes r.Add(GET, "/users", func(c *Context) error { c.Set("path", "/users") return nil }, e) r.Add(GET, "/users/:id", func(c *Context) error { return nil }, e) r.Add(GET, "/users/:uid/files/:fid", func(c *Context) error { return nil }, e) c := NewContext(nil, nil, e) // Route > /users h, _ := r.Find(GET, "/users", c) if assert.NotNil(t, h) { h(c) assert.Equal(t, "/users", c.Get("path")) } // Route > /users/:id h, _ = r.Find(GET, "/users/1", c) if assert.NotNil(t, h) { assert.Equal(t, "id", c.pnames[0]) assert.Equal(t, "1", c.P(0)) } // Route > /users/:uid/files/:fid h, _ = r.Find(GET, "/users/1/files/1", c) if assert.NotNil(t, h) { assert.Equal(t, "uid", c.pnames[0]) assert.Equal(t, "1", c.P(0)) assert.Equal(t, "fid", c.pnames[1]) assert.Equal(t, "1", c.P(1)) } }
func TestContext(t *testing.T) { userJSON := `{"id":"1","name":"Joe"}` userXML := `<user><id>1</id><name>Joe</name></user>` req, _ := http.NewRequest(POST, "/", strings.NewReader(userJSON)) rec := httptest.NewRecorder() c := NewContext(req, NewResponse(rec), New()) // Request assert.NotNil(t, c.Request()) // Response assert.NotNil(t, c.Response()) // Socket assert.Nil(t, c.Socket()) // Param by id c.pnames = []string{"id"} c.pvalues = []string{"1"} assert.Equal(t, "1", c.P(0)) // Param by name assert.Equal(t, "1", c.Param("id")) // Store c.Set("user", "Joe") assert.Equal(t, "Joe", c.Get("user")) //------ // Bind //------ // JSON testBind(t, c, "application/json") // XML c.request, _ = http.NewRequest(POST, "/", strings.NewReader(userXML)) testBind(t, c, ApplicationXML) // Unsupported testBind(t, c, "") //-------- // Render //-------- tpl := &Template{ templates: template.Must(template.New("hello").Parse("Hello, {{.}}!")), } c.vodka.SetRenderer(tpl) err := c.Render(http.StatusOK, "hello", "Joe") if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, "Hello, Joe!", rec.Body.String()) } c.vodka.renderer = nil err = c.Render(http.StatusOK, "hello", "Joe") assert.Error(t, err) // JSON rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.JSON(http.StatusOK, user{"1", "Joe"}) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, ApplicationJSONCharsetUTF8, rec.Header().Get(ContentType)) assert.Equal(t, userJSON+"\n", rec.Body.String()) } // JSONP rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) callback := "callback" err = c.JSONP(http.StatusOK, callback, user{"1", "Joe"}) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, ApplicationJavaScriptCharsetUTF8, rec.Header().Get(ContentType)) assert.Equal(t, callback+"("+userJSON+"\n);", rec.Body.String()) } // XML rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.XML(http.StatusOK, user{"1", "Joe"}) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, ApplicationXMLCharsetUTF8, rec.Header().Get(ContentType)) assert.Equal(t, xml.Header, xml.Header, rec.Body.String()) } // String rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.String(http.StatusOK, "Hello, World!") if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, TextPlain, rec.Header().Get(ContentType)) assert.Equal(t, "Hello, World!", rec.Body.String()) } // HTML rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.HTML(http.StatusOK, "Hello, <strong>World!</strong>") if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, TextHTMLCharsetUTF8, rec.Header().Get(ContentType)) assert.Equal(t, "Hello, <strong>World!</strong>", rec.Body.String()) } // File rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.File("test/fixture/walle.png", false) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, 219885, rec.Body.Len()) } // File as attachment rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) err = c.File("test/fixture/walle.png", true) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, rec.Header().Get(ContentDisposition), "attachment; filename=walle.png") assert.Equal(t, 219885, rec.Body.Len()) } // Status rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) c.Status(http.StatusOK) assert.Equal(t, http.StatusOK, c.response.status) // Redirect rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) assert.Equal(t, nil, c.Redirect(http.StatusMovedPermanently, "http://github.com/insionng/vodka")) // Error rec = httptest.NewRecorder() c = NewContext(req, NewResponse(rec), New()) c.Error(errors.New("error")) assert.Equal(t, http.StatusInternalServerError, c.response.status) // reset c.reset(req, NewResponse(httptest.NewRecorder()), New()) }