Engine: better testing of streams and of basic engine primitives. Coverage=81.2%

This commit is contained in:
Solomon Hykes 2013-11-20 07:38:59 +00:00
Родитель a4f8a2494b
Коммит 3553a803e3
3 изменённых файлов: 379 добавлений и 0 удалений

Просмотреть файл

@ -1,6 +1,9 @@
package engine
import (
"io/ioutil"
"os"
"path"
"testing"
)
@ -54,3 +57,47 @@ func TestJob(t *testing.T) {
t.Fatalf("handler dummy2 was not found in job2")
}
}
func TestEngineRoot(t *testing.T) {
tmp, err := ioutil.TempDir("", "docker-test-TestEngineCreateDir")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
dir := path.Join(tmp, "dir")
eng, err := New(dir)
if err != nil {
t.Fatal(err)
}
if st, err := os.Stat(dir); err != nil {
t.Fatal(err)
} else if !st.IsDir() {
t.Fatalf("engine.New() created something other than a directory at %s", dir)
}
if r := eng.Root(); r != dir {
t.Fatalf("Expected: %v\nReceived: %v", dir, r)
}
}
func TestEngineString(t *testing.T) {
eng1 := newTestEngine(t)
defer os.RemoveAll(eng1.Root())
eng2 := newTestEngine(t)
defer os.RemoveAll(eng2.Root())
s1 := eng1.String()
s2 := eng2.String()
if eng1 == eng2 {
t.Fatalf("Different engines should have different names (%v == %v)", s1, s2)
}
}
func TestEngineLogf(t *testing.T) {
eng := newTestEngine(t)
defer os.RemoveAll(eng.Root())
input := "Test log line"
if n, err := eng.Logf("%s\n", input); err != nil {
t.Fatal(err)
} else if n < len(input) {
t.Fatalf("Test: Logf() should print at least as much as the input\ninput=%d\nprinted=%d", len(input), n)
}
}

80
engine/job_test.go Normal file
Просмотреть файл

@ -0,0 +1,80 @@
package engine
import (
"os"
"testing"
)
func TestJobStatusOK(t *testing.T) {
eng := newTestEngine(t)
defer os.RemoveAll(eng.Root())
eng.Register("return_ok", func(job *Job) Status { return StatusOK })
err := eng.Job("return_ok").Run()
if err != nil {
t.Fatalf("Expected: err=%v\nReceived: err=%v", nil, err)
}
}
func TestJobStatusErr(t *testing.T) {
eng := newTestEngine(t)
defer os.RemoveAll(eng.Root())
eng.Register("return_err", func(job *Job) Status { return StatusErr })
err := eng.Job("return_err").Run()
if err == nil {
t.Fatalf("When a job returns StatusErr, Run() should return an error")
}
}
func TestJobStatusNotFound(t *testing.T) {
eng := newTestEngine(t)
defer os.RemoveAll(eng.Root())
eng.Register("return_not_found", func(job *Job) Status { return StatusNotFound })
err := eng.Job("return_not_found").Run()
if err == nil {
t.Fatalf("When a job returns StatusNotFound, Run() should return an error")
}
}
func TestJobStdoutString(t *testing.T) {
eng := newTestEngine(t)
defer os.RemoveAll(eng.Root())
// FIXME: test multiple combinations of output and status
eng.Register("say_something_in_stdout", func(job *Job) Status {
job.Printf("Hello world\n")
return StatusOK
})
job := eng.Job("say_something_in_stdout")
var output string
if err := job.Stdout.AddString(&output); err != nil {
t.Fatal(err)
}
if err := job.Run(); err != nil {
t.Fatal(err)
}
if expectedOutput := "Hello world"; output != expectedOutput {
t.Fatalf("Stdout last line:\nExpected: %v\nReceived: %v", expectedOutput, output)
}
}
func TestJobStderrString(t *testing.T) {
eng := newTestEngine(t)
defer os.RemoveAll(eng.Root())
// FIXME: test multiple combinations of output and status
eng.Register("say_something_in_stderr", func(job *Job) Status {
job.Errorf("Warning, something might happen\nHere it comes!\nOh no...\nSomething happened\n")
return StatusOK
})
job := eng.Job("say_something_in_stderr")
var output string
if err := job.Stderr.AddString(&output); err != nil {
t.Fatal(err)
}
if err := job.Run(); err != nil {
t.Fatal(err)
}
if expectedOutput := "Something happened"; output != expectedOutput {
t.Fatalf("Stderr last line:\nExpected: %v\nReceived: %v", expectedOutput, output)
}
}

252
engine/streams_test.go Normal file
Просмотреть файл

@ -0,0 +1,252 @@
package engine
import (
"bufio"
"bytes"
"fmt"
"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 TestOutputAddClose(t *testing.T) {
o := NewOutput()
var s sentinelWriteCloser
if err := o.Add(&s); err != nil {
t.Fatal(err)
}
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 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)
}
}