github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/mime/multipart/formdata_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package multipart 6 7 import ( 8 "bytes" 9 "io" 10 "os" 11 "strings" 12 "testing" 13 ) 14 15 func TestReadForm(t *testing.T) { 16 b := strings.NewReader(strings.Replace(message, "\n", "\r\n", -1)) 17 r := NewReader(b, boundary) 18 f, err := r.ReadForm(25) 19 if err != nil { 20 t.Fatal("ReadForm:", err) 21 } 22 defer f.RemoveAll() 23 if g, e := f.Value["texta"][0], textaValue; g != e { 24 t.Errorf("texta value = %q, want %q", g, e) 25 } 26 if g, e := f.Value["textb"][0], textbValue; g != e { 27 t.Errorf("texta value = %q, want %q", g, e) 28 } 29 fd := testFile(t, f.File["filea"][0], "filea.txt", fileaContents) 30 if _, ok := fd.(*os.File); ok { 31 t.Error("file is *os.File, should not be") 32 } 33 fd.Close() 34 fd = testFile(t, f.File["fileb"][0], "fileb.txt", filebContents) 35 if _, ok := fd.(*os.File); !ok { 36 t.Errorf("file has unexpected underlying type %T", fd) 37 } 38 fd.Close() 39 } 40 41 func TestReadFormWithNamelessFile(t *testing.T) { 42 b := strings.NewReader(strings.Replace(messageWithFileWithoutName, "\n", "\r\n", -1)) 43 r := NewReader(b, boundary) 44 f, err := r.ReadForm(25) 45 if err != nil { 46 t.Fatal("ReadForm:", err) 47 } 48 defer f.RemoveAll() 49 50 fd := testFile(t, f.File["hiddenfile"][0], "", filebContents) 51 if _, ok := fd.(sectionReadCloser); !ok { 52 t.Errorf("file has unexpected underlying type %T", fd) 53 } 54 fd.Close() 55 56 } 57 58 func testFile(t *testing.T, fh *FileHeader, efn, econtent string) File { 59 if fh.Filename != efn { 60 t.Errorf("filename = %q, want %q", fh.Filename, efn) 61 } 62 if fh.Size != int64(len(econtent)) { 63 t.Errorf("size = %d, want %d", fh.Size, len(econtent)) 64 } 65 f, err := fh.Open() 66 if err != nil { 67 t.Fatal("opening file:", err) 68 } 69 b := new(bytes.Buffer) 70 _, err = io.Copy(b, f) 71 if err != nil { 72 t.Fatal("copying contents:", err) 73 } 74 if g := b.String(); g != econtent { 75 t.Errorf("contents = %q, want %q", g, econtent) 76 } 77 return f 78 } 79 80 const ( 81 fileaContents = "This is a test file." 82 filebContents = "Another test file." 83 textaValue = "foo" 84 textbValue = "bar" 85 boundary = `MyBoundary` 86 ) 87 88 const messageWithFileWithoutName = ` 89 --MyBoundary 90 Content-Disposition: form-data; name="hiddenfile"; filename="" 91 Content-Type: text/plain 92 93 ` + filebContents + ` 94 --MyBoundary-- 95 ` 96 97 const message = ` 98 --MyBoundary 99 Content-Disposition: form-data; name="filea"; filename="filea.txt" 100 Content-Type: text/plain 101 102 ` + fileaContents + ` 103 --MyBoundary 104 Content-Disposition: form-data; name="fileb"; filename="fileb.txt" 105 Content-Type: text/plain 106 107 ` + filebContents + ` 108 --MyBoundary 109 Content-Disposition: form-data; name="texta" 110 111 ` + textaValue + ` 112 --MyBoundary 113 Content-Disposition: form-data; name="textb" 114 115 ` + textbValue + ` 116 --MyBoundary-- 117 ` 118 119 func TestReadForm_NoReadAfterEOF(t *testing.T) { 120 maxMemory := int64(32) << 20 121 boundary := `---------------------------8d345eef0d38dc9` 122 body := ` 123 -----------------------------8d345eef0d38dc9 124 Content-Disposition: form-data; name="version" 125 126 171 127 -----------------------------8d345eef0d38dc9--` 128 129 mr := NewReader(&failOnReadAfterErrorReader{t: t, r: strings.NewReader(body)}, boundary) 130 131 f, err := mr.ReadForm(maxMemory) 132 if err != nil { 133 t.Fatal(err) 134 } 135 t.Logf("Got: %#v", f) 136 } 137 138 // failOnReadAfterErrorReader is an io.Reader wrapping r. 139 // It fails t if any Read is called after a failing Read. 140 type failOnReadAfterErrorReader struct { 141 t *testing.T 142 r io.Reader 143 sawErr error 144 } 145 146 func (r *failOnReadAfterErrorReader) Read(p []byte) (n int, err error) { 147 if r.sawErr != nil { 148 r.t.Fatalf("unexpected Read on Reader after previous read saw error %v", r.sawErr) 149 } 150 n, err = r.r.Read(p) 151 r.sawErr = err 152 return 153 } 154 155 // TestReadForm_NonFileMaxMemory asserts that the ReadForm maxMemory limit is applied 156 // while processing non-file form data as well as file form data. 157 func TestReadForm_NonFileMaxMemory(t *testing.T) { 158 largeTextValue := strings.Repeat("1", (10<<20)+25) 159 message := `--MyBoundary 160 Content-Disposition: form-data; name="largetext" 161 162 ` + largeTextValue + ` 163 --MyBoundary-- 164 ` 165 166 testBody := strings.Replace(message, "\n", "\r\n", -1) 167 testCases := []struct { 168 name string 169 maxMemory int64 170 err error 171 }{ 172 {"smaller", 50, nil}, 173 {"exact-fit", 25, nil}, 174 {"too-large", 0, ErrMessageTooLarge}, 175 } 176 for _, tc := range testCases { 177 t.Run(tc.name, func(t *testing.T) { 178 b := strings.NewReader(testBody) 179 r := NewReader(b, boundary) 180 f, err := r.ReadForm(tc.maxMemory) 181 if err == nil { 182 defer f.RemoveAll() 183 } 184 if tc.err != err { 185 t.Fatalf("ReadForm error - got: %v; expected: %v", tc.err, err) 186 } 187 if err == nil { 188 if g := f.Value["largetext"][0]; g != largeTextValue { 189 t.Errorf("largetext mismatch: got size: %v, expected size: %v", len(g), len(largeTextValue)) 190 } 191 } 192 }) 193 } 194 }