binding_test.go 29 KB

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