1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
package main_test
import (
"fmt"
"os"
"os/exec"
"testing"
"time"
. "github.com/onsi/ginkgo/v2"
"github.com/onsi/ginkgo/v2/internal"
. "github.com/onsi/gomega"
)
func TestInterceptorFixture(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "InterceptorFixture Suite")
}
var _ = Describe("Ensuring the OutputInterceptor handles the edge case where an external process keeps the interceptor's pipe open", func() {
var interceptor internal.OutputInterceptor
sharedBehavior := func() {
It("can avoid getting stuck, but also doesn't block the external process", func() {
interceptor.StartInterceptingOutput()
cmd := exec.Command("./interceptor")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Ω(cmd.Start()).Should(Succeed())
By("Bailing out because the pipe is stuck")
outputChan := make(chan string)
go func() {
outputChan <- interceptor.StopInterceptingAndReturnOutput()
}()
var output string
Eventually(outputChan, internal.BAILOUT_TIME*2).Should(Receive(&output))
Ω(output).Should(Equal(internal.BAILOUT_MESSAGE))
By("Not subsequently bailing out because the new pipe isn't tied to an external process")
interceptor.StartInterceptingOutput()
output = interceptor.StopInterceptingAndReturnOutput()
Ω(output).ShouldNot(ContainSubstring("STDOUT"), "we're no longer capturing this output")
Ω(output).ShouldNot(ContainSubstring("STDERR"), "we're no longer capturing this output")
Ω(output).ShouldNot(ContainSubstring(internal.BAILOUT_MESSAGE), "we didn't have to bail out")
expected := ""
for i := 0; i < 300; i++ {
expected += fmt.Sprintf("FILE %d\n", i)
}
Eventually(func(g Gomega) string {
out, err := os.ReadFile("file-output")
g.Ω(err).ShouldNot(HaveOccurred())
return string(out)
}, 5*time.Second).Should(Equal(expected))
os.Remove("file-output")
})
It("works successfully if the user pauses then resumes around starting an external process", func() {
interceptor.StartInterceptingOutput()
interceptor.PauseIntercepting()
cmd := exec.Command("./interceptor")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Ω(cmd.Start()).Should(Succeed())
interceptor.ResumeIntercepting()
output := interceptor.StopInterceptingAndReturnOutput()
Ω(output).ShouldNot(ContainSubstring(internal.BAILOUT_MESSAGE), "we didn't have to bail out")
interceptor.StartInterceptingOutput()
output = interceptor.StopInterceptingAndReturnOutput()
Ω(output).ShouldNot(ContainSubstring(internal.BAILOUT_MESSAGE), "we still didn't have to bail out")
expected := ""
for i := 0; i < 300; i++ {
expected += fmt.Sprintf("FILE %d\n", i)
}
Eventually(func(g Gomega) string {
out, err := os.ReadFile("file-output")
g.Ω(err).ShouldNot(HaveOccurred())
return string(out)
}, 5*time.Second).Should(Equal(expected))
os.Remove("file-output")
})
}
Context("the dup2 interceptor", func() {
BeforeEach(func() {
interceptor = internal.NewOutputInterceptor()
})
sharedBehavior()
})
Context("the global reassigning interceptor", func() {
BeforeEach(func() {
interceptor = internal.NewOSGlobalReassigningOutputInterceptor()
})
sharedBehavior()
})
})
|