github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/internal/internal_integration/cleanup_test.go (about)

     1  package internal_integration_test
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	. "github.com/onsi/ginkgo"
     8  	"github.com/onsi/ginkgo/internal/interrupt_handler"
     9  	. "github.com/onsi/ginkgo/internal/test_helpers"
    10  	"github.com/onsi/ginkgo/types"
    11  	. "github.com/onsi/gomega"
    12  )
    13  
    14  var _ = Describe("Cleanup", func() {
    15  	C := func(label string) func() {
    16  		return func() {
    17  			DeferCleanup(rt.Run, label)
    18  		}
    19  	}
    20  
    21  	Context("the happy path", func() {
    22  		BeforeEach(func() {
    23  			success, _ := RunFixture("cleanup happy path", func() {
    24  				BeforeSuite(rt.T("BS", C("C-BS")))
    25  				AfterSuite(rt.T("AS", C("C-AS")))
    26  
    27  				BeforeEach(rt.T("BE-outer", C("C-BE-outer")))
    28  				AfterEach(rt.T("AE-outer", C("C-AE-outer")))
    29  
    30  				Context("non-randomizing container", func() {
    31  					Context("container", Ordered, func() {
    32  						JustBeforeEach(rt.T("JBE", C("C-JBE")))
    33  						It("A", rt.T("A", C("C-A")))
    34  						JustAfterEach(rt.T("JAE", C("C-JAE")))
    35  					})
    36  
    37  					Context("ordered container", Ordered, func() {
    38  						BeforeAll(rt.T("BA", C("C-BA")))
    39  						BeforeEach(rt.T("BE-inner", C("C-BE-inner")))
    40  						It("B", rt.T("B", C("C-B")))
    41  						It("C", rt.T("C", C("C-C")))
    42  						It("D", rt.T("D", C("C-D")))
    43  						AfterEach(rt.T("AE-inner", C("C-AE-inner")))
    44  						AfterAll(rt.T("AA", C("C-AA")))
    45  					})
    46  				})
    47  			})
    48  			Ω(success).Should(BeTrue())
    49  		})
    50  
    51  		It("runs all the things in the correct order", func() {
    52  			Ω(rt).Should(HaveTracked(
    53  				//before suite
    54  				"BS",
    55  
    56  				//container
    57  				"BE-outer", "JBE", "A", "JAE", "AE-outer", "C-AE-outer", "C-JAE", "C-A", "C-JBE", "C-BE-outer",
    58  
    59  				//ordered container
    60  				"BE-outer", "BA", "BE-inner", "B", "AE-inner", "AE-outer", "C-AE-outer", "C-AE-inner", "C-B", "C-BE-inner", "C-BE-outer",
    61  				"BE-outer", "BE-inner", "C", "AE-inner", "AE-outer", "C-AE-outer", "C-AE-inner", "C-C", "C-BE-inner", "C-BE-outer",
    62  				"BE-outer", "BE-inner", "D", "AE-inner", "AA", "AE-outer", "C-AE-outer", "C-AE-inner", "C-D", "C-BE-inner", "C-BE-outer", "C-AA", "C-BA",
    63  
    64  				//after suite
    65  				"AS",
    66  				"C-AS", "C-BS",
    67  			))
    68  		})
    69  	})
    70  
    71  	Context("when cleanup fails", func() {
    72  		Context("because of a failed assertion", func() {
    73  			BeforeEach(func() {
    74  				success, _ := RunFixture("cleanup failure", func() {
    75  					BeforeEach(rt.T("BE", func() {
    76  						DeferCleanup(func() {
    77  							rt.Run("C-BE")
    78  							F("fail")
    79  						})
    80  					}))
    81  
    82  					It("A", rt.T("A", C("C-A")))
    83  				})
    84  				Ω(success).Should(BeFalse())
    85  			})
    86  
    87  			It("reports a failure", func() {
    88  				Ω(rt).Should(HaveTracked("BE", "A", "C-A", "C-BE"))
    89  				Ω(reporter.Did.Find("A")).Should(HaveFailed("fail", FailureNodeType(types.NodeTypeCleanupAfterEach), types.FailureNodeAtTopLevel))
    90  			})
    91  		})
    92  
    93  		Context("because of a returned error", func() {
    94  			BeforeEach(func() {
    95  				success, _ := RunFixture("cleanup failure", func() {
    96  					BeforeEach(rt.T("BE", C("C-BE")))
    97  					It("A", rt.T("A", func() {
    98  						DeferCleanup(func() error {
    99  							rt.Run("C-A")
   100  							return fmt.Errorf("fail")
   101  						})
   102  					}))
   103  				})
   104  				Ω(success).Should(BeFalse())
   105  			})
   106  
   107  			It("reports a failure", func() {
   108  				Ω(rt).Should(HaveTracked("BE", "A", "C-A", "C-BE"))
   109  				Ω(reporter.Did.Find("A")).Should(HaveFailed("DeferCleanup callback returned error: fail", FailureNodeType(types.NodeTypeCleanupAfterEach), types.FailureNodeAtTopLevel))
   110  			})
   111  		})
   112  
   113  		Context("at the suite level", func() {
   114  			BeforeEach(func() {
   115  				success, _ := RunFixture("cleanup failure", func() {
   116  					BeforeSuite(rt.T("BS", func() {
   117  						DeferCleanup(func() {
   118  							rt.Run("C-BS")
   119  							F("fail")
   120  						})
   121  					}))
   122  					Context("container", func() {
   123  						It("A", rt.T("A"))
   124  						It("B", rt.T("B"))
   125  					})
   126  				})
   127  				Ω(success).Should(BeFalse())
   128  			})
   129  
   130  			It("marks the suite as failed", func() {
   131  				Ω(rt).Should(HaveTracked("BS", "A", "B", "C-BS"))
   132  				Ω(reporter.End).Should(BeASuiteSummary(false, NSpecs(2), NPassed(2)))
   133  				Ω(reporter.Did.FindByLeafNodeType(types.NodeTypeBeforeSuite)).Should(HavePassed())
   134  				Ω(reporter.Did.FindByLeafNodeType(types.NodeTypeCleanupAfterSuite)).Should(HaveFailed("fail", FailureNodeType(types.NodeTypeCleanupAfterSuite)))
   135  			})
   136  		})
   137  
   138  		Context("when cleanup is interrupted", func() {
   139  			BeforeEach(func() {
   140  				success, _ := RunFixture("cleanup failure", func() {
   141  					BeforeEach(rt.T("BE", C("C-BE")))
   142  					It("A", rt.T("A", func() {
   143  						DeferCleanup(func() {
   144  							rt.Run("C-A")
   145  							interruptHandler.Interrupt(interrupt_handler.InterruptCauseSignal)
   146  							time.Sleep(time.Minute)
   147  						})
   148  					}))
   149  				})
   150  				Ω(success).Should(BeFalse())
   151  			})
   152  			It("runs subsequent cleanups and is marked as interrupted", func() {
   153  				Ω(rt).Should(HaveTracked("BE", "A", "C-A", "C-BE"))
   154  
   155  				Ω(reporter.Did.Find("A")).Should(HaveBeenInterrupted(interrupt_handler.InterruptCauseSignal))
   156  			})
   157  		})
   158  	})
   159  
   160  	Context("edge cases", func() {
   161  		Context("cleanup is added in a SynchronizedBeforeSuite and SynchronizedAfterSuite", func() {
   162  			Context("when running in serial", func() {
   163  				BeforeEach(func() {
   164  					success, _ := RunFixture("cleanup in synchronized suites", func() {
   165  						SynchronizedBeforeSuite(func() []byte {
   166  							rt.Run("BS1")
   167  							DeferCleanup(rt.Run, "C-BS1")
   168  							return nil
   169  						}, func(_ []byte) {
   170  							rt.Run("BS2")
   171  							DeferCleanup(rt.Run, "C-BS2")
   172  						})
   173  
   174  						SynchronizedAfterSuite(func() {
   175  							rt.Run("AS1")
   176  							DeferCleanup(rt.Run, "C-AS1")
   177  						}, func() {
   178  							rt.Run("AS2")
   179  							DeferCleanup(rt.Run, "C-AS2")
   180  						})
   181  						Context("ordering", func() {
   182  							It("A", rt.T("A", C("C-A")))
   183  							It("B", rt.T("B", C("C-B")))
   184  						})
   185  					})
   186  					Ω(success).Should(BeTrue())
   187  
   188  				})
   189  				It("runs the cleanup at the appropriate time", func() {
   190  					Ω(rt).Should(HaveTracked("BS1", "BS2", "A", "C-A", "B", "C-B", "AS1", "AS2", "C-AS2", "C-AS1", "C-BS2", "C-BS1"))
   191  				})
   192  			})
   193  
   194  			Context("when running in parallel and there is no SynchronizedAfterSuite", func() {
   195  				fixture := func() {
   196  					SynchronizedBeforeSuite(func() []byte {
   197  						rt.Run("BS1")
   198  						DeferCleanup(rt.Run, "C-BS1")
   199  						return nil
   200  					}, func(_ []byte) {
   201  						rt.Run("BS2")
   202  						DeferCleanup(rt.Run, "C-BS2")
   203  					})
   204  
   205  					Context("ordering", func() {
   206  						It("A", rt.T("A", C("C-A")))
   207  						It("B", rt.T("B", C("C-B")))
   208  					})
   209  				}
   210  
   211  				BeforeEach(func() {
   212  					SetUpForParallel(2)
   213  				})
   214  
   215  				Context("as process #1", func() {
   216  					It("runs the cleanup only _after_ the other processes have finished", func() {
   217  						done := make(chan interface{})
   218  						go func() {
   219  							defer GinkgoRecover()
   220  							success, _ := RunFixture("DeferCleanup on SBS in parallel on process 1", fixture)
   221  							Ω(success).Should(BeTrue())
   222  							close(done)
   223  						}()
   224  
   225  						Eventually(rt).Should(HaveTracked("BS1", "BS2", "A", "C-A", "B", "C-B"))
   226  						Consistently(rt).Should(HaveTracked("BS1", "BS2", "A", "C-A", "B", "C-B"))
   227  						close(exitChannels[2])
   228  						Eventually(rt).Should(HaveTracked("BS1", "BS2", "A", "C-A", "B", "C-B", "C-BS2", "C-BS1"))
   229  						Eventually(done).Should(BeClosed())
   230  					})
   231  				})
   232  
   233  				Context("as process #2", func() {
   234  					BeforeEach(func() {
   235  						conf.ParallelProcess = 2
   236  						client.PostSynchronizedBeforeSuiteCompleted(types.SpecStatePassed, []byte("hola hola"))
   237  						success, _ := RunFixture("DeferCleanup on SBS in parallel on process 2", fixture)
   238  						Ω(success).Should(BeTrue())
   239  					})
   240  
   241  					It("runs the cleanup at the appropriate time", func() {
   242  						Ω(rt).Should(HaveTracked("BS2", "A", "C-A", "B", "C-B", "C-BS2"))
   243  					})
   244  				})
   245  			})
   246  		})
   247  
   248  		Context("cleanup is added in an AfterAll that is called because an AfterEach has caused the non-final spec in an ordered group to fail", func() {
   249  			BeforeEach(func() {
   250  				success, _ := RunFixture("cleanup in hairy edge case", func() {
   251  					Context("ordered", Ordered, func() {
   252  						It("A", rt.T("A", C("C-A")))
   253  						It("B", rt.T("B"))
   254  						AfterEach(rt.T("AE", func() {
   255  							DeferCleanup(rt.Run, "C-AE")
   256  							F("fail")
   257  						}))
   258  						AfterAll(rt.T("AA", C("C-AA")))
   259  					})
   260  				})
   261  				Ω(success).Should(BeFalse())
   262  			})
   263  
   264  			It("notes that a cleanup was registered in the AfterAll and runs it", func() {
   265  				Ω(rt).Should(HaveTracked("A", "AE", "AA", "C-AE", "C-A", "C-AA"))
   266  			})
   267  		})
   268  	})
   269  })