Пример #1
0
// Job creates a new job which can later be executed.
// This function mimics `Command` from the standard os/exec package.
func (eng *Engine) Job(name string, args ...string) *Job {
	job := &Job{
		Eng:     eng,
		Name:    name,
		Args:    args,
		Stdin:   NewInput(),
		Stdout:  NewOutput(),
		Stderr:  NewOutput(),
		env:     &Env{},
		closeIO: true,

		cancelled: make(chan struct{}),
	}
	if eng.Logging {
		job.Stderr.Add(ioutils.NopWriteCloser(eng.Stderr))
	}

	// Catchall is shadowed by specific Register.
	if handler, exists := eng.handlers[name]; exists {
		job.handler = handler
	} else if eng.catchall != nil && name != "" {
		// empty job names are illegal, catchall or not.
		job.handler = eng.catchall
	}
	return job
}
Пример #2
0
// 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) error {
		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 nil
	}

	innerHandler = func(job *Job) error {
		job.Stdout.Write([]byte(" inner"))

		return nil
	}

	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())
	}
}