|
@@ -4,6 +4,8 @@ import (
|
|
|
"bytes"
|
|
|
"strings"
|
|
|
"testing"
|
|
|
+
|
|
|
+ "github.com/docker/docker/pkg/ioutils"
|
|
|
)
|
|
|
|
|
|
func TestRegister(t *testing.T) {
|
|
@@ -150,3 +152,85 @@ func TestCatchallEmptyName(t *testing.T) {
|
|
|
t.Fatalf("Engine.Job(\"\").Run() should return an error")
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// 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())
|
|
|
+ }
|
|
|
+}
|