...
1 package integration_test
2
3 import (
4 "encoding/json"
5 "os/exec"
6 "time"
7
8 . "github.com/onsi/ginkgo/v2"
9 "github.com/onsi/ginkgo/v2/types"
10 . "github.com/onsi/gomega"
11 "github.com/onsi/gomega/gbytes"
12 "github.com/onsi/gomega/gexec"
13 )
14
15 var _ = Describe("Interrupt and Timeout", func() {
16 Context("when interrupting a suite", func() {
17 It("gives the user feedback as the session is interrupted", func() {
18 fm.MountFixture("hanging")
19
20
21 session := startGinkgo(fm.PathTo("hanging"), "build")
22 Eventually(session).Should(gexec.Exit(0))
23
24
25 cmd := exec.Command("./hanging.test", "--test.v", "--ginkgo.no-color", "--ginkgo.grace-period=2s")
26 cmd.Dir = fm.PathTo("hanging")
27 var err error
28 session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
29 Ω(err).ShouldNot(HaveOccurred())
30
31 Eventually(session).Should(gbytes.Say("Sleeping..."))
32 session.Interrupt()
33 Eventually(session).Should(gbytes.Say(`First interrupt received`))
34 Eventually(session).Should(gbytes.Say("Begin Captured GinkgoWriter Output"))
35 Eventually(session).Should(gbytes.Say("Just beginning"))
36 Eventually(session).Should(gbytes.Say("Almost there..."))
37 Eventually(session).Should(gbytes.Say("Hanging Out"))
38 Eventually(session).Should(gbytes.Say(`goroutine \d+ \[select\]`))
39 Eventually(session).Should(gbytes.Say(`>\s*select {`), "The actual source code gets emitted")
40
41 Eventually(session, time.Second*5).Should(gbytes.Say("Cleaning up once..."), "The two second grace period should move on past the napping node")
42 Eventually(session).Should(gbytes.Say("Cleaning up twice..."))
43 Eventually(session).Should(gbytes.Say("Sleeping again..."))
44 session.Interrupt()
45 Eventually(session).Should(gbytes.Say(`Second interrupt received`))
46 Eventually(session).Should(gbytes.Say(`goroutine \d+ \[sleep\]`))
47 Eventually(session).Should(gbytes.Say(`>\s*time.Sleep\(time.Hour\)`), "The actual source code gets emitted now")
48
49 Eventually(session).Should(gbytes.Say(`\[INTERRUPTED\]`))
50 Eventually(session).Should(gbytes.Say(`Interrupted by User`))
51 Eventually(session).Should(gbytes.Say(`Spec Goroutine`))
52 Eventually(session).Should(gbytes.Say(`goroutine \d+ \[select\]`))
53 Eventually(session).Should(gbytes.Say(`>\s*select {`), "The actual source code gets emitted now")
54 Eventually(session).Should(gbytes.Say(`Other Goroutines`))
55 Eventually(session).Should(gbytes.Say(`main\.main\(\)`))
56
57 Eventually(session).Should(gbytes.Say("Reporting at the end"))
58
59 Eventually(session).Should(gbytes.Say(`FAIL! - Interrupted by User`))
60 Eventually(session, time.Second*10).Should(gexec.Exit(1))
61
62
63 Ω(string(session.Out.Contents())).ShouldNot(ContainSubstring("Cleaning up thrice"))
64 Ω(string(session.Out.Contents())).ShouldNot(ContainSubstring("Heading Out After Suite"))
65 })
66 })
67
68 Context("when the suite times out", func() {
69 It("interrupts the suite and gives the user feedback as it does so", func() {
70 fm.MountFixture("hanging")
71
72 session := startGinkgo(fm.PathTo("hanging"), "--no-color", "--timeout=5s", "--grace-period=1s")
73 Eventually(session, time.Second*10).Should(gexec.Exit(1))
74
75 Ω(session).Should(gbytes.Say("Sleeping..."))
76 Ω(session).Should(gbytes.Say("Got your signal, but still taking a nap"), "the timeout has signaled the it to stop, but it's napping...")
77 Ω(session).Should(gbytes.Say("A running node failed to exit in time"), "so we forcibly casue it to exit after the grace-period elapses")
78 Ω(session).Should(gbytes.Say("Cleaning up once..."))
79 Ω(session).Should(gbytes.Say("Cleaning up twice..."))
80 Ω(session).Should(gbytes.Say("Cleaning up thrice..."), "we manage to get here even though the second after-each gets stuck. that's thanks to the GracePeriod configuration.")
81
82 Ω(session).Should(gbytes.Say(`\[TIMEDOUT\]`))
83 Ω(session).Should(gbytes.Say(`Spec Goroutine`))
84 Ω(session).Should(gbytes.Say(`goroutine \d+ \[select\]`))
85 Ω(session).Should(gbytes.Say(`>\s*select {`), "The actual source code gets emitted now")
86 Ω(session).ShouldNot(gbytes.Say(`Other Goroutines`))
87
88 Ω(session).Should(gbytes.Say("FAIL! - Suite Timeout Elapsed"))
89 })
90 })
91
92 Describe("applying the timeout to multiple suites", func() {
93 It("tracks the timeout across the suites, decrementing the available timeout for each individual suite, and reports on any suites that did not run because the timeout elapsed", Label("slow"), func() {
94 fm.MountFixture("timeout")
95 session := startGinkgo(fm.PathTo("timeout"), "--no-color", "-r", "--timeout=10s", "--keep-going", "--json-report=out.json")
96 Eventually(session).Should(gbytes.Say("TimeoutA Suite"))
97 Eventually(session, "15s").Should(gexec.Exit(1))
98 Ω(session).Should(gbytes.Say(`timeout_D ./timeout_D \[Suite did not run because the timeout elapsed\]`))
99
100 data := []byte(fm.ContentOf("timeout", "out.json"))
101 reports := []types.Report{}
102 Ω(json.Unmarshal(data, &reports)).Should(Succeed())
103 Ω(reports[3].SpecialSuiteFailureReasons).Should(ContainElement("Suite did not run because the timeout elapsed"))
104 })
105 })
106 })
107
View as plain text