aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Smith <quentin@golang.org>2016-10-25 15:41:14 -0400
committerBrad Fitzpatrick <bradfitz@golang.org>2016-11-07 19:32:11 +0000
commit9e4a70e8fd3e6fed93fcd6159228b3a8ecae1d80 (patch)
tree5ee3e1f57057e5179a4e88879ddd1cbda329428e
parent44febb28b626695e2daa693b1aa9ad7e516518e3 (diff)
downloadgo-9e4a70e8fd3e6fed93fcd6159228b3a8ecae1d80.tar.gz
go-9e4a70e8fd3e6fed93fcd6159228b3a8ecae1d80.zip
mime/multipart: test for overreading on a stream
Some multipart data arrives in a stream, where subsequent parts may not be ready yet. Read should return a complete part as soon as possible. Fixes #15431 Change-Id: Ie8c041b853f3e07f0f2a66fbf4bcab5fe9132a7c Reviewed-on: https://go-review.googlesource.com/32032 Run-TryBot: Quentin Smith <quentin@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
-rw-r--r--src/mime/multipart/multipart_test.go67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/mime/multipart/multipart_test.go b/src/mime/multipart/multipart_test.go
index d74ef61b88..7fbee90ac3 100644
--- a/src/mime/multipart/multipart_test.go
+++ b/src/mime/multipart/multipart_test.go
@@ -324,6 +324,73 @@ func (s *slowReader) Read(p []byte) (int, error) {
return s.r.Read(p[:1])
}
+type sentinelReader struct {
+ // done is closed when this reader is read from.
+ done chan struct{}
+}
+
+func (s *sentinelReader) Read([]byte) (int, error) {
+ if s.done != nil {
+ close(s.done)
+ s.done = nil
+ }
+ return 0, io.EOF
+}
+
+// TestMultipartStreamReadahead tests that PartReader does not block
+// on reading past the end of a part, ensuring that it can be used on
+// a stream like multipart/x-mixed-replace. See golang.org/issue/15431
+func TestMultipartStreamReadahead(t *testing.T) {
+ testBody1 := `
+This is a multi-part message. This line is ignored.
+--MyBoundary
+foo-bar: baz
+
+Body
+--MyBoundary
+`
+ testBody2 := `foo-bar: bop
+
+Body 2
+--MyBoundary--
+`
+ done1 := make(chan struct{})
+ reader := NewReader(
+ io.MultiReader(
+ strings.NewReader(testBody1),
+ &sentinelReader{done1},
+ strings.NewReader(testBody2)),
+ "MyBoundary")
+
+ var i int
+ readPart := func(hdr textproto.MIMEHeader, body string) {
+ part, err := reader.NextPart()
+ if part == nil || err != nil {
+ t.Fatalf("Part %d: NextPart failed: %v", i, err)
+ }
+
+ if !reflect.DeepEqual(part.Header, hdr) {
+ t.Errorf("Part %d: part.Header = %v, want %v", i, part.Header, hdr)
+ }
+ data, err := ioutil.ReadAll(part)
+ expectEq(t, body, string(data), fmt.Sprintf("Part %d body", i))
+ if err != nil {
+ t.Fatalf("Part %d: ReadAll failed: %v", i, err)
+ }
+ i++
+ }
+
+ readPart(textproto.MIMEHeader{"Foo-Bar": {"baz"}}, "Body")
+
+ select {
+ case <-done1:
+ t.Errorf("Reader read past second boundary")
+ default:
+ }
+
+ readPart(textproto.MIMEHeader{"Foo-Bar": {"bop"}}, "Body 2")
+}
+
func TestLineContinuation(t *testing.T) {
// This body, extracted from an email, contains headers that span multiple
// lines.