// 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)
		}

	}
}
