How to use registerForInterrupts method of interrupt_handler Package

Best Ginkgo code snippet using interrupt_handler.registerForInterrupts

Run Ginkgo automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

fake_interrupt_handler.go

Source: fake_interrupt_handler.go Github

copy
1package test_helpers
2
3import (
4	"sync"
5
6	"github.com/onsi/ginkgo/v2/internal/interrupt_handler"
7)
8
9type FakeInterruptHandler struct {
10	triggerInterrupt chan bool
11
12	c                                  chan interface{}
13	stop                               chan interface{}
14	lock                               *sync.Mutex
15	interrupted                        bool
16	cause                              interrupt_handler.InterruptCause
17	interruptPlaceholderMessage        string
18	emittedInterruptPlaceholderMessage string
19}
20
21func NewFakeInterruptHandler() *FakeInterruptHandler {
22	handler := &FakeInterruptHandler{
23		triggerInterrupt: make(chan bool),
24		c:                make(chan interface{}),
25		lock:             &sync.Mutex{},
26		interrupted:      false,
27		stop:             make(chan interface{}),
28	}
29	handler.registerForInterrupts()
30	return handler
31}
32
33func (handler *FakeInterruptHandler) Stop() {
34	close(handler.stop)
35}
36
37func (handler *FakeInterruptHandler) registerForInterrupts() {
38	go func() {
39		for {
40			select {
41			case <-handler.triggerInterrupt:
42			case <-handler.stop:
43				return
44			}
45			handler.lock.Lock()
46			handler.interrupted = true
47			handler.emittedInterruptPlaceholderMessage = handler.interruptPlaceholderMessage
48			close(handler.c)
49			handler.c = make(chan interface{})
50			handler.lock.Unlock()
51		}
52	}()
53}
54
55func (handler *FakeInterruptHandler) Interrupt(cause interrupt_handler.InterruptCause) {
56	handler.lock.Lock()
57	handler.cause = cause
58	handler.lock.Unlock()
59
60	handler.triggerInterrupt <- true
61}
62
63func (handler *FakeInterruptHandler) Status() interrupt_handler.InterruptStatus {
64	handler.lock.Lock()
65	defer handler.lock.Unlock()
66
67	return interrupt_handler.InterruptStatus{
68		Interrupted: handler.interrupted,
69		Channel:     handler.c,
70		Cause:       handler.cause,
71	}
72}
73
74func (handler *FakeInterruptHandler) SetInterruptPlaceholderMessage(message string) {
75	handler.lock.Lock()
76	defer handler.lock.Unlock()
77
78	handler.interruptPlaceholderMessage = message
79}
80
81func (handler *FakeInterruptHandler) ClearInterruptPlaceholderMessage() {
82	handler.lock.Lock()
83	defer handler.lock.Unlock()
84
85	handler.interruptPlaceholderMessage = ""
86}
87
88func (handler *FakeInterruptHandler) EmittedInterruptPlaceholderMessage() string {
89	handler.lock.Lock()
90	defer handler.lock.Unlock()
91	return handler.emittedInterruptPlaceholderMessage
92}
93
94func (handler *FakeInterruptHandler) InterruptMessageWithStackTraces() string {
95	handler.lock.Lock()
96	defer handler.lock.Unlock()
97
98	return handler.cause.String() + "\nstack trace"
99}
100
Full Screen

interrupt_handler.go

Source: interrupt_handler.go Github

copy
1package interrupt_handler
2
3import (
4	"fmt"
5	"os"
6	"os/signal"
7	"runtime"
8	"sync"
9	"syscall"
10	"time"
11
12	"github.com/onsi/ginkgo/v2/formatter"
13	"github.com/onsi/ginkgo/v2/internal/parallel_support"
14)
15
16const TIMEOUT_REPEAT_INTERRUPT_MAXIMUM_DURATION = 30 * time.Second
17const TIMEOUT_REPEAT_INTERRUPT_FRACTION_OF_TIMEOUT = 10
18const ABORT_POLLING_INTERVAL = 500 * time.Millisecond
19const ABORT_REPEAT_INTERRUPT_DURATION = 30 * time.Second
20
21type InterruptCause uint
22
23const (
24	InterruptCauseInvalid InterruptCause = iota
25
26	InterruptCauseSignal
27	InterruptCauseTimeout
28	InterruptCauseAbortByOtherProcess
29)
30
31func (ic InterruptCause) String() string {
32	switch ic {
33	case InterruptCauseSignal:
34		return "Interrupted by User"
35	case InterruptCauseTimeout:
36		return "Interrupted by Timeout"
37	case InterruptCauseAbortByOtherProcess:
38		return "Interrupted by Other Ginkgo Process"
39	}
40	return "INVALID_INTERRUPT_CAUSE"
41}
42
43type InterruptStatus struct {
44	Interrupted bool
45	Channel     chan interface{}
46	Cause       InterruptCause
47}
48
49type InterruptHandlerInterface interface {
50	Status() InterruptStatus
51	SetInterruptPlaceholderMessage(string)
52	ClearInterruptPlaceholderMessage()
53	InterruptMessageWithStackTraces() string
54}
55
56type InterruptHandler struct {
57	c                           chan interface{}
58	lock                        *sync.Mutex
59	interrupted                 bool
60	interruptPlaceholderMessage string
61	interruptCause              InterruptCause
62	client                      parallel_support.Client
63	stop                        chan interface{}
64}
65
66func NewInterruptHandler(timeout time.Duration, client parallel_support.Client) *InterruptHandler {
67	handler := &InterruptHandler{
68		c:           make(chan interface{}),
69		lock:        &sync.Mutex{},
70		interrupted: false,
71		stop:        make(chan interface{}),
72		client:      client,
73	}
74	handler.registerForInterrupts(timeout)
75	return handler
76}
77
78func (handler *InterruptHandler) Stop() {
79	close(handler.stop)
80}
81
82func (handler *InterruptHandler) registerForInterrupts(timeout time.Duration) {
83	// os signal handling
84	signalChannel := make(chan os.Signal, 1)
85	signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM)
86
87	// timeout handling
88	var timeoutChannel <-chan time.Time
89	var timeoutTimer *time.Timer
90	if timeout > 0 {
91		timeoutTimer = time.NewTimer(timeout)
92		timeoutChannel = timeoutTimer.C
93	}
94
95	// cross-process abort handling
96	var abortChannel chan bool
97	if handler.client != nil {
98		abortChannel = make(chan bool)
99		go func() {
100			pollTicker := time.NewTicker(ABORT_POLLING_INTERVAL)
101			for {
102				select {
103				case <-pollTicker.C:
104					if handler.client.ShouldAbort() {
105						abortChannel <- true
106						pollTicker.Stop()
107						return
108					}
109				case <-handler.stop:
110					pollTicker.Stop()
111					return
112				}
113			}
114		}()
115	}
116
117	// listen for any interrupt signals
118	// note that some (timeouts, cross-process aborts) will only trigger once
119	// for these we set up a ticker to keep interrupting the suite until it ends
120	// this ensures any `AfterEach` or `AfterSuite`s that get stuck cleaning up
121	// get interrupted eventually
122	go func() {
123		var interruptCause InterruptCause
124		var repeatChannel <-chan time.Time
125		var repeatTicker *time.Ticker
126		for {
127			select {
128			case <-signalChannel:
129				interruptCause = InterruptCauseSignal
130			case <-timeoutChannel:
131				interruptCause = InterruptCauseTimeout
132				repeatInterruptTimeout := timeout / time.Duration(TIMEOUT_REPEAT_INTERRUPT_FRACTION_OF_TIMEOUT)
133				if repeatInterruptTimeout > TIMEOUT_REPEAT_INTERRUPT_MAXIMUM_DURATION {
134					repeatInterruptTimeout = TIMEOUT_REPEAT_INTERRUPT_MAXIMUM_DURATION
135				}
136				timeoutTimer.Stop()
137				repeatTicker = time.NewTicker(repeatInterruptTimeout)
138				repeatChannel = repeatTicker.C
139			case <-abortChannel:
140				interruptCause = InterruptCauseAbortByOtherProcess
141				repeatTicker = time.NewTicker(ABORT_REPEAT_INTERRUPT_DURATION)
142				repeatChannel = repeatTicker.C
143			case <-repeatChannel:
144				//do nothing, just interrupt again using the same interruptCause
145			case <-handler.stop:
146				if timeoutTimer != nil {
147					timeoutTimer.Stop()
148				}
149				if repeatTicker != nil {
150					repeatTicker.Stop()
151				}
152				signal.Stop(signalChannel)
153				return
154			}
155			handler.lock.Lock()
156			handler.interruptCause = interruptCause
157			if handler.interruptPlaceholderMessage != "" {
158				fmt.Println(handler.interruptPlaceholderMessage)
159			}
160			handler.interrupted = true
161			close(handler.c)
162			handler.c = make(chan interface{})
163			handler.lock.Unlock()
164		}
165	}()
166}
167
168func (handler *InterruptHandler) Status() InterruptStatus {
169	handler.lock.Lock()
170	defer handler.lock.Unlock()
171
172	return InterruptStatus{
173		Interrupted: handler.interrupted,
174		Channel:     handler.c,
175		Cause:       handler.interruptCause,
176	}
177}
178
179func (handler *InterruptHandler) SetInterruptPlaceholderMessage(message string) {
180	handler.lock.Lock()
181	defer handler.lock.Unlock()
182
183	handler.interruptPlaceholderMessage = message
184}
185
186func (handler *InterruptHandler) ClearInterruptPlaceholderMessage() {
187	handler.lock.Lock()
188	defer handler.lock.Unlock()
189
190	handler.interruptPlaceholderMessage = ""
191}
192
193func (handler *InterruptHandler) InterruptMessageWithStackTraces() string {
194	handler.lock.Lock()
195	out := fmt.Sprintf("%s\n\n", handler.interruptCause.String())
196	defer handler.lock.Unlock()
197	if handler.interruptCause == InterruptCauseAbortByOtherProcess {
198		return out
199	}
200	out += "Here's a stack trace of all running goroutines:\n"
201	buf := make([]byte, 8192)
202	for {
203		n := runtime.Stack(buf, true)
204		if n < len(buf) {
205			buf = buf[:n]
206			break
207		}
208		buf = make([]byte, 2*len(buf))
209	}
210	out += formatter.Fi(1, "%s", string(buf))
211	return out
212}
213
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Trigger registerForInterrupts code on LambdaTest Cloud Grid

Execute automation tests with registerForInterrupts on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)