It("invokes the delegate's Failed callback", func() { Eventually(process.Wait()).Should(Receive(Equal(disaster))) Ω(taskDelegate.FailedCallCount()).Should(Equal(1)) Ω(taskDelegate.FailedArgsForCall(0)).Should(Equal(disaster)) }) }) Describe("signalling", func() { var stopped chan struct{} BeforeEach(func() { stopped = make(chan struct{}) fakeProcess.WaitStub = func() (int, error) { <-stopped return 128 + 15, nil } fakeContainer.StopStub = func(bool) error { close(stopped) return nil } }) It("stops the container", func() { process.Signal(os.Interrupt) Eventually(process.Wait()).Should(Receive(Equal(ErrInterrupted))) Ω(fakeContainer.StopCallCount()).Should(Equal(1)) }) })
) BeforeEach(func() { source = atc.Source{"some": "source"} params = atc.Params{"some": "params"} fakeArtifactSource = new(fakes.FakeArtifactSource) outScriptStdout = "{}" outScriptStderr = "" outScriptExitStatus = 0 runOutError = nil outScriptProcess = new(gfakes.FakeProcess) outScriptProcess.IDReturns(42) outScriptProcess.WaitStub = func() (int, error) { return outScriptExitStatus, nil } stdoutBuf = gbytes.NewBuffer() stderrBuf = gbytes.NewBuffer() ioConfig = IOConfig{ Stdout: stdoutBuf, Stderr: stderrBuf, } }) JustBeforeEach(func() { fakeContainer.RunStub = func(spec garden.ProcessSpec, io garden.ProcessIO) (garden.Process, error) { if runOutError != nil { return nil, runOutError
in, err := ioutil.ReadAll(io.Stdin) Ω(err).ShouldNot(HaveOccurred()) _, err = fmt.Fprintf(io.Stdout, "mirrored %s", string(in)) Ω(err).ShouldNot(HaveOccurred()) _, err = fmt.Fprintf(io.Stderr, "stderr data") Ω(err).ShouldNot(HaveOccurred()) }() process := new(fakes.FakeProcess) process.IDReturns(42) process.WaitStub = func() (int, error) { writing.Wait() return 123, nil } return process, nil } }) It("responds with a ProcessPayload for every chunk", func() { stdout := gbytes.NewBuffer() stderr := gbytes.NewBuffer() processIO := garden.ProcessIO{ Stdin: bytes.NewBufferString("stdin data"), Stdout: stdout, Stderr: stderr, }
checkResult []atc.Version checkErr error ) BeforeEach(func() { source = atc.Source{"some": "source"} version = atc.Version{"some": "version"} checkScriptStdout = "[]" checkScriptStderr = "" checkScriptExitStatus = 0 runCheckError = nil checkScriptProcess = new(gfakes.FakeProcess) checkScriptProcess.WaitStub = func() (int, error) { return checkScriptExitStatus, nil } checkResult = nil checkErr = nil }) JustBeforeEach(func() { fakeContainer.RunStub = func(spec garden.ProcessSpec, io garden.ProcessIO) (garden.Process, error) { if runCheckError != nil { return nil, runCheckError } _, err := io.Stdout.Write([]byte(checkScriptStdout)) Expect(err).NotTo(HaveOccurred())
defer writing.Done() defer GinkgoRecover() _, err := fmt.Fprintf(io.Stdout, "hi out\n") Expect(err).ToNot(HaveOccurred()) _, err = fmt.Fprintf(io.Stderr, "hi err\n") Expect(err).ToNot(HaveOccurred()) }() process := new(wfakes.FakeProcess) process.IDReturns(processID) process.WaitStub = func() (int, error) { writing.Wait() return 123, nil } return process, nil } }) It("streams stderr and stdout and exit status", func() { stdout := gbytes.NewBuffer() stderr := gbytes.NewBuffer() process, err := container.Run(garden.ProcessSpec{ User: "******", Path: "/some/script", }, garden.ProcessIO{ Stdout: stdout,
Describe("emitting logs", func() { var stdoutBuffer, stderrBuffer *gbytes.Buffer BeforeEach(func() { stdoutBuffer = gbytes.NewBuffer() stderrBuffer = gbytes.NewBuffer() fakeStreamer.StdoutReturns(stdoutBuffer) fakeStreamer.StderrReturns(stderrBuffer) spawnedProcess.WaitStub = func() (int, error) { _, _, io := gardenClient.Connection.RunArgsForCall(0) _, err := io.Stdout.Write([]byte("hi out")) Expect(err).NotTo(HaveOccurred()) _, err = io.Stderr.Write([]byte("hi err")) Expect(err).NotTo(HaveOccurred()) return 34, nil } }) It("emits the output chunks as they come in", func() { Expect(stdoutBuffer).To(gbytes.Say("hi out")) Expect(stderrBuffer).To(gbytes.Say("hi err")) }) It("should flush the output when the code exits", func() { Expect(fakeStreamer.FlushCallCount()).To(Equal(1)) })
Ω(handle).Should(Equal("la-contineur")) Ω(processID).Should(Equal(uint32(6))) Ω(calledProcessIO).Should(Equal(processIO)) }) Describe("the process", func() { Describe("Wait", func() { BeforeEach(func() { errs := make(chan error, 1) errs <- fmt.Errorf("connection: decode failed: %s", io.EOF) close(errs) fakeProcess.WaitStub = func() (int, error) { err := <-errs if err == nil { return 42, nil } return 0, err } }) It("reattaches on EOF", func() { result, err := process.Wait() Ω(err).ShouldNot(HaveOccurred()) Ω(result).Should(Equal(42)) Ω(innerConnection.AttachCallCount()).Should(Equal(2)) handle, processID, calledProcessIO := innerConnection.AttachArgsForCall(1) Ω(handle).Should(Equal("la-contineur")) Ω(processID).Should(Equal(uint32(6))) Ω(calledProcessIO).Should(Equal(processIO))
Eventually(created).Should(Receive()) err := apiClient.Ping() Ω(err).Should(HaveOccurred()) }) }) Context("when a Run request is in-flight", func() { It("does not wait for the request to complete", func(done Done) { fakeContainer := new(fakes.FakeContainer) fakeContainer.RunStub = func(spec garden.ProcessSpec, io garden.ProcessIO) (garden.Process, error) { process := new(fakes.FakeProcess) process.WaitStub = func() (int, error) { time.Sleep(time.Minute) return 0, nil } go func() { defer GinkgoRecover() _, err := io.Stdout.Write([]byte("msg 1\n")) Ω(err).ShouldNot(HaveOccurred()) time.Sleep(time.Minute) _, err = io.Stdout.Write([]byte("msg 2\n")) Ω(err).ShouldNot(HaveOccurred()) }() return process, nil
}) }) Context("when running the process succeeds", func() { var ( fakeProcess *gfakes.FakeProcess processExit chan int ) BeforeEach(func() { exit := make(chan int) processExit = exit fakeProcess = new(gfakes.FakeProcess) fakeProcess.WaitStub = func() (int, error) { return <-exit, nil } fakeContainer.RunReturns(fakeProcess, nil) }) AfterEach(func() { close(processExit) }) It("hijacks the build", func() { Eventually(fakeContainer.RunCallCount).Should(Equal(1)) _, lookedUpID := fakeWorkerClient.LookupContainerArgsForCall(0) Expect(lookedUpID).To(Equal(handle))