e7a9d23640
Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)
292 lines
6.5 KiB
Go
292 lines
6.5 KiB
Go
package engine
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestOutputAddString(t *testing.T) {
|
|
var testInputs = [][2]string{
|
|
{
|
|
"hello, world!",
|
|
"hello, world!",
|
|
},
|
|
|
|
{
|
|
"One\nTwo\nThree",
|
|
"Three",
|
|
},
|
|
|
|
{
|
|
"",
|
|
"",
|
|
},
|
|
|
|
{
|
|
"A line\nThen another nl-terminated line\n",
|
|
"Then another nl-terminated line",
|
|
},
|
|
|
|
{
|
|
"A line followed by an empty line\n\n",
|
|
"",
|
|
},
|
|
}
|
|
for _, testData := range testInputs {
|
|
input := testData[0]
|
|
expectedOutput := testData[1]
|
|
o := NewOutput()
|
|
var output string
|
|
if err := o.AddString(&output); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if n, err := o.Write([]byte(input)); err != nil {
|
|
t.Error(err)
|
|
} else if n != len(input) {
|
|
t.Errorf("Expected %d, got %d", len(input), n)
|
|
}
|
|
o.Close()
|
|
if output != expectedOutput {
|
|
t.Errorf("Last line is not stored as return string.\nInput: '%s'\nExpected: '%s'\nGot: '%s'", input, expectedOutput, output)
|
|
}
|
|
}
|
|
}
|
|
|
|
type sentinelWriteCloser struct {
|
|
calledWrite bool
|
|
calledClose bool
|
|
}
|
|
|
|
func (w *sentinelWriteCloser) Write(p []byte) (int, error) {
|
|
w.calledWrite = true
|
|
return len(p), nil
|
|
}
|
|
|
|
func (w *sentinelWriteCloser) Close() error {
|
|
w.calledClose = true
|
|
return nil
|
|
}
|
|
|
|
func TestOutputAddEnv(t *testing.T) {
|
|
input := "{\"foo\": \"bar\", \"answer_to_life_the_universe_and_everything\": 42}"
|
|
o := NewOutput()
|
|
result, err := o.AddEnv()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
o.Write([]byte(input))
|
|
o.Close()
|
|
if v := result.Get("foo"); v != "bar" {
|
|
t.Errorf("Expected %v, got %v", "bar", v)
|
|
}
|
|
if v := result.GetInt("answer_to_life_the_universe_and_everything"); v != 42 {
|
|
t.Errorf("Expected %v, got %v", 42, v)
|
|
}
|
|
if v := result.Get("this-value-doesnt-exist"); v != "" {
|
|
t.Errorf("Expected %v, got %v", "", v)
|
|
}
|
|
}
|
|
|
|
func TestOutputAddClose(t *testing.T) {
|
|
o := NewOutput()
|
|
var s sentinelWriteCloser
|
|
o.Add(&s)
|
|
if err := o.Close(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Write data after the output is closed.
|
|
// Write should succeed, but no destination should receive it.
|
|
if _, err := o.Write([]byte("foo bar")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !s.calledClose {
|
|
t.Fatal("Output.Close() didn't close the destination")
|
|
}
|
|
}
|
|
|
|
func TestOutputAddPipe(t *testing.T) {
|
|
var testInputs = []string{
|
|
"hello, world!",
|
|
"One\nTwo\nThree",
|
|
"",
|
|
"A line\nThen another nl-terminated line\n",
|
|
"A line followed by an empty line\n\n",
|
|
}
|
|
for _, input := range testInputs {
|
|
expectedOutput := input
|
|
o := NewOutput()
|
|
r, err := o.AddPipe()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
go func(o *Output) {
|
|
if n, err := o.Write([]byte(input)); err != nil {
|
|
t.Error(err)
|
|
} else if n != len(input) {
|
|
t.Errorf("Expected %d, got %d", len(input), n)
|
|
}
|
|
if err := o.Close(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}(o)
|
|
output, err := ioutil.ReadAll(r)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(output) != expectedOutput {
|
|
t.Errorf("Last line is not stored as return string.\nExpected: '%s'\nGot: '%s'", expectedOutput, output)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTail(t *testing.T) {
|
|
var tests = make(map[string][][]string)
|
|
tests["hello, world!"] = [][]string{
|
|
{},
|
|
{"hello, world!"},
|
|
{"hello, world!"},
|
|
{"hello, world!"},
|
|
}
|
|
tests["One\nTwo\nThree"] = [][]string{
|
|
{},
|
|
{"Three"},
|
|
{"Two", "Three"},
|
|
{"One", "Two", "Three"},
|
|
}
|
|
for input, outputs := range tests {
|
|
for n, expectedOutput := range outputs {
|
|
var output []string
|
|
Tail(strings.NewReader(input), n, &output)
|
|
if fmt.Sprintf("%v", output) != fmt.Sprintf("%v", expectedOutput) {
|
|
t.Errorf("Tail n=%d returned wrong result.\nExpected: '%s'\nGot : '%s'", expectedOutput, output)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOutputAddTail(t *testing.T) {
|
|
var tests = make(map[string][][]string)
|
|
tests["hello, world!"] = [][]string{
|
|
{},
|
|
{"hello, world!"},
|
|
{"hello, world!"},
|
|
{"hello, world!"},
|
|
}
|
|
tests["One\nTwo\nThree"] = [][]string{
|
|
{},
|
|
{"Three"},
|
|
{"Two", "Three"},
|
|
{"One", "Two", "Three"},
|
|
}
|
|
for input, outputs := range tests {
|
|
for n, expectedOutput := range outputs {
|
|
o := NewOutput()
|
|
var output []string
|
|
if err := o.AddTail(&output, n); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if n, err := o.Write([]byte(input)); err != nil {
|
|
t.Error(err)
|
|
} else if n != len(input) {
|
|
t.Errorf("Expected %d, got %d", len(input), n)
|
|
}
|
|
o.Close()
|
|
if fmt.Sprintf("%v", output) != fmt.Sprintf("%v", expectedOutput) {
|
|
t.Errorf("Tail(%d) returned wrong result.\nExpected: %v\nGot: %v", n, expectedOutput, output)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func lastLine(txt string) string {
|
|
scanner := bufio.NewScanner(strings.NewReader(txt))
|
|
var lastLine string
|
|
for scanner.Scan() {
|
|
lastLine = scanner.Text()
|
|
}
|
|
return lastLine
|
|
}
|
|
|
|
func TestOutputAdd(t *testing.T) {
|
|
o := NewOutput()
|
|
b := &bytes.Buffer{}
|
|
o.Add(b)
|
|
input := "hello, world!"
|
|
if n, err := o.Write([]byte(input)); err != nil {
|
|
t.Fatal(err)
|
|
} else if n != len(input) {
|
|
t.Fatalf("Expected %d, got %d", len(input), n)
|
|
}
|
|
if output := b.String(); output != input {
|
|
t.Fatal("Received wrong data from Add.\nExpected: '%s'\nGot: '%s'", input, output)
|
|
}
|
|
}
|
|
|
|
func TestOutputWriteError(t *testing.T) {
|
|
o := NewOutput()
|
|
buf := &bytes.Buffer{}
|
|
o.Add(buf)
|
|
r, w := io.Pipe()
|
|
input := "Hello there"
|
|
expectedErr := fmt.Errorf("This is an error")
|
|
r.CloseWithError(expectedErr)
|
|
o.Add(w)
|
|
n, err := o.Write([]byte(input))
|
|
if err != expectedErr {
|
|
t.Fatalf("Output.Write() should return the first error encountered, if any")
|
|
}
|
|
if buf.String() != input {
|
|
t.Fatalf("Output.Write() should attempt write on all destinations, even after encountering an error")
|
|
}
|
|
if n != len(input) {
|
|
t.Fatalf("Output.Write() should return the size of the input if it successfully writes to at least one destination")
|
|
}
|
|
}
|
|
|
|
func TestInputAddEmpty(t *testing.T) {
|
|
i := NewInput()
|
|
var b bytes.Buffer
|
|
if err := i.Add(&b); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data, err := ioutil.ReadAll(i)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(data) > 0 {
|
|
t.Fatalf("Read from empty input shoul yield no data")
|
|
}
|
|
}
|
|
|
|
func TestInputAddTwo(t *testing.T) {
|
|
i := NewInput()
|
|
var b1 bytes.Buffer
|
|
// First add should succeed
|
|
if err := i.Add(&b1); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var b2 bytes.Buffer
|
|
// Second add should fail
|
|
if err := i.Add(&b2); err == nil {
|
|
t.Fatalf("Adding a second source should return an error")
|
|
}
|
|
}
|
|
|
|
func TestInputAddNotEmpty(t *testing.T) {
|
|
i := NewInput()
|
|
b := bytes.NewBufferString("hello world\nabc")
|
|
expectedResult := b.String()
|
|
i.Add(b)
|
|
result, err := ioutil.ReadAll(i)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(result) != expectedResult {
|
|
t.Fatalf("Expected: %v\nReceived: %v", expectedResult, result)
|
|
}
|
|
}
|