blob: f737a907008a8432cf53b2b0172d5e00cafb7505 [file] [log] [blame]
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package multipart
import (
"bytes"
"fmt"
"io"
"json"
"regexp"
"strings"
"testing"
)
func TestHorizontalWhitespace(t *testing.T) {
if !onlyHorizontalWhitespace(" \t") {
t.Error("expected pass")
}
if onlyHorizontalWhitespace("foo bar") {
t.Error("expected failure")
}
}
func TestBoundaryLine(t *testing.T) {
boundary := "myBoundary"
prefix := "--" + boundary
if !isBoundaryDelimiterLine("--myBoundary\r\n", prefix) {
t.Error("expected")
}
if !isBoundaryDelimiterLine("--myBoundary \r\n", prefix) {
t.Error("expected")
}
if !isBoundaryDelimiterLine("--myBoundary \n", prefix) {
t.Error("expected")
}
if isBoundaryDelimiterLine("--myBoundary bogus \n", prefix) {
t.Error("expected fail")
}
if isBoundaryDelimiterLine("--myBoundary bogus--", prefix) {
t.Error("expected fail")
}
}
func escapeString(v string) string {
bytes, _ := json.Marshal(v)
return string(bytes)
}
func expectEq(t *testing.T, expected, actual, what string) {
if expected == actual {
return
}
t.Errorf("Unexpected value for %s; got %s (len %d) but expected: %s (len %d)",
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{
[2]string{`form-data; name="foo"`, "foo"},
[2]string{` form-data ; name=foo`, "foo"},
[2]string{`FORM-DATA;name="foo"`, "foo"},
[2]string{` FORM-DATA ; name="foo"`, "foo"},
[2]string{` FORM-DATA ; name="foo"`, "foo"},
[2]string{` FORM-DATA ; name=foo`, "foo"},
[2]string{` FORM-DATA ; filename="foo.txt"; name=foo; baz=quux`, "foo"},
}
for _, test := range tests {
p.Header["Content-Disposition"] = test[0]
expected := test[1]
actual := p.FormName()
if actual != expected {
t.Errorf("expected \"%s\"; got: \"%s\"", expected, actual)
}
}
}
func TestMultipart(t *testing.T) {
testBody := `
This is a multi-part message. This line is ignored.
--MyBoundary
Header1: value1
HEADER2: value2
foo-bar: baz
My value
The end.
--MyBoundary
Header1: value1b
HEADER2: value2b
foo-bar: bazb
Line 1
Line 2
Line 3 ends in a newline, but just one.
--MyBoundary
never read data
--MyBoundary--
`
testBody = regexp.MustCompile("\n").ReplaceAllString(testBody, "\r\n")
bodyReader := strings.NewReader(testBody)
reader := NewReader(bodyReader, "MyBoundary")
buf := new(bytes.Buffer)
// Part1
part, err := reader.NextPart()
if part == nil || err != nil {
t.Error("Expected part1")
return
}
if part.Header["Header1"] != "value1" {
t.Error("Expected Header1: value")
}
if part.Header["foo-bar"] != "baz" {
t.Error("Expected foo-bar: baz")
}
buf.Reset()
io.Copy(buf, part)
expectEq(t, "My value\r\nThe end.",
buf.String(), "Value of first part")
// Part2
part, err = reader.NextPart()
if part == nil || err != nil {
t.Error("Expected part2")
return
}
if part.Header["foo-bar"] != "bazb" {
t.Error("Expected foo-bar: bazb")
}
buf.Reset()
io.Copy(buf, part)
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")
// Part3
part, err = reader.NextPart()
if part == nil || err != nil {
t.Error("Expected part3 without errors")
return
}
// Non-existent part4
part, err = reader.NextPart()
if part != nil {
t.Error("Didn't expect a third part.")
}
if err != nil {
t.Errorf("Unexpected error getting third part: %v", err)
}
}
func TestVariousTextLineEndings(t *testing.T) {
tests := [...]string{
"Foo\nBar",
"Foo\nBar\n",
"Foo\r\nBar",
"Foo\r\nBar\r\n",
"Foo\rBar",
"Foo\rBar\r",
"\x00\x01\x02\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10",
}
for testNum, expectedBody := range tests {
body := "--BOUNDARY\r\n" +
"Content-Disposition: form-data; name=\"value\"\r\n" +
"\r\n" +
expectedBody +
"\r\n--BOUNDARY--\r\n"
bodyReader := strings.NewReader(body)
reader := NewReader(bodyReader, "BOUNDARY")
buf := new(bytes.Buffer)
part, err := reader.NextPart()
if part == nil {
t.Errorf("Expected a body part on text %d", testNum)
continue
}
if err != nil {
t.Errorf("Unexpected error on text %d: %v", testNum, err)
continue
}
written, err := io.Copy(buf, part)
expectEq(t, expectedBody, buf.String(), fmt.Sprintf("test %d", testNum))
if err != nil {
t.Errorf("Error copying multipart; bytes=%v, error=%v", written, err)
}
part, err = reader.NextPart()
if part != nil {
t.Errorf("Unexpected part in test %d", testNum)
}
if err != nil {
t.Errorf("Unexpected error in test %d: %v", testNum, err)
}
}
}