package engine import ( "bufio" "bytes" "fmt" "github.com/dotcloud/docker/pkg/beam" "io" "strings" "testing" "time" ) func TestHelloWorld(t *testing.T) { for i := 0; i < 10; i++ { testRemote(t, // Sender side func(eng *Engine) { job := eng.Job("echo", "hello", "world") out := &bytes.Buffer{} job.Stdout.Add(out) job.Run() if job.status != StatusOK { t.Fatalf("#%v", job.StatusCode()) } lines := bufio.NewScanner(out) var i int for lines.Scan() { if lines.Text() != "hello world" { t.Fatalf("%#v", lines.Text()) } i++ } if i != 1000 { t.Fatalf("%#v", i) } }, // Receiver side func(eng *Engine) { eng.Register("echo", func(job *Job) Status { // Simulate more output with a delay in the middle for i := 0; i < 500; i++ { fmt.Fprintf(job.Stdout, "%s\n", strings.Join(job.Args, " ")) } time.Sleep(5 * time.Millisecond) for i := 0; i < 500; i++ { fmt.Fprintf(job.Stdout, "%s\n", strings.Join(job.Args, " ")) } return StatusOK }) }, ) } } func TestStdin(t *testing.T) { testRemote(t, func(eng *Engine) { job := eng.Job("mirror") job.Stdin.Add(strings.NewReader("hello world!\n")) out := &bytes.Buffer{} job.Stdout.Add(out) if err := job.Run(); err != nil { t.Fatal(err) } if out.String() != "hello world!\n" { t.Fatalf("%#v", out.String()) } }, func(eng *Engine) { eng.Register("mirror", func(job *Job) Status { if _, err := io.Copy(job.Stdout, job.Stdin); err != nil { t.Fatal(err) } return StatusOK }) }, ) } func TestEnv(t *testing.T) { var ( foo string answer int shadok_words []string ) testRemote(t, func(eng *Engine) { job := eng.Job("sendenv") job.Env().Set("foo", "bar") job.Env().SetInt("answer", 42) job.Env().SetList("shadok_words", []string{"ga", "bu", "zo", "meu"}) if err := job.Run(); err != nil { t.Fatal(err) } }, func(eng *Engine) { eng.Register("sendenv", func(job *Job) Status { foo = job.Env().Get("foo") answer = job.Env().GetInt("answer") shadok_words = job.Env().GetList("shadok_words") return StatusOK }) }, ) // Check for results here rather than inside the job handler, // otherwise the tests may incorrectly pass if the handler is not // called. if foo != "bar" { t.Fatalf("%#v", foo) } if answer != 42 { t.Fatalf("%#v", answer) } if strings.Join(shadok_words, ", ") != "ga, bu, zo, meu" { t.Fatalf("%#v", shadok_words) } } // Helpers func testRemote(t *testing.T, senderSide, receiverSide func(*Engine)) { sndConn, rcvConn, err := beam.USocketPair() if err != nil { t.Fatal(err) } defer sndConn.Close() defer rcvConn.Close() sender := NewSender(sndConn) receiver := NewReceiver(rcvConn) // Setup the sender side eng := New() sender.Install(eng) // Setup the receiver side receiverSide(receiver.Engine) go receiver.Run() timeout(t, func() { senderSide(eng) }) } func timeout(t *testing.T, f func()) { onTimeout := time.After(100 * time.Millisecond) onDone := make(chan bool) go func() { f() close(onDone) }() select { case <-onTimeout: t.Fatalf("timeout") case <-onDone: } }