...

Source file src/github.com/onsi/ginkgo/v2/internal/interrupt_handler/interrupt_handler_test.go

Documentation: github.com/onsi/ginkgo/v2/internal/interrupt_handler

     1  //go:build freebsd || openbsd || netbsd || dragonfly || darwin || linux || solaris
     2  // +build freebsd openbsd netbsd dragonfly darwin linux solaris
     3  
     4  package interrupt_handler_test
     5  
     6  import (
     7  	"syscall"
     8  	"time"
     9  
    10  	. "github.com/onsi/ginkgo/v2"
    11  	"github.com/onsi/ginkgo/v2/internal/interrupt_handler"
    12  	"github.com/onsi/ginkgo/v2/internal/parallel_support"
    13  	. "github.com/onsi/ginkgo/v2/internal/test_helpers"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("InterruptHandler", func() {
    18  	var trigger func()
    19  	var interruptHandler *interrupt_handler.InterruptHandler
    20  	BeforeEach(func() {
    21  		trigger = func() {
    22  			syscall.Kill(syscall.Getpid(), syscall.SIGUSR2)
    23  		}
    24  	})
    25  
    26  	Describe("Signal interrupts", func() {
    27  		BeforeEach(func() {
    28  			interruptHandler = interrupt_handler.NewInterruptHandler(nil, syscall.SIGUSR2)
    29  			DeferCleanup(interruptHandler.Stop)
    30  		}, OncePerOrdered)
    31  
    32  		It("starts off uninterrupted", func() {
    33  			status := interruptHandler.Status()
    34  			Ω(status.Interrupted()).Should(BeFalse())
    35  			Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseInvalid))
    36  			Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelUninterrupted))
    37  			Consistently(status.Channel).ShouldNot(BeClosed())
    38  		})
    39  
    40  		When("interrupted repeatedly", Ordered, func() {
    41  			var status interrupt_handler.InterruptStatus
    42  			BeforeAll(func() {
    43  				status = interruptHandler.Status()
    44  				Ω(status.Interrupted()).Should(BeFalse())
    45  			})
    46  
    47  			Specify("when first interrupted, it closes the channel and goes to the next Cleanup and Report level", func() {
    48  				trigger()
    49  				Eventually(status.Channel).Should(BeClosed())
    50  
    51  				status = interruptHandler.Status()
    52  				Ω(status.Interrupted()).Should(BeTrue())
    53  				Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseSignal))
    54  				Ω(status.Message()).Should(Equal("Interrupted by User"))
    55  				Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelCleanupAndReport))
    56  				Ω(status.ShouldIncludeProgressReport()).Should(BeTrue())
    57  			})
    58  
    59  			Specify("when interrupted a second time, it closes the next channel and goes to the Report Only level", func() {
    60  				trigger()
    61  				Eventually(status.Channel).Should(BeClosed())
    62  
    63  				status = interruptHandler.Status()
    64  				Ω(status.Interrupted()).Should(BeTrue())
    65  				Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseSignal))
    66  				Ω(status.Message()).Should(Equal("Interrupted by User"))
    67  				Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelReportOnly))
    68  				Ω(status.ShouldIncludeProgressReport()).Should(BeTrue())
    69  			})
    70  
    71  			Specify("when interrupted a third time, it closes the next channel and goes to the Bail-Out level", func() {
    72  				trigger()
    73  				Eventually(status.Channel).Should(BeClosed())
    74  
    75  				status = interruptHandler.Status()
    76  				Ω(status.Interrupted()).Should(BeTrue())
    77  				Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseSignal))
    78  				Ω(status.Message()).Should(Equal("Interrupted by User"))
    79  				Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelBailOut))
    80  				Ω(status.ShouldIncludeProgressReport()).Should(BeTrue())
    81  			})
    82  
    83  			Specify("when interrupted again and again, it no longer interrupts once the last level has been reached", func() {
    84  				trigger()
    85  				Consistently(status.Channel).ShouldNot(BeClosed())
    86  				trigger()
    87  				Consistently(status.Channel).ShouldNot(BeClosed())
    88  
    89  				status = interruptHandler.Status()
    90  				Ω(status.Interrupted()).Should(BeTrue())
    91  				Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseSignal))
    92  				Ω(status.Message()).Should(Equal("Interrupted by User"))
    93  				Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelBailOut))
    94  				Ω(status.ShouldIncludeProgressReport()).Should(BeTrue())
    95  			})
    96  		})
    97  	})
    98  
    99  	Describe("Interrupting when another Ginkgo process has aborted", func() {
   100  		var client parallel_support.Client
   101  		BeforeEach(func() {
   102  			_, client, _ = SetUpServerAndClient(2)
   103  			interruptHandler = interrupt_handler.NewInterruptHandler(client, syscall.SIGUSR2)
   104  			DeferCleanup(interruptHandler.Stop)
   105  		})
   106  
   107  		It("interrupts when the server is told to abort", func() {
   108  			status := interruptHandler.Status()
   109  			Consistently(status.Channel).ShouldNot(BeClosed())
   110  
   111  			client.PostAbort()
   112  
   113  			Eventually(status.Channel).Should(BeClosed())
   114  		})
   115  
   116  		It("notes the correct cause and returns an interrupt message that does not include a progress report", func() {
   117  			status := interruptHandler.Status()
   118  			Ω(status.Interrupted()).Should(BeFalse())
   119  
   120  			client.PostAbort()
   121  			Eventually(status.Channel).Should(BeClosed())
   122  
   123  			status = interruptHandler.Status()
   124  			Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseAbortByOtherProcess))
   125  			Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelCleanupAndReport))
   126  			Ω(status.Interrupted()).Should(BeTrue())
   127  			Ω(status.Message()).Should(Equal("Interrupted by Other Ginkgo Process"))
   128  			Ω(status.ShouldIncludeProgressReport()).Should(BeFalse())
   129  		})
   130  
   131  		It("does not retrigger on subsequent aborts", func() {
   132  			status := interruptHandler.Status()
   133  			Ω(status.Interrupted()).Should(BeFalse())
   134  
   135  			client.PostAbort()
   136  			Eventually(status.Channel).Should(BeClosed())
   137  
   138  			status = interruptHandler.Status()
   139  			client.PostAbort()
   140  			Consistently(status.Channel, interrupt_handler.ABORT_POLLING_INTERVAL+100*time.Millisecond).ShouldNot(BeClosed())
   141  
   142  			status = interruptHandler.Status()
   143  			Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseAbortByOtherProcess))
   144  			Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelCleanupAndReport))
   145  		})
   146  
   147  		It("does not trigger if the suite has already been interrupted", func() {
   148  			status := interruptHandler.Status()
   149  			Ω(status.Interrupted()).Should(BeFalse())
   150  
   151  			trigger()
   152  			Eventually(status.Channel).Should(BeClosed())
   153  
   154  			status = interruptHandler.Status()
   155  			Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseSignal))
   156  			Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelCleanupAndReport))
   157  
   158  			status = interruptHandler.Status()
   159  			client.PostAbort()
   160  			Consistently(status.Channel, interrupt_handler.ABORT_POLLING_INTERVAL+100*time.Millisecond).ShouldNot(BeClosed())
   161  
   162  			status = interruptHandler.Status()
   163  			Ω(status.Cause).Should(Equal(interrupt_handler.InterruptCauseSignal))
   164  			Ω(status.Level).Should(Equal(interrupt_handler.InterruptLevelCleanupAndReport))
   165  		})
   166  
   167  		It("doesn't just rely on the ABORT_POLLING_INTERVAL timer to report that the interrupt has happened", func() {
   168  			client.PostAbort()
   169  			Ω(interruptHandler.Status().Cause).Should(Equal(interrupt_handler.InterruptCauseAbortByOtherProcess))
   170  		}, MustPassRepeatedly(10))
   171  	})
   172  })
   173  

View as plain text