Reputation: 7430
I'm trying to separate tests to use different NATS servers. (I'm not yet sure it is NATS, but my tests influence each other.)
Doing that works fine when running a single test or testing a single package. Running go test ./...
on all my packages (as done in CI) I get this error (paths anonymised):
panic: Unable to start NATS Server in Go Routine
goroutine 1 [running]:
github.com/nats-io/gnatsd/test.RunServer(0xc000163400, 0xc000163400)
./go/pkg/mod/github.com/nats-io/[email protected]/test/test.go:66 +0xbd
./lib/msgQueue/nats.NewTestConn(0xc0002adf68, 0x1879e12)
./lib/msgQueue/nats/testconn.go:19 +0x80
It seems like Go starts goroutines to run tests in them. Both using TestMain
and init
in the tests does not solve the problem.
Is it possible to start a server per test without running into the goroutine
error? Or is there some lightweight, but functioning in-memory replacement?
Here some code:
// +build !build
package myNats
import (
"fmt"
"github.com/pkg/errors"
"github.com/nats-io/gnatsd/server"
"github.com/nats-io/gnatsd/test"
gonats "github.com/nats-io/go-nats"
)
type Conn struct {
db *gonats.Conn
}
func NewTestConn() (conn *Conn, shutdown func()) {
opts := server.Options{
Host: "localhost",
Port: 53347,
NoLog: true,
NoSigs: true,
}
gnatsd := test.RunServer(&opts)
if gnatsd == nil {
panic("could not start NATS test server")
}
url := fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port)
conn, err := open(url)
if err != nil {
panic(errors.Wrap(err, "could not connect to test NATS"))
}
return conn, func() {
conn.close()
gnatsd.Shutdown()
}
}
func open(addr string) (*Conn, error) {
// Connect to NATS
nc, err := gonats.Connect(addr)
if err != nil {
return nil, errors.Wrapf(err, "nats not reachable on %s", addr)
}
if !nc.IsConnected() {
errorMsg := fmt.Errorf("could not establish connection to nats-server at: %s", addr)
return nil, errorMsg
}
return &Conn{
db: nc,
}, nil
}
My goal would be to have a server per test:
func TestSomeThing(t *testing.T) {
conn, shutdown := myNats.NewTestConn()
defer shutdown()
_ = conn
// test code here
}
Upvotes: 0
Views: 1717
Reputation: 49
The solution for me was to add GODEBUG=x509sha1=1
before go test
command
P.S. go1.18.3
Upvotes: 0
Reputation: 1316
In my case the problem was that I already ran an instance of nats-server so the tests were failing. By stopping the server, tests were passed successfully.
Upvotes: 0
Reputation: 18567
I suspect the error message:
Unable to start NATS Server in Go Routine
is misleading. The part about the Go Routine is likely just an implementation detail of how it tries to start the NATS Server. I suspect the server is failing to start because you have hardcoded your port in the options, and because multiple test packages are likely being run in parallel. Only one of your test packages will be able to bind to the port to start the NATS Server, and all others will fail.
The docs on go test
flags say:
-parallel n
Allow parallel execution of test functions that call t.Parallel.
The value of this flag is the maximum number of tests to run
simultaneously; by default, it is set to the value of GOMAXPROCS.
Note that -parallel only applies within a single test binary.
The 'go test' command may run tests for different packages
in parallel as well, according to the setting of the -p flag
(see 'go help build').
Unless you have parallel tests within your given test suites, which I'll assume you don't, the problem may be different packages running in parallel. Following the clue at the end of the above, let's look at build flags:
-p n
the number of programs, such as build commands or
test binaries, that can be run in parallel.
The default is the number of CPUs available.
This is from the "Compile packages and dependencies" docs. Note you can pass build flags and test flags to go test
:
$ go test -h
usage: go test [build/test flags] [packages] [build/test flags & test binary flags]
Run 'go help test' for details.
So consider running go test -p 1 ./...
. Alternatively, pass options to the RunServer
function that allow multiple of them to happen safely in parallel.
Upvotes: 1
Reputation: 46413
It likely already starts a server per test. You cannot run things concurrently without a goroutine. The error doesn't really make any sense - anything in Go must be able to run in a goroutine, and in fact everything does run in a goroutine (even main
), so it's unclear what they're really trying to say here (I would definitely recommend opening a bug report about it as that error message is terrible). In the meantime, you can keep go test
from running concurrently with -parallel 1
(as indicated in go help testflag
), which might help.
Upvotes: 1