Skip to content
This repository has been archived by the owner on Mar 15, 2024. It is now read-only.

Commit

Permalink
- more tests
Browse files Browse the repository at this point in the history
- update go mod (go 1.11 released 🎉)
  • Loading branch information
im-kulikov committed Aug 25, 2018
1 parent cec246d commit db3a022
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 35 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/hpcloud/tail v1.0.0 // indirect
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // indirect
github.com/jtolds/gls v4.2.1+incompatible // indirect
github.com/labstack/echo v0.0.0-20180412143600-6d227dfea4d2
github.com/labstack/echo v3.2.2-0.20180412143600-6d227dfea4d2+incompatible
github.com/labstack/gommon v0.0.0-20180613044413-d6898124de91
github.com/magiconair/properties v1.8.0 // indirect
github.com/mattn/go-colorable v0.0.9 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a h1:eeaG9XMUvRBYX
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/labstack/echo v0.0.0-20180412143600-6d227dfea4d2 h1:4VNLf+IgSES2mEa6UEjNJRaHLudI75mB0aJDkRpHpv0=
github.com/labstack/echo v0.0.0-20180412143600-6d227dfea4d2/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo v3.2.2-0.20180412143600-6d227dfea4d2+incompatible h1:1ObmfX+G/szkR+Dw4vSheGMUL0ZuLPTsZ/8dZZ8bqCA=
github.com/labstack/echo v3.2.2-0.20180412143600-6d227dfea4d2+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.0.0-20180613044413-d6898124de91 h1:6R2WAx0PYNGtK2ZED9xKlTGEha51GsCFZijom+NMGEk=
github.com/labstack/gommon v0.0.0-20180613044413-d6898124de91/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
Expand Down
26 changes: 18 additions & 8 deletions web/binder.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,35 @@ func (b *binder) Bind(i interface{}, c echo.Context) (err error) {
}
}()

var qParams = make(map[string][]string, len(c.ParamNames()))
defer func() {
if err == nil {
err = b.validate(i, c)
}
}()

for _, name := range c.ParamNames() {
var (
paramNames = c.ParamNames()
qParams = make(map[string][]string, len(paramNames))
)

for _, name := range paramNames {
qParams[name] = []string{c.Param(name)}
}

if err = b.bindData(i, qParams, "param"); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
if len(paramNames) > 0 {
if err = b.bindData(i, qParams, "param"); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
}

if req.ContentLength == 0 {
if req.Method == "GET" || req.Method == "DELETE" {
if err = b.bindData(i, c.QueryParams(), "query"); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return b.validate(i, c)
return
} else if req.Method == "POST" {
return b.validate(i, c)
return
}
return echo.NewHTTPError(http.StatusBadRequest, "Request body can't be empty")
}
Expand All @@ -92,8 +103,7 @@ func (b *binder) Bind(i interface{}, c echo.Context) (err error) {
default:
return echo.ErrUnsupportedMediaType
}

return b.validate(i, c)
return
}

func dumpError(err error, logger echo.Logger, dump []byte) {
Expand Down
126 changes: 102 additions & 24 deletions web/binder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"mime/multipart"
"net/http/httptest"
"reflect"
"strconv"
"strings"
"testing"
"time"
Expand All @@ -17,36 +18,50 @@ import (
)

const (
userJSON = `{"id":1,"name":"Jon Snow", "Sliced": {"Items": [1, 2, 3, 4, 5]}}`
userXML = `<user><id>1</id><name>Jon Snow</name></user>`
userForm = `id=1&name=Jon Snow&array[]=a&array[]=b&array[]=c`
userParam = `/1/Jon%20Snow`
invalidContent = "invalid content"
invalidFormContent = `ID=a&name=Jon+Snow&Sliced[Items][]=1&Sliced[Items][]=2&Sliced[Items][]=3&Sliced[Items][]=4&Sliced[Items][]=5&Sliced[Items][]=a&Recursive[array][]=a&Recursive[array][]=b&Recursive[Sliced][Items][]=1&Recursive[Sliced][Items][]=2&Recursive[Sliced][Items][]=3&Recursive[Sliced][Items][]=4&Recursive[Sliced][Items][]=5&Recursive[Sliced][Items][]=a&user[id]=a&user[name]=Jon+Snow`
invalidJSONContent = `{"id":1,"name":"Jon Snow", "Sliced": {"Items": [1, 2, 3, 4, 5, "a"]}, "user": {"id": nil,"name":"Jon Snow"}}`
userJSON = `{"id":1,"name":"Jon Snow", "array": [], "Sliced": {"Items": [1, 2, 3, 4, 5]}}`
userXML = `<user><id>1</id><name>Jon Snow</name></user>`
userForm = `id=1&name=Jon Snow&array[]=a&array[]=b&array[]=c`
userParam = `/1/Jon%20Snow`
invalidUserParam = `/abc/Jon%20Snow`
invalidContent = "invalid content"
invalidFormContent = `ID=1&name=Jon+Snow&Sliced[Items][]=b&Sliced[Items][]=1&Sliced[Items][]=2&Sliced[Items][]=3&Sliced[Items][]=4&Sliced[Items][]=5&Sliced[Items][]=a&Recursive[array][]=a&Recursive[array][]=b&Recursive[Sliced][Items][]=1&Recursive[Sliced][Items][]=2&Recursive[Sliced][Items][]=3&Recursive[Sliced][Items][]=4&Recursive[Sliced][Items][]=5&Recursive[Sliced][Items][]=a&user[id]=a&user[name]=Jon+Snow&array[]=1&array=b`
invalidFormArrayContent = `array=0,2,3,4,5,6,a,b,C`
invalidFormRecursiveContent = `first=0,2,3,4,5,6&Second=1,a,b,c&result=1,a,b,c`
invalidJSONContent = `{"id":1,"name":"Jon Snow", "Sliced": {"Items": [1, 2, 3, 4, 5, "a"]}, "user": {"id": nil,"name":"Jon Snow"}}`
invalidFormSliced = `Items=1&Items=2&Items=3&Items=a`
)

type (
user struct {
ID int `json:"id" xml:"id" form:"id" query:"id" param:"id"`
Name string `json:"name" xml:"name" form:"name" query:"name" param:"name"`
Array []string `json:"array" xml:"array" form:"array" query:"array" param:"array"`
Array IntArray `json:"array" xml:"array" form:"array" query:"array" param:"array"`
Sliced
}

Sliced struct {
Items []int
}

ErrType struct {
Result ErrArray
}

WithError struct {
First IntArray `json:"first" xml:"first" form:"first" query:"first" param:"first"`
Second ErrType `json:"" xml:"" form:"" query:"" param:""`
}

Recursive struct {
Array []string `json:"array" xml:"array" form:"array" query:"array" param:"array"`
Array IntArray `json:"array" xml:"array" form:"array" query:"array" param:"array"`
Sliced
}

userValidate struct {
ID int `json:"id" xml:"id" form:"id" query:"id" param:"id" validate:"required"`
Name string `json:"name" xml:"name" form:"name" query:"name" param:"name" validate:"required"`
User *user `json:"user" xml:"user" form:"user" query:"user" param:"user"`
ID int `json:"id" xml:"id" form:"id" query:"id" param:"id" validate:"required"`
Name string `json:"name" xml:"name" form:"name" query:"name" param:"name" validate:"required"`
User *user `json:"user" xml:"user" form:"user" query:"user" param:"user"`
Array IntArray `json:"array" xml:"array" form:"array" query:"array" param:"array" validate:"required"`
Sliced
Recursive
}
Expand Down Expand Up @@ -88,6 +103,8 @@ type (
}
Timestamp time.Time
StringArray []string
IntArray []int
ErrArray struct{}
Struct struct {
Foo string
}
Expand All @@ -104,6 +121,24 @@ func (a *StringArray) UnmarshalParam(src string) error {
return nil
}

func (a *IntArray) UnmarshalParam(src string) error {
array := strings.Split(src, ",")
result := make(IntArray, 0, len(array))
for _, item := range array {
v, err := strconv.Atoi(item)
if err != nil {
return err
}
result = append(result, v)
}
*a = result
return nil
}

func (a *ErrArray) UnmarshalParam(src string) error {
return errors.New("test")
}

func (s *Struct) UnmarshalParam(src string) error {
*s = Struct{
Foo: src,
Expand Down Expand Up @@ -231,6 +266,36 @@ func TestBindRecursive(t *testing.T) {
err := c.Bind(u)
assert.Error(t, err)
})

t.Run("fail form array", func(t *testing.T) {
req := httptest.NewRequest(echo.POST, "/", strings.NewReader(invalidFormArrayContent))
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationForm)
u := new(Recursive)
err := c.Bind(u)
assert.Error(t, err)
})

t.Run("fail form recursive", func(t *testing.T) {
req := httptest.NewRequest(echo.POST, "/", strings.NewReader(invalidFormRecursiveContent))
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationForm)
u := new(WithError)
err := c.Bind(u)
assert.Error(t, err)
})

t.Run("fail form sliced", func(t *testing.T) {
req := httptest.NewRequest(echo.POST, "/", strings.NewReader(invalidFormSliced))
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationForm)
u := new(Sliced)
err := c.Bind(u)
assert.Error(t, err)
})
}

func TestBindJSON(t *testing.T) {
Expand Down Expand Up @@ -282,20 +347,33 @@ func TestBindQueryParams(t *testing.T) {

func TestBindParams(t *testing.T) {
e := testNew()
req := httptest.NewRequest(echo.GET, userParam, nil)
rec := httptest.NewRecorder()
testHandler := func(ctx echo.Context) error {
u := new(user)
err := ctx.Bind(u)
if assert.NoError(t, err) {
assert.Equal(t, 1, u.ID)
assert.Equal(t, "Jon Snow", u.Name)
t.Run("should be ok", func(t *testing.T) {
req := httptest.NewRequest(echo.GET, userParam, nil)
testHandler := func(ctx echo.Context) error {
u := new(user)
err := ctx.Bind(u)
if assert.NoError(t, err) {
assert.Equal(t, 1, u.ID)
assert.Equal(t, "Jon Snow", u.Name)
}

return nil
}

return nil
}
e.GET("/:id/:name", testHandler)
e.ServeHTTP(rec, req)
e.GET("/:id/:name", testHandler)
e.ServeHTTP(rec, req)
})
t.Run("should fail", func(t *testing.T) {
req := httptest.NewRequest(echo.GET, invalidUserParam, nil)
testHandler := func(ctx echo.Context) error {
u := new(user)
err := ctx.Bind(u)
assert.Error(t, err)
return nil
}
e.GET("/:id/:name", testHandler)
e.ServeHTTP(rec, req)
})
}

func TestBindQueryParamsCaseSensitivePrioritized(t *testing.T) {
Expand Down

0 comments on commit db3a022

Please sign in to comment.