binding_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. )
  14. type FooStruct struct {
  15. Foo string `json:"foo" form:"foo" xml:"foo" binding:"required"`
  16. }
  17. type FooBarStruct struct {
  18. FooStruct
  19. Bar string `json:"bar" form:"bar" xml:"bar" binding:"required"`
  20. }
  21. func TestBindingDefault(t *testing.T) {
  22. assert.Equal(t, Default("GET", ""), Form)
  23. assert.Equal(t, Default("GET", MIMEJSON), Form)
  24. assert.Equal(t, Default("POST", MIMEJSON), JSON)
  25. assert.Equal(t, Default("PUT", MIMEJSON), JSON)
  26. assert.Equal(t, Default("POST", MIMEXML), XML)
  27. assert.Equal(t, Default("PUT", MIMEXML2), XML)
  28. assert.Equal(t, Default("POST", MIMEPOSTForm), Form)
  29. assert.Equal(t, Default("PUT", MIMEPOSTForm), Form)
  30. assert.Equal(t, Default("POST", MIMEMultipartPOSTForm), Form)
  31. assert.Equal(t, Default("PUT", MIMEMultipartPOSTForm), Form)
  32. assert.Equal(t, Default("POST", MIMEPROTOBUF), ProtoBuf)
  33. assert.Equal(t, Default("PUT", MIMEPROTOBUF), ProtoBuf)
  34. }
  35. func TestBindingJSON(t *testing.T) {
  36. testBodyBinding(t,
  37. JSON, "json",
  38. "/", "/",
  39. `{"foo": "bar"}`, `{"bar": "foo"}`)
  40. }
  41. func TestBindingForm(t *testing.T) {
  42. testFormBinding(t, "POST",
  43. "/", "/",
  44. "foo=bar&bar=foo", "bar2=foo")
  45. }
  46. func TestBindingForm2(t *testing.T) {
  47. testFormBinding(t, "GET",
  48. "/?foo=bar&bar=foo", "/?bar2=foo",
  49. "", "")
  50. }
  51. func TestBindingXML(t *testing.T) {
  52. testBodyBinding(t,
  53. XML, "xml",
  54. "/", "/",
  55. "<map><foo>bar</foo></map>", "<map><bar>foo</bar></map>")
  56. }
  57. func createFormPostRequest() *http.Request {
  58. req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
  59. req.Header.Set("Content-Type", MIMEPOSTForm)
  60. return req
  61. }
  62. func createFormMultipartRequest() *http.Request {
  63. boundary := "--testboundary"
  64. body := new(bytes.Buffer)
  65. mw := multipart.NewWriter(body)
  66. defer mw.Close()
  67. mw.SetBoundary(boundary)
  68. mw.WriteField("foo", "bar")
  69. mw.WriteField("bar", "foo")
  70. req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
  71. req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
  72. return req
  73. }
  74. func TestBindingFormPost(t *testing.T) {
  75. req := createFormPostRequest()
  76. var obj FooBarStruct
  77. FormPost.Bind(req, &obj)
  78. assert.Equal(t, obj.Foo, "bar")
  79. assert.Equal(t, obj.Bar, "foo")
  80. }
  81. func TestBindingFormMultipart(t *testing.T) {
  82. req := createFormMultipartRequest()
  83. var obj FooBarStruct
  84. FormMultipart.Bind(req, &obj)
  85. assert.Equal(t, obj.Foo, "bar")
  86. assert.Equal(t, obj.Bar, "foo")
  87. }
  88. func TestBindingProtoBuf(t *testing.T) {
  89. test := &example.Test{
  90. Label: proto.String("yes"),
  91. }
  92. data, _ := proto.Marshal(test)
  93. testProtoBodyBinding(t,
  94. ProtoBuf, "protobuf",
  95. "/", "/",
  96. string(data), string(data[1:]))
  97. }
  98. func TestValidationFails(t *testing.T) {
  99. var obj FooStruct
  100. req := requestWithBody("POST", "/", `{"bar": "foo"}`)
  101. err := JSON.Bind(req, &obj)
  102. assert.Error(t, err)
  103. }
  104. func TestValidationDisabled(t *testing.T) {
  105. backup := Validator
  106. Validator = nil
  107. defer func() { Validator = backup }()
  108. var obj FooStruct
  109. req := requestWithBody("POST", "/", `{"bar": "foo"}`)
  110. err := JSON.Bind(req, &obj)
  111. assert.NoError(t, err)
  112. }
  113. func TestExistsSucceeds(t *testing.T) {
  114. type HogeStruct struct {
  115. Hoge *int `json:"hoge" binding:"exists"`
  116. }
  117. var obj HogeStruct
  118. req := requestWithBody("POST", "/", `{"hoge": 0}`)
  119. err := JSON.Bind(req, &obj)
  120. assert.NoError(t, err)
  121. }
  122. func TestExistsFails(t *testing.T) {
  123. type HogeStruct struct {
  124. Hoge *int `json:"foo" binding:"exists"`
  125. }
  126. var obj HogeStruct
  127. req := requestWithBody("POST", "/", `{"boen": 0}`)
  128. err := JSON.Bind(req, &obj)
  129. assert.Error(t, err)
  130. }
  131. func testFormBinding(t *testing.T, method, path, badPath, body, badBody string) {
  132. b := Form
  133. assert.Equal(t, b.Name(), "form")
  134. obj := FooBarStruct{}
  135. req := requestWithBody(method, path, body)
  136. if method == "POST" {
  137. req.Header.Add("Content-Type", MIMEPOSTForm)
  138. }
  139. err := b.Bind(req, &obj)
  140. assert.NoError(t, err)
  141. assert.Equal(t, obj.Foo, "bar")
  142. assert.Equal(t, obj.Bar, "foo")
  143. obj = FooBarStruct{}
  144. req = requestWithBody(method, badPath, badBody)
  145. err = JSON.Bind(req, &obj)
  146. assert.Error(t, err)
  147. }
  148. func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  149. assert.Equal(t, b.Name(), name)
  150. obj := FooStruct{}
  151. req := requestWithBody("POST", path, body)
  152. err := b.Bind(req, &obj)
  153. assert.NoError(t, err)
  154. assert.Equal(t, obj.Foo, "bar")
  155. obj = FooStruct{}
  156. req = requestWithBody("POST", badPath, badBody)
  157. err = JSON.Bind(req, &obj)
  158. assert.Error(t, err)
  159. }
  160. func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  161. assert.Equal(t, b.Name(), name)
  162. obj := example.Test{}
  163. req := requestWithBody("POST", path, body)
  164. req.Header.Add("Content-Type", MIMEPROTOBUF)
  165. err := b.Bind(req, &obj)
  166. assert.NoError(t, err)
  167. assert.Equal(t, *obj.Label, "yes")
  168. obj = example.Test{}
  169. req = requestWithBody("POST", badPath, badBody)
  170. req.Header.Add("Content-Type", MIMEPROTOBUF)
  171. err = ProtoBuf.Bind(req, &obj)
  172. assert.Error(t, err)
  173. }
  174. func requestWithBody(method, path, body string) (req *http.Request) {
  175. req, _ = http.NewRequest(method, path, bytes.NewBufferString(body))
  176. return
  177. }