I met a strange issue when doing test with channels.
In a normal main function, the following code will report the deadlock error.
package main
import (
"fmt"
)
func main() {
c := make(chan int)
c <- 1
fmt.Println(<-c)
}
But on my machine, this simple test seems deadlocked or blocked forever or just fails to exit for whatever reason I don't know. I invoked the test in both Emacs and terminal, and I got the same result. The command is go test -run TestChan\$ . -v -count=1
. I tried with a simpler command (go test -run TestChan
) but still got the same result. I tried it on Go playground (here) and it reported the deadlock error. Is there something wrong with my Go environment?
package main
import (
"fmt"
"testing"
)
func TestChan(t *testing.T) {
c := make(chan int)
c <- 1
fmt.Println(<-c)
}
----------------------------------------------------------------------------------------------------
Update
Looks like I haven't made my question clear. The situation is: the same test behaves differently on my machine and on Go playground. Now I set -timeout 5s
, but the error message is different from that on Go playground.
Another thing I found different with my local is that the test runner seems different from my local. It's under package go-faketime
.
local output
$ go test main_test.go -timeout 5s
panic: test timed out after 5s
goroutine 17 [running]:
testing.(*M).startAlarm.func1()
/usr/local/go/src/testing/testing.go:1460 +0xdf
created by time.goFunc
/usr/local/go/src/time/sleep.go:168 +0x44
goroutine 1 [chan receive]:
testing.(*T).Run(0xc000108120, 0x1141975, 0x8, 0x114a528, 0x1075a96)
/usr/local/go/src/testing/testing.go:1044 +0x37e
testing.runTests.func1(0xc000108000)
/usr/local/go/src/testing/testing.go:1285 +0x78
testing.tRunner(0xc000108000, 0xc000066e10)
/usr/local/go/src/testing/testing.go:992 +0xdc
testing.runTests(0xc00000c060, 0x1236220, 0x1, 0x1, 0x0)
/usr/local/go/src/testing/testing.go:1283 +0x2a7
testing.(*M).Run(0xc000106000, 0x0)
/usr/local/go/src/testing/testing.go:1200 +0x15f
main.main()
_testmain.go:44 +0x135
goroutine 6 [chan send]:
command-line-arguments.TestChan(0xc000108120)
/Users/james/prog/allez/mtest/main_test.go:10 +0x59
testing.tRunner(0xc000108120, 0x114a528)
/usr/local/go/src/testing/testing.go:992 +0xdc
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1043 +0x357
FAIL command-line-arguments 5.013s
FAIL
Go playground output
=== RUN TestChan
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
testing.(*T).Run(0xc00011a120, 0x4f71c0, 0x8, 0x4ff688, 0x498336)
/usr/local/go-faketime/src/testing/testing.go:1043 +0x37e
testing.runTests.func1(0xc00011a000)
/usr/local/go-faketime/src/testing/testing.go:1284 +0x78
testing.tRunner(0xc00011a000, 0xc000066df8)
/usr/local/go-faketime/src/testing/testing.go:991 +0xdc
testing.runTests(0xc00010c040, 0xc00010c020, 0x1, 0x1, 0x0)
/usr/local/go-faketime/src/testing/testing.go:1282 +0x2a7
testing.(*M).Run(0xc000118000, 0x0)
/usr/local/go-faketime/src/testing/testing.go:1199 +0x15f
testing.Main(0x4ff690, 0xc00010c020, 0x1, 0x1, 0x0, 0x0, 0x0, 0x5e8860, 0x0, 0x0)
/usr/local/go-faketime/src/testing/testing.go:1126 +0xd4
main.main()
/tmp/sandbox970213620/prog.go:24 +0x9c
goroutine 18 [chan send]:
main.TestChan(0xc00011a120)
/tmp/sandbox970213620/prog.go:10 +0x59
testing.tRunner(0xc00011a120, 0x4ff688)
/usr/local/go-faketime/src/testing/testing.go:991 +0xdc
created by testing.(*T).Run
/usr/local/go-faketime/src/testing/testing.go:1042 +0x357
My questions are
- Why does Go test with blocked channel not reporting deadlock?
- If it's work-as-design (because there are other goroutines running meanwhile), then how does the same test in Go playground reports the same error message as if the code is run in a main func? (this question diverges from the domain of Go channel to how Go Playground handles test)
go test
, there are other goroutines running, hence no deadlock. Compile and run the binary itself. – Lardergo test
while the playground is not. Build and run the main binary. – Lardergo test
. That's where my questions arose. I know running the main binary will report the deadlock message. btw, do you know whether the Go playground is actually building and running the main binary for tests? – Lowmindedgo test
command. Whether a deadlock is reported or not is not really interesting, as deadlocks can only be detected in basic cases; detecting a deadlock in any sufficiently complex program is akin to solving the halting problem. – Larder