I have a function that is executed concurrently. It's task is to run a command line method, logging an error if there is one. My main thread of execution does not wait for this method to finish. It simply returns optimistically.
How do I test my function? Assuming that I give it a cmdStr
, such as {"sleep", "1"}
, that works but doesn't return instantly, how can I get my test to wait for this function to finish?
I want to ensure that the actual program that runs this does not have to wait for it to finish.
func runCmd(cmdStr []string, errChan chan error) {
cmd := exec.Command(cmdStr...)
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Start()
if err != nil {
errChan <- err
return
}
// Command started successfully, so our caller can continue.
errChan <- nil
err = cmd.Wait()
if err != nil {
log.Println(err)
}
}
Use a wait group
wg := sync.WaitGroup{}
errc := make(chan error)
wg.Add(1)
go func() {
runCmd([]string{"sleep", 1}, errc)
wg.Done()
}()
err <- errc
if err != nil {
// handle error
}
wg.Wait()
Simplest method to aware all goroutings done is to add select{}
as last main.main()
statement. But main()
will never return this way and you should kill process explicitly. It's also more gentle runtime.Goshed()
to wait for others, but it can't provide such a strong guarantee. And the canonical way would be
wg := sync.WaitGroup
...
wg.Add(1)
go runCmd(...)
...
wg.Wait()