summaryrefslogtreecommitdiff
path: root/libgo/go/mime/multipart/multipart_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/mime/multipart/multipart_test.go')
-rw-r--r--libgo/go/mime/multipart/multipart_test.go196
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])
+}