...
Run Format

Source file src/mime/multipart/formdata_test.go

Documentation: mime/multipart

     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  }
   195  

View as plain text