multipart_form_mapping_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright 2019 Gin Core Team. 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. "io/ioutil"
  8. "mime/multipart"
  9. "net/http"
  10. "testing"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestFormMultipartBindingBindOneFile(t *testing.T) {
  14. var s struct {
  15. FileValue multipart.FileHeader `form:"file"`
  16. FilePtr *multipart.FileHeader `form:"file"`
  17. SliceValues []multipart.FileHeader `form:"file"`
  18. SlicePtrs []*multipart.FileHeader `form:"file"`
  19. ArrayValues [1]multipart.FileHeader `form:"file"`
  20. ArrayPtrs [1]*multipart.FileHeader `form:"file"`
  21. }
  22. file := testFile{"file", "file1", []byte("hello")}
  23. req := createRequestMultipartFiles(t, file)
  24. err := FormMultipart.Bind(req, &s)
  25. assert.NoError(t, err)
  26. assertMultipartFileHeader(t, &s.FileValue, file)
  27. assertMultipartFileHeader(t, s.FilePtr, file)
  28. assert.Len(t, s.SliceValues, 1)
  29. assertMultipartFileHeader(t, &s.SliceValues[0], file)
  30. assert.Len(t, s.SlicePtrs, 1)
  31. assertMultipartFileHeader(t, s.SlicePtrs[0], file)
  32. assertMultipartFileHeader(t, &s.ArrayValues[0], file)
  33. assertMultipartFileHeader(t, s.ArrayPtrs[0], file)
  34. }
  35. func TestFormMultipartBindingBindTwoFiles(t *testing.T) {
  36. var s struct {
  37. SliceValues []multipart.FileHeader `form:"file"`
  38. SlicePtrs []*multipart.FileHeader `form:"file"`
  39. ArrayValues [2]multipart.FileHeader `form:"file"`
  40. ArrayPtrs [2]*multipart.FileHeader `form:"file"`
  41. }
  42. files := []testFile{
  43. {"file", "file1", []byte("hello")},
  44. {"file", "file2", []byte("world")},
  45. }
  46. req := createRequestMultipartFiles(t, files...)
  47. err := FormMultipart.Bind(req, &s)
  48. assert.NoError(t, err)
  49. assert.Len(t, s.SliceValues, len(files))
  50. assert.Len(t, s.SlicePtrs, len(files))
  51. assert.Len(t, s.ArrayValues, len(files))
  52. assert.Len(t, s.ArrayPtrs, len(files))
  53. for i, file := range files {
  54. assertMultipartFileHeader(t, &s.SliceValues[i], file)
  55. assertMultipartFileHeader(t, s.SlicePtrs[i], file)
  56. assertMultipartFileHeader(t, &s.ArrayValues[i], file)
  57. assertMultipartFileHeader(t, s.ArrayPtrs[i], file)
  58. }
  59. }
  60. func TestFormMultipartBindingBindError(t *testing.T) {
  61. files := []testFile{
  62. {"file", "file1", []byte("hello")},
  63. {"file", "file2", []byte("world")},
  64. }
  65. for _, tt := range []struct {
  66. name string
  67. s interface{}
  68. }{
  69. {"wrong type", &struct {
  70. Files int `form:"file"`
  71. }{}},
  72. {"wrong array size", &struct {
  73. Files [1]*multipart.FileHeader `form:"file"`
  74. }{}},
  75. {"wrong slice type", &struct {
  76. Files []int `form:"file"`
  77. }{}},
  78. } {
  79. req := createRequestMultipartFiles(t, files...)
  80. err := FormMultipart.Bind(req, tt.s)
  81. assert.Error(t, err)
  82. }
  83. }
  84. type testFile struct {
  85. Fieldname string
  86. Filename string
  87. Content []byte
  88. }
  89. func createRequestMultipartFiles(t *testing.T, files ...testFile) *http.Request {
  90. var body bytes.Buffer
  91. mw := multipart.NewWriter(&body)
  92. for _, file := range files {
  93. fw, err := mw.CreateFormFile(file.Fieldname, file.Filename)
  94. assert.NoError(t, err)
  95. n, err := fw.Write(file.Content)
  96. assert.NoError(t, err)
  97. assert.Equal(t, len(file.Content), n)
  98. }
  99. err := mw.Close()
  100. assert.NoError(t, err)
  101. req, err := http.NewRequest("POST", "/", &body)
  102. assert.NoError(t, err)
  103. req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+mw.Boundary())
  104. return req
  105. }
  106. func assertMultipartFileHeader(t *testing.T, fh *multipart.FileHeader, file testFile) {
  107. assert.Equal(t, file.Filename, fh.Filename)
  108. // assert.Equal(t, int64(len(file.Content)), fh.Size) // fh.Size does not exist on go1.8
  109. fl, err := fh.Open()
  110. assert.NoError(t, err)
  111. body, err := ioutil.ReadAll(fl)
  112. assert.NoError(t, err)
  113. assert.Equal(t, string(file.Content), string(body))
  114. err = fl.Close()
  115. assert.NoError(t, err)
  116. }