binding_test.go 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  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. "encoding/json"
  8. "errors"
  9. "io/ioutil"
  10. "mime/multipart"
  11. "net/http"
  12. "testing"
  13. "time"
  14. "github.com/gin-gonic/gin/binding/example"
  15. "github.com/golang/protobuf/proto"
  16. "github.com/stretchr/testify/assert"
  17. "github.com/ugorji/go/codec"
  18. )
  19. type FooStruct struct {
  20. Foo string `msgpack:"foo" json:"foo" form:"foo" xml:"foo" binding:"required"`
  21. }
  22. type FooBarStruct struct {
  23. FooStruct
  24. Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"`
  25. }
  26. type FooStructUseNumber struct {
  27. Foo interface{} `json:"foo" binding:"required"`
  28. }
  29. type FooBarStructForTimeType struct {
  30. TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"`
  31. TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"`
  32. }
  33. type FooStructForTimeTypeNotFormat struct {
  34. TimeFoo time.Time `form:"time_foo"`
  35. }
  36. type FooStructForTimeTypeFailFormat struct {
  37. TimeFoo time.Time `form:"time_foo" time_format:"2017-11-15"`
  38. }
  39. type FooStructForTimeTypeFailLocation struct {
  40. TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_location:"/asia/chongqing"`
  41. }
  42. type FooStructForMapType struct {
  43. // Unknown type: not support map
  44. MapFoo map[string]interface{} `form:"map_foo"`
  45. }
  46. type InvalidNameType struct {
  47. TestName string `invalid_name:"test_name"`
  48. }
  49. type InvalidNameMapType struct {
  50. TestName struct {
  51. MapFoo map[string]interface{} `form:"map_foo"`
  52. }
  53. }
  54. type FooStructForSliceType struct {
  55. SliceFoo []int `form:"slice_foo"`
  56. }
  57. type FooStructForSliceMapType struct {
  58. // Unknown type: not support map
  59. SliceMapFoo []map[string]interface{} `form:"slice_map_foo"`
  60. }
  61. type FooBarStructForIntType struct {
  62. IntFoo int `form:"int_foo"`
  63. IntBar int `form:"int_bar" binding:"required"`
  64. }
  65. type FooBarStructForInt8Type struct {
  66. Int8Foo int8 `form:"int8_foo"`
  67. Int8Bar int8 `form:"int8_bar" binding:"required"`
  68. }
  69. type FooBarStructForInt16Type struct {
  70. Int16Foo int16 `form:"int16_foo"`
  71. Int16Bar int16 `form:"int16_bar" binding:"required"`
  72. }
  73. type FooBarStructForInt32Type struct {
  74. Int32Foo int32 `form:"int32_foo"`
  75. Int32Bar int32 `form:"int32_bar" binding:"required"`
  76. }
  77. type FooBarStructForInt64Type struct {
  78. Int64Foo int64 `form:"int64_foo"`
  79. Int64Bar int64 `form:"int64_bar" binding:"required"`
  80. }
  81. type FooBarStructForUintType struct {
  82. UintFoo uint `form:"uint_foo"`
  83. UintBar uint `form:"uint_bar" binding:"required"`
  84. }
  85. type FooBarStructForUint8Type struct {
  86. Uint8Foo uint8 `form:"uint8_foo"`
  87. Uint8Bar uint8 `form:"uint8_bar" binding:"required"`
  88. }
  89. type FooBarStructForUint16Type struct {
  90. Uint16Foo uint16 `form:"uint16_foo"`
  91. Uint16Bar uint16 `form:"uint16_bar" binding:"required"`
  92. }
  93. type FooBarStructForUint32Type struct {
  94. Uint32Foo uint32 `form:"uint32_foo"`
  95. Uint32Bar uint32 `form:"uint32_bar" binding:"required"`
  96. }
  97. type FooBarStructForUint64Type struct {
  98. Uint64Foo uint64 `form:"uint64_foo"`
  99. Uint64Bar uint64 `form:"uint64_bar" binding:"required"`
  100. }
  101. type FooBarStructForBoolType struct {
  102. BoolFoo bool `form:"bool_foo"`
  103. BoolBar bool `form:"bool_bar" binding:"required"`
  104. }
  105. type FooBarStructForFloat32Type struct {
  106. Float32Foo float32 `form:"float32_foo"`
  107. Float32Bar float32 `form:"float32_bar" binding:"required"`
  108. }
  109. type FooBarStructForFloat64Type struct {
  110. Float64Foo float64 `form:"float64_foo"`
  111. Float64Bar float64 `form:"float64_bar" binding:"required"`
  112. }
  113. func TestBindingDefault(t *testing.T) {
  114. assert.Equal(t, Form, Default("GET", ""))
  115. assert.Equal(t, Form, Default("GET", MIMEJSON))
  116. assert.Equal(t, JSON, Default("POST", MIMEJSON))
  117. assert.Equal(t, JSON, Default("PUT", MIMEJSON))
  118. assert.Equal(t, XML, Default("POST", MIMEXML))
  119. assert.Equal(t, XML, Default("PUT", MIMEXML2))
  120. assert.Equal(t, Form, Default("POST", MIMEPOSTForm))
  121. assert.Equal(t, Form, Default("PUT", MIMEPOSTForm))
  122. assert.Equal(t, Form, Default("POST", MIMEMultipartPOSTForm))
  123. assert.Equal(t, Form, Default("PUT", MIMEMultipartPOSTForm))
  124. assert.Equal(t, ProtoBuf, Default("POST", MIMEPROTOBUF))
  125. assert.Equal(t, ProtoBuf, Default("PUT", MIMEPROTOBUF))
  126. assert.Equal(t, MsgPack, Default("POST", MIMEMSGPACK))
  127. assert.Equal(t, MsgPack, Default("PUT", MIMEMSGPACK2))
  128. }
  129. func TestBindingJSON(t *testing.T) {
  130. testBodyBinding(t,
  131. JSON, "json",
  132. "/", "/",
  133. `{"foo": "bar"}`, `{"bar": "foo"}`)
  134. }
  135. func TestBindingJSONUseNumber(t *testing.T) {
  136. testBodyBindingUseNumber(t,
  137. JSON, "json",
  138. "/", "/",
  139. `{"foo": 123}`, `{"bar": "foo"}`)
  140. }
  141. func TestBindingJSONUseNumber2(t *testing.T) {
  142. testBodyBindingUseNumber2(t,
  143. JSON, "json",
  144. "/", "/",
  145. `{"foo": 123}`, `{"bar": "foo"}`)
  146. }
  147. func TestBindingForm(t *testing.T) {
  148. testFormBinding(t, "POST",
  149. "/", "/",
  150. "foo=bar&bar=foo", "bar2=foo")
  151. }
  152. func TestBindingForm2(t *testing.T) {
  153. testFormBinding(t, "GET",
  154. "/?foo=bar&bar=foo", "/?bar2=foo",
  155. "", "")
  156. }
  157. func TestBindingFormForTime(t *testing.T) {
  158. testFormBindingForTime(t, "POST",
  159. "/", "/",
  160. "time_foo=2017-11-15&time_bar=", "bar2=foo")
  161. testFormBindingForTimeNotFormat(t, "POST",
  162. "/", "/",
  163. "time_foo=2017-11-15", "bar2=foo")
  164. testFormBindingForTimeFailFormat(t, "POST",
  165. "/", "/",
  166. "time_foo=2017-11-15", "bar2=foo")
  167. testFormBindingForTimeFailLocation(t, "POST",
  168. "/", "/",
  169. "time_foo=2017-11-15", "bar2=foo")
  170. }
  171. func TestBindingFormForTime2(t *testing.T) {
  172. testFormBindingForTime(t, "GET",
  173. "/?time_foo=2017-11-15&time_bar=", "/?bar2=foo",
  174. "", "")
  175. testFormBindingForTimeNotFormat(t, "GET",
  176. "/?time_foo=2017-11-15", "/?bar2=foo",
  177. "", "")
  178. testFormBindingForTimeFailFormat(t, "GET",
  179. "/?time_foo=2017-11-15", "/?bar2=foo",
  180. "", "")
  181. testFormBindingForTimeFailLocation(t, "GET",
  182. "/?time_foo=2017-11-15", "/?bar2=foo",
  183. "", "")
  184. }
  185. func TestBindingFormInvalidName(t *testing.T) {
  186. testFormBindingInvalidName(t, "POST",
  187. "/", "/",
  188. "test_name=bar", "bar2=foo")
  189. }
  190. func TestBindingFormInvalidName2(t *testing.T) {
  191. testFormBindingInvalidName2(t, "POST",
  192. "/", "/",
  193. "map_foo=bar", "bar2=foo")
  194. }
  195. func TestBindingFormForType(t *testing.T) {
  196. testFormBindingForType(t, "POST",
  197. "/", "/",
  198. "map_foo=", "bar2=1", "Map")
  199. testFormBindingForType(t, "POST",
  200. "/", "/",
  201. "slice_foo=1&slice_foo=2", "bar2=1&bar2=2", "Slice")
  202. testFormBindingForType(t, "GET",
  203. "/?slice_foo=1&slice_foo=2", "/?bar2=1&bar2=2",
  204. "", "", "Slice")
  205. testFormBindingForType(t, "POST",
  206. "/", "/",
  207. "slice_map_foo=1&slice_map_foo=2", "bar2=1&bar2=2", "SliceMap")
  208. testFormBindingForType(t, "GET",
  209. "/?slice_map_foo=1&slice_map_foo=2", "/?bar2=1&bar2=2",
  210. "", "", "SliceMap")
  211. testFormBindingForType(t, "POST",
  212. "/", "/",
  213. "int_foo=&int_bar=-12", "bar2=-123", "Int")
  214. testFormBindingForType(t, "GET",
  215. "/?int_foo=&int_bar=-12", "/?bar2=-123",
  216. "", "", "Int")
  217. testFormBindingForType(t, "POST",
  218. "/", "/",
  219. "int8_foo=&int8_bar=-12", "bar2=-123", "Int8")
  220. testFormBindingForType(t, "GET",
  221. "/?int8_foo=&int8_bar=-12", "/?bar2=-123",
  222. "", "", "Int8")
  223. testFormBindingForType(t, "POST",
  224. "/", "/",
  225. "int16_foo=&int16_bar=-12", "bar2=-123", "Int16")
  226. testFormBindingForType(t, "GET",
  227. "/?int16_foo=&int16_bar=-12", "/?bar2=-123",
  228. "", "", "Int16")
  229. testFormBindingForType(t, "POST",
  230. "/", "/",
  231. "int32_foo=&int32_bar=-12", "bar2=-123", "Int32")
  232. testFormBindingForType(t, "GET",
  233. "/?int32_foo=&int32_bar=-12", "/?bar2=-123",
  234. "", "", "Int32")
  235. testFormBindingForType(t, "POST",
  236. "/", "/",
  237. "int64_foo=&int64_bar=-12", "bar2=-123", "Int64")
  238. testFormBindingForType(t, "GET",
  239. "/?int64_foo=&int64_bar=-12", "/?bar2=-123",
  240. "", "", "Int64")
  241. testFormBindingForType(t, "POST",
  242. "/", "/",
  243. "uint_foo=&uint_bar=12", "bar2=123", "Uint")
  244. testFormBindingForType(t, "GET",
  245. "/?uint_foo=&uint_bar=12", "/?bar2=123",
  246. "", "", "Uint")
  247. testFormBindingForType(t, "POST",
  248. "/", "/",
  249. "uint8_foo=&uint8_bar=12", "bar2=123", "Uint8")
  250. testFormBindingForType(t, "GET",
  251. "/?uint8_foo=&uint8_bar=12", "/?bar2=123",
  252. "", "", "Uint8")
  253. testFormBindingForType(t, "POST",
  254. "/", "/",
  255. "uint16_foo=&uint16_bar=12", "bar2=123", "Uint16")
  256. testFormBindingForType(t, "GET",
  257. "/?uint16_foo=&uint16_bar=12", "/?bar2=123",
  258. "", "", "Uint16")
  259. testFormBindingForType(t, "POST",
  260. "/", "/",
  261. "uint32_foo=&uint32_bar=12", "bar2=123", "Uint32")
  262. testFormBindingForType(t, "GET",
  263. "/?uint32_foo=&uint32_bar=12", "/?bar2=123",
  264. "", "", "Uint32")
  265. testFormBindingForType(t, "POST",
  266. "/", "/",
  267. "uint64_foo=&uint64_bar=12", "bar2=123", "Uint64")
  268. testFormBindingForType(t, "GET",
  269. "/?uint64_foo=&uint64_bar=12", "/?bar2=123",
  270. "", "", "Uint64")
  271. testFormBindingForType(t, "POST",
  272. "/", "/",
  273. "bool_foo=&bool_bar=true", "bar2=true", "Bool")
  274. testFormBindingForType(t, "GET",
  275. "/?bool_foo=&bool_bar=true", "/?bar2=true",
  276. "", "", "Bool")
  277. testFormBindingForType(t, "POST",
  278. "/", "/",
  279. "float32_foo=&float32_bar=-12.34", "bar2=12.3", "Float32")
  280. testFormBindingForType(t, "GET",
  281. "/?float32_foo=&float32_bar=-12.34", "/?bar2=12.3",
  282. "", "", "Float32")
  283. testFormBindingForType(t, "POST",
  284. "/", "/",
  285. "float64_foo=&float64_bar=-12.34", "bar2=12.3", "Float64")
  286. testFormBindingForType(t, "GET",
  287. "/?float64_foo=&float64_bar=-12.34", "/?bar2=12.3",
  288. "", "", "Float64")
  289. }
  290. func TestBindingQuery(t *testing.T) {
  291. testQueryBinding(t, "POST",
  292. "/?foo=bar&bar=foo", "/",
  293. "foo=unused", "bar2=foo")
  294. }
  295. func TestBindingQuery2(t *testing.T) {
  296. testQueryBinding(t, "GET",
  297. "/?foo=bar&bar=foo", "/?bar2=foo",
  298. "foo=unused", "")
  299. }
  300. func TestBindingQueryFail(t *testing.T) {
  301. testQueryBindingFail(t, "POST",
  302. "/?map_foo=", "/",
  303. "map_foo=unused", "bar2=foo")
  304. }
  305. func TestBindingQueryFail2(t *testing.T) {
  306. testQueryBindingFail(t, "GET",
  307. "/?map_foo=", "/?bar2=foo",
  308. "map_foo=unused", "")
  309. }
  310. func TestBindingXML(t *testing.T) {
  311. testBodyBinding(t,
  312. XML, "xml",
  313. "/", "/",
  314. "<map><foo>bar</foo></map>", "<map><bar>foo</bar></map>")
  315. }
  316. func TestBindingXMLFail(t *testing.T) {
  317. testBodyBindingFail(t,
  318. XML, "xml",
  319. "/", "/",
  320. "<map><foo>bar<foo></map>", "<map><bar>foo</bar></map>")
  321. }
  322. func createFormPostRequest() *http.Request {
  323. req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
  324. req.Header.Set("Content-Type", MIMEPOSTForm)
  325. return req
  326. }
  327. func createFormPostRequestFail() *http.Request {
  328. req, _ := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=bar"))
  329. req.Header.Set("Content-Type", MIMEPOSTForm)
  330. return req
  331. }
  332. func createFormMultipartRequest() *http.Request {
  333. boundary := "--testboundary"
  334. body := new(bytes.Buffer)
  335. mw := multipart.NewWriter(body)
  336. defer mw.Close()
  337. mw.SetBoundary(boundary)
  338. mw.WriteField("foo", "bar")
  339. mw.WriteField("bar", "foo")
  340. req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
  341. req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
  342. return req
  343. }
  344. func createFormMultipartRequestFail() *http.Request {
  345. boundary := "--testboundary"
  346. body := new(bytes.Buffer)
  347. mw := multipart.NewWriter(body)
  348. defer mw.Close()
  349. mw.SetBoundary(boundary)
  350. mw.WriteField("map_foo", "bar")
  351. req, _ := http.NewRequest("POST", "/?map_foo=getfoo", body)
  352. req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
  353. return req
  354. }
  355. func TestBindingFormPost(t *testing.T) {
  356. req := createFormPostRequest()
  357. var obj FooBarStruct
  358. FormPost.Bind(req, &obj)
  359. assert.Equal(t, "form-urlencoded", FormPost.Name())
  360. assert.Equal(t, "bar", obj.Foo)
  361. assert.Equal(t, "foo", obj.Bar)
  362. }
  363. func TestBindingFormPostFail(t *testing.T) {
  364. req := createFormPostRequestFail()
  365. var obj FooStructForMapType
  366. err := FormPost.Bind(req, &obj)
  367. assert.Error(t, err)
  368. }
  369. func TestBindingFormMultipart(t *testing.T) {
  370. req := createFormMultipartRequest()
  371. var obj FooBarStruct
  372. FormMultipart.Bind(req, &obj)
  373. assert.Equal(t, "multipart/form-data", FormMultipart.Name())
  374. assert.Equal(t, "bar", obj.Foo)
  375. assert.Equal(t, "foo", obj.Bar)
  376. }
  377. func TestBindingFormMultipartFail(t *testing.T) {
  378. req := createFormMultipartRequestFail()
  379. var obj FooStructForMapType
  380. err := FormMultipart.Bind(req, &obj)
  381. assert.Error(t, err)
  382. }
  383. func TestBindingProtoBuf(t *testing.T) {
  384. test := &example.Test{
  385. Label: proto.String("yes"),
  386. }
  387. data, _ := proto.Marshal(test)
  388. testProtoBodyBinding(t,
  389. ProtoBuf, "protobuf",
  390. "/", "/",
  391. string(data), string(data[1:]))
  392. }
  393. func TestBindingProtoBufFail(t *testing.T) {
  394. test := &example.Test{
  395. Label: proto.String("yes"),
  396. }
  397. data, _ := proto.Marshal(test)
  398. testProtoBodyBindingFail(t,
  399. ProtoBuf, "protobuf",
  400. "/", "/",
  401. string(data), string(data[1:]))
  402. }
  403. func TestBindingMsgPack(t *testing.T) {
  404. test := FooStruct{
  405. Foo: "bar",
  406. }
  407. h := new(codec.MsgpackHandle)
  408. assert.NotNil(t, h)
  409. buf := bytes.NewBuffer([]byte{})
  410. assert.NotNil(t, buf)
  411. err := codec.NewEncoder(buf, h).Encode(test)
  412. assert.NoError(t, err)
  413. data := buf.Bytes()
  414. testMsgPackBodyBinding(t,
  415. MsgPack, "msgpack",
  416. "/", "/",
  417. string(data), string(data[1:]))
  418. }
  419. func TestValidationFails(t *testing.T) {
  420. var obj FooStruct
  421. req := requestWithBody("POST", "/", `{"bar": "foo"}`)
  422. err := JSON.Bind(req, &obj)
  423. assert.Error(t, err)
  424. }
  425. func TestValidationDisabled(t *testing.T) {
  426. backup := Validator
  427. Validator = nil
  428. defer func() { Validator = backup }()
  429. var obj FooStruct
  430. req := requestWithBody("POST", "/", `{"bar": "foo"}`)
  431. err := JSON.Bind(req, &obj)
  432. assert.NoError(t, err)
  433. }
  434. func TestExistsSucceeds(t *testing.T) {
  435. type HogeStruct struct {
  436. Hoge *int `json:"hoge" binding:"exists"`
  437. }
  438. var obj HogeStruct
  439. req := requestWithBody("POST", "/", `{"hoge": 0}`)
  440. err := JSON.Bind(req, &obj)
  441. assert.NoError(t, err)
  442. }
  443. func TestExistsFails(t *testing.T) {
  444. type HogeStruct struct {
  445. Hoge *int `json:"foo" binding:"exists"`
  446. }
  447. var obj HogeStruct
  448. req := requestWithBody("POST", "/", `{"boen": 0}`)
  449. err := JSON.Bind(req, &obj)
  450. assert.Error(t, err)
  451. }
  452. func testFormBinding(t *testing.T, method, path, badPath, body, badBody string) {
  453. b := Form
  454. assert.Equal(t, "form", b.Name())
  455. obj := FooBarStruct{}
  456. req := requestWithBody(method, path, body)
  457. if method == "POST" {
  458. req.Header.Add("Content-Type", MIMEPOSTForm)
  459. }
  460. err := b.Bind(req, &obj)
  461. assert.NoError(t, err)
  462. assert.Equal(t, "bar", obj.Foo)
  463. assert.Equal(t, "foo", obj.Bar)
  464. obj = FooBarStruct{}
  465. req = requestWithBody(method, badPath, badBody)
  466. err = JSON.Bind(req, &obj)
  467. assert.Error(t, err)
  468. }
  469. func TestFormBindingFail(t *testing.T) {
  470. b := Form
  471. assert.Equal(t, "form", b.Name())
  472. obj := FooBarStruct{}
  473. req, _ := http.NewRequest("POST", "/", nil)
  474. err := b.Bind(req, &obj)
  475. assert.Error(t, err)
  476. }
  477. func TestFormPostBindingFail(t *testing.T) {
  478. b := FormPost
  479. assert.Equal(t, "form-urlencoded", b.Name())
  480. obj := FooBarStruct{}
  481. req, _ := http.NewRequest("POST", "/", nil)
  482. err := b.Bind(req, &obj)
  483. assert.Error(t, err)
  484. }
  485. func TestFormMultipartBindingFail(t *testing.T) {
  486. b := FormMultipart
  487. assert.Equal(t, "multipart/form-data", b.Name())
  488. obj := FooBarStruct{}
  489. req, _ := http.NewRequest("POST", "/", nil)
  490. err := b.Bind(req, &obj)
  491. assert.Error(t, err)
  492. }
  493. func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody string) {
  494. b := Form
  495. assert.Equal(t, "form", b.Name())
  496. obj := FooBarStructForTimeType{}
  497. req := requestWithBody(method, path, body)
  498. if method == "POST" {
  499. req.Header.Add("Content-Type", MIMEPOSTForm)
  500. }
  501. err := b.Bind(req, &obj)
  502. assert.NoError(t, err)
  503. assert.Equal(t, int64(1510675200), obj.TimeFoo.Unix())
  504. assert.Equal(t, "Asia/Chongqing", obj.TimeFoo.Location().String())
  505. assert.Equal(t, int64(-62135596800), obj.TimeBar.Unix())
  506. assert.Equal(t, "UTC", obj.TimeBar.Location().String())
  507. obj = FooBarStructForTimeType{}
  508. req = requestWithBody(method, badPath, badBody)
  509. err = JSON.Bind(req, &obj)
  510. assert.Error(t, err)
  511. }
  512. func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body, badBody string) {
  513. b := Form
  514. assert.Equal(t, "form", b.Name())
  515. obj := FooStructForTimeTypeNotFormat{}
  516. req := requestWithBody(method, path, body)
  517. if method == "POST" {
  518. req.Header.Add("Content-Type", MIMEPOSTForm)
  519. }
  520. err := b.Bind(req, &obj)
  521. assert.Error(t, err)
  522. obj = FooStructForTimeTypeNotFormat{}
  523. req = requestWithBody(method, badPath, badBody)
  524. err = JSON.Bind(req, &obj)
  525. assert.Error(t, err)
  526. }
  527. func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body, badBody string) {
  528. b := Form
  529. assert.Equal(t, "form", b.Name())
  530. obj := FooStructForTimeTypeFailFormat{}
  531. req := requestWithBody(method, path, body)
  532. if method == "POST" {
  533. req.Header.Add("Content-Type", MIMEPOSTForm)
  534. }
  535. err := b.Bind(req, &obj)
  536. assert.Error(t, err)
  537. obj = FooStructForTimeTypeFailFormat{}
  538. req = requestWithBody(method, badPath, badBody)
  539. err = JSON.Bind(req, &obj)
  540. assert.Error(t, err)
  541. }
  542. func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, body, badBody string) {
  543. b := Form
  544. assert.Equal(t, "form", b.Name())
  545. obj := FooStructForTimeTypeFailLocation{}
  546. req := requestWithBody(method, path, body)
  547. if method == "POST" {
  548. req.Header.Add("Content-Type", MIMEPOSTForm)
  549. }
  550. err := b.Bind(req, &obj)
  551. assert.Error(t, err)
  552. obj = FooStructForTimeTypeFailLocation{}
  553. req = requestWithBody(method, badPath, badBody)
  554. err = JSON.Bind(req, &obj)
  555. assert.Error(t, err)
  556. }
  557. func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBody string) {
  558. b := Form
  559. assert.Equal(t, "form", b.Name())
  560. obj := InvalidNameType{}
  561. req := requestWithBody(method, path, body)
  562. if method == "POST" {
  563. req.Header.Add("Content-Type", MIMEPOSTForm)
  564. }
  565. err := b.Bind(req, &obj)
  566. assert.NoError(t, err)
  567. assert.Equal(t, "", obj.TestName)
  568. obj = InvalidNameType{}
  569. req = requestWithBody(method, badPath, badBody)
  570. err = JSON.Bind(req, &obj)
  571. assert.Error(t, err)
  572. }
  573. func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badBody string) {
  574. b := Form
  575. assert.Equal(t, "form", b.Name())
  576. obj := InvalidNameMapType{}
  577. req := requestWithBody(method, path, body)
  578. if method == "POST" {
  579. req.Header.Add("Content-Type", MIMEPOSTForm)
  580. }
  581. err := b.Bind(req, &obj)
  582. assert.Error(t, err)
  583. obj = InvalidNameMapType{}
  584. req = requestWithBody(method, badPath, badBody)
  585. err = JSON.Bind(req, &obj)
  586. assert.Error(t, err)
  587. }
  588. func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody string, typ string) {
  589. b := Form
  590. assert.Equal(t, "form", b.Name())
  591. req := requestWithBody(method, path, body)
  592. if method == "POST" {
  593. req.Header.Add("Content-Type", MIMEPOSTForm)
  594. }
  595. switch typ {
  596. case "Int":
  597. obj := FooBarStructForIntType{}
  598. err := b.Bind(req, &obj)
  599. assert.NoError(t, err)
  600. assert.Equal(t, int(0), obj.IntFoo)
  601. assert.Equal(t, int(-12), obj.IntBar)
  602. obj = FooBarStructForIntType{}
  603. req = requestWithBody(method, badPath, badBody)
  604. err = JSON.Bind(req, &obj)
  605. assert.Error(t, err)
  606. case "Int8":
  607. obj := FooBarStructForInt8Type{}
  608. err := b.Bind(req, &obj)
  609. assert.NoError(t, err)
  610. assert.Equal(t, int8(0), obj.Int8Foo)
  611. assert.Equal(t, int8(-12), obj.Int8Bar)
  612. obj = FooBarStructForInt8Type{}
  613. req = requestWithBody(method, badPath, badBody)
  614. err = JSON.Bind(req, &obj)
  615. assert.Error(t, err)
  616. case "Int16":
  617. obj := FooBarStructForInt16Type{}
  618. err := b.Bind(req, &obj)
  619. assert.NoError(t, err)
  620. assert.Equal(t, int16(0), obj.Int16Foo)
  621. assert.Equal(t, int16(-12), obj.Int16Bar)
  622. obj = FooBarStructForInt16Type{}
  623. req = requestWithBody(method, badPath, badBody)
  624. err = JSON.Bind(req, &obj)
  625. assert.Error(t, err)
  626. case "Int32":
  627. obj := FooBarStructForInt32Type{}
  628. err := b.Bind(req, &obj)
  629. assert.NoError(t, err)
  630. assert.Equal(t, int32(0), obj.Int32Foo)
  631. assert.Equal(t, int32(-12), obj.Int32Bar)
  632. obj = FooBarStructForInt32Type{}
  633. req = requestWithBody(method, badPath, badBody)
  634. err = JSON.Bind(req, &obj)
  635. assert.Error(t, err)
  636. case "Int64":
  637. obj := FooBarStructForInt64Type{}
  638. err := b.Bind(req, &obj)
  639. assert.NoError(t, err)
  640. assert.Equal(t, int64(0), obj.Int64Foo)
  641. assert.Equal(t, int64(-12), obj.Int64Bar)
  642. obj = FooBarStructForInt64Type{}
  643. req = requestWithBody(method, badPath, badBody)
  644. err = JSON.Bind(req, &obj)
  645. assert.Error(t, err)
  646. case "Uint":
  647. obj := FooBarStructForUintType{}
  648. err := b.Bind(req, &obj)
  649. assert.NoError(t, err)
  650. assert.Equal(t, uint(0x0), obj.UintFoo)
  651. assert.Equal(t, uint(0xc), obj.UintBar)
  652. obj = FooBarStructForUintType{}
  653. req = requestWithBody(method, badPath, badBody)
  654. err = JSON.Bind(req, &obj)
  655. assert.Error(t, err)
  656. case "Uint8":
  657. obj := FooBarStructForUint8Type{}
  658. err := b.Bind(req, &obj)
  659. assert.NoError(t, err)
  660. assert.Equal(t, uint8(0x0), obj.Uint8Foo)
  661. assert.Equal(t, uint8(0xc), obj.Uint8Bar)
  662. obj = FooBarStructForUint8Type{}
  663. req = requestWithBody(method, badPath, badBody)
  664. err = JSON.Bind(req, &obj)
  665. assert.Error(t, err)
  666. case "Uint16":
  667. obj := FooBarStructForUint16Type{}
  668. err := b.Bind(req, &obj)
  669. assert.NoError(t, err)
  670. assert.Equal(t, uint16(0x0), obj.Uint16Foo)
  671. assert.Equal(t, uint16(0xc), obj.Uint16Bar)
  672. obj = FooBarStructForUint16Type{}
  673. req = requestWithBody(method, badPath, badBody)
  674. err = JSON.Bind(req, &obj)
  675. assert.Error(t, err)
  676. case "Uint32":
  677. obj := FooBarStructForUint32Type{}
  678. err := b.Bind(req, &obj)
  679. assert.NoError(t, err)
  680. assert.Equal(t, uint32(0x0), obj.Uint32Foo)
  681. assert.Equal(t, uint32(0xc), obj.Uint32Bar)
  682. obj = FooBarStructForUint32Type{}
  683. req = requestWithBody(method, badPath, badBody)
  684. err = JSON.Bind(req, &obj)
  685. assert.Error(t, err)
  686. case "Uint64":
  687. obj := FooBarStructForUint64Type{}
  688. err := b.Bind(req, &obj)
  689. assert.NoError(t, err)
  690. assert.Equal(t, uint64(0x0), obj.Uint64Foo)
  691. assert.Equal(t, uint64(0xc), obj.Uint64Bar)
  692. obj = FooBarStructForUint64Type{}
  693. req = requestWithBody(method, badPath, badBody)
  694. err = JSON.Bind(req, &obj)
  695. assert.Error(t, err)
  696. case "Float32":
  697. obj := FooBarStructForFloat32Type{}
  698. err := b.Bind(req, &obj)
  699. assert.NoError(t, err)
  700. assert.Equal(t, float32(0.0), obj.Float32Foo)
  701. assert.Equal(t, float32(-12.34), obj.Float32Bar)
  702. obj = FooBarStructForFloat32Type{}
  703. req = requestWithBody(method, badPath, badBody)
  704. err = JSON.Bind(req, &obj)
  705. assert.Error(t, err)
  706. case "Float64":
  707. obj := FooBarStructForFloat64Type{}
  708. err := b.Bind(req, &obj)
  709. assert.NoError(t, err)
  710. assert.Equal(t, float64(0.0), obj.Float64Foo)
  711. assert.Equal(t, float64(-12.34), obj.Float64Bar)
  712. obj = FooBarStructForFloat64Type{}
  713. req = requestWithBody(method, badPath, badBody)
  714. err = JSON.Bind(req, &obj)
  715. assert.Error(t, err)
  716. case "Bool":
  717. obj := FooBarStructForBoolType{}
  718. err := b.Bind(req, &obj)
  719. assert.NoError(t, err)
  720. assert.False(t, obj.BoolFoo)
  721. assert.True(t, obj.BoolBar)
  722. obj = FooBarStructForBoolType{}
  723. req = requestWithBody(method, badPath, badBody)
  724. err = JSON.Bind(req, &obj)
  725. assert.Error(t, err)
  726. case "Slice":
  727. obj := FooStructForSliceType{}
  728. err := b.Bind(req, &obj)
  729. assert.NoError(t, err)
  730. assert.Equal(t, []int{1, 2}, obj.SliceFoo)
  731. obj = FooStructForSliceType{}
  732. req = requestWithBody(method, badPath, badBody)
  733. err = JSON.Bind(req, &obj)
  734. assert.Error(t, err)
  735. case "Map":
  736. obj := FooStructForMapType{}
  737. err := b.Bind(req, &obj)
  738. assert.Error(t, err)
  739. case "SliceMap":
  740. obj := FooStructForSliceMapType{}
  741. err := b.Bind(req, &obj)
  742. assert.Error(t, err)
  743. }
  744. }
  745. func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string) {
  746. b := Query
  747. assert.Equal(t, "query", b.Name())
  748. obj := FooBarStruct{}
  749. req := requestWithBody(method, path, body)
  750. if method == "POST" {
  751. req.Header.Add("Content-Type", MIMEPOSTForm)
  752. }
  753. err := b.Bind(req, &obj)
  754. assert.NoError(t, err)
  755. assert.Equal(t, "bar", obj.Foo)
  756. assert.Equal(t, "foo", obj.Bar)
  757. }
  758. func testQueryBindingFail(t *testing.T, method, path, badPath, body, badBody string) {
  759. b := Query
  760. assert.Equal(t, "query", b.Name())
  761. obj := FooStructForMapType{}
  762. req := requestWithBody(method, path, body)
  763. if method == "POST" {
  764. req.Header.Add("Content-Type", MIMEPOSTForm)
  765. }
  766. err := b.Bind(req, &obj)
  767. assert.Error(t, err)
  768. }
  769. func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  770. assert.Equal(t, name, b.Name())
  771. obj := FooStruct{}
  772. req := requestWithBody("POST", path, body)
  773. err := b.Bind(req, &obj)
  774. assert.NoError(t, err)
  775. assert.Equal(t, "bar", obj.Foo)
  776. obj = FooStruct{}
  777. req = requestWithBody("POST", badPath, badBody)
  778. err = JSON.Bind(req, &obj)
  779. assert.Error(t, err)
  780. }
  781. func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  782. assert.Equal(t, name, b.Name())
  783. obj := FooStructUseNumber{}
  784. req := requestWithBody("POST", path, body)
  785. EnableDecoderUseNumber = true
  786. err := b.Bind(req, &obj)
  787. assert.NoError(t, err)
  788. // we hope it is int64(123)
  789. v, e := obj.Foo.(json.Number).Int64()
  790. assert.NoError(t, e)
  791. assert.Equal(t, int64(123), v)
  792. obj = FooStructUseNumber{}
  793. req = requestWithBody("POST", badPath, badBody)
  794. err = JSON.Bind(req, &obj)
  795. assert.Error(t, err)
  796. }
  797. func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  798. assert.Equal(t, name, b.Name())
  799. obj := FooStructUseNumber{}
  800. req := requestWithBody("POST", path, body)
  801. EnableDecoderUseNumber = false
  802. err := b.Bind(req, &obj)
  803. assert.NoError(t, err)
  804. // it will return float64(123) if not use EnableDecoderUseNumber
  805. // maybe it is not hoped
  806. assert.Equal(t, float64(123), obj.Foo)
  807. obj = FooStructUseNumber{}
  808. req = requestWithBody("POST", badPath, badBody)
  809. err = JSON.Bind(req, &obj)
  810. assert.Error(t, err)
  811. }
  812. func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  813. assert.Equal(t, name, b.Name())
  814. obj := FooStruct{}
  815. req := requestWithBody("POST", path, body)
  816. err := b.Bind(req, &obj)
  817. assert.Error(t, err)
  818. assert.Equal(t, "", obj.Foo)
  819. obj = FooStruct{}
  820. req = requestWithBody("POST", badPath, badBody)
  821. err = JSON.Bind(req, &obj)
  822. assert.Error(t, err)
  823. }
  824. func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  825. assert.Equal(t, name, b.Name())
  826. obj := example.Test{}
  827. req := requestWithBody("POST", path, body)
  828. req.Header.Add("Content-Type", MIMEPROTOBUF)
  829. err := b.Bind(req, &obj)
  830. assert.NoError(t, err)
  831. assert.Equal(t, "yes", *obj.Label)
  832. obj = example.Test{}
  833. req = requestWithBody("POST", badPath, badBody)
  834. req.Header.Add("Content-Type", MIMEPROTOBUF)
  835. err = ProtoBuf.Bind(req, &obj)
  836. assert.Error(t, err)
  837. }
  838. type hook struct{}
  839. func (h hook) Read([]byte) (int, error) {
  840. return 0, errors.New("error")
  841. }
  842. func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  843. assert.Equal(t, name, b.Name())
  844. obj := example.Test{}
  845. req := requestWithBody("POST", path, body)
  846. req.Body = ioutil.NopCloser(&hook{})
  847. req.Header.Add("Content-Type", MIMEPROTOBUF)
  848. err := b.Bind(req, &obj)
  849. assert.Error(t, err)
  850. obj = example.Test{}
  851. req = requestWithBody("POST", badPath, badBody)
  852. req.Header.Add("Content-Type", MIMEPROTOBUF)
  853. err = ProtoBuf.Bind(req, &obj)
  854. assert.Error(t, err)
  855. }
  856. func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
  857. assert.Equal(t, name, b.Name())
  858. obj := FooStruct{}
  859. req := requestWithBody("POST", path, body)
  860. req.Header.Add("Content-Type", MIMEMSGPACK)
  861. err := b.Bind(req, &obj)
  862. assert.NoError(t, err)
  863. assert.Equal(t, "bar", obj.Foo)
  864. obj = FooStruct{}
  865. req = requestWithBody("POST", badPath, badBody)
  866. req.Header.Add("Content-Type", MIMEMSGPACK)
  867. err = MsgPack.Bind(req, &obj)
  868. assert.Error(t, err)
  869. }
  870. func requestWithBody(method, path, body string) (req *http.Request) {
  871. req, _ = http.NewRequest(method, path, bytes.NewBufferString(body))
  872. return
  873. }