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() }