2015-03-27 23:35:15 +02:00
|
|
|
package echo
|
|
|
|
|
|
|
|
import (
|
2015-03-30 16:38:53 +02:00
|
|
|
"bytes"
|
2015-05-22 07:48:34 +02:00
|
|
|
"fmt"
|
2015-03-27 23:35:15 +02:00
|
|
|
"net/http"
|
|
|
|
"testing"
|
2015-05-22 07:48:34 +02:00
|
|
|
|
2015-05-30 01:00:02 +02:00
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
|
2015-05-31 00:20:36 +02:00
|
|
|
"errors"
|
|
|
|
|
2016-01-09 19:44:18 +02:00
|
|
|
"github.com/labstack/echo/test"
|
2015-05-30 19:54:55 +02:00
|
|
|
"github.com/stretchr/testify/assert"
|
2015-03-27 23:35:15 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
user struct {
|
2016-05-01 21:38:51 +02:00
|
|
|
ID int `json:"id" xml:"id" form:"id"`
|
|
|
|
Name string `json:"name" xml:"name" form:"name"`
|
2015-03-27 23:35:15 +02:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2016-05-01 21:38:51 +02:00
|
|
|
const (
|
|
|
|
userJSON = `{"id":1,"name":"Jon Snow"}`
|
|
|
|
userXML = `<user><id>1</id><name>Jon Snow</name></user>`
|
|
|
|
userForm = `id=1&name=Jon Snow`
|
|
|
|
invalidContent = "invalid content"
|
|
|
|
)
|
|
|
|
|
2015-05-31 00:20:36 +02:00
|
|
|
func TestEcho(t *testing.T) {
|
|
|
|
e := New()
|
2016-04-24 19:21:23 +02:00
|
|
|
req := test.NewRequest(GET, "/", nil)
|
|
|
|
rec := test.NewResponseRecorder()
|
|
|
|
c := e.NewContext(req, rec)
|
2015-05-31 00:20:36 +02:00
|
|
|
|
|
|
|
// Router
|
|
|
|
assert.NotNil(t, e.Router())
|
|
|
|
|
|
|
|
// Debug
|
2015-09-13 19:03:20 +02:00
|
|
|
e.SetDebug(true)
|
2015-09-01 17:03:01 +02:00
|
|
|
assert.True(t, e.debug)
|
2015-05-31 00:20:36 +02:00
|
|
|
|
|
|
|
// DefaultHTTPErrorHandler
|
|
|
|
e.DefaultHTTPErrorHandler(errors.New("error"), c)
|
2016-04-24 19:21:23 +02:00
|
|
|
assert.Equal(t, http.StatusInternalServerError, rec.Status())
|
2015-05-31 00:20:36 +02:00
|
|
|
}
|
|
|
|
|
2016-03-12 15:14:15 +02:00
|
|
|
func TestEchoStatic(t *testing.T) {
|
|
|
|
e := New()
|
|
|
|
|
|
|
|
// OK
|
|
|
|
e.Static("/images", "_fixture/images")
|
|
|
|
c, b := request(GET, "/images/walle.png", e)
|
|
|
|
assert.Equal(t, http.StatusOK, c)
|
|
|
|
assert.NotEmpty(t, b)
|
|
|
|
|
|
|
|
// No file
|
|
|
|
e.Static("/images", "_fixture/scripts")
|
|
|
|
c, _ = request(GET, "/images/bolt.png", e)
|
|
|
|
assert.Equal(t, http.StatusNotFound, c)
|
|
|
|
|
|
|
|
// Directory
|
|
|
|
e.Static("/images", "_fixture/images")
|
|
|
|
c, _ = request(GET, "/images", e)
|
|
|
|
assert.Equal(t, http.StatusNotFound, c)
|
|
|
|
|
|
|
|
// Directory with index.html
|
|
|
|
e.Static("/", "_fixture")
|
|
|
|
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, true, strings.HasPrefix(r, "<!doctype html>"))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoFile(t *testing.T) {
|
|
|
|
e := New()
|
|
|
|
e.File("/walle", "_fixture/images/walle.png")
|
|
|
|
c, b := request(GET, "/walle", e)
|
|
|
|
assert.Equal(t, http.StatusOK, c)
|
|
|
|
assert.NotEmpty(t, b)
|
|
|
|
}
|
|
|
|
|
2015-03-30 05:44:55 +02:00
|
|
|
func TestEchoMiddleware(t *testing.T) {
|
2015-03-30 08:35:08 +02:00
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
buf := new(bytes.Buffer)
|
2015-03-30 05:44:55 +02:00
|
|
|
|
2016-04-02 23:19:39 +02:00
|
|
|
e.Pre(WrapMiddleware(func(c Context) error {
|
2016-03-17 22:24:52 +02:00
|
|
|
assert.Empty(t, c.Path())
|
|
|
|
buf.WriteString("-1")
|
|
|
|
return nil
|
2016-04-02 23:19:39 +02:00
|
|
|
}))
|
2016-03-17 22:24:52 +02:00
|
|
|
|
2016-04-02 23:19:39 +02:00
|
|
|
e.Use(WrapMiddleware(func(c Context) error {
|
2016-03-17 22:24:52 +02:00
|
|
|
buf.WriteString("1")
|
|
|
|
return nil
|
2016-04-02 23:19:39 +02:00
|
|
|
}))
|
2016-03-17 22:24:52 +02:00
|
|
|
|
2016-04-02 23:19:39 +02:00
|
|
|
e.Use(WrapMiddleware(func(c Context) error {
|
2016-03-17 22:24:52 +02:00
|
|
|
buf.WriteString("2")
|
|
|
|
return nil
|
2016-04-02 23:19:39 +02:00
|
|
|
}))
|
2016-03-17 22:24:52 +02:00
|
|
|
|
2016-04-02 23:19:39 +02:00
|
|
|
e.Use(WrapMiddleware(func(c Context) error {
|
2016-03-17 22:24:52 +02:00
|
|
|
buf.WriteString("3")
|
|
|
|
return nil
|
2016-04-02 23:19:39 +02:00
|
|
|
}))
|
2015-03-30 08:35:08 +02:00
|
|
|
|
2015-03-30 05:44:55 +02:00
|
|
|
// Route
|
2016-04-19 01:59:58 +02:00
|
|
|
e.GET("/", func(c Context) error {
|
2016-01-09 19:44:18 +02:00
|
|
|
return c.String(http.StatusOK, "OK")
|
2016-04-02 23:19:39 +02:00
|
|
|
})
|
2015-03-30 05:44:55 +02:00
|
|
|
|
2015-05-31 00:20:36 +02:00
|
|
|
c, b := request(GET, "/", e)
|
2016-03-17 22:24:52 +02:00
|
|
|
assert.Equal(t, "-1123", buf.String())
|
2015-05-31 00:20:36 +02:00
|
|
|
assert.Equal(t, http.StatusOK, c)
|
2016-01-09 19:44:18 +02:00
|
|
|
assert.Equal(t, "OK", b)
|
2016-03-17 22:24:52 +02:00
|
|
|
}
|
2015-05-31 00:20:36 +02:00
|
|
|
|
2016-03-17 22:24:52 +02:00
|
|
|
func TestEchoMiddlewareError(t *testing.T) {
|
|
|
|
e := New()
|
2016-04-02 23:19:39 +02:00
|
|
|
e.Use(WrapMiddleware(func(c Context) error {
|
2016-03-17 22:24:52 +02:00
|
|
|
return errors.New("error")
|
2016-04-02 23:19:39 +02:00
|
|
|
}))
|
2016-04-19 01:59:58 +02:00
|
|
|
e.GET("/", notFoundHandler)
|
2016-03-17 22:24:52 +02:00
|
|
|
c, _ := request(GET, "/", e)
|
2015-05-31 00:20:36 +02:00
|
|
|
assert.Equal(t, http.StatusInternalServerError, c)
|
2015-03-30 08:35:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoHandler(t *testing.T) {
|
|
|
|
e := New()
|
|
|
|
|
2015-04-29 20:22:07 +02:00
|
|
|
// HandlerFunc
|
2016-04-19 01:59:58 +02:00
|
|
|
e.GET("/ok", func(c Context) error {
|
2016-01-09 19:44:18 +02:00
|
|
|
return c.String(http.StatusOK, "OK")
|
2016-04-02 23:19:39 +02:00
|
|
|
})
|
2015-04-19 01:47:48 +02:00
|
|
|
|
2016-01-09 19:44:18 +02:00
|
|
|
c, b := request(GET, "/ok", e)
|
|
|
|
assert.Equal(t, http.StatusOK, c)
|
|
|
|
assert.Equal(t, "OK", b)
|
2015-03-30 05:44:55 +02:00
|
|
|
}
|
|
|
|
|
2015-05-30 01:00:02 +02:00
|
|
|
func TestEchoConnect(t *testing.T) {
|
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, CONNECT, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoDelete(t *testing.T) {
|
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, DELETE, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoGet(t *testing.T) {
|
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, GET, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoHead(t *testing.T) {
|
2015-04-06 00:30:03 +02:00
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, HEAD, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoOptions(t *testing.T) {
|
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, OPTIONS, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoPatch(t *testing.T) {
|
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, PATCH, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoPost(t *testing.T) {
|
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, POST, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoPut(t *testing.T) {
|
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, PUT, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoTrace(t *testing.T) {
|
|
|
|
e := New()
|
2015-05-31 00:20:36 +02:00
|
|
|
testMethod(t, TRACE, "/", e)
|
2015-05-30 01:00:02 +02:00
|
|
|
}
|
|
|
|
|
2015-08-26 05:36:15 +02:00
|
|
|
func TestEchoAny(t *testing.T) { // JFC
|
|
|
|
e := New()
|
2016-04-02 23:19:39 +02:00
|
|
|
e.Any("/", func(c Context) error {
|
2015-08-26 05:36:15 +02:00
|
|
|
return c.String(http.StatusOK, "Any")
|
2016-04-02 23:19:39 +02:00
|
|
|
})
|
2015-08-26 05:36:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoMatch(t *testing.T) { // JFC
|
|
|
|
e := New()
|
2016-04-02 23:19:39 +02:00
|
|
|
e.Match([]string{GET, POST}, "/", func(c Context) error {
|
2015-08-26 05:36:15 +02:00
|
|
|
return c.String(http.StatusOK, "Match")
|
2016-04-02 23:19:39 +02:00
|
|
|
})
|
2015-08-26 05:36:15 +02:00
|
|
|
}
|
|
|
|
|
2015-04-22 07:12:41 +02:00
|
|
|
func TestEchoURL(t *testing.T) {
|
|
|
|
e := New()
|
2016-04-02 23:19:39 +02:00
|
|
|
static := func(Context) error { return nil }
|
|
|
|
getUser := func(Context) error { return nil }
|
|
|
|
getFile := func(Context) error { return nil }
|
2015-05-31 18:37:26 +02:00
|
|
|
|
2016-04-19 01:59:58 +02:00
|
|
|
e.GET("/static/file", static)
|
|
|
|
e.GET("/users/:id", getUser)
|
2015-05-31 18:37:26 +02:00
|
|
|
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"))
|
2015-04-22 07:12:41 +02:00
|
|
|
}
|
|
|
|
|
2015-06-01 09:07:53 +02:00
|
|
|
func TestEchoRoutes(t *testing.T) {
|
|
|
|
e := New()
|
|
|
|
routes := []Route{
|
2016-01-09 19:44:18 +02:00
|
|
|
{GET, "/users/:user/events", ""},
|
|
|
|
{GET, "/users/:user/events/public", ""},
|
|
|
|
{POST, "/repos/:owner/:repo/git/refs", ""},
|
|
|
|
{POST, "/repos/:owner/:repo/git/tags", ""},
|
2015-06-01 09:07:53 +02:00
|
|
|
}
|
|
|
|
for _, r := range routes {
|
2016-04-02 23:19:39 +02:00
|
|
|
e.add(r.Method, r.Path, func(c Context) error {
|
2016-01-09 19:44:18 +02:00
|
|
|
return c.String(http.StatusOK, "OK")
|
2016-04-02 23:19:39 +02:00
|
|
|
})
|
2015-06-01 09:07:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, r := range e.Routes() {
|
|
|
|
assert.Equal(t, routes[i].Method, r.Method)
|
|
|
|
assert.Equal(t, routes[i].Path, r.Path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEchoGroup(t *testing.T) {
|
|
|
|
e := New()
|
|
|
|
buf := new(bytes.Buffer)
|
2016-04-02 23:19:39 +02:00
|
|
|
e.Use(MiddlewareFunc(func(h HandlerFunc) HandlerFunc {
|
|
|
|
return func(c Context) error {
|
2016-01-29 09:46:11 +02:00
|
|
|
buf.WriteString("0")
|
2016-04-02 23:19:39 +02:00
|
|
|
return h(c)
|
|
|
|
}
|
2016-02-16 03:12:15 +02:00
|
|
|
}))
|
2016-04-02 23:19:39 +02:00
|
|
|
h := func(c Context) error {
|
2016-01-29 09:46:11 +02:00
|
|
|
return c.NoContent(http.StatusOK)
|
2016-04-02 23:19:39 +02:00
|
|
|
}
|
2015-06-01 09:07:53 +02:00
|
|
|
|
|
|
|
//--------
|
|
|
|
// Routes
|
|
|
|
//--------
|
|
|
|
|
2016-04-19 01:59:58 +02:00
|
|
|
e.GET("/users", h)
|
2015-06-01 09:07:53 +02:00
|
|
|
|
|
|
|
// Group
|
|
|
|
g1 := e.Group("/group1")
|
2016-04-02 23:19:39 +02:00
|
|
|
g1.Use(WrapMiddleware(func(c Context) error {
|
2016-03-17 05:15:38 +02:00
|
|
|
buf.WriteString("1")
|
2016-04-02 23:19:39 +02:00
|
|
|
return h(c)
|
|
|
|
}))
|
2016-03-09 05:31:11 +02:00
|
|
|
g1.Get("", h)
|
2015-06-01 09:07:53 +02:00
|
|
|
|
2016-03-17 05:15:38 +02:00
|
|
|
// Nested groups with middleware
|
2016-02-15 18:11:29 +02:00
|
|
|
g2 := e.Group("/group2")
|
2016-04-02 23:19:39 +02:00
|
|
|
g2.Use(WrapMiddleware(func(c Context) error {
|
2016-03-17 05:15:38 +02:00
|
|
|
buf.WriteString("2")
|
|
|
|
return nil
|
2016-04-02 23:19:39 +02:00
|
|
|
}))
|
2016-02-15 18:11:29 +02:00
|
|
|
g3 := g2.Group("/group3")
|
2016-04-02 23:19:39 +02:00
|
|
|
g3.Use(WrapMiddleware(func(c Context) error {
|
2016-03-17 05:15:38 +02:00
|
|
|
buf.WriteString("3")
|
|
|
|
return nil
|
2016-04-02 23:19:39 +02:00
|
|
|
}))
|
2016-03-09 05:31:11 +02:00
|
|
|
g3.Get("", h)
|
2015-06-01 09:07:53 +02:00
|
|
|
|
|
|
|
request(GET, "/users", e)
|
|
|
|
assert.Equal(t, "0", buf.String())
|
|
|
|
|
|
|
|
buf.Reset()
|
2016-03-09 05:31:11 +02:00
|
|
|
request(GET, "/group1", e)
|
2015-06-01 09:07:53 +02:00
|
|
|
assert.Equal(t, "01", buf.String())
|
|
|
|
|
|
|
|
buf.Reset()
|
2016-03-17 05:15:38 +02:00
|
|
|
request(GET, "/group2/group3", e)
|
|
|
|
assert.Equal(t, "023", buf.String())
|
2015-06-01 09:07:53 +02:00
|
|
|
}
|
|
|
|
|
2015-04-06 05:08:52 +02:00
|
|
|
func TestEchoNotFound(t *testing.T) {
|
2015-03-31 05:54:38 +02:00
|
|
|
e := New()
|
2016-04-24 19:21:23 +02:00
|
|
|
req := test.NewRequest(GET, "/files", nil)
|
2016-02-05 00:40:08 +02:00
|
|
|
rec := test.NewResponseRecorder()
|
2016-04-24 19:21:23 +02:00
|
|
|
e.ServeHTTP(req, rec)
|
2016-02-05 00:40:08 +02:00
|
|
|
assert.Equal(t, http.StatusNotFound, rec.Status())
|
2015-03-31 05:54:38 +02:00
|
|
|
}
|
|
|
|
|
2015-10-06 15:48:33 +02:00
|
|
|
func TestEchoMethodNotAllowed(t *testing.T) {
|
2015-11-04 02:26:20 +02:00
|
|
|
e := New()
|
2016-04-19 01:59:58 +02:00
|
|
|
e.GET("/", func(c Context) error {
|
2015-11-04 02:26:20 +02:00
|
|
|
return c.String(http.StatusOK, "Echo!")
|
2016-04-02 23:19:39 +02:00
|
|
|
})
|
2016-04-24 19:21:23 +02:00
|
|
|
req := test.NewRequest(POST, "/", nil)
|
2016-02-05 00:40:08 +02:00
|
|
|
rec := test.NewResponseRecorder()
|
2016-04-24 19:21:23 +02:00
|
|
|
e.ServeHTTP(req, rec)
|
2016-02-05 00:40:08 +02:00
|
|
|
assert.Equal(t, http.StatusMethodNotAllowed, rec.Status())
|
2015-07-24 21:03:36 +02:00
|
|
|
}
|
|
|
|
|
2015-05-31 00:20:36 +02:00
|
|
|
func TestEchoHTTPError(t *testing.T) {
|
|
|
|
m := http.StatusText(http.StatusBadRequest)
|
|
|
|
he := NewHTTPError(http.StatusBadRequest, m)
|
2016-03-11 17:53:54 +02:00
|
|
|
assert.Equal(t, http.StatusBadRequest, he.Code)
|
2015-05-31 00:20:36 +02:00
|
|
|
assert.Equal(t, m, he.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
func testMethod(t *testing.T, method, path string, e *Echo) {
|
|
|
|
m := fmt.Sprintf("%c%s", method[0], strings.ToLower(method[1:]))
|
|
|
|
p := reflect.ValueOf(path)
|
2016-04-02 23:19:39 +02:00
|
|
|
h := reflect.ValueOf(func(c Context) error {
|
2015-07-24 21:03:36 +02:00
|
|
|
return c.String(http.StatusOK, method)
|
2016-04-02 23:19:39 +02:00
|
|
|
})
|
2015-05-31 00:20:36 +02:00
|
|
|
i := interface{}(e)
|
|
|
|
reflect.ValueOf(i).MethodByName(m).Call([]reflect.Value{p, h})
|
|
|
|
_, body := request(method, path, e)
|
|
|
|
if body != method {
|
|
|
|
t.Errorf("expected body `%s`, got %s.", method, body)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func request(method, path string, e *Echo) (int, string) {
|
2016-04-24 19:21:23 +02:00
|
|
|
req := test.NewRequest(method, path, nil)
|
2016-02-05 00:40:08 +02:00
|
|
|
rec := test.NewResponseRecorder()
|
2016-04-24 19:21:23 +02:00
|
|
|
e.ServeHTTP(req, rec)
|
2016-02-05 00:40:08 +02:00
|
|
|
return rec.Status(), rec.Body.String()
|
2015-05-31 00:20:36 +02:00
|
|
|
}
|
2016-04-27 14:57:35 +02:00
|
|
|
|
|
|
|
func TestEchoBinder(t *testing.T) {
|
|
|
|
e := New()
|
|
|
|
b := &binder{}
|
|
|
|
e.SetBinder(b)
|
|
|
|
assert.Equal(t, b, e.Binder())
|
|
|
|
}
|