binding_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
  2. // Use of this source code is governed by a MIT style
  3. // license that can be found in the LICENSE file.
  4. package binding
  5. import (
  6. "bytes"
  7. "mime/multipart"
  8. "net/http"
  9. "testing"
  10. "github.com/gin-gonic/gin/binding/example"
  11. "github.com/golang/protobuf/proto"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/ugorji/go/codec"
  14. )
  15. type FooStruct struct {
  16. Foo string `msgpack:"foo" json:"foo" form:"foo" xml:"foo" binding:"required"`
  17. }
  18. type FooBarStruct struct {
  19. FooStruct
  20. Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"`
  21. }
  22. func TestBindingDefault(t *testing.T) {
  23. assert.Equal(t, Default("GET", ""), Form)
  24. assert.Equal(t, Default("GET", MIMEJSON), Form)
  25. assert.Equal(t, Default("POST", MIMEJSON), JSON)
  26. assert.Equal(t, Default("PUT", MIMEJSON), JSON)
  27. assert.Equal(t, Default("POST", MIMEXML), XML)
  28. assert.Equal(t, Default("PUT", MIMEXML2), XML)
  29. assert.Equal(t, Default("POST", MIMEPOSTForm), Form)
  30. assert.Equal(t, Default("PUT", MIMEPOSTForm), Form)
  31. assert.Equal(t, Default("POST", MIMEMultipartPOSTForm), Form)
  32. assert.Equal(t, Default("PUT", MIMEMultipartPOSTForm), Form)
  33. assert.Equal(t, Default("POST", MIMEPROTOBUF), ProtoBuf)
  34. assert.Equal(t, Default("PUT", MIMEPROTOBUF), ProtoBuf)
  35. assert.Equal(t, Default("POST", MIMEMSGPACK), MsgPack)
  36. assert.Equal(t, Default("PUT", MIMEMSGPACK2), MsgPack)
  37. }
  38. func TestBindingJSON(t *testing.T) {
  39. testBodyBinding(t,
  40. JSON, "json",
  41. "/", "/",
  42. `{"foo": "bar"}`, `{"bar": "foo"}`)
  43. }
  44. func TestBindingForm(t *testing.T) {
  45. testFormBinding(t, "POST",
  46. "/", "/",
  47. "foo=bar&bar=foo", "bar2=foo")
  48. }
  49. func TestBindingForm2(t *testing.T) {
  50. testFormBinding(t, "GET",
  51. "/?foo=bar&bar=foo", "/?bar2=foo",
  52. "", "")
  53. }
  54. func TestBindingXML(t *testing.T) {
  55. testBodyBinding(t,
  56. XML, "xml",
  57. "/", "/",
  58. "<map><foo>bar</foo></map>", "<map><bar>foo</bar></map>")
  59. }
  60. func createFormPostRequest() *http.Request {
  61. req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
  62. req.Header.Set("Content-Type", MIMEPOSTForm)
  63. return req
  64. }
  65. func createFormMultipartRequest() *http.Request {
  66. boundary := "--testboundary"
  67. body := new(bytes.Buffer)
  68. mw := multipart.NewWriter(body)
  69. defer mw.Close()
  70. mw.SetBoundary(boundary)
  71. mw.WriteField("foo", "bar")
  72. mw.WriteField("bar", "foo")
  73. req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
  74. req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
  75. return req
  76. }
  77. func TestBindingFormPost(t *testing.T) {
  78. req := createFormPostRequest()
  79. var obj FooBarStruct
  80. FormPost.Bind(req, &obj)
  81. assert.Equal(t, obj.Foo, "bar")
  82. assert.Equal(t, obj.Bar, "foo")
  83. }
  84. func TestBindingFormMultipart(t *testing.T) {
  85. req := createFormMultipartRequest()
  86. var obj FooBarStruct
  87. FormMultipart.Bind(req, &obj)
  88. assert.Equal(t, obj.Foo, "bar")
  89. assert.Equal(t, obj.Bar, "foo")
  90. }
  91. func TestBindingProtoBuf(t *testing.T) {
  92. test := &example.Test{
  93. Label: proto.String("yes"),
  94. }
  95. data, _ := proto.Marshal(test)
  96. testProtoBodyBinding(t,
  97. ProtoBuf, "protobuf",
  98. "/", "/",
  99. string(data), string(data[1:]))
  100. }
  101. func TestBindingMsgPack(t *testing.T) {
  102. test := FooStruct{
  103. Foo: "bar",
  104. }
  105. h := new(codec.MsgpackHandle)
  106. assert.NotNil(t, h)
  107. buf := bytes.NewBuffer([]byte{})
  108. assert.NotNil(t, buf)
  109. err := codec.NewEncoder(buf, h).Encode(test)
  110. assert.NoError(t, err)
  111. data := buf.Bytes()
  112. testMsgPackBodyBinding(t,
  113. MsgPack, "msgpack",
  114. "/", "/",
  115. string(data), string(data[1:]))
  116. }
  117. func TestValidationFails(t *testing.T) {
  118. var obj FooStruct
  119. req := requestWithBody("POST", "/", `{"bar": "foo"}`)
  120. err := JSON.Bind(req, &obj)
  121. assert.Error(t, err)
  122. }
  123. func TestValidationDisabled(t *testing.T) {
  124. backup := Validator
  125. Validator = nil
  126. defer func() { Validator = backup }()
  127. var obj FooStruct
  128. req := requestWithBody("POST", "/", `{"bar": "foo"}`)
  129. err := JSON.Bind(req, &obj)
  130. assert.NoError(t, err)
  131. }
  132. func TestExistsSucceeds(t *testing.T) {
  133. type HogeStruct struct {
  134. Hoge *int `json:"hoge" binding:"exists"`
  135. }
  136. var obj HogeStruct
  137. req := requestWithBody("POST", "/", `{"hoge": 0}`)
  138. err := JSON.Bind(req, &obj)
  139. assert.NoError(t, err)
  140. }
  141. func TestExistsFails(t *testing.T) {
  142. type HogeStruct struct {
  143. Hoge *int `json:"foo" binding:"exists"`
  144. }
  145. var obj HogeStruct
  146. req := requestWithBody("POST", "/", `{"boen": 0}`)
  147. err := JSON.Bind(req, &obj)
  148. assert.Error(t, err)
  149. }
  150. func testFormBinding(t *testing.T, method, path, badPath, body, badBody string) {
  151. b := Form
  152. assert.Equal(t, b.Name(), "form")
  153. obj := FooBarStruct{}
  154. req := requestWithBody(method, path, body)
  155. if method == "POST" {
  156. req.Header.Add("Content-Type", MIMEPOSTForm)
  157. }
  158. err := b.Bind(req, &obj)
  159. assert.NoError(t, err)
  160. assert.Equal(t, obj.Foo, "bar")
  161. assert.Equal(t, obj.Bar, "foo")
  162. obj = FooBarStruct{}
  163. req = requestWithBody(method, badPath, badBody)
  164. err = JSON.Bind(req, &obj)
  165. assert.Error(t, err)
  166. }
  167. func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  168. assert.Equal(t, b.Name(), name)
  169. obj := FooStruct{}
  170. req := requestWithBody("POST", path, body)
  171. err := b.Bind(req, &obj)
  172. assert.NoError(t, err)
  173. assert.Equal(t, obj.Foo, "bar")
  174. obj = FooStruct{}
  175. req = requestWithBody("POST", badPath, badBody)
  176. err = JSON.Bind(req, &obj)
  177. assert.Error(t, err)
  178. }
  179. func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  180. assert.Equal(t, b.Name(), name)
  181. obj := example.Test{}
  182. req := requestWithBody("POST", path, body)
  183. req.Header.Add("Content-Type", MIMEPROTOBUF)
  184. err := b.Bind(req, &obj)
  185. assert.NoError(t, err)
  186. assert.Equal(t, *obj.Label, "yes")
  187. obj = example.Test{}
  188. req = requestWithBody("POST", badPath, badBody)
  189. req.Header.Add("Content-Type", MIMEPROTOBUF)
  190. err = ProtoBuf.Bind(req, &obj)
  191. assert.Error(t, err)
  192. }
  193. func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  194. assert.Equal(t, b.Name(), name)
  195. obj := FooStruct{}
  196. req := requestWithBody("POST", path, body)
  197. req.Header.Add("Content-Type", MIMEMSGPACK)
  198. err := b.Bind(req, &obj)
  199. assert.NoError(t, err)
  200. assert.Equal(t, obj.Foo, "bar")
  201. obj = FooStruct{}
  202. req = requestWithBody("POST", badPath, badBody)
  203. req.Header.Add("Content-Type", MIMEMSGPACK)
  204. err = MsgPack.Bind(req, &obj)
  205. assert.Error(t, err)
  206. }
  207. func requestWithBody(method, path, body string) (req *http.Request) {
  208. req, _ = http.NewRequest(method, path, bytes.NewBufferString(body))
  209. return
  210. }