func (s *TestSuite) TestChannelsAfterReconnect(t *C) { /** * Client send/recv chans should work after disconnect and reconnect. */ ws, err := client.NewWebsocketClient(s.logger, s.api, "agent", nil) t.Assert(err, IsNil) ws.Start() defer ws.Stop() defer ws.Disconnect() ws.Connect() c := <-mock.ClientConnectChan <-ws.ConnectChan() // connect ack // Send cmd and wait for reply to ensure we're fully connected. cmd := &proto.Cmd{ User: "******", Ts: time.Now(), Cmd: "Status", } c.SendChan <- cmd got := test.WaitCmd(ws.RecvChan()) t.Assert(len(got), Equals, 1) reply := cmd.Reply(nil, nil) ws.SendChan() <- reply data := test.WaitData(c.RecvChan) t.Assert(len(data), Equals, 1) // Disconnect client. mock.DisconnectClient(c) <-ws.ConnectChan() // disconnect ack // Reconnect client and send/recv again. ws.Connect() c = <-mock.ClientConnectChan <-ws.ConnectChan() // connect ack c.SendChan <- cmd got = test.WaitCmd(ws.RecvChan()) t.Assert(len(got), Equals, 1) reply = cmd.Reply(nil, nil) ws.SendChan() <- reply data = test.WaitData(c.RecvChan) t.Assert(len(data), Equals, 1) }
func (s *TestSuite) TestChannels(t *C) { /** * Agent uses send/recv channels instead of "direct" interface. */ ws, err := client.NewWebsocketClient(s.logger, s.api, "agent") t.Assert(err, IsNil) // Start send/recv chans, but idle until successful Connect. ws.Start() defer ws.Stop() ws.Connect() c := <-mock.ClientConnectChan <-ws.ConnectChan() // API sends Cmd to client. cmd := &proto.Cmd{ User: "******", Ts: time.Now(), Cmd: "Status", } c.SendChan <- cmd // If client's recvChan is working, it will receive the Cmd. got := test.WaitCmd(ws.RecvChan()) t.Assert(len(got), Equals, 1) t.Assert(got[0], DeepEquals, *cmd) // Client sends Reply in response to Cmd. reply := cmd.Reply(nil, nil) ws.SendChan() <- reply // If client's sendChan is working, we/API will receive the Reply. data := test.WaitData(c.RecvChan) t.Assert(len(data), Equals, 1) // We're dealing with generic data again. m := data[0].(map[string]interface{}) t.Assert(m["Cmd"], Equals, "Status") t.Assert(m["Error"], Equals, "") err = ws.Disconnect() t.Assert(err, IsNil) }
func (s *TestSuite) TestSendBytes(t *C) { ws, err := client.NewWebsocketClient(s.logger, s.api, "agent", nil) t.Assert(err, IsNil) ws.ConnectOnce(5) c := <-mock.ClientConnectChan data := []byte(`["Hello"]`) err = ws.SendBytes(data, 5) t.Assert(err, IsNil) // Recv what we just sent. got := test.WaitData(c.RecvChan) t.Assert(len(got), Equals, 1) gotData := got[0].([]interface{}) t.Check(gotData[0].(string), Equals, "Hello") ws.DisconnectOnce() }
func (s *TestSuite) TestWssConnection(t *C) { /** * This test ensures our slighly customized wss connectio handling works, * i.e. that TLS works. Only drawback is: client disables cert verification * because the mock ws server uses a self-signed cert, but this only happens * when the remote addr is localhost:8443, so it shouldn't affect real connections. */ ws, err := client.NewWebsocketClient(s.logger, s.apiWss, "agent", nil) t.Assert(err, IsNil) // Client sends state of connection (true=connected, false=disconnected) // on its ConnectChan. connected := false doneChan := make(chan bool) go func() { connected = <-ws.ConnectChan() doneChan <- true }() // Wait for connection in mock ws server. ws.Connect() c := <-mock.ClientConnectChanWss <-doneChan t.Check(connected, Equals, true) // Send a log entry. logEntry := &proto.LogEntry{ Level: 2, Service: "qan", Msg: "Hello", } err = ws.Send(logEntry, 5) t.Assert(err, IsNil) // Recv what we just sent. got := test.WaitData(c.RecvChanWss) t.Assert(len(got), Equals, 1) ws.Conn().Close() }
func (s *TestSuite) TestCloseTimeout(t *C) { // https://jira.percona.com/browse/PCT-1045 ws, err := client.NewWebsocketClient(s.logger, s.api, "agent", nil) t.Assert(err, IsNil) connected := false doneChan := make(chan bool) go func() { connected = <-ws.ConnectChan() doneChan <- true }() // Wait for connection in mock ws server. ws.Connect() c := <-mock.ClientConnectChan <-doneChan t.Check(connected, Equals, true) // Send a log entry. logEntry := &proto.LogEntry{ Level: 2, Service: "qan", Msg: "Hello", } err = ws.Send(logEntry, 1) t.Assert(err, IsNil) // Recv what we just sent. got := test.WaitData(c.RecvChan) t.Assert(len(got), Equals, 1) // Wait 1s for that ^ 1s timeout to pass. time.Sleep(1400 * time.Millisecond) err = ws.Disconnect() t.Check(err, IsNil) }
func (s *TestSuite) TestSend(t *C) { /** * LogRelay (logrelay/) uses "direct" interface, not send/recv chans. */ ws, err := client.NewWebsocketClient(s.logger, s.api, "agent", nil) t.Assert(err, IsNil) // Client sends state of connection (true=connected, false=disconnected) // on its ConnectChan. connected := false doneChan := make(chan bool) go func() { connected = <-ws.ConnectChan() doneChan <- true }() // Wait for connection in mock ws server. ws.Connect() c := <-mock.ClientConnectChan <-doneChan t.Check(connected, Equals, true) // Send a log entry. logEntry := &proto.LogEntry{ Level: 2, Service: "qan", Msg: "Hello", } err = ws.Send(logEntry, 5) t.Assert(err, IsNil) // Recv what we just sent. got := test.WaitData(c.RecvChan) t.Assert(len(got), Equals, 1) // We're dealing with generic data. m := got[0].(map[string]interface{}) t.Check(m["Level"], Equals, float64(2)) t.Check(m["Service"], Equals, "qan") t.Check(m["Msg"], Equals, "Hello") // Quick check that Conn() works. conn := ws.Conn() t.Check(conn, NotNil) // Status should report connected to the proper link. status := ws.Status() t.Check(status, DeepEquals, map[string]string{ "ws": "Connected " + URL, "ws-link": URL, }) ws.Disconnect() select { case connected = <-ws.ConnectChan(): case <-time.After(1 * time.Second): t.Error("No connected=false notify on Disconnect()") } // Status should report disconnected and still the proper link. status = ws.Status() t.Check(status, DeepEquals, map[string]string{ "ws": "Disconnected", "ws-link": URL, }) }