github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/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 "regexp" 12 "strings" 13 "testing" 14 ) 15 16 func TestReadForm(t *testing.T) { 17 testBody := regexp.MustCompile("\n").ReplaceAllString(message, "\r\n") 18 b := strings.NewReader(testBody) 19 r := NewReader(b, boundary) 20 f, err := r.ReadForm(25) 21 if err != nil { 22 t.Fatal("ReadForm:", err) 23 } 24 defer f.RemoveAll() 25 if g, e := f.Value["texta"][0], textaValue; g != e { 26 t.Errorf("texta value = %q, want %q", g, e) 27 } 28 if g, e := f.Value["textb"][0], textbValue; g != e { 29 t.Errorf("texta value = %q, want %q", g, e) 30 } 31 fd := testFile(t, f.File["filea"][0], "filea.txt", fileaContents) 32 if _, ok := fd.(*os.File); ok { 33 t.Error("file is *os.File, should not be") 34 } 35 fd.Close() 36 fd = testFile(t, f.File["fileb"][0], "fileb.txt", filebContents) 37 if _, ok := fd.(*os.File); !ok { 38 t.Errorf("file has unexpected underlying type %T", fd) 39 } 40 fd.Close() 41 } 42 43 func testFile(t *testing.T, fh *FileHeader, efn, econtent string) File { 44 if fh.Filename != efn { 45 t.Errorf("filename = %q, want %q", fh.Filename, efn) 46 } 47 if fh.Size != int64(len(econtent)) { 48 t.Errorf("size = %d, want %d", fh.Size, len(econtent)) 49 } 50 f, err := fh.Open() 51 if err != nil { 52 t.Fatal("opening file:", err) 53 } 54 b := new(bytes.Buffer) 55 _, err = io.Copy(b, f) 56 if err != nil { 57 t.Fatal("copying contents:", err) 58 } 59 if g := b.String(); g != econtent { 60 t.Errorf("contents = %q, want %q", g, econtent) 61 } 62 return f 63 } 64 65 const ( 66 fileaContents = "This is a test file." 67 filebContents = "Another test file." 68 textaValue = "foo" 69 textbValue = "bar" 70 boundary = `MyBoundary` 71 ) 72 73 const message = ` 74 --MyBoundary 75 Content-Disposition: form-data; name="filea"; filename="filea.txt" 76 Content-Type: text/plain 77 78 ` + fileaContents + ` 79 --MyBoundary 80 Content-Disposition: form-data; name="fileb"; filename="fileb.txt" 81 Content-Type: text/plain 82 83 ` + filebContents + ` 84 --MyBoundary 85 Content-Disposition: form-data; name="texta" 86 87 ` + textaValue + ` 88 --MyBoundary 89 Content-Disposition: form-data; name="textb" 90 91 ` + textbValue + ` 92 --MyBoundary-- 93 ` 94 95 func TestReadForm_NoReadAfterEOF(t *testing.T) { 96 maxMemory := int64(32) << 20 97 boundary := `---------------------------8d345eef0d38dc9` 98 body := ` 99 -----------------------------8d345eef0d38dc9 100 Content-Disposition: form-data; name="version" 101 102 171 103 -----------------------------8d345eef0d38dc9--` 104 105 mr := NewReader(&failOnReadAfterErrorReader{t: t, r: strings.NewReader(body)}, boundary) 106 107 f, err := mr.ReadForm(maxMemory) 108 if err != nil { 109 t.Fatal(err) 110 } 111 t.Logf("Got: %#v", f) 112 } 113 114 // failOnReadAfterErrorReader is an io.Reader wrapping r. 115 // It fails t if any Read is called after a failing Read. 116 type failOnReadAfterErrorReader struct { 117 t *testing.T 118 r io.Reader 119 sawErr error 120 } 121 122 func (r *failOnReadAfterErrorReader) Read(p []byte) (n int, err error) { 123 if r.sawErr != nil { 124 r.t.Fatalf("unexpected Read on Reader after previous read saw error %v", r.sawErr) 125 } 126 n, err = r.r.Read(p) 127 r.sawErr = err 128 return 129 }