github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/gin/binding/binding_test.go (about) 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 5 package binding 6 7 import ( 8 "bytes" 9 "encoding/json" 10 "errors" 11 "io" 12 "io/ioutil" 13 "mime/multipart" 14 "github.com/hellobchain/newcryptosm/http" 15 "os" 16 "reflect" 17 "strconv" 18 "strings" 19 "testing" 20 "time" 21 22 "github.com/golang/protobuf/proto" 23 "github.com/stretchr/testify/assert" 24 "github.com/hellobchain/third_party/gin/testdata/protoexample" 25 ) 26 27 type appkey struct { 28 Appkey string `json:"appkey" form:"appkey"` 29 } 30 31 type QueryTest struct { 32 Page int `json:"page" form:"page"` 33 Size int `json:"size" form:"size"` 34 appkey 35 } 36 37 type FooStruct struct { 38 Foo string `msgpack:"foo" json:"foo" form:"foo" xml:"foo" binding:"required,max=32"` 39 } 40 41 type FooBarStruct struct { 42 FooStruct 43 Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"` 44 } 45 46 type FooBarFileStruct struct { 47 FooBarStruct 48 File *multipart.FileHeader `form:"file" binding:"required"` 49 } 50 51 type FooBarFileFailStruct struct { 52 FooBarStruct 53 File *multipart.FileHeader `invalid_name:"file" binding:"required"` 54 // for unexport test 55 data *multipart.FileHeader `form:"data" binding:"required"` 56 } 57 58 type FooDefaultBarStruct struct { 59 FooStruct 60 Bar string `msgpack:"bar" json:"bar" form:"bar,default=hello" xml:"bar" binding:"required"` 61 } 62 63 type FooStructUseNumber struct { 64 Foo interface{} `json:"foo" binding:"required"` 65 } 66 67 type FooStructDisallowUnknownFields struct { 68 Foo interface{} `json:"foo" binding:"required"` 69 } 70 71 type FooBarStructForTimeType struct { 72 TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"` 73 TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"` 74 CreateTime time.Time `form:"createTime" time_format:"unixNano"` 75 UnixTime time.Time `form:"unixTime" time_format:"unix"` 76 } 77 78 type FooStructForTimeTypeNotUnixFormat struct { 79 CreateTime time.Time `form:"createTime" time_format:"unixNano"` 80 UnixTime time.Time `form:"unixTime" time_format:"unix"` 81 } 82 83 type FooStructForTimeTypeNotFormat struct { 84 TimeFoo time.Time `form:"time_foo"` 85 } 86 87 type FooStructForTimeTypeFailFormat struct { 88 TimeFoo time.Time `form:"time_foo" time_format:"2017-11-15"` 89 } 90 91 type FooStructForTimeTypeFailLocation struct { 92 TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_location:"/asia/chongqing"` 93 } 94 95 type FooStructForMapType struct { 96 MapFoo map[string]interface{} `form:"map_foo"` 97 } 98 99 type FooStructForIgnoreFormTag struct { 100 Foo *string `form:"-"` 101 } 102 103 type InvalidNameType struct { 104 TestName string `invalid_name:"test_name"` 105 } 106 107 type InvalidNameMapType struct { 108 TestName struct { 109 MapFoo map[string]interface{} `form:"map_foo"` 110 } 111 } 112 113 type FooStructForSliceType struct { 114 SliceFoo []int `form:"slice_foo"` 115 } 116 117 type FooStructForStructType struct { 118 StructFoo struct { 119 Idx int `form:"idx"` 120 } 121 } 122 123 type FooStructForStructPointerType struct { 124 StructPointerFoo *struct { 125 Name string `form:"name"` 126 } 127 } 128 129 type FooStructForSliceMapType struct { 130 // Unknown type: not support map 131 SliceMapFoo []map[string]interface{} `form:"slice_map_foo"` 132 } 133 134 type FooStructForBoolType struct { 135 BoolFoo bool `form:"bool_foo"` 136 } 137 138 type FooStructForStringPtrType struct { 139 PtrFoo *string `form:"ptr_foo"` 140 PtrBar *string `form:"ptr_bar" binding:"required"` 141 } 142 143 type FooStructForMapPtrType struct { 144 PtrBar *map[string]interface{} `form:"ptr_bar"` 145 } 146 147 func TestBindingDefault(t *testing.T) { 148 assert.Equal(t, Form, Default("GET", "")) 149 assert.Equal(t, Form, Default("GET", MIMEJSON)) 150 151 assert.Equal(t, JSON, Default("POST", MIMEJSON)) 152 assert.Equal(t, JSON, Default("PUT", MIMEJSON)) 153 154 assert.Equal(t, XML, Default("POST", MIMEXML)) 155 assert.Equal(t, XML, Default("PUT", MIMEXML2)) 156 157 assert.Equal(t, Form, Default("POST", MIMEPOSTForm)) 158 assert.Equal(t, Form, Default("PUT", MIMEPOSTForm)) 159 160 assert.Equal(t, FormMultipart, Default("POST", MIMEMultipartPOSTForm)) 161 assert.Equal(t, FormMultipart, Default("PUT", MIMEMultipartPOSTForm)) 162 163 assert.Equal(t, ProtoBuf, Default("POST", MIMEPROTOBUF)) 164 assert.Equal(t, ProtoBuf, Default("PUT", MIMEPROTOBUF)) 165 166 assert.Equal(t, YAML, Default("POST", MIMEYAML)) 167 assert.Equal(t, YAML, Default("PUT", MIMEYAML)) 168 } 169 170 func TestBindingJSONNilBody(t *testing.T) { 171 var obj FooStruct 172 req, _ := http.NewRequest(http.MethodPost, "/", nil) 173 err := JSON.Bind(req, &obj) 174 assert.Error(t, err) 175 } 176 177 func TestBindingJSON(t *testing.T) { 178 testBodyBinding(t, 179 JSON, "json", 180 "/", "/", 181 `{"foo": "bar"}`, `{"bar": "foo"}`) 182 } 183 184 func TestBindingJSONSlice(t *testing.T) { 185 EnableDecoderDisallowUnknownFields = true 186 defer func() { 187 EnableDecoderDisallowUnknownFields = false 188 }() 189 190 testBodyBindingSlice(t, JSON, "json", "/", "/", `[]`, ``) 191 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{}]`) 192 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{"foo": ""}]`) 193 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{"foo": 123}]`) 194 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{"bar": 123}]`) 195 testBodyBindingSlice(t, JSON, "json", "/", "/", `[{"foo": "123"}]`, `[{"foo": "123456789012345678901234567890123"}]`) 196 } 197 198 func TestBindingJSONUseNumber(t *testing.T) { 199 testBodyBindingUseNumber(t, 200 JSON, "json", 201 "/", "/", 202 `{"foo": 123}`, `{"bar": "foo"}`) 203 } 204 205 func TestBindingJSONUseNumber2(t *testing.T) { 206 testBodyBindingUseNumber2(t, 207 JSON, "json", 208 "/", "/", 209 `{"foo": 123}`, `{"bar": "foo"}`) 210 } 211 212 func TestBindingJSONDisallowUnknownFields(t *testing.T) { 213 testBodyBindingDisallowUnknownFields(t, JSON, 214 "/", "/", 215 `{"foo": "bar"}`, `{"foo": "bar", "what": "this"}`) 216 } 217 218 func TestBindingJSONStringMap(t *testing.T) { 219 testBodyBindingStringMap(t, JSON, 220 "/", "/", 221 `{"foo": "bar", "hello": "world"}`, `{"num": 2}`) 222 } 223 224 func TestBindingForm(t *testing.T) { 225 testFormBinding(t, "POST", 226 "/", "/", 227 "foo=bar&bar=foo", "bar2=foo") 228 } 229 230 func TestBindingForm2(t *testing.T) { 231 testFormBinding(t, "GET", 232 "/?foo=bar&bar=foo", "/?bar2=foo", 233 "", "") 234 } 235 236 func TestBindingFormEmbeddedStruct(t *testing.T) { 237 testFormBindingEmbeddedStruct(t, "POST", 238 "/", "/", 239 "page=1&size=2&appkey=test-appkey", "bar2=foo") 240 } 241 242 func TestBindingFormEmbeddedStruct2(t *testing.T) { 243 testFormBindingEmbeddedStruct(t, "GET", 244 "/?page=1&size=2&appkey=test-appkey", "/?bar2=foo", 245 "", "") 246 } 247 248 func TestBindingFormDefaultValue(t *testing.T) { 249 testFormBindingDefaultValue(t, "POST", 250 "/", "/", 251 "foo=bar", "bar2=foo") 252 } 253 254 func TestBindingFormDefaultValue2(t *testing.T) { 255 testFormBindingDefaultValue(t, "GET", 256 "/?foo=bar", "/?bar2=foo", 257 "", "") 258 } 259 260 func TestBindingFormForTime(t *testing.T) { 261 testFormBindingForTime(t, "POST", 262 "/", "/", 263 "time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "bar2=foo") 264 testFormBindingForTimeNotUnixFormat(t, "POST", 265 "/", "/", 266 "time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo") 267 testFormBindingForTimeNotFormat(t, "POST", 268 "/", "/", 269 "time_foo=2017-11-15", "bar2=foo") 270 testFormBindingForTimeFailFormat(t, "POST", 271 "/", "/", 272 "time_foo=2017-11-15", "bar2=foo") 273 testFormBindingForTimeFailLocation(t, "POST", 274 "/", "/", 275 "time_foo=2017-11-15", "bar2=foo") 276 } 277 278 func TestBindingFormForTime2(t *testing.T) { 279 testFormBindingForTime(t, "GET", 280 "/?time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "/?bar2=foo", 281 "", "") 282 testFormBindingForTimeNotUnixFormat(t, "POST", 283 "/", "/", 284 "time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo") 285 testFormBindingForTimeNotFormat(t, "GET", 286 "/?time_foo=2017-11-15", "/?bar2=foo", 287 "", "") 288 testFormBindingForTimeFailFormat(t, "GET", 289 "/?time_foo=2017-11-15", "/?bar2=foo", 290 "", "") 291 testFormBindingForTimeFailLocation(t, "GET", 292 "/?time_foo=2017-11-15", "/?bar2=foo", 293 "", "") 294 } 295 296 func TestFormBindingIgnoreField(t *testing.T) { 297 testFormBindingIgnoreField(t, "POST", 298 "/", "/", 299 "-=bar", "") 300 } 301 302 func TestBindingFormInvalidName(t *testing.T) { 303 testFormBindingInvalidName(t, "POST", 304 "/", "/", 305 "test_name=bar", "bar2=foo") 306 } 307 308 func TestBindingFormInvalidName2(t *testing.T) { 309 testFormBindingInvalidName2(t, "POST", 310 "/", "/", 311 "map_foo=bar", "bar2=foo") 312 } 313 314 func TestBindingFormForType(t *testing.T) { 315 testFormBindingForType(t, "POST", 316 "/", "/", 317 "map_foo={\"bar\":123}", "map_foo=1", "Map") 318 319 testFormBindingForType(t, "POST", 320 "/", "/", 321 "slice_foo=1&slice_foo=2", "bar2=1&bar2=2", "Slice") 322 323 testFormBindingForType(t, "GET", 324 "/?slice_foo=1&slice_foo=2", "/?bar2=1&bar2=2", 325 "", "", "Slice") 326 327 testFormBindingForType(t, "POST", 328 "/", "/", 329 "slice_map_foo=1&slice_map_foo=2", "bar2=1&bar2=2", "SliceMap") 330 331 testFormBindingForType(t, "GET", 332 "/?slice_map_foo=1&slice_map_foo=2", "/?bar2=1&bar2=2", 333 "", "", "SliceMap") 334 335 testFormBindingForType(t, "POST", 336 "/", "/", 337 "ptr_bar=test", "bar2=test", "Ptr") 338 339 testFormBindingForType(t, "GET", 340 "/?ptr_bar=test", "/?bar2=test", 341 "", "", "Ptr") 342 343 testFormBindingForType(t, "POST", 344 "/", "/", 345 "idx=123", "id1=1", "Struct") 346 347 testFormBindingForType(t, "GET", 348 "/?idx=123", "/?id1=1", 349 "", "", "Struct") 350 351 testFormBindingForType(t, "POST", 352 "/", "/", 353 "name=thinkerou", "name1=ou", "StructPointer") 354 355 testFormBindingForType(t, "GET", 356 "/?name=thinkerou", "/?name1=ou", 357 "", "", "StructPointer") 358 } 359 360 func TestBindingFormStringMap(t *testing.T) { 361 testBodyBindingStringMap(t, Form, 362 "/", "", 363 `foo=bar&hello=world`, "") 364 // Should pick the last value 365 testBodyBindingStringMap(t, Form, 366 "/", "", 367 `foo=something&foo=bar&hello=world`, "") 368 } 369 370 func TestBindingFormStringSliceMap(t *testing.T) { 371 obj := make(map[string][]string) 372 req := requestWithBody("POST", "/", "foo=something&foo=bar&hello=world") 373 req.Header.Add("Content-Type", MIMEPOSTForm) 374 err := Form.Bind(req, &obj) 375 assert.NoError(t, err) 376 assert.NotNil(t, obj) 377 assert.Len(t, obj, 2) 378 target := map[string][]string{ 379 "foo": {"something", "bar"}, 380 "hello": {"world"}, 381 } 382 assert.True(t, reflect.DeepEqual(obj, target)) 383 384 objInvalid := make(map[string][]int) 385 req = requestWithBody("POST", "/", "foo=something&foo=bar&hello=world") 386 req.Header.Add("Content-Type", MIMEPOSTForm) 387 err = Form.Bind(req, &objInvalid) 388 assert.Error(t, err) 389 } 390 391 func TestBindingQuery(t *testing.T) { 392 testQueryBinding(t, "POST", 393 "/?foo=bar&bar=foo", "/", 394 "foo=unused", "bar2=foo") 395 } 396 397 func TestBindingQuery2(t *testing.T) { 398 testQueryBinding(t, "GET", 399 "/?foo=bar&bar=foo", "/?bar2=foo", 400 "foo=unused", "") 401 } 402 403 func TestBindingQueryFail(t *testing.T) { 404 testQueryBindingFail(t, "POST", 405 "/?map_foo=", "/", 406 "map_foo=unused", "bar2=foo") 407 } 408 409 func TestBindingQueryFail2(t *testing.T) { 410 testQueryBindingFail(t, "GET", 411 "/?map_foo=", "/?bar2=foo", 412 "map_foo=unused", "") 413 } 414 415 func TestBindingQueryBoolFail(t *testing.T) { 416 testQueryBindingBoolFail(t, "GET", 417 "/?bool_foo=fasl", "/?bar2=foo", 418 "bool_foo=unused", "") 419 } 420 421 func TestBindingQueryStringMap(t *testing.T) { 422 b := Query 423 424 obj := make(map[string]string) 425 req := requestWithBody("GET", "/?foo=bar&hello=world", "") 426 err := b.Bind(req, &obj) 427 assert.NoError(t, err) 428 assert.NotNil(t, obj) 429 assert.Len(t, obj, 2) 430 assert.Equal(t, "bar", obj["foo"]) 431 assert.Equal(t, "world", obj["hello"]) 432 433 obj = make(map[string]string) 434 req = requestWithBody("GET", "/?foo=bar&foo=2&hello=world", "") // should pick last 435 err = b.Bind(req, &obj) 436 assert.NoError(t, err) 437 assert.NotNil(t, obj) 438 assert.Len(t, obj, 2) 439 assert.Equal(t, "2", obj["foo"]) 440 assert.Equal(t, "world", obj["hello"]) 441 } 442 443 func TestBindingXML(t *testing.T) { 444 testBodyBinding(t, 445 XML, "xml", 446 "/", "/", 447 "<map><foo>bar</foo></map>", "<map><bar>foo</bar></map>") 448 } 449 450 func TestBindingXMLFail(t *testing.T) { 451 testBodyBindingFail(t, 452 XML, "xml", 453 "/", "/", 454 "<map><foo>bar<foo></map>", "<map><bar>foo</bar></map>") 455 } 456 457 func TestBindingYAML(t *testing.T) { 458 testBodyBinding(t, 459 YAML, "yaml", 460 "/", "/", 461 `foo: bar`, `bar: foo`) 462 } 463 464 func TestBindingYAMLStringMap(t *testing.T) { 465 // YAML is a superset of JSON, so the test below is JSON (to avoid newlines) 466 testBodyBindingStringMap(t, YAML, 467 "/", "/", 468 `{"foo": "bar", "hello": "world"}`, `{"nested": {"foo": "bar"}}`) 469 } 470 471 func TestBindingYAMLFail(t *testing.T) { 472 testBodyBindingFail(t, 473 YAML, "yaml", 474 "/", "/", 475 `foo:\nbar`, `bar: foo`) 476 } 477 478 func createFormPostRequest(t *testing.T) *http.Request { 479 req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo")) 480 assert.NoError(t, err) 481 req.Header.Set("Content-Type", MIMEPOSTForm) 482 return req 483 } 484 485 func createDefaultFormPostRequest(t *testing.T) *http.Request { 486 req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar")) 487 assert.NoError(t, err) 488 req.Header.Set("Content-Type", MIMEPOSTForm) 489 return req 490 } 491 492 func createFormPostRequestForMap(t *testing.T) *http.Request { 493 req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo={\"bar\":123}")) 494 assert.NoError(t, err) 495 req.Header.Set("Content-Type", MIMEPOSTForm) 496 return req 497 } 498 499 func createFormPostRequestForMapFail(t *testing.T) *http.Request { 500 req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=hello")) 501 assert.NoError(t, err) 502 req.Header.Set("Content-Type", MIMEPOSTForm) 503 return req 504 } 505 506 func createFormFilesMultipartRequest(t *testing.T) *http.Request { 507 boundary := "--testboundary" 508 body := new(bytes.Buffer) 509 mw := multipart.NewWriter(body) 510 defer mw.Close() 511 512 assert.NoError(t, mw.SetBoundary(boundary)) 513 assert.NoError(t, mw.WriteField("foo", "bar")) 514 assert.NoError(t, mw.WriteField("bar", "foo")) 515 516 f, err := os.Open("form.go") 517 assert.NoError(t, err) 518 defer f.Close() 519 fw, err1 := mw.CreateFormFile("file", "form.go") 520 assert.NoError(t, err1) 521 _, err = io.Copy(fw, f) 522 assert.NoError(t, err) 523 524 req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body) 525 assert.NoError(t, err2) 526 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) 527 528 return req 529 } 530 531 func createFormFilesMultipartRequestFail(t *testing.T) *http.Request { 532 boundary := "--testboundary" 533 body := new(bytes.Buffer) 534 mw := multipart.NewWriter(body) 535 defer mw.Close() 536 537 assert.NoError(t, mw.SetBoundary(boundary)) 538 assert.NoError(t, mw.WriteField("foo", "bar")) 539 assert.NoError(t, mw.WriteField("bar", "foo")) 540 541 f, err := os.Open("form.go") 542 assert.NoError(t, err) 543 defer f.Close() 544 fw, err1 := mw.CreateFormFile("file_foo", "form_foo.go") 545 assert.NoError(t, err1) 546 _, err = io.Copy(fw, f) 547 assert.NoError(t, err) 548 549 req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body) 550 assert.NoError(t, err2) 551 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) 552 553 return req 554 } 555 556 func createFormMultipartRequest(t *testing.T) *http.Request { 557 boundary := "--testboundary" 558 body := new(bytes.Buffer) 559 mw := multipart.NewWriter(body) 560 defer mw.Close() 561 562 assert.NoError(t, mw.SetBoundary(boundary)) 563 assert.NoError(t, mw.WriteField("foo", "bar")) 564 assert.NoError(t, mw.WriteField("bar", "foo")) 565 req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body) 566 assert.NoError(t, err) 567 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) 568 return req 569 } 570 571 func createFormMultipartRequestForMap(t *testing.T) *http.Request { 572 boundary := "--testboundary" 573 body := new(bytes.Buffer) 574 mw := multipart.NewWriter(body) 575 defer mw.Close() 576 577 assert.NoError(t, mw.SetBoundary(boundary)) 578 assert.NoError(t, mw.WriteField("map_foo", "{\"bar\":123, \"name\":\"thinkerou\", \"pai\": 3.14}")) 579 req, err := http.NewRequest("POST", "/?map_foo=getfoo", body) 580 assert.NoError(t, err) 581 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) 582 return req 583 } 584 585 func createFormMultipartRequestForMapFail(t *testing.T) *http.Request { 586 boundary := "--testboundary" 587 body := new(bytes.Buffer) 588 mw := multipart.NewWriter(body) 589 defer mw.Close() 590 591 assert.NoError(t, mw.SetBoundary(boundary)) 592 assert.NoError(t, mw.WriteField("map_foo", "3.14")) 593 req, err := http.NewRequest("POST", "/?map_foo=getfoo", body) 594 assert.NoError(t, err) 595 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) 596 return req 597 } 598 599 func TestBindingFormPost(t *testing.T) { 600 req := createFormPostRequest(t) 601 var obj FooBarStruct 602 assert.NoError(t, FormPost.Bind(req, &obj)) 603 604 assert.Equal(t, "form-urlencoded", FormPost.Name()) 605 assert.Equal(t, "bar", obj.Foo) 606 assert.Equal(t, "foo", obj.Bar) 607 } 608 609 func TestBindingDefaultValueFormPost(t *testing.T) { 610 req := createDefaultFormPostRequest(t) 611 var obj FooDefaultBarStruct 612 assert.NoError(t, FormPost.Bind(req, &obj)) 613 614 assert.Equal(t, "bar", obj.Foo) 615 assert.Equal(t, "hello", obj.Bar) 616 } 617 618 func TestBindingFormPostForMap(t *testing.T) { 619 req := createFormPostRequestForMap(t) 620 var obj FooStructForMapType 621 err := FormPost.Bind(req, &obj) 622 assert.NoError(t, err) 623 assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64)) 624 } 625 626 func TestBindingFormPostForMapFail(t *testing.T) { 627 req := createFormPostRequestForMapFail(t) 628 var obj FooStructForMapType 629 err := FormPost.Bind(req, &obj) 630 assert.Error(t, err) 631 } 632 633 func TestBindingFormFilesMultipart(t *testing.T) { 634 req := createFormFilesMultipartRequest(t) 635 var obj FooBarFileStruct 636 err := FormMultipart.Bind(req, &obj) 637 assert.NoError(t, err) 638 639 // file from os 640 f, _ := os.Open("form.go") 641 defer f.Close() 642 fileActual, _ := ioutil.ReadAll(f) 643 644 // file from multipart 645 mf, _ := obj.File.Open() 646 defer mf.Close() 647 fileExpect, _ := ioutil.ReadAll(mf) 648 649 assert.Equal(t, FormMultipart.Name(), "multipart/form-data") 650 assert.Equal(t, obj.Foo, "bar") 651 assert.Equal(t, obj.Bar, "foo") 652 assert.Equal(t, fileExpect, fileActual) 653 } 654 655 func TestBindingFormFilesMultipartFail(t *testing.T) { 656 req := createFormFilesMultipartRequestFail(t) 657 var obj FooBarFileFailStruct 658 err := FormMultipart.Bind(req, &obj) 659 assert.Error(t, err) 660 } 661 662 func TestBindingFormMultipart(t *testing.T) { 663 req := createFormMultipartRequest(t) 664 var obj FooBarStruct 665 assert.NoError(t, FormMultipart.Bind(req, &obj)) 666 667 assert.Equal(t, "multipart/form-data", FormMultipart.Name()) 668 assert.Equal(t, "bar", obj.Foo) 669 assert.Equal(t, "foo", obj.Bar) 670 } 671 672 func TestBindingFormMultipartForMap(t *testing.T) { 673 req := createFormMultipartRequestForMap(t) 674 var obj FooStructForMapType 675 err := FormMultipart.Bind(req, &obj) 676 assert.NoError(t, err) 677 assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64)) 678 assert.Equal(t, "thinkerou", obj.MapFoo["name"].(string)) 679 assert.Equal(t, float64(3.14), obj.MapFoo["pai"].(float64)) 680 } 681 682 func TestBindingFormMultipartForMapFail(t *testing.T) { 683 req := createFormMultipartRequestForMapFail(t) 684 var obj FooStructForMapType 685 err := FormMultipart.Bind(req, &obj) 686 assert.Error(t, err) 687 } 688 689 func TestBindingProtoBuf(t *testing.T) { 690 test := &protoexample.Test{ 691 Label: proto.String("yes"), 692 } 693 data, _ := proto.Marshal(test) 694 695 testProtoBodyBinding(t, 696 ProtoBuf, "protobuf", 697 "/", "/", 698 string(data), string(data[1:])) 699 } 700 701 func TestBindingProtoBufFail(t *testing.T) { 702 test := &protoexample.Test{ 703 Label: proto.String("yes"), 704 } 705 data, _ := proto.Marshal(test) 706 707 testProtoBodyBindingFail(t, 708 ProtoBuf, "protobuf", 709 "/", "/", 710 string(data), string(data[1:])) 711 } 712 713 func TestValidationFails(t *testing.T) { 714 var obj FooStruct 715 req := requestWithBody("POST", "/", `{"bar": "foo"}`) 716 err := JSON.Bind(req, &obj) 717 assert.Error(t, err) 718 } 719 720 func TestValidationDisabled(t *testing.T) { 721 backup := Validator 722 Validator = nil 723 defer func() { Validator = backup }() 724 725 var obj FooStruct 726 req := requestWithBody("POST", "/", `{"bar": "foo"}`) 727 err := JSON.Bind(req, &obj) 728 assert.NoError(t, err) 729 } 730 731 func TestRequiredSucceeds(t *testing.T) { 732 type HogeStruct struct { 733 Hoge *int `json:"hoge" binding:"required"` 734 } 735 736 var obj HogeStruct 737 req := requestWithBody("POST", "/", `{"hoge": 0}`) 738 err := JSON.Bind(req, &obj) 739 assert.NoError(t, err) 740 } 741 742 func TestRequiredFails(t *testing.T) { 743 type HogeStruct struct { 744 Hoge *int `json:"foo" binding:"required"` 745 } 746 747 var obj HogeStruct 748 req := requestWithBody("POST", "/", `{"boen": 0}`) 749 err := JSON.Bind(req, &obj) 750 assert.Error(t, err) 751 } 752 753 func TestHeaderBinding(t *testing.T) { 754 h := Header 755 assert.Equal(t, "header", h.Name()) 756 757 type tHeader struct { 758 Limit int `header:"limit"` 759 } 760 761 var theader tHeader 762 req := requestWithBody("GET", "/", "") 763 req.Header.Add("limit", "1000") 764 assert.NoError(t, h.Bind(req, &theader)) 765 assert.Equal(t, 1000, theader.Limit) 766 767 req = requestWithBody("GET", "/", "") 768 req.Header.Add("fail", `{fail:fail}`) 769 770 type failStruct struct { 771 Fail map[string]interface{} `header:"fail"` 772 } 773 774 err := h.Bind(req, &failStruct{}) 775 assert.Error(t, err) 776 } 777 778 func TestUriBinding(t *testing.T) { 779 b := Uri 780 assert.Equal(t, "uri", b.Name()) 781 782 type Tag struct { 783 Name string `uri:"name"` 784 } 785 var tag Tag 786 m := make(map[string][]string) 787 m["name"] = []string{"thinkerou"} 788 assert.NoError(t, b.BindUri(m, &tag)) 789 assert.Equal(t, "thinkerou", tag.Name) 790 791 type NotSupportStruct struct { 792 Name map[string]interface{} `uri:"name"` 793 } 794 var not NotSupportStruct 795 assert.Error(t, b.BindUri(m, ¬)) 796 assert.Equal(t, map[string]interface{}(nil), not.Name) 797 } 798 799 func TestUriInnerBinding(t *testing.T) { 800 type Tag struct { 801 Name string `uri:"name"` 802 S struct { 803 Age int `uri:"age"` 804 } 805 } 806 807 expectedName := "mike" 808 expectedAge := 25 809 810 m := map[string][]string{ 811 "name": {expectedName}, 812 "age": {strconv.Itoa(expectedAge)}, 813 } 814 815 var tag Tag 816 assert.NoError(t, Uri.BindUri(m, &tag)) 817 assert.Equal(t, tag.Name, expectedName) 818 assert.Equal(t, tag.S.Age, expectedAge) 819 } 820 821 func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, badBody string) { 822 b := Form 823 assert.Equal(t, "form", b.Name()) 824 825 obj := QueryTest{} 826 req := requestWithBody(method, path, body) 827 if method == "POST" { 828 req.Header.Add("Content-Type", MIMEPOSTForm) 829 } 830 err := b.Bind(req, &obj) 831 assert.NoError(t, err) 832 assert.Equal(t, 1, obj.Page) 833 assert.Equal(t, 2, obj.Size) 834 assert.Equal(t, "test-appkey", obj.Appkey) 835 836 } 837 838 func testFormBinding(t *testing.T, method, path, badPath, body, badBody string) { 839 b := Form 840 assert.Equal(t, "form", b.Name()) 841 842 obj := FooBarStruct{} 843 req := requestWithBody(method, path, body) 844 if method == "POST" { 845 req.Header.Add("Content-Type", MIMEPOSTForm) 846 } 847 err := b.Bind(req, &obj) 848 assert.NoError(t, err) 849 assert.Equal(t, "bar", obj.Foo) 850 assert.Equal(t, "foo", obj.Bar) 851 852 obj = FooBarStruct{} 853 req = requestWithBody(method, badPath, badBody) 854 err = JSON.Bind(req, &obj) 855 assert.Error(t, err) 856 } 857 858 func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badBody string) { 859 b := Form 860 assert.Equal(t, "form", b.Name()) 861 862 obj := FooDefaultBarStruct{} 863 req := requestWithBody(method, path, body) 864 if method == "POST" { 865 req.Header.Add("Content-Type", MIMEPOSTForm) 866 } 867 err := b.Bind(req, &obj) 868 assert.NoError(t, err) 869 assert.Equal(t, "bar", obj.Foo) 870 assert.Equal(t, "hello", obj.Bar) 871 872 obj = FooDefaultBarStruct{} 873 req = requestWithBody(method, badPath, badBody) 874 err = JSON.Bind(req, &obj) 875 assert.Error(t, err) 876 } 877 878 func TestFormBindingFail(t *testing.T) { 879 b := Form 880 assert.Equal(t, "form", b.Name()) 881 882 obj := FooBarStruct{} 883 req, _ := http.NewRequest("POST", "/", nil) 884 err := b.Bind(req, &obj) 885 assert.Error(t, err) 886 } 887 888 func TestFormBindingMultipartFail(t *testing.T) { 889 obj := FooBarStruct{} 890 req, err := http.NewRequest("POST", "/", strings.NewReader("foo=bar")) 891 assert.NoError(t, err) 892 req.Header.Set("Content-Type", MIMEMultipartPOSTForm+";boundary=testboundary") 893 _, err = req.MultipartReader() 894 assert.NoError(t, err) 895 err = Form.Bind(req, &obj) 896 assert.Error(t, err) 897 } 898 899 func TestFormPostBindingFail(t *testing.T) { 900 b := FormPost 901 assert.Equal(t, "form-urlencoded", b.Name()) 902 903 obj := FooBarStruct{} 904 req, _ := http.NewRequest("POST", "/", nil) 905 err := b.Bind(req, &obj) 906 assert.Error(t, err) 907 } 908 909 func TestFormMultipartBindingFail(t *testing.T) { 910 b := FormMultipart 911 assert.Equal(t, "multipart/form-data", b.Name()) 912 913 obj := FooBarStruct{} 914 req, _ := http.NewRequest("POST", "/", nil) 915 err := b.Bind(req, &obj) 916 assert.Error(t, err) 917 } 918 919 func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody string) { 920 b := Form 921 assert.Equal(t, "form", b.Name()) 922 923 obj := FooBarStructForTimeType{} 924 req := requestWithBody(method, path, body) 925 if method == "POST" { 926 req.Header.Add("Content-Type", MIMEPOSTForm) 927 } 928 err := b.Bind(req, &obj) 929 930 assert.NoError(t, err) 931 assert.Equal(t, int64(1510675200), obj.TimeFoo.Unix()) 932 assert.Equal(t, "Asia/Chongqing", obj.TimeFoo.Location().String()) 933 assert.Equal(t, int64(-62135596800), obj.TimeBar.Unix()) 934 assert.Equal(t, "UTC", obj.TimeBar.Location().String()) 935 assert.Equal(t, int64(1562400033000000123), obj.CreateTime.UnixNano()) 936 assert.Equal(t, int64(1562400033), obj.UnixTime.Unix()) 937 938 obj = FooBarStructForTimeType{} 939 req = requestWithBody(method, badPath, badBody) 940 err = JSON.Bind(req, &obj) 941 assert.Error(t, err) 942 } 943 944 func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, body, badBody string) { 945 b := Form 946 assert.Equal(t, "form", b.Name()) 947 948 obj := FooStructForTimeTypeNotUnixFormat{} 949 req := requestWithBody(method, path, body) 950 if method == "POST" { 951 req.Header.Add("Content-Type", MIMEPOSTForm) 952 } 953 err := b.Bind(req, &obj) 954 assert.Error(t, err) 955 956 obj = FooStructForTimeTypeNotUnixFormat{} 957 req = requestWithBody(method, badPath, badBody) 958 err = JSON.Bind(req, &obj) 959 assert.Error(t, err) 960 } 961 962 func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body, badBody string) { 963 b := Form 964 assert.Equal(t, "form", b.Name()) 965 966 obj := FooStructForTimeTypeNotFormat{} 967 req := requestWithBody(method, path, body) 968 if method == "POST" { 969 req.Header.Add("Content-Type", MIMEPOSTForm) 970 } 971 err := b.Bind(req, &obj) 972 assert.Error(t, err) 973 974 obj = FooStructForTimeTypeNotFormat{} 975 req = requestWithBody(method, badPath, badBody) 976 err = JSON.Bind(req, &obj) 977 assert.Error(t, err) 978 } 979 980 func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body, badBody string) { 981 b := Form 982 assert.Equal(t, "form", b.Name()) 983 984 obj := FooStructForTimeTypeFailFormat{} 985 req := requestWithBody(method, path, body) 986 if method == "POST" { 987 req.Header.Add("Content-Type", MIMEPOSTForm) 988 } 989 err := b.Bind(req, &obj) 990 assert.Error(t, err) 991 992 obj = FooStructForTimeTypeFailFormat{} 993 req = requestWithBody(method, badPath, badBody) 994 err = JSON.Bind(req, &obj) 995 assert.Error(t, err) 996 } 997 998 func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, body, badBody string) { 999 b := Form 1000 assert.Equal(t, "form", b.Name()) 1001 1002 obj := FooStructForTimeTypeFailLocation{} 1003 req := requestWithBody(method, path, body) 1004 if method == "POST" { 1005 req.Header.Add("Content-Type", MIMEPOSTForm) 1006 } 1007 err := b.Bind(req, &obj) 1008 assert.Error(t, err) 1009 1010 obj = FooStructForTimeTypeFailLocation{} 1011 req = requestWithBody(method, badPath, badBody) 1012 err = JSON.Bind(req, &obj) 1013 assert.Error(t, err) 1014 } 1015 1016 func testFormBindingIgnoreField(t *testing.T, method, path, badPath, body, badBody string) { 1017 b := Form 1018 assert.Equal(t, "form", b.Name()) 1019 1020 obj := FooStructForIgnoreFormTag{} 1021 req := requestWithBody(method, path, body) 1022 if method == "POST" { 1023 req.Header.Add("Content-Type", MIMEPOSTForm) 1024 } 1025 err := b.Bind(req, &obj) 1026 assert.NoError(t, err) 1027 1028 assert.Nil(t, obj.Foo) 1029 } 1030 1031 func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBody string) { 1032 b := Form 1033 assert.Equal(t, "form", b.Name()) 1034 1035 obj := InvalidNameType{} 1036 req := requestWithBody(method, path, body) 1037 if method == "POST" { 1038 req.Header.Add("Content-Type", MIMEPOSTForm) 1039 } 1040 err := b.Bind(req, &obj) 1041 assert.NoError(t, err) 1042 assert.Equal(t, "", obj.TestName) 1043 1044 obj = InvalidNameType{} 1045 req = requestWithBody(method, badPath, badBody) 1046 err = JSON.Bind(req, &obj) 1047 assert.Error(t, err) 1048 } 1049 1050 func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badBody string) { 1051 b := Form 1052 assert.Equal(t, "form", b.Name()) 1053 1054 obj := InvalidNameMapType{} 1055 req := requestWithBody(method, path, body) 1056 if method == "POST" { 1057 req.Header.Add("Content-Type", MIMEPOSTForm) 1058 } 1059 err := b.Bind(req, &obj) 1060 assert.Error(t, err) 1061 1062 obj = InvalidNameMapType{} 1063 req = requestWithBody(method, badPath, badBody) 1064 err = JSON.Bind(req, &obj) 1065 assert.Error(t, err) 1066 } 1067 1068 func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody string, typ string) { 1069 b := Form 1070 assert.Equal(t, "form", b.Name()) 1071 1072 req := requestWithBody(method, path, body) 1073 if method == "POST" { 1074 req.Header.Add("Content-Type", MIMEPOSTForm) 1075 } 1076 switch typ { 1077 case "Slice": 1078 obj := FooStructForSliceType{} 1079 err := b.Bind(req, &obj) 1080 assert.NoError(t, err) 1081 assert.Equal(t, []int{1, 2}, obj.SliceFoo) 1082 1083 obj = FooStructForSliceType{} 1084 req = requestWithBody(method, badPath, badBody) 1085 err = JSON.Bind(req, &obj) 1086 assert.Error(t, err) 1087 case "Struct": 1088 obj := FooStructForStructType{} 1089 err := b.Bind(req, &obj) 1090 assert.NoError(t, err) 1091 assert.Equal(t, 1092 struct { 1093 Idx int "form:\"idx\"" 1094 }(struct { 1095 Idx int "form:\"idx\"" 1096 }{Idx: 123}), 1097 obj.StructFoo) 1098 case "StructPointer": 1099 obj := FooStructForStructPointerType{} 1100 err := b.Bind(req, &obj) 1101 assert.NoError(t, err) 1102 assert.Equal(t, 1103 struct { 1104 Name string "form:\"name\"" 1105 }(struct { 1106 Name string "form:\"name\"" 1107 }{Name: "thinkerou"}), 1108 *obj.StructPointerFoo) 1109 case "Map": 1110 obj := FooStructForMapType{} 1111 err := b.Bind(req, &obj) 1112 assert.NoError(t, err) 1113 assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64)) 1114 case "SliceMap": 1115 obj := FooStructForSliceMapType{} 1116 err := b.Bind(req, &obj) 1117 assert.Error(t, err) 1118 case "Ptr": 1119 obj := FooStructForStringPtrType{} 1120 err := b.Bind(req, &obj) 1121 assert.NoError(t, err) 1122 assert.Nil(t, obj.PtrFoo) 1123 assert.Equal(t, "test", *obj.PtrBar) 1124 1125 obj = FooStructForStringPtrType{} 1126 obj.PtrBar = new(string) 1127 err = b.Bind(req, &obj) 1128 assert.NoError(t, err) 1129 assert.Equal(t, "test", *obj.PtrBar) 1130 1131 objErr := FooStructForMapPtrType{} 1132 err = b.Bind(req, &objErr) 1133 assert.Error(t, err) 1134 1135 obj = FooStructForStringPtrType{} 1136 req = requestWithBody(method, badPath, badBody) 1137 err = b.Bind(req, &obj) 1138 assert.Error(t, err) 1139 } 1140 } 1141 1142 func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string) { 1143 b := Query 1144 assert.Equal(t, "query", b.Name()) 1145 1146 obj := FooBarStruct{} 1147 req := requestWithBody(method, path, body) 1148 if method == "POST" { 1149 req.Header.Add("Content-Type", MIMEPOSTForm) 1150 } 1151 err := b.Bind(req, &obj) 1152 assert.NoError(t, err) 1153 assert.Equal(t, "bar", obj.Foo) 1154 assert.Equal(t, "foo", obj.Bar) 1155 } 1156 1157 func testQueryBindingFail(t *testing.T, method, path, badPath, body, badBody string) { 1158 b := Query 1159 assert.Equal(t, "query", b.Name()) 1160 1161 obj := FooStructForMapType{} 1162 req := requestWithBody(method, path, body) 1163 if method == "POST" { 1164 req.Header.Add("Content-Type", MIMEPOSTForm) 1165 } 1166 err := b.Bind(req, &obj) 1167 assert.Error(t, err) 1168 } 1169 1170 func testQueryBindingBoolFail(t *testing.T, method, path, badPath, body, badBody string) { 1171 b := Query 1172 assert.Equal(t, "query", b.Name()) 1173 1174 obj := FooStructForBoolType{} 1175 req := requestWithBody(method, path, body) 1176 if method == "POST" { 1177 req.Header.Add("Content-Type", MIMEPOSTForm) 1178 } 1179 err := b.Bind(req, &obj) 1180 assert.Error(t, err) 1181 } 1182 1183 func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) { 1184 assert.Equal(t, name, b.Name()) 1185 1186 obj := FooStruct{} 1187 req := requestWithBody("POST", path, body) 1188 err := b.Bind(req, &obj) 1189 assert.NoError(t, err) 1190 assert.Equal(t, "bar", obj.Foo) 1191 1192 obj = FooStruct{} 1193 req = requestWithBody("POST", badPath, badBody) 1194 err = JSON.Bind(req, &obj) 1195 assert.Error(t, err) 1196 } 1197 1198 func testBodyBindingSlice(t *testing.T, b Binding, name, path, badPath, body, badBody string) { 1199 assert.Equal(t, name, b.Name()) 1200 1201 var obj1 []FooStruct 1202 req := requestWithBody("POST", path, body) 1203 err := b.Bind(req, &obj1) 1204 assert.NoError(t, err) 1205 1206 var obj2 []FooStruct 1207 req = requestWithBody("POST", badPath, badBody) 1208 err = JSON.Bind(req, &obj2) 1209 assert.Error(t, err) 1210 } 1211 1212 func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badBody string) { 1213 obj := make(map[string]string) 1214 req := requestWithBody("POST", path, body) 1215 if b.Name() == "form" { 1216 req.Header.Add("Content-Type", MIMEPOSTForm) 1217 } 1218 err := b.Bind(req, &obj) 1219 assert.NoError(t, err) 1220 assert.NotNil(t, obj) 1221 assert.Len(t, obj, 2) 1222 assert.Equal(t, "bar", obj["foo"]) 1223 assert.Equal(t, "world", obj["hello"]) 1224 1225 if badPath != "" && badBody != "" { 1226 obj = make(map[string]string) 1227 req = requestWithBody("POST", badPath, badBody) 1228 err = b.Bind(req, &obj) 1229 assert.Error(t, err) 1230 } 1231 1232 objInt := make(map[string]int) 1233 req = requestWithBody("POST", path, body) 1234 err = b.Bind(req, &objInt) 1235 assert.Error(t, err) 1236 } 1237 1238 func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body, badBody string) { 1239 assert.Equal(t, name, b.Name()) 1240 1241 obj := FooStructUseNumber{} 1242 req := requestWithBody("POST", path, body) 1243 EnableDecoderUseNumber = true 1244 err := b.Bind(req, &obj) 1245 assert.NoError(t, err) 1246 // we hope it is int64(123) 1247 v, e := obj.Foo.(json.Number).Int64() 1248 assert.NoError(t, e) 1249 assert.Equal(t, int64(123), v) 1250 1251 obj = FooStructUseNumber{} 1252 req = requestWithBody("POST", badPath, badBody) 1253 err = JSON.Bind(req, &obj) 1254 assert.Error(t, err) 1255 } 1256 1257 func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, body, badBody string) { 1258 assert.Equal(t, name, b.Name()) 1259 1260 obj := FooStructUseNumber{} 1261 req := requestWithBody("POST", path, body) 1262 EnableDecoderUseNumber = false 1263 err := b.Bind(req, &obj) 1264 assert.NoError(t, err) 1265 // it will return float64(123) if not use EnableDecoderUseNumber 1266 // maybe it is not hoped 1267 assert.Equal(t, float64(123), obj.Foo) 1268 1269 obj = FooStructUseNumber{} 1270 req = requestWithBody("POST", badPath, badBody) 1271 err = JSON.Bind(req, &obj) 1272 assert.Error(t, err) 1273 } 1274 1275 func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath, body, badBody string) { 1276 EnableDecoderDisallowUnknownFields = true 1277 defer func() { 1278 EnableDecoderDisallowUnknownFields = false 1279 }() 1280 1281 obj := FooStructDisallowUnknownFields{} 1282 req := requestWithBody("POST", path, body) 1283 err := b.Bind(req, &obj) 1284 assert.NoError(t, err) 1285 assert.Equal(t, "bar", obj.Foo) 1286 1287 obj = FooStructDisallowUnknownFields{} 1288 req = requestWithBody("POST", badPath, badBody) 1289 err = JSON.Bind(req, &obj) 1290 assert.Error(t, err) 1291 assert.Contains(t, err.Error(), "what") 1292 } 1293 1294 func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) { 1295 assert.Equal(t, name, b.Name()) 1296 1297 obj := FooStruct{} 1298 req := requestWithBody("POST", path, body) 1299 err := b.Bind(req, &obj) 1300 assert.Error(t, err) 1301 assert.Equal(t, "", obj.Foo) 1302 1303 obj = FooStruct{} 1304 req = requestWithBody("POST", badPath, badBody) 1305 err = JSON.Bind(req, &obj) 1306 assert.Error(t, err) 1307 } 1308 1309 func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) { 1310 assert.Equal(t, name, b.Name()) 1311 1312 obj := protoexample.Test{} 1313 req := requestWithBody("POST", path, body) 1314 req.Header.Add("Content-Type", MIMEPROTOBUF) 1315 err := b.Bind(req, &obj) 1316 assert.NoError(t, err) 1317 assert.Equal(t, "yes", *obj.Label) 1318 1319 obj = protoexample.Test{} 1320 req = requestWithBody("POST", badPath, badBody) 1321 req.Header.Add("Content-Type", MIMEPROTOBUF) 1322 err = ProtoBuf.Bind(req, &obj) 1323 assert.Error(t, err) 1324 } 1325 1326 type hook struct{} 1327 1328 func (h hook) Read([]byte) (int, error) { 1329 return 0, errors.New("error") 1330 } 1331 1332 func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) { 1333 assert.Equal(t, name, b.Name()) 1334 1335 obj := protoexample.Test{} 1336 req := requestWithBody("POST", path, body) 1337 1338 req.Body = ioutil.NopCloser(&hook{}) 1339 req.Header.Add("Content-Type", MIMEPROTOBUF) 1340 err := b.Bind(req, &obj) 1341 assert.Error(t, err) 1342 1343 obj = protoexample.Test{} 1344 req = requestWithBody("POST", badPath, badBody) 1345 req.Header.Add("Content-Type", MIMEPROTOBUF) 1346 err = ProtoBuf.Bind(req, &obj) 1347 assert.Error(t, err) 1348 } 1349 1350 func requestWithBody(method, path, body string) (req *http.Request) { 1351 req, _ = http.NewRequest(method, path, bytes.NewBufferString(body)) 1352 return 1353 }