205 lines
4.6 KiB
Go
205 lines
4.6 KiB
Go
|
// 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{
|
||
|
{`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"},
|
||
|
}
|
||
|
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)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|