diff options
Diffstat (limited to 'libgo/go/mime/multipart/multipart_test.go')
-rw-r--r-- | libgo/go/mime/multipart/multipart_test.go | 196 |
1 files changed, 154 insertions, 42 deletions
diff --git a/libgo/go/mime/multipart/multipart_test.go b/libgo/go/mime/multipart/multipart_test.go index 1f3d32d7ed6..8222fbd8a4d 100644 --- a/libgo/go/mime/multipart/multipart_test.go +++ b/libgo/go/mime/multipart/multipart_test.go @@ -8,37 +8,37 @@ import ( "bytes" "fmt" "io" + "io/ioutil" "json" - "regexp" + "os" "strings" "testing" ) func TestHorizontalWhitespace(t *testing.T) { - if !onlyHorizontalWhitespace(" \t") { + if !onlyHorizontalWhitespace([]byte(" \t")) { t.Error("expected pass") } - if onlyHorizontalWhitespace("foo bar") { + if onlyHorizontalWhitespace([]byte("foo bar")) { t.Error("expected failure") } } func TestBoundaryLine(t *testing.T) { - boundary := "myBoundary" - prefix := "--" + boundary - if !isBoundaryDelimiterLine("--myBoundary\r\n", prefix) { + mr := NewReader(strings.NewReader(""), "myBoundary").(*multiReader) + if !mr.isBoundaryDelimiterLine([]byte("--myBoundary\r\n")) { t.Error("expected") } - if !isBoundaryDelimiterLine("--myBoundary \r\n", prefix) { + if !mr.isBoundaryDelimiterLine([]byte("--myBoundary \r\n")) { t.Error("expected") } - if !isBoundaryDelimiterLine("--myBoundary \n", prefix) { + if !mr.isBoundaryDelimiterLine([]byte("--myBoundary \n")) { t.Error("expected") } - if isBoundaryDelimiterLine("--myBoundary bogus \n", prefix) { + if mr.isBoundaryDelimiterLine([]byte("--myBoundary bogus \n")) { t.Error("expected fail") } - if isBoundaryDelimiterLine("--myBoundary bogus--", prefix) { + if mr.isBoundaryDelimiterLine([]byte("--myBoundary bogus--")) { t.Error("expected fail") } } @@ -56,29 +56,32 @@ func expectEq(t *testing.T, expected, actual, what string) { what, escapeString(actual), len(actual), escapeString(expected), len(expected)) } -func TestFormName(t *testing.T) { - p := new(Part) - p.Header = make(map[string][]string) - tests := [...][2]string{ - {`form-data; name="foo"`, "foo"}, - {` form-data ; name=foo`, "foo"}, - {`FORM-DATA;name="foo"`, "foo"}, - {` FORM-DATA ; name="foo"`, "foo"}, - {` FORM-DATA ; name="foo"`, "foo"}, - {` FORM-DATA ; name=foo`, "foo"}, - {` FORM-DATA ; filename="foo.txt"; name=foo; baz=quux`, "foo"}, +func TestNameAccessors(t *testing.T) { + tests := [...][3]string{ + {`form-data; name="foo"`, "foo", ""}, + {` form-data ; name=foo`, "foo", ""}, + {`FORM-DATA;name="foo"`, "foo", ""}, + {` FORM-DATA ; name="foo"`, "foo", ""}, + {` FORM-DATA ; name="foo"`, "foo", ""}, + {` FORM-DATA ; name=foo`, "foo", ""}, + {` FORM-DATA ; filename="foo.txt"; name=foo; baz=quux`, "foo", "foo.txt"}, + {` not-form-data ; filename="bar.txt"; name=foo; baz=quux`, "", "bar.txt"}, } - for _, test := range tests { + for i, test := range tests { + p := &Part{Header: make(map[string][]string)} p.Header.Set("Content-Disposition", test[0]) - expected := test[1] - actual := p.FormName() - if actual != expected { - t.Errorf("expected \"%s\"; got: \"%s\"", expected, actual) + if g, e := p.FormName(), test[1]; g != e { + t.Errorf("test %d: FormName() = %q; want %q", i, g, e) + } + if g, e := p.FileName(), test[2]; g != e { + t.Errorf("test %d: FileName() = %q; want %q", i, g, e) } } } -func TestMultipart(t *testing.T) { +var longLine = strings.Repeat("\n\n\r\r\r\n\r\000", (1<<20)/8) + +func testMultipartBody() string { testBody := ` This is a multi-part message. This line is ignored. --MyBoundary @@ -89,6 +92,10 @@ foo-bar: baz My value The end. --MyBoundary +name: bigsection + +[longline] +--MyBoundary Header1: value1b HEADER2: value2b foo-bar: bazb @@ -101,11 +108,26 @@ Line 3 ends in a newline, but just one. never read data --MyBoundary-- + + +useless trailer ` - testBody = regexp.MustCompile("\n").ReplaceAllString(testBody, "\r\n") - bodyReader := strings.NewReader(testBody) + testBody = strings.Replace(testBody, "\n", "\r\n", -1) + return strings.Replace(testBody, "[longline]", longLine, 1) +} - reader := NewReader(bodyReader, "MyBoundary") +func TestMultipart(t *testing.T) { + bodyReader := strings.NewReader(testMultipartBody()) + testMultipart(t, bodyReader) +} + +func TestMultipartSlowInput(t *testing.T) { + bodyReader := strings.NewReader(testMultipartBody()) + testMultipart(t, &slowReader{bodyReader}) +} + +func testMultipart(t *testing.T, r io.Reader) { + reader := NewReader(r, "MyBoundary") buf := new(bytes.Buffer) // Part1 @@ -124,38 +146,64 @@ never read data t.Error("Expected Foo-Bar: baz") } buf.Reset() - io.Copy(buf, part) + if _, err := io.Copy(buf, part); err != nil { + t.Errorf("part 1 copy: %v", err) + } expectEq(t, "My value\r\nThe end.", buf.String(), "Value of first part") // Part2 part, err = reader.NextPart() + if err != nil { + t.Fatalf("Expected part2; got: %v", err) + return + } + if e, g := "bigsection", part.Header.Get("name"); e != g { + t.Errorf("part2's name header: expected %q, got %q", e, g) + } + buf.Reset() + if _, err := io.Copy(buf, part); err != nil { + t.Errorf("part 2 copy: %v", err) + } + s := buf.String() + if len(s) != len(longLine) { + t.Errorf("part2 body expected long line of length %d; got length %d", + len(longLine), len(s)) + } + if s != longLine { + t.Errorf("part2 long body didn't match") + } + + // Part3 + part, err = reader.NextPart() if part == nil || err != nil { - t.Error("Expected part2") + t.Error("Expected part3") return } if part.Header.Get("foo-bar") != "bazb" { t.Error("Expected foo-bar: bazb") } buf.Reset() - io.Copy(buf, part) + if _, err := io.Copy(buf, part); err != nil { + t.Errorf("part 3 copy: %v", err) + } expectEq(t, "Line 1\r\nLine 2\r\nLine 3 ends in a newline, but just one.\r\n", - buf.String(), "Value of second part") + buf.String(), "body of part 3") - // Part3 + // Part4 part, err = reader.NextPart() if part == nil || err != nil { - t.Error("Expected part3 without errors") + t.Error("Expected part 4 without errors") return } - // Non-existent part4 + // Non-existent part5 part, err = reader.NextPart() if part != nil { - t.Error("Didn't expect a third part.") + t.Error("Didn't expect a fifth part.") } - if err != nil { - t.Errorf("Unexpected error getting third part: %v", err) + if err != os.EOF { + t.Errorf("On fifth part expected os.EOF; got %v", err) } } @@ -199,9 +247,73 @@ func TestVariousTextLineEndings(t *testing.T) { if part != nil { t.Errorf("Unexpected part in test %d", testNum) } - if err != nil { - t.Errorf("Unexpected error in test %d: %v", testNum, err) + if err != os.EOF { + t.Errorf("On test %d expected os.EOF; got %v", testNum, err) } } } + +type maliciousReader struct { + t *testing.T + n int +} + +const maxReadThreshold = 1 << 20 + +func (mr *maliciousReader) Read(b []byte) (n int, err os.Error) { + mr.n += len(b) + if mr.n >= maxReadThreshold { + mr.t.Fatal("too much was read") + return 0, os.EOF + } + return len(b), nil +} + +func TestLineLimit(t *testing.T) { + mr := &maliciousReader{t: t} + r := NewReader(mr, "fooBoundary") + part, err := r.NextPart() + if part != nil { + t.Errorf("unexpected part read") + } + if err == nil { + t.Errorf("expected an error") + } + if mr.n >= maxReadThreshold { + t.Errorf("expected to read < %d bytes; read %d", maxReadThreshold, mr.n) + } +} + +func TestMultipartTruncated(t *testing.T) { + testBody := ` +This is a multi-part message. This line is ignored. +--MyBoundary +foo-bar: baz + +Oh no, premature EOF! +` + body := strings.Replace(testBody, "\n", "\r\n", -1) + bodyReader := strings.NewReader(body) + r := NewReader(bodyReader, "MyBoundary") + + part, err := r.NextPart() + if err != nil { + t.Fatalf("didn't get a part") + } + _, err = io.Copy(ioutil.Discard, part) + if err != io.ErrUnexpectedEOF { + t.Fatalf("expected error io.ErrUnexpectedEOF; got %v", err) + } +} + +type slowReader struct { + r io.Reader +} + +func (s *slowReader) Read(p []byte) (int, os.Error) { + if len(p) == 0 { + return s.r.Read(p) + } + return s.r.Read(p[:1]) +} |