src.dualinventive.com/go/websocketserver/internal/testenv/testenv.go

113 lines
2.7 KiB
Go

package testenv
import (
"net"
"testing"
"time"
"github.com/gomodule/redigo/redis"
"github.com/mna/redisc"
"github.com/mna/redisc/redistest"
"github.com/stretchr/testify/require"
"src.dualinventive.com/go/websocketserver/internal/mtiwss"
mtiep "src.dualinventive.com/go/websocketserver/internal/mtiwss/testutil"
wsclnt "src.dualinventive.com/go/websocketserver/internal/wsconn/testutil"
"src.dualinventive.com/go/websocketserver/internal/wss"
)
// TestEnv holds a redis cluster, redis client, websocket client and an MTI WSS HTTP server
type TestEnv struct {
wsclnt *wsclnt.Client
mti *mtiep.Server
srv *wss.Server
rc *redisc.Cluster
rcClose func()
}
// MtiWss returns the instance to the MTI WSS HTTP endpoint test server
func (t *TestEnv) MtiWss() *mtiep.Server {
return t.mti
}
// Ws returns the instance to the Websocket client
func (t *TestEnv) Ws() *wsclnt.Client {
return t.wsclnt
}
// RedisDo executes a redis command on the cluster
func (t *TestEnv) RedisDo(cmd string, args ...interface{}) (interface{}, error) {
conn := t.rc.Get()
c, err := redisc.RetryConn(conn, 3, 10*time.Second)
if err != nil {
return nil, err
}
defer c.Close()
return c.Do(cmd, args...)
}
// New create a new testing environment with a Redis cluster, redis client and a MTI WSS HTTP endpoint
func New(t *testing.T) *TestEnv {
addr := getFreeAddr(t)
tenv := &TestEnv{}
// Setup, spawn MTI Wss stub endpoint and redis server
mti := mtiep.New(mtiwss.Endpoint)
// Start redis cluster
clusterClose, clusterPorts := redistest.StartCluster(t, nil)
// Create new websocket server
srv, err := wss.NewServer([]string{":" + clusterPorts[0]}, addr, mti.URL())
require.Nil(t, err)
require.NotNil(t, srv)
// Start the wss server in the background
go srv.ListenAndServe()
// Create redis cluster client
rc := redisc.Cluster{
StartupNodes: []string{":" + clusterPorts[0]},
DialOptions: []redis.DialOption{redis.DialConnectTimeout(10 * time.Second)},
}
require.Nil(t, rc.Refresh())
// Create websocket client
clnt, err := wsclnt.NewClient("ws://" + addr)
require.Nil(t, err)
// Attach to TestEnv context
tenv.mti = mti
tenv.rcClose = clusterClose
tenv.srv = srv
tenv.rc = &rc
tenv.wsclnt = clnt
return tenv
}
// Close closes all the connections and waits fo stopping the servers
func (t *TestEnv) Close() error {
err := t.rc.Close()
if err != nil {
return err
}
err = t.srv.Close()
if err != nil {
return err
}
err = t.mti.Close()
if err != nil {
return err
}
t.rcClose()
return nil
}
// getFreeAddr gets a free TCP port from the kernel
func getFreeAddr(t *testing.T) string {
l, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err, "listen on port 0")
defer l.Close()
return l.Addr().String()
}