github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/internal/suite_test.go (about) 1 package internal_test 2 3 import ( 4 "fmt" 5 "io" 6 7 . "github.com/onsi/ginkgo" 8 "github.com/onsi/ginkgo/internal" 9 "github.com/onsi/ginkgo/internal/interrupt_handler" 10 "github.com/onsi/ginkgo/internal/parallel_support" 11 . "github.com/onsi/ginkgo/internal/test_helpers" 12 "github.com/onsi/ginkgo/types" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("Suite", func() { 17 It("is heavily integration tested over in internal_integration", func() { 18 }) 19 20 var suite *internal.Suite 21 var failer *internal.Failer 22 var reporter *FakeReporter 23 var writer *internal.Writer 24 var outputInterceptor *FakeOutputInterceptor 25 var interruptHandler *interrupt_handler.InterruptHandler 26 var conf types.SuiteConfig 27 var rt *RunTracker 28 var client parallel_support.Client 29 30 BeforeEach(func() { 31 failer = internal.NewFailer() 32 reporter = &FakeReporter{} 33 writer = internal.NewWriter(io.Discard) 34 outputInterceptor = NewFakeOutputInterceptor() 35 client = nil 36 interruptHandler = interrupt_handler.NewInterruptHandler(0, client) 37 DeferCleanup(interruptHandler.Stop) 38 conf = types.SuiteConfig{ 39 ParallelTotal: 1, 40 ParallelProcess: 1, 41 } 42 rt = NewRunTracker() 43 suite = internal.NewSuite() 44 }) 45 46 Describe("Constructing Trees", func() { 47 Describe("PhaseBuildTopLevel vs PhaseBuildTree", func() { 48 var err1, err2, err3 error 49 BeforeEach(func() { 50 err1 = suite.PushNode(N(ntCon, "a top-level container", func() { 51 rt.Run("traversing outer") 52 err2 = suite.PushNode(N(ntCon, "a nested container", func() { 53 rt.Run("traversing nested") 54 err3 = suite.PushNode(N(ntIt, "an it", rt.T("running it"))) 55 })) 56 })) 57 }) 58 59 It("only traverses top-level containers when told to BuildTree", func() { 60 fmt.Fprintln(GinkgoWriter, "HELLO!") 61 Ω(rt).Should(HaveTrackedNothing()) 62 Ω(suite.BuildTree()).Should(Succeed()) 63 Ω(rt).Should(HaveTracked("traversing outer", "traversing nested")) 64 65 rt.Reset() 66 suite.Run("suite", Labels{}, "/path/to/suite", failer, reporter, writer, outputInterceptor, interruptHandler, client, conf) 67 Ω(rt).Should(HaveTracked("running it")) 68 69 Ω(err1).ShouldNot(HaveOccurred()) 70 Ω(err2).ShouldNot(HaveOccurred()) 71 Ω(err3).ShouldNot(HaveOccurred()) 72 }) 73 }) 74 75 Context("when pushing nodes during PhaseRun", func() { 76 var pushNodeErrDuringRun error 77 78 BeforeEach(func() { 79 err := suite.PushNode(N(ntCon, "a top-level container", func() { 80 suite.PushNode(N(ntIt, "an it", func() { 81 rt.Run("in it") 82 pushNodeErrDuringRun = suite.PushNode(N(ntIt, "oops - illegal operation", cl, rt.T("illegal"))) 83 })) 84 })) 85 86 Ω(err).ShouldNot(HaveOccurred()) 87 Ω(suite.BuildTree()).Should(Succeed()) 88 }) 89 90 It("errors", func() { 91 suite.Run("suite", Labels{}, "/path/to/suite", failer, reporter, writer, outputInterceptor, interruptHandler, client, conf) 92 Ω(pushNodeErrDuringRun).Should(HaveOccurred()) 93 Ω(rt).Should(HaveTracked("in it")) 94 }) 95 96 }) 97 98 Context("when the user attemps to fail during PhaseBuildTree", func() { 99 BeforeEach(func() { 100 suite.PushNode(N(ntCon, "a top-level container", func() { 101 failer.Fail("boom", cl) 102 panic("simulate ginkgo panic") 103 })) 104 }) 105 106 It("errors", func() { 107 err := suite.BuildTree() 108 Ω(err.Error()).Should(ContainSubstring(cl.String())) 109 Ω(err.Error()).Should(ContainSubstring("simulate ginkgo panic")) 110 }) 111 }) 112 113 Context("when the user panics during PhaseBuildTree", func() { 114 BeforeEach(func() { 115 suite.PushNode(N(ntCon, "a top-level container", func() { 116 panic("boom") 117 })) 118 }) 119 120 It("errors", func() { 121 err := suite.BuildTree() 122 Ω(err).Should(HaveOccurred()) 123 Ω(err.Error()).Should(ContainSubstring("boom")) 124 }) 125 }) 126 127 Describe("Suite Nodes", func() { 128 Context("when pushing suite nodes at the top level", func() { 129 BeforeEach(func() { 130 err := suite.PushNode(N(types.NodeTypeBeforeSuite)) 131 Ω(err).ShouldNot(HaveOccurred()) 132 133 err = suite.PushNode(N(types.NodeTypeAfterSuite)) 134 Ω(err).ShouldNot(HaveOccurred()) 135 }) 136 137 Context("when pushing more than one BeforeSuite node", func() { 138 It("errors", func() { 139 err := suite.PushNode(N(types.NodeTypeBeforeSuite)) 140 Ω(err).Should(HaveOccurred()) 141 142 err = suite.PushNode(N(types.NodeTypeSynchronizedBeforeSuite)) 143 Ω(err).Should(HaveOccurred()) 144 }) 145 }) 146 147 Context("when pushing more than one AfterSuite node", func() { 148 It("errors", func() { 149 err := suite.PushNode(N(types.NodeTypeAfterSuite)) 150 Ω(err).Should(HaveOccurred()) 151 152 err = suite.PushNode(N(types.NodeTypeSynchronizedAfterSuite)) 153 Ω(err).Should(HaveOccurred()) 154 }) 155 }) 156 }) 157 158 Context("when pushing a serial node in an ordered container", func() { 159 Context("when the outer-most ordered container is marked serial", func() { 160 It("succeeds", func() { 161 var errors = make([]error, 3) 162 errors[0] = suite.PushNode(N(ntCon, "top-level-container", Ordered, Serial, func() { 163 errors[1] = suite.PushNode(N(ntCon, "inner-container", func() { 164 errors[2] = suite.PushNode(N(ntIt, "it", Serial, func() {})) 165 })) 166 })) 167 Ω(errors[0]).ShouldNot(HaveOccurred()) 168 Ω(suite.BuildTree()).Should(Succeed()) 169 Ω(errors[1]).ShouldNot(HaveOccurred()) 170 Ω(errors[2]).ShouldNot(HaveOccurred()) 171 }) 172 }) 173 174 Context("when the outer-most ordered container is not marked serial", func() { 175 It("errors", func() { 176 var errors = make([]error, 3) 177 errors[0] = suite.PushNode(N(ntCon, "top-level-container", Ordered, func() { 178 errors[1] = suite.PushNode(N(ntCon, "inner-container", func() { 179 errors[2] = suite.PushNode(N(ntIt, "it", Serial, cl, func() {})) 180 })) 181 })) 182 Ω(errors[0]).ShouldNot(HaveOccurred()) 183 Ω(suite.BuildTree()).Should(Succeed()) 184 Ω(errors[1]).ShouldNot(HaveOccurred()) 185 Ω(errors[2]).Should(MatchError(types.GinkgoErrors.InvalidSerialNodeInNonSerialOrderedContainer(cl, ntIt))) 186 }) 187 }) 188 }) 189 190 Context("when pushing BeforeAll and AfterAll nodes", func() { 191 Context("in an ordered container", func() { 192 It("succeeds", func() { 193 var errors = make([]error, 3) 194 errors[0] = suite.PushNode(N(ntCon, "top-level-container", Ordered, func() { 195 errors[1] = suite.PushNode(N(types.NodeTypeBeforeAll, func() {})) 196 errors[2] = suite.PushNode(N(types.NodeTypeAfterAll, func() {})) 197 })) 198 Ω(errors[0]).ShouldNot(HaveOccurred()) 199 Ω(suite.BuildTree()).Should(Succeed()) 200 Ω(errors[1]).ShouldNot(HaveOccurred()) 201 Ω(errors[2]).ShouldNot(HaveOccurred()) 202 }) 203 }) 204 205 Context("anywhere else", func() { 206 It("errors", func() { 207 var errors = make([]error, 3) 208 errors[0] = suite.PushNode(N(ntCon, "top-level-container", func() { 209 errors[1] = suite.PushNode(N(types.NodeTypeBeforeAll, cl, func() {})) 210 errors[2] = suite.PushNode(N(types.NodeTypeAfterAll, cl, func() {})) 211 })) 212 Ω(errors[0]).ShouldNot(HaveOccurred()) 213 Ω(suite.BuildTree()).Should(Succeed()) 214 Ω(errors[1]).Should(MatchError(types.GinkgoErrors.SetupNodeNotInOrderedContainer(cl, types.NodeTypeBeforeAll))) 215 Ω(errors[2]).Should(MatchError(types.GinkgoErrors.SetupNodeNotInOrderedContainer(cl, types.NodeTypeAfterAll))) 216 }) 217 }) 218 }) 219 220 Context("when pushing a suite node during PhaseBuildTree", func() { 221 It("errors", func() { 222 var pushSuiteNodeErr error 223 err := suite.PushNode(N(ntCon, "top-level-container", func() { 224 pushSuiteNodeErr = suite.PushNode(N(types.NodeTypeBeforeSuite, cl)) 225 })) 226 227 Ω(err).ShouldNot(HaveOccurred()) 228 Ω(suite.BuildTree()).Should(Succeed()) 229 Ω(pushSuiteNodeErr).Should(HaveOccurred()) 230 }) 231 }) 232 233 Context("when pushing a suite node during PhaseRun", func() { 234 It("errors", func() { 235 var pushSuiteNodeErr error 236 err := suite.PushNode(N(ntIt, "top-level it", func() { 237 pushSuiteNodeErr = suite.PushNode(N(types.NodeTypeBeforeSuite, cl)) 238 })) 239 240 Ω(err).ShouldNot(HaveOccurred()) 241 Ω(suite.BuildTree()).Should(Succeed()) 242 suite.Run("suite", Labels{}, "/path/to/suite", failer, reporter, writer, outputInterceptor, interruptHandler, client, conf) 243 Ω(pushSuiteNodeErr).Should(HaveOccurred()) 244 }) 245 }) 246 }) 247 248 Describe("Cleanup Nodes", func() { 249 Context("when pushing a cleanup node during PhaseTopLevel", func() { 250 It("errors", func() { 251 err := suite.PushNode(N(types.NodeTypeCleanupInvalid, cl)) 252 Ω(err).Should(MatchError(types.GinkgoErrors.PushingCleanupNodeDuringTreeConstruction(cl))) 253 }) 254 }) 255 256 Context("when pushing a cleanup node during PhaseBuildTree", func() { 257 It("errors", func() { 258 var errors = make([]error, 2) 259 errors[0] = suite.PushNode(N(ntCon, "container", func() { 260 errors[1] = suite.PushNode(N(types.NodeTypeCleanupInvalid, cl)) 261 })) 262 Ω(errors[0]).ShouldNot(HaveOccurred()) 263 Ω(suite.BuildTree()).Should(Succeed()) 264 Ω(errors[1]).Should(MatchError(types.GinkgoErrors.PushingCleanupNodeDuringTreeConstruction(cl))) 265 }) 266 }) 267 268 Context("when pushing a cleanup node in a ReportBeforeEach node", func() { 269 It("errors", func() { 270 var errors = make([]error, 4) 271 reportBeforeEachNode, _ := internal.NewReportBeforeEachNode(func(_ types.SpecReport) { 272 errors[3] = suite.PushNode(N(types.NodeTypeCleanupInvalid, cl)) 273 }, types.NewCodeLocation(0)) 274 275 errors[0] = suite.PushNode(N(ntCon, "container", func() { 276 errors[1] = suite.PushNode(reportBeforeEachNode) 277 errors[2] = suite.PushNode(N(ntIt, "test")) 278 })) 279 Ω(errors[0]).ShouldNot(HaveOccurred()) 280 281 Ω(suite.BuildTree()).Should(Succeed()) 282 Ω(errors[1]).ShouldNot(HaveOccurred()) 283 Ω(errors[2]).ShouldNot(HaveOccurred()) 284 285 suite.Run("suite", Labels{}, "/path/to/suite", failer, reporter, writer, outputInterceptor, interruptHandler, client, conf) 286 Ω(errors[3]).Should(MatchError(types.GinkgoErrors.PushingCleanupInReportingNode(cl, types.NodeTypeReportBeforeEach))) 287 }) 288 }) 289 290 Context("when pushing a cleanup node in a ReportAfterEach node", func() { 291 It("errors", func() { 292 var errors = make([]error, 4) 293 reportAfterEachNode, _ := internal.NewReportAfterEachNode(func(_ types.SpecReport) { 294 errors[3] = suite.PushNode(N(types.NodeTypeCleanupInvalid, cl)) 295 }, types.NewCodeLocation(0)) 296 297 errors[0] = suite.PushNode(N(ntCon, "container", func() { 298 errors[1] = suite.PushNode(N(ntIt, "test")) 299 errors[2] = suite.PushNode(reportAfterEachNode) 300 })) 301 Ω(errors[0]).ShouldNot(HaveOccurred()) 302 303 Ω(suite.BuildTree()).Should(Succeed()) 304 Ω(errors[1]).ShouldNot(HaveOccurred()) 305 Ω(errors[2]).ShouldNot(HaveOccurred()) 306 307 suite.Run("suite", Labels{}, "/path/to/suite", failer, reporter, writer, outputInterceptor, interruptHandler, client, conf) 308 Ω(errors[3]).Should(MatchError(types.GinkgoErrors.PushingCleanupInReportingNode(cl, types.NodeTypeReportAfterEach))) 309 }) 310 }) 311 312 Context("when pushing a cleanup node in a ReportAfterSuite node", func() { 313 It("errors", func() { 314 var errors = make([]error, 4) 315 reportAfterSuiteNode, _ := internal.NewReportAfterSuiteNode("report", func(_ types.Report) { 316 errors[3] = suite.PushNode(N(types.NodeTypeCleanupInvalid, cl)) 317 }, types.NewCodeLocation(0)) 318 319 errors[0] = suite.PushNode(N(ntCon, "container", func() { 320 errors[2] = suite.PushNode(N(ntIt, "test")) 321 })) 322 errors[1] = suite.PushNode(reportAfterSuiteNode) 323 Ω(errors[0]).ShouldNot(HaveOccurred()) 324 Ω(errors[1]).ShouldNot(HaveOccurred()) 325 326 Ω(suite.BuildTree()).Should(Succeed()) 327 Ω(errors[2]).ShouldNot(HaveOccurred()) 328 329 suite.Run("suite", Labels{}, "/path/to/suite", failer, reporter, writer, outputInterceptor, interruptHandler, client, conf) 330 Ω(errors[3]).Should(MatchError(types.GinkgoErrors.PushingCleanupInReportingNode(cl, types.NodeTypeReportAfterSuite))) 331 }) 332 }) 333 334 Context("when pushing a cleanup node within a cleanup node", func() { 335 It("errors", func() { 336 var errors = make([]error, 3) 337 errors[0] = suite.PushNode(N(ntIt, "It", func() { 338 cleanupNode, _ := internal.NewCleanupNode(nil, types.NewCustomCodeLocation("outerCleanup"), func() { 339 innerCleanupNode, _ := internal.NewCleanupNode(nil, cl, func() {}) 340 errors[2] = suite.PushNode(innerCleanupNode) 341 }) 342 errors[1] = suite.PushNode(cleanupNode) 343 })) 344 Ω(errors[0]).ShouldNot(HaveOccurred()) 345 Ω(suite.BuildTree()).Should(Succeed()) 346 suite.Run("suite", Labels{}, "/path/to/suite", failer, reporter, writer, outputInterceptor, interruptHandler, client, conf) 347 Ω(errors[1]).ShouldNot(HaveOccurred()) 348 Ω(errors[2]).Should(MatchError(types.GinkgoErrors.PushingCleanupInCleanupNode(cl))) 349 }) 350 }) 351 }) 352 353 Describe("ReportEntries", func() { 354 Context("when adding a report entry outside of the run phase", func() { 355 It("errors", func() { 356 entry, err := internal.NewReportEntry("name", cl) 357 Ω(err).ShouldNot(HaveOccurred()) 358 err = suite.AddReportEntry(entry) 359 Ω(err).Should(MatchError(types.GinkgoErrors.AddReportEntryNotDuringRunPhase(cl))) 360 suite.BuildTree() 361 err = suite.AddReportEntry(entry) 362 Ω(err).Should(MatchError(types.GinkgoErrors.AddReportEntryNotDuringRunPhase(cl))) 363 }) 364 }) 365 }) 366 }) 367 })