diff --git a/pkg/gocui/gui.go b/pkg/gocui/gui.go index 936e1a310..dbef57b59 100644 --- a/pkg/gocui/gui.go +++ b/pkg/gocui/gui.go @@ -148,6 +148,10 @@ type Gui struct { maxX, maxY int outputMode OutputMode stop chan struct{} + // loopExited is closed when MainLoop returns, so callers (e.g. the + // integration-test harness) can wait for the event loop to actually finish + // rather than polling or sleeping a fixed interval. + loopExited chan struct{} // BgColor and FgColor allow to configure the background and foreground // colors of the GUI. @@ -260,6 +264,7 @@ func NewGui(opts NewGuiOpts) (*Gui, error) { g.outputMode = opts.OutputMode g.stop = make(chan struct{}) + g.loopExited = make(chan struct{}) g.gEvents = make(chan GocuiEvent, 20) g.userEvents = newUserEventQueue() @@ -348,6 +353,11 @@ func (g *Gui) Close() { Screen.Fini() } +// LoopExited returns a channel that is closed once MainLoop has returned. +func (g *Gui) LoopExited() <-chan struct{} { + return g.loopExited +} + // Size returns the terminal's size. func (g *Gui) Size() (x, y int) { return g.maxX, g.maxY @@ -965,6 +975,8 @@ func (g *Gui) SetManagerFunc(manager func(*Gui) error) { // MainLoop runs the main loop until an error is returned. A successful // finish should return ErrQuit. func (g *Gui) MainLoop() error { + defer close(g.loopExited) + g.uiThreadID.Store(goid.Get()) go func() { diff --git a/pkg/gui/test_mode.go b/pkg/gui/test_mode.go index 2d5958fbb..d6893c92d 100644 --- a/pkg/gui/test_mode.go +++ b/pkg/gui/test_mode.go @@ -40,11 +40,8 @@ func (gui *Gui) handleTestMode() { return gocui.ErrQuit }) - waitUntilIdle() - - time.Sleep(time.Second * 1) - - log.Fatal("gocui should have already exited") + // Wait for the event loop to actually exit. + <-gui.g.LoopExited() }() if os.Getenv(components.WAIT_FOR_DEBUGGER_ENV_VAR) == "" {