github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/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 testFile(t *testing.T, fh *FileHeader, efn, econtent string) File { 42 if fh.Filename != efn { 43 t.Errorf("filename = %q, want %q", fh.Filename, efn) 44 } 45 if fh.Size != int64(len(econtent)) { 46 t.Errorf("size = %d, want %d", fh.Size, len(econtent)) 47 } 48 f, err := fh.Open() 49 if err != nil { 50 t.Fatal("opening file:", err) 51 } 52 b := new(bytes.Buffer) 53 _, err = io.Copy(b, f) 54 if err != nil { 55 t.Fatal("copying contents:", err) 56 } 57 if g := b.String(); g != econtent { 58 t.Errorf("contents = %q, want %q", g, econtent) 59 } 60 return f 61 } 62 63 const ( 64 fileaContents = "This is a test file." 65 filebContents = "Another test file." 66 textaValue = "foo" 67 textbValue = "bar" 68 boundary = `MyBoundary` 69 ) 70 71 const message = ` 72 --MyBoundary 73 Content-Disposition: form-data; name="filea"; filename="filea.txt" 74 Content-Type: text/plain 75 76 ` + fileaContents + ` 77 --MyBoundary 78 Content-Disposition: form-data; name="fileb"; filename="fileb.txt" 79 Content-Type: text/plain 80 81 ` + filebContents + ` 82 --MyBoundary 83 Content-Disposition: form-data; name="texta" 84 85 ` + textaValue + ` 86 --MyBoundary 87 Content-Disposition: form-data; name="textb" 88 89 ` + textbValue + ` 90 --MyBoundary-- 91 ` 92 93 func TestReadForm_NoReadAfterEOF(t *testing.T) { 94 maxMemory := int64(32) << 20 95 boundary := `---------------------------8d345eef0d38dc9` 96 body := ` 97 -----------------------------8d345eef0d38dc9 98 Content-Disposition: form-data; name="version" 99 100 171 101 -----------------------------8d345eef0d38dc9--` 102 103 mr := NewReader(&failOnReadAfterErrorReader{t: t, r: strings.NewReader(body)}, boundary) 104 105 f, err := mr.ReadForm(maxMemory) 106 if err != nil { 107 t.Fatal(err) 108 } 109 t.Logf("Got: %#v", f) 110 } 111 112 // failOnReadAfterErrorReader is an io.Reader wrapping r. 113 // It fails t if any Read is called after a failing Read. 114 type failOnReadAfterErrorReader struct { 115 t *testing.T 116 r io.Reader 117 sawErr error 118 } 119 120 func (r *failOnReadAfterErrorReader) Read(p []byte) (n int, err error) { 121 if r.sawErr != nil { 122 r.t.Fatalf("unexpected Read on Reader after previous read saw error %v", r.sawErr) 123 } 124 n, err = r.r.Read(p) 125 r.sawErr = err 126 return 127 } 128 129 // TestReadForm_NonFileMaxMemory asserts that the ReadForm maxMemory limit is applied 130 // while processing non-file form data as well as file form data. 131 func TestReadForm_NonFileMaxMemory(t *testing.T) { 132 largeTextValue := strings.Repeat("1", (10<<20)+25) 133 message := `--MyBoundary 134 Content-Disposition: form-data; name="largetext" 135 136 ` + largeTextValue + ` 137 --MyBoundary-- 138 ` 139 140 testBody := strings.Replace(message, "\n", "\r\n", -1) 141 testCases := []struct { 142 name string 143 maxMemory int64 144 err error 145 }{ 146 {"smaller", 50, nil}, 147 {"exact-fit", 25, nil}, 148 {"too-large", 0, ErrMessageTooLarge}, 149 } 150 for _, tc := range testCases { 151 t.Run(tc.name, func(t *testing.T) { 152 b := strings.NewReader(testBody) 153 r := NewReader(b, boundary) 154 f, err := r.ReadForm(tc.maxMemory) 155 if err == nil { 156 defer f.RemoveAll() 157 } 158 if tc.err != err { 159 t.Fatalf("ReadForm error - got: %v; expected: %v", tc.err, err) 160 } 161 if err == nil { 162 if g := f.Value["largetext"][0]; g != largeTextValue { 163 t.Errorf("largetext mismatch: got size: %v, expected size: %v", len(g), len(largeTextValue)) 164 } 165 } 166 }) 167 } 168 }