fix(bonfire): kill a live view on a signal only after it has started (IN-12, quick-261028-rqd)
This commit is contained in:
@@ -769,3 +769,86 @@ func TestErrorPrintsAboveView(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestSignalRelayWaitsForStart (IN-12): the signal relay kills the program
|
||||
// only once it has started (its Init closed ready) or its Run has ended,
|
||||
// so a signal during the view's start-up still restores the cursor; then
|
||||
// it waits for the program, unregisters and raises the signal again.
|
||||
func TestSignalRelayWaitsForStart(t *testing.T) {
|
||||
type relayRun struct {
|
||||
sigs chan os.Signal
|
||||
quit, ready, finished chan struct{}
|
||||
killed, unregistered chan struct{}
|
||||
raised chan os.Signal
|
||||
done chan struct{}
|
||||
}
|
||||
start := func() *relayRun {
|
||||
r := &relayRun{
|
||||
sigs: make(chan os.Signal, 1), quit: make(chan struct{}),
|
||||
ready: make(chan struct{}), finished: make(chan struct{}),
|
||||
killed: make(chan struct{}, 1), unregistered: make(chan struct{}, 1),
|
||||
raised: make(chan os.Signal, 2), done: make(chan struct{}),
|
||||
}
|
||||
go func() {
|
||||
defer close(r.done)
|
||||
relaySignals(r.sigs, r.quit, r.ready, r.finished,
|
||||
func() { r.killed <- struct{}{} },
|
||||
func() { r.unregistered <- struct{}{} },
|
||||
func(sig os.Signal) { r.raised <- sig })
|
||||
}()
|
||||
return r
|
||||
}
|
||||
wait := func(t *testing.T, ch <-chan struct{}, what string) {
|
||||
t.Helper()
|
||||
select {
|
||||
case <-ch:
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatalf("%s did not happen", what)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("signal before start", func(t *testing.T) {
|
||||
r := start()
|
||||
r.sigs <- os.Interrupt
|
||||
select {
|
||||
case <-r.killed:
|
||||
t.Fatal("killed before the program started")
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
}
|
||||
close(r.ready)
|
||||
wait(t, r.killed, "kill after ready")
|
||||
select {
|
||||
case sig := <-r.raised:
|
||||
t.Fatalf("raised %v before the program finished", sig)
|
||||
case <-time.After(50 * time.Millisecond):
|
||||
}
|
||||
close(r.finished)
|
||||
wait(t, r.done, "relay end")
|
||||
wait(t, r.unregistered, "unregister")
|
||||
if len(r.raised) != 1 {
|
||||
t.Fatalf("raised %d signals, want 1", len(r.raised))
|
||||
}
|
||||
if sig := <-r.raised; sig != os.Interrupt {
|
||||
t.Errorf("raised %v, want %v", sig, os.Interrupt)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("program ended without starting", func(t *testing.T) {
|
||||
r := start()
|
||||
r.sigs <- os.Interrupt
|
||||
close(r.finished)
|
||||
wait(t, r.done, "relay end")
|
||||
if len(r.raised) != 1 {
|
||||
t.Fatalf("raised %d signals, want 1", len(r.raised))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("quit", func(t *testing.T) {
|
||||
r := start()
|
||||
close(r.quit)
|
||||
wait(t, r.done, "relay end")
|
||||
if len(r.killed) != 0 || len(r.raised) != 0 {
|
||||
t.Errorf("quit killed %d times and raised %d signals", len(r.killed), len(r.raised))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user