package gexec_test import ( "os/exec" "syscall" "time" . "github.com/onsi/gomega/gbytes" . "github.com/onsi/gomega/gexec" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Session", func() { var command *exec.Cmd var session *Session var outWriter, errWriter *Buffer BeforeEach(func() { outWriter = nil errWriter = nil }) JustBeforeEach(func() { command = exec.Command(fireflyPath) var err error session, err = Start(command, outWriter, errWriter) Ω(err).ShouldNot(HaveOccurred()) }) Context("running a command", func() { It("should start the process", func() { Ω(command.Process).ShouldNot(BeNil()) }) It("should wrap the process's stdout and stderr with gbytes buffers", func(done Done) { Eventually(session.Out).Should(Say("We've done the impossible, and that makes us mighty")) Eventually(session.Err).Should(Say("Ah, curse your sudden but inevitable betrayal!")) defer session.Out.CancelDetects() select { case <-session.Out.Detect("Can we maybe vote on the whole murdering people issue"): Eventually(session).Should(Exit(0)) case <-session.Out.Detect("I swear by my pretty floral bonnet, I will end you."): Eventually(session).Should(Exit(1)) case <-session.Out.Detect("My work's illegal, but at least it's honest."): Eventually(session).Should(Exit(2)) } close(done) }) It("should satisfy the gbytes.BufferProvider interface, passing Stdout", func() { Eventually(session).Should(Say("We've done the impossible, and that makes us mighty")) Eventually(session).Should(Exit()) }) }) Describe("providing the exit code", func() { It("should provide the app's exit code", func() { Ω(session.ExitCode()).Should(Equal(-1)) Eventually(session).Should(Exit()) Ω(session.ExitCode()).Should(BeNumerically(">=", 0)) Ω(session.ExitCode()).Should(BeNumerically("<", 3)) }) }) Describe("wait", func() { It("should wait till the command exits", func() { Ω(session.ExitCode()).Should(Equal(-1)) Ω(session.Wait().ExitCode()).Should(BeNumerically(">=", 0)) Ω(session.Wait().ExitCode()).Should(BeNumerically("<", 3)) }) }) Describe("exited", func() { It("should close when the command exits", func() { Eventually(session.Exited).Should(BeClosed()) Ω(session.ExitCode()).ShouldNot(Equal(-1)) }) }) Describe("kill", func() { It("should kill the command and don't wait for it to exit", func() { session, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session.Kill() Ω(session).ShouldNot(Exit(), "Should not exit immediately...") Eventually(session).Should(Exit(128 + 9)) }) }) Describe("interrupt", func() { It("should interrupt the command", func() { session, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session.Interrupt() Ω(session).ShouldNot(Exit(), "Should not exit immediately...") Eventually(session).Should(Exit(128 + 2)) }) }) Describe("terminate", func() { It("should terminate the command", func() { session, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session.Terminate() Ω(session).ShouldNot(Exit(), "Should not exit immediately...") Eventually(session).Should(Exit(128 + 15)) }) }) Describe("signal", func() { It("should send the signal to the command", func() { session, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session.Signal(syscall.SIGABRT) Ω(session).ShouldNot(Exit(), "Should not exit immediately...") Eventually(session).Should(Exit(128 + 6)) }) }) Context("tracking sessions", func() { BeforeEach(func() { KillAndWait() }) Describe("kill", func() { It("should kill all the started sessions", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session2, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session3, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Kill() Eventually(session1).Should(Exit(128 + 9)) Eventually(session2).Should(Exit(128 + 9)) Eventually(session3).Should(Exit(128 + 9)) }) It("should not wait for exit", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Kill() Ω(session1).ShouldNot(Exit(), "Should not exit immediately...") Eventually(session1).Should(Exit(128 + 9)) }) It("should not track unstarted sessions", func() { _, err := Start(exec.Command("does not exist", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).Should(HaveOccurred()) session2, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session3, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Kill() Eventually(session2).Should(Exit(128 + 9)) Eventually(session3).Should(Exit(128 + 9)) }) }) Describe("killAndWait", func() { It("should kill all the started sessions and wait for them to finish", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session2, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session3, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) KillAndWait() Ω(session1).Should(Exit(128+9), "Should have exited") Ω(session2).Should(Exit(128+9), "Should have exited") Ω(session3).Should(Exit(128+9), "Should have exited") }) }) Describe("terminate", func() { It("should terminate all the started sessions", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session2, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session3, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Terminate() Eventually(session1).Should(Exit(128 + 15)) Eventually(session2).Should(Exit(128 + 15)) Eventually(session3).Should(Exit(128 + 15)) }) It("should not wait for exit", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Terminate() Ω(session1).ShouldNot(Exit(), "Should not exit immediately...") }) }) Describe("terminateAndWait", func() { It("should terminate all the started sessions, and wait for them to exit", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session2, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session3, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) TerminateAndWait() Ω(session1).Should(Exit(128+15), "Should have exited") Ω(session2).Should(Exit(128+15), "Should have exited") Ω(session3).Should(Exit(128+15), "Should have exited") }) }) Describe("signal", func() { It("should signal all the started sessions", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session2, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session3, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Signal(syscall.SIGABRT) Eventually(session1).Should(Exit(128 + 6)) Eventually(session2).Should(Exit(128 + 6)) Eventually(session3).Should(Exit(128 + 6)) }) It("should not wait", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Signal(syscall.SIGABRT) Ω(session1).ShouldNot(Exit(), "Should not exit immediately...") }) }) Describe("interrupt", func() { It("should interrupt all the started sessions, and not wait", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session2, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) session3, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Interrupt() Eventually(session1).Should(Exit(128 + 2)) Eventually(session2).Should(Exit(128 + 2)) Eventually(session3).Should(Exit(128 + 2)) }) It("should not wait", func() { session1, err := Start(exec.Command("sleep", "10000000"), GinkgoWriter, GinkgoWriter) Ω(err).ShouldNot(HaveOccurred()) Interrupt() Ω(session1).ShouldNot(Exit(), "Should not exit immediately...") }) }) }) Context("when the command exits", func() { It("should close the buffers", func() { Eventually(session).Should(Exit()) Ω(session.Out.Closed()).Should(BeTrue()) Ω(session.Err.Closed()).Should(BeTrue()) Ω(session.Out).Should(Say("We've done the impossible, and that makes us mighty")) }) var So = It So("this means that eventually should short circuit", func() { t := time.Now() failures := InterceptGomegaFailures(func() { Eventually(session).Should(Say("blah blah blah blah blah")) }) Ω(time.Since(t)).Should(BeNumerically("<=", 500*time.Millisecond)) Ω(failures).Should(HaveLen(1)) }) }) Context("when wrapping out and err", func() { BeforeEach(func() { outWriter = NewBuffer() errWriter = NewBuffer() }) It("should route to both the provided writers and the gbytes buffers", func() { Eventually(session.Out).Should(Say("We've done the impossible, and that makes us mighty")) Eventually(session.Err).Should(Say("Ah, curse your sudden but inevitable betrayal!")) Ω(outWriter.Contents()).Should(ContainSubstring("We've done the impossible, and that makes us mighty")) Ω(errWriter.Contents()).Should(ContainSubstring("Ah, curse your sudden but inevitable betrayal!")) Eventually(session).Should(Exit()) Ω(outWriter.Contents()).Should(Equal(session.Out.Contents())) Ω(errWriter.Contents()).Should(Equal(session.Err.Contents())) }) }) Describe("when the command fails to start", func() { It("should return an error", func() { _, err := Start(exec.Command("agklsjdfas"), nil, nil) Ω(err).Should(HaveOccurred()) }) }) })