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  }