// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. package binding import ( "bytes" "github.com/gin-gonic/gin/binding/example" "github.com/golang/protobuf/proto" "net/http" "testing" "github.com/stretchr/testify/assert" ) type FooStruct struct { Foo string `json:"foo" form:"foo" xml:"foo" binding:"required"` } type FooBarStruct struct { FooStruct Bar string `json:"bar" form:"bar" xml:"bar" binding:"required"` } func TestBindingDefault(t *testing.T) { assert.Equal(t, Default("GET", ""), Form) assert.Equal(t, Default("GET", MIMEJSON), Form) assert.Equal(t, Default("POST", MIMEJSON), JSON) assert.Equal(t, Default("PUT", MIMEJSON), JSON) assert.Equal(t, Default("POST", MIMEXML), XML) assert.Equal(t, Default("PUT", MIMEXML2), XML) assert.Equal(t, Default("POST", MIMEPOSTForm), Form) assert.Equal(t, Default("PUT", MIMEPOSTForm), Form) assert.Equal(t, Default("POST", MIMEMultipartPOSTForm), Form) assert.Equal(t, Default("PUT", MIMEMultipartPOSTForm), Form) assert.Equal(t, Default("POST", MIMEPROTOBUF), ProtoBuf) assert.Equal(t, Default("PUT", MIMEPROTOBUF), ProtoBuf) } func TestBindingJSON(t *testing.T) { testBodyBinding(t, JSON, "json", "/", "/", `{"foo": "bar"}`, `{"bar": "foo"}`) } func TestBindingForm(t *testing.T) { testFormBinding(t, "POST", "/", "/", "foo=bar&bar=foo", "bar2=foo") } func TestBindingForm2(t *testing.T) { testFormBinding(t, "GET", "/?foo=bar&bar=foo", "/?bar2=foo", "", "") } func TestBindingXML(t *testing.T) { testBodyBinding(t, XML, "xml", "/", "/", "bar", "foo") } func TestBindingProtoBuf(t *testing.T) { test := &example.Test{ Label: proto.String("yes"), } data, _ := proto.Marshal(test) testProtoBodyBinding(t, ProtoBuf, "protobuf", "/", "/", string(data), string(data[1:])) } func TestValidationFails(t *testing.T) { var obj FooStruct req := requestWithBody("POST", "/", `{"bar": "foo"}`) err := JSON.Bind(req, &obj) assert.Error(t, err) } func TestValidationDisabled(t *testing.T) { backup := Validator Validator = nil defer func() { Validator = backup }() var obj FooStruct req := requestWithBody("POST", "/", `{"bar": "foo"}`) err := JSON.Bind(req, &obj) assert.NoError(t, err) } func testFormBinding(t *testing.T, method, path, badPath, body, badBody string) { b := Form assert.Equal(t, b.Name(), "form") obj := FooBarStruct{} req := requestWithBody(method, path, body) if method == "POST" { req.Header.Add("Content-Type", MIMEPOSTForm) } err := b.Bind(req, &obj) assert.NoError(t, err) assert.Equal(t, obj.Foo, "bar") assert.Equal(t, obj.Bar, "foo") obj = FooBarStruct{} req = requestWithBody(method, badPath, badBody) err = JSON.Bind(req, &obj) assert.Error(t, err) } func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) { assert.Equal(t, b.Name(), name) obj := FooStruct{} req := requestWithBody("POST", path, body) err := b.Bind(req, &obj) assert.NoError(t, err) assert.Equal(t, obj.Foo, "bar") obj = FooStruct{} req = requestWithBody("POST", badPath, badBody) err = JSON.Bind(req, &obj) assert.Error(t, err) } func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) { assert.Equal(t, b.Name(), name) obj := example.Test{} req := requestWithBody("POST", path, body) req.Header.Add("Content-Type", MIMEPROTOBUF) err := b.Bind(req, &obj) assert.NoError(t, err) assert.Equal(t, *obj.Label, "yes") obj = example.Test{} req = requestWithBody("POST", badPath, badBody) req.Header.Add("Content-Type", MIMEPROTOBUF) err = ProtoBuf.Bind(req, &obj) assert.Error(t, err) } func requestWithBody(method, path, body string) (req *http.Request) { req, _ = http.NewRequest(method, path, bytes.NewBufferString(body)) return }