engine/engine_test.go
8e5ab5bf
 package engine
 
 import (
cd846ecb
 	"bytes"
d985fd49
 	"strings"
8e5ab5bf
 	"testing"
fa5dfbb1
 
 	"github.com/docker/docker/pkg/ioutils"
8e5ab5bf
 )
 
 func TestRegister(t *testing.T) {
 	if err := Register("dummy1", nil); err != nil {
 		t.Fatal(err)
 	}
 
 	if err := Register("dummy1", nil); err == nil {
 		t.Fatalf("Expecting error, got none")
 	}
62b21dad
 	// Register is global so let's cleanup to avoid conflicts
 	defer unregister("dummy1")
8e5ab5bf
 
7100ace4
 	eng := New()
8e5ab5bf
 
0fccf0f6
 	//Should fail because global handlers are copied
8e5ab5bf
 	//at the engine creation
 	if err := eng.Register("dummy1", nil); err == nil {
 		t.Fatalf("Expecting error, got none")
 	}
 
 	if err := eng.Register("dummy2", nil); err != nil {
 		t.Fatal(err)
 	}
 
 	if err := eng.Register("dummy2", nil); err == nil {
 		t.Fatalf("Expecting error, got none")
 	}
62b21dad
 	defer unregister("dummy2")
8e5ab5bf
 }
 
 func TestJob(t *testing.T) {
7100ace4
 	eng := New()
8e5ab5bf
 	job1 := eng.Job("dummy1", "--level=awesome")
 
 	if job1.handler != nil {
 		t.Fatalf("job1.handler should be empty")
 	}
 
a4f8a249
 	h := func(j *Job) Status {
 		j.Printf("%s\n", j.Name)
 		return 42
8e5ab5bf
 	}
 
 	eng.Register("dummy2", h)
62b21dad
 	defer unregister("dummy2")
8e5ab5bf
 	job2 := eng.Job("dummy2", "--level=awesome")
 
 	if job2.handler == nil {
 		t.Fatalf("job2.handler shouldn't be nil")
 	}
 
a4f8a249
 	if job2.handler(job2) != 42 {
8e5ab5bf
 		t.Fatalf("handler dummy2 was not found in job2")
 	}
 }
3553a803
 
0800f8cc
 func TestEngineShutdown(t *testing.T) {
 	eng := New()
 	if eng.IsShutdown() {
 		t.Fatalf("Engine should not show as shutdown")
 	}
 	eng.Shutdown()
 	if !eng.IsShutdown() {
 		t.Fatalf("Engine should show as shutdown")
 	}
 }
 
cd846ecb
 func TestEngineCommands(t *testing.T) {
7100ace4
 	eng := New()
cd846ecb
 	handler := func(job *Job) Status { return StatusOK }
 	eng.Register("foo", handler)
 	eng.Register("bar", handler)
 	eng.Register("echo", handler)
 	eng.Register("die", handler)
 	var output bytes.Buffer
 	commands := eng.Job("commands")
 	commands.Stdout.Add(&output)
 	commands.Run()
 	expected := "bar\ncommands\ndie\necho\nfoo\n"
 	if result := output.String(); result != expected {
 		t.Fatalf("Unexpected output:\nExpected = %v\nResult   = %v\n", expected, result)
 	}
 }
 
3553a803
 func TestEngineString(t *testing.T) {
7100ace4
 	eng1 := New()
 	eng2 := New()
3553a803
 	s1 := eng1.String()
 	s2 := eng2.String()
 	if eng1 == eng2 {
 		t.Fatalf("Different engines should have different names (%v == %v)", s1, s2)
 	}
 }
 
d985fd49
 func TestParseJob(t *testing.T) {
7100ace4
 	eng := New()
d985fd49
 	// Verify that the resulting job calls to the right place
 	var called bool
 	eng.Register("echo", func(job *Job) Status {
 		called = true
 		return StatusOK
 	})
 	input := "echo DEBUG=1 hello world VERBOSITY=42"
 	job, err := eng.ParseJob(input)
 	if err != nil {
 		t.Fatal(err)
 	}
 	if job.Name != "echo" {
 		t.Fatalf("Invalid job name: %v", job.Name)
 	}
 	if strings.Join(job.Args, ":::") != "hello:::world" {
 		t.Fatalf("Invalid job args: %v", job.Args)
 	}
 	if job.Env().Get("DEBUG") != "1" {
 		t.Fatalf("Invalid job env: %v", job.Env)
 	}
 	if job.Env().Get("VERBOSITY") != "42" {
 		t.Fatalf("Invalid job env: %v", job.Env)
 	}
 	if len(job.Env().Map()) != 2 {
 		t.Fatalf("Invalid job env: %v", job.Env)
 	}
 	if err := job.Run(); err != nil {
 		t.Fatal(err)
 	}
 	if !called {
 		t.Fatalf("Job was not called")
 	}
 }
3b73c261
 
 func TestCatchallEmptyName(t *testing.T) {
 	eng := New()
 	var called bool
 	eng.RegisterCatchall(func(job *Job) Status {
 		called = true
 		return StatusOK
 	})
 	err := eng.Job("").Run()
 	if err == nil {
 		t.Fatalf("Engine.Job(\"\").Run() should return an error")
 	}
 	if called {
 		t.Fatalf("Engine.Job(\"\").Run() should return an error")
 	}
 }
fa5dfbb1
 
 // Ensure that a job within a job both using the same underlying standard
 // output writer does not close the output of the outer job when the inner
 // job's stdout is wrapped with a NopCloser. When not wrapped, it should
 // close the outer job's output.
 func TestNestedJobSharedOutput(t *testing.T) {
 	var (
 		outerHandler Handler
 		innerHandler Handler
 		wrapOutput   bool
 	)
 
 	outerHandler = func(job *Job) Status {
 		job.Stdout.Write([]byte("outer1"))
 
 		innerJob := job.Eng.Job("innerJob")
 
 		if wrapOutput {
 			innerJob.Stdout.Add(ioutils.NopWriteCloser(job.Stdout))
 		} else {
 			innerJob.Stdout.Add(job.Stdout)
 		}
 
 		if err := innerJob.Run(); err != nil {
 			t.Fatal(err)
 		}
 
 		// If wrapOutput was *false* this write will do nothing.
 		// FIXME (jlhawn): It should cause an error to write to
 		// closed output.
 		job.Stdout.Write([]byte(" outer2"))
 
 		return StatusOK
 	}
 
 	innerHandler = func(job *Job) Status {
 		job.Stdout.Write([]byte(" inner"))
 
 		return StatusOK
 	}
 
 	eng := New()
 	eng.Register("outerJob", outerHandler)
 	eng.Register("innerJob", innerHandler)
 
 	// wrapOutput starts *false* so the expected
 	// output of running the outer job will be:
 	//
 	//     "outer1 inner"
 	//
 	outBuf := new(bytes.Buffer)
 	outerJob := eng.Job("outerJob")
 	outerJob.Stdout.Add(outBuf)
 
 	if err := outerJob.Run(); err != nil {
 		t.Fatal(err)
 	}
 
 	expectedOutput := "outer1 inner"
 	if outBuf.String() != expectedOutput {
 		t.Fatalf("expected job output to be %q, got %q", expectedOutput, outBuf.String())
 	}
 
 	// Set wrapOutput to true so that the expected
 	// output of running the outer job will be:
 	//
 	//     "outer1 inner outer2"
 	//
 	wrapOutput = true
 	outBuf.Reset()
 	outerJob = eng.Job("outerJob")
 	outerJob.Stdout.Add(outBuf)
 
 	if err := outerJob.Run(); err != nil {
 		t.Fatal(err)
 	}
 
 	expectedOutput = "outer1 inner outer2"
 	if outBuf.String() != expectedOutput {
 		t.Fatalf("expected job output to be %q, got %q", expectedOutput, outBuf.String())
 	}
 }