Reputation: 821
I'm experimenting with parallel subtests, and I'm hitting a goroutine deadlock error. Assuming that tt
is a table test with valid values, and LastIndex
is the function being tested, the following code runs all the tests, but errors out:
for _, tt := range tests {
tt := tt
t.Run("foo", func(t *testing.T) {
t.Parallel()
done := make(chan bool)
for {
select {
case <-done:
return
case <-time.After(time.Second):
if got := LastIndex(tt.list, tt.x); got != tt.want {
t.Fatalf("LastIndex(%v, %v) = %v, want %v", tt.list, tt.x, got, tt.want)
} else {
done <- true
}
}
}
})
}
Specifically: fatal error: all goroutines are asleep - deadlock!
The error implies that the supertest is still waiting on results from these subtests, but shouldn't return
and t.Fatalf()
have exited them? The Go docs say that channels don't necessarily need to be closed, but I tried closing them anyway, and it still didn't work. I also tried to create the channel outside the subtest scope, inside the range iteration, and defer closing it with a t.Cleanup()
, but that didn't work either.
Full code here: https://play.golang.org/p/1ujIIl7pjY9 Not all tests pass, this is intentional
What am I doing wrong?
Upvotes: 1
Views: 652
Reputation: 51652
The t.Run
call runs the test function in a separate goroutine and waits until it returns. The for-loop in the test writes to the done
channel if a test is successful, however there are no other goroutines reading from the done
channel, hence the deadlock.
Instead of writing to the done
channel, you can close it. That will be detected next time around. However note that you are running only one goroutine, there is no concurrency here.
Upvotes: 1