github.com/supragya/TendermintConnector@v0.0.0-20210619045051-113e32b84fb1/_deprecated_chains/irisnet/conn/connection_test.go (about)

     1  package conn
     2  
     3  import (
     4  	"bytes"
     5  	"net"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/fortytw2/leaktest"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  
    13  	amino "github.com/tendermint/go-amino"
    14  	"github.com/tendermint/tendermint/libs/log"
    15  )
    16  
    17  const maxPingPongPacketSize = 1024 // bytes
    18  
    19  func createTestMConnection(conn net.Conn) *MConnection {
    20  	onReceive := func(chID byte, msgBytes []byte) {
    21  	}
    22  	onError := func(r interface{}) {
    23  	}
    24  	c := createMConnectionWithCallbacks(conn, onReceive, onError)
    25  	c.SetLogger(log.TestingLogger())
    26  	return c
    27  }
    28  
    29  func createMConnectionWithCallbacks(conn net.Conn, onReceive func(chID byte, msgBytes []byte), onError func(r interface{})) *MConnection {
    30  	cfg := DefaultMConnConfig()
    31  	cfg.PingInterval = 90 * time.Millisecond
    32  	cfg.PongTimeout = 45 * time.Millisecond
    33  	chDescs := []*ChannelDescriptor{{ID: 0x01, Priority: 1, SendQueueCapacity: 1}}
    34  	c := NewMConnectionWithConfig(conn, chDescs, onReceive, onError, cfg)
    35  	c.SetLogger(log.TestingLogger())
    36  	return c
    37  }
    38  
    39  func TestMConnectionSendFlushStop(t *testing.T) {
    40  	server, client := NetPipe()
    41  	defer server.Close() // nolint: errcheck
    42  	defer client.Close() // nolint: errcheck
    43  
    44  	clientConn := createTestMConnection(client)
    45  	err := clientConn.Start()
    46  	require.Nil(t, err)
    47  	defer clientConn.Stop()
    48  
    49  	msg := []byte("abc")
    50  	assert.True(t, clientConn.Send(0x01, msg))
    51  
    52  	aminoMsgLength := 14
    53  
    54  	// start the reader in a new routine, so we can flush
    55  	errCh := make(chan error)
    56  	go func() {
    57  		msgB := make([]byte, aminoMsgLength)
    58  		_, err := server.Read(msgB)
    59  		if err != nil {
    60  			t.Error(err)
    61  			return
    62  		}
    63  		errCh <- err
    64  	}()
    65  
    66  	// stop the conn - it should flush all conns
    67  	clientConn.FlushStop()
    68  
    69  	timer := time.NewTimer(3 * time.Second)
    70  	select {
    71  	case <-errCh:
    72  	case <-timer.C:
    73  		t.Error("timed out waiting for msgs to be read")
    74  	}
    75  }
    76  
    77  func TestMConnectionSend(t *testing.T) {
    78  	server, client := NetPipe()
    79  	defer server.Close() // nolint: errcheck
    80  	defer client.Close() // nolint: errcheck
    81  
    82  	mconn := createTestMConnection(client)
    83  	err := mconn.Start()
    84  	require.Nil(t, err)
    85  	defer mconn.Stop()
    86  
    87  	msg := []byte("Ant-Man")
    88  	assert.True(t, mconn.Send(0x01, msg))
    89  	// Note: subsequent Send/TrySend calls could pass because we are reading from
    90  	// the send queue in a separate goroutine.
    91  	_, err = server.Read(make([]byte, len(msg)))
    92  	if err != nil {
    93  		t.Error(err)
    94  	}
    95  	assert.True(t, mconn.CanSend(0x01))
    96  
    97  	msg = []byte("Spider-Man")
    98  	assert.True(t, mconn.TrySend(0x01, msg))
    99  	_, err = server.Read(make([]byte, len(msg)))
   100  	if err != nil {
   101  		t.Error(err)
   102  	}
   103  
   104  	assert.False(t, mconn.CanSend(0x05), "CanSend should return false because channel is unknown")
   105  	assert.False(t, mconn.Send(0x05, []byte("Absorbing Man")), "Send should return false because channel is unknown")
   106  }
   107  
   108  func TestMConnectionReceive(t *testing.T) {
   109  	server, client := NetPipe()
   110  	defer server.Close() // nolint: errcheck
   111  	defer client.Close() // nolint: errcheck
   112  
   113  	receivedCh := make(chan []byte)
   114  	errorsCh := make(chan interface{})
   115  	onReceive := func(chID byte, msgBytes []byte) {
   116  		receivedCh <- msgBytes
   117  	}
   118  	onError := func(r interface{}) {
   119  		errorsCh <- r
   120  	}
   121  	mconn1 := createMConnectionWithCallbacks(client, onReceive, onError)
   122  	err := mconn1.Start()
   123  	require.Nil(t, err)
   124  	defer mconn1.Stop()
   125  
   126  	mconn2 := createTestMConnection(server)
   127  	err = mconn2.Start()
   128  	require.Nil(t, err)
   129  	defer mconn2.Stop()
   130  
   131  	msg := []byte("Cyclops")
   132  	assert.True(t, mconn2.Send(0x01, msg))
   133  
   134  	select {
   135  	case receivedBytes := <-receivedCh:
   136  		assert.Equal(t, []byte(msg), receivedBytes)
   137  	case err := <-errorsCh:
   138  		t.Fatalf("Expected %s, got %+v", msg, err)
   139  	case <-time.After(500 * time.Millisecond):
   140  		t.Fatalf("Did not receive %s message in 500ms", msg)
   141  	}
   142  }
   143  
   144  func TestMConnectionStatus(t *testing.T) {
   145  	server, client := NetPipe()
   146  	defer server.Close() // nolint: errcheck
   147  	defer client.Close() // nolint: errcheck
   148  
   149  	mconn := createTestMConnection(client)
   150  	err := mconn.Start()
   151  	require.Nil(t, err)
   152  	defer mconn.Stop()
   153  
   154  	status := mconn.Status()
   155  	assert.NotNil(t, status)
   156  	assert.Zero(t, status.Channels[0].SendQueueSize)
   157  }
   158  
   159  func TestMConnectionPongTimeoutResultsInError(t *testing.T) {
   160  	server, client := net.Pipe()
   161  	defer server.Close()
   162  	defer client.Close()
   163  
   164  	receivedCh := make(chan []byte)
   165  	errorsCh := make(chan interface{})
   166  	onReceive := func(chID byte, msgBytes []byte) {
   167  		receivedCh <- msgBytes
   168  	}
   169  	onError := func(r interface{}) {
   170  		errorsCh <- r
   171  	}
   172  	mconn := createMConnectionWithCallbacks(client, onReceive, onError)
   173  	err := mconn.Start()
   174  	require.Nil(t, err)
   175  	defer mconn.Stop()
   176  
   177  	serverGotPing := make(chan struct{})
   178  	go func() {
   179  		// read ping
   180  		var pkt PacketPing
   181  		_, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize)
   182  		assert.Nil(t, err)
   183  		serverGotPing <- struct{}{}
   184  	}()
   185  	<-serverGotPing
   186  
   187  	pongTimerExpired := mconn.config.PongTimeout + 20*time.Millisecond
   188  	select {
   189  	case msgBytes := <-receivedCh:
   190  		t.Fatalf("Expected error, but got %v", msgBytes)
   191  	case err := <-errorsCh:
   192  		assert.NotNil(t, err)
   193  	case <-time.After(pongTimerExpired):
   194  		t.Fatalf("Expected to receive error after %v", pongTimerExpired)
   195  	}
   196  }
   197  
   198  func TestMConnectionMultiplePongsInTheBeginning(t *testing.T) {
   199  	server, client := net.Pipe()
   200  	defer server.Close()
   201  	defer client.Close()
   202  
   203  	receivedCh := make(chan []byte)
   204  	errorsCh := make(chan interface{})
   205  	onReceive := func(chID byte, msgBytes []byte) {
   206  		receivedCh <- msgBytes
   207  	}
   208  	onError := func(r interface{}) {
   209  		errorsCh <- r
   210  	}
   211  	mconn := createMConnectionWithCallbacks(client, onReceive, onError)
   212  	err := mconn.Start()
   213  	require.Nil(t, err)
   214  	defer mconn.Stop()
   215  
   216  	// sending 3 pongs in a row (abuse)
   217  	_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{}))
   218  	require.Nil(t, err)
   219  	_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{}))
   220  	require.Nil(t, err)
   221  	_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{}))
   222  	require.Nil(t, err)
   223  
   224  	serverGotPing := make(chan struct{})
   225  	go func() {
   226  		// read ping (one byte)
   227  		var (
   228  			packet Packet
   229  			err    error
   230  		)
   231  		_, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &packet, maxPingPongPacketSize)
   232  		require.Nil(t, err)
   233  		serverGotPing <- struct{}{}
   234  		// respond with pong
   235  		_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{}))
   236  		require.Nil(t, err)
   237  	}()
   238  	<-serverGotPing
   239  
   240  	pongTimerExpired := mconn.config.PongTimeout + 20*time.Millisecond
   241  	select {
   242  	case msgBytes := <-receivedCh:
   243  		t.Fatalf("Expected no data, but got %v", msgBytes)
   244  	case err := <-errorsCh:
   245  		t.Fatalf("Expected no error, but got %v", err)
   246  	case <-time.After(pongTimerExpired):
   247  		assert.True(t, mconn.IsRunning())
   248  	}
   249  }
   250  
   251  func TestMConnectionMultiplePings(t *testing.T) {
   252  	server, client := net.Pipe()
   253  	defer server.Close()
   254  	defer client.Close()
   255  
   256  	receivedCh := make(chan []byte)
   257  	errorsCh := make(chan interface{})
   258  	onReceive := func(chID byte, msgBytes []byte) {
   259  		receivedCh <- msgBytes
   260  	}
   261  	onError := func(r interface{}) {
   262  		errorsCh <- r
   263  	}
   264  	mconn := createMConnectionWithCallbacks(client, onReceive, onError)
   265  	err := mconn.Start()
   266  	require.Nil(t, err)
   267  	defer mconn.Stop()
   268  
   269  	// sending 3 pings in a row (abuse)
   270  	// see https://github.com/tendermint/tendermint/issues/1190
   271  	_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{}))
   272  	require.Nil(t, err)
   273  	var pkt PacketPong
   274  	_, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize)
   275  	require.Nil(t, err)
   276  	_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{}))
   277  	require.Nil(t, err)
   278  	_, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize)
   279  	require.Nil(t, err)
   280  	_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPing{}))
   281  	require.Nil(t, err)
   282  	_, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize)
   283  	require.Nil(t, err)
   284  
   285  	assert.True(t, mconn.IsRunning())
   286  }
   287  
   288  func TestMConnectionPingPongs(t *testing.T) {
   289  	// check that we are not leaking any go-routines
   290  	defer leaktest.CheckTimeout(t, 10*time.Second)()
   291  
   292  	server, client := net.Pipe()
   293  
   294  	defer server.Close()
   295  	defer client.Close()
   296  
   297  	receivedCh := make(chan []byte)
   298  	errorsCh := make(chan interface{})
   299  	onReceive := func(chID byte, msgBytes []byte) {
   300  		receivedCh <- msgBytes
   301  	}
   302  	onError := func(r interface{}) {
   303  		errorsCh <- r
   304  	}
   305  	mconn := createMConnectionWithCallbacks(client, onReceive, onError)
   306  	err := mconn.Start()
   307  	require.Nil(t, err)
   308  	defer mconn.Stop()
   309  
   310  	serverGotPing := make(chan struct{})
   311  	go func() {
   312  		// read ping
   313  		var pkt PacketPing
   314  		_, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize)
   315  		require.Nil(t, err)
   316  		serverGotPing <- struct{}{}
   317  		// respond with pong
   318  		_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{}))
   319  		require.Nil(t, err)
   320  
   321  		time.Sleep(mconn.config.PingInterval)
   322  
   323  		// read ping
   324  		_, err = cdc.UnmarshalBinaryLengthPrefixedReader(server, &pkt, maxPingPongPacketSize)
   325  		require.Nil(t, err)
   326  		// respond with pong
   327  		_, err = server.Write(cdc.MustMarshalBinaryLengthPrefixed(PacketPong{}))
   328  		require.Nil(t, err)
   329  	}()
   330  	<-serverGotPing
   331  
   332  	pongTimerExpired := (mconn.config.PongTimeout + 20*time.Millisecond) * 2
   333  	select {
   334  	case msgBytes := <-receivedCh:
   335  		t.Fatalf("Expected no data, but got %v", msgBytes)
   336  	case err := <-errorsCh:
   337  		t.Fatalf("Expected no error, but got %v", err)
   338  	case <-time.After(2 * pongTimerExpired):
   339  		assert.True(t, mconn.IsRunning())
   340  	}
   341  }
   342  
   343  func TestMConnectionStopsAndReturnsError(t *testing.T) {
   344  	server, client := NetPipe()
   345  	defer server.Close() // nolint: errcheck
   346  	defer client.Close() // nolint: errcheck
   347  
   348  	receivedCh := make(chan []byte)
   349  	errorsCh := make(chan interface{})
   350  	onReceive := func(chID byte, msgBytes []byte) {
   351  		receivedCh <- msgBytes
   352  	}
   353  	onError := func(r interface{}) {
   354  		errorsCh <- r
   355  	}
   356  	mconn := createMConnectionWithCallbacks(client, onReceive, onError)
   357  	err := mconn.Start()
   358  	require.Nil(t, err)
   359  	defer mconn.Stop()
   360  
   361  	if err := client.Close(); err != nil {
   362  		t.Error(err)
   363  	}
   364  
   365  	select {
   366  	case receivedBytes := <-receivedCh:
   367  		t.Fatalf("Expected error, got %v", receivedBytes)
   368  	case err := <-errorsCh:
   369  		assert.NotNil(t, err)
   370  		assert.False(t, mconn.IsRunning())
   371  	case <-time.After(500 * time.Millisecond):
   372  		t.Fatal("Did not receive error in 500ms")
   373  	}
   374  }
   375  
   376  func newClientAndServerConnsForReadErrors(t *testing.T, chOnErr chan struct{}) (*MConnection, *MConnection) {
   377  	server, client := NetPipe()
   378  
   379  	onReceive := func(chID byte, msgBytes []byte) {}
   380  	onError := func(r interface{}) {}
   381  
   382  	// create client conn with two channels
   383  	chDescs := []*ChannelDescriptor{
   384  		{ID: 0x01, Priority: 1, SendQueueCapacity: 1},
   385  		{ID: 0x02, Priority: 1, SendQueueCapacity: 1},
   386  	}
   387  	mconnClient := NewMConnection(client, chDescs, onReceive, onError)
   388  	mconnClient.SetLogger(log.TestingLogger().With("module", "client"))
   389  	err := mconnClient.Start()
   390  	require.Nil(t, err)
   391  
   392  	// create server conn with 1 channel
   393  	// it fires on chOnErr when there's an error
   394  	serverLogger := log.TestingLogger().With("module", "server")
   395  	onError = func(r interface{}) {
   396  		chOnErr <- struct{}{}
   397  	}
   398  	mconnServer := createMConnectionWithCallbacks(server, onReceive, onError)
   399  	mconnServer.SetLogger(serverLogger)
   400  	err = mconnServer.Start()
   401  	require.Nil(t, err)
   402  	return mconnClient, mconnServer
   403  }
   404  
   405  func expectSend(ch chan struct{}) bool {
   406  	after := time.After(time.Second * 5)
   407  	select {
   408  	case <-ch:
   409  		return true
   410  	case <-after:
   411  		return false
   412  	}
   413  }
   414  
   415  func TestMConnectionReadErrorBadEncoding(t *testing.T) {
   416  	chOnErr := make(chan struct{})
   417  	mconnClient, mconnServer := newClientAndServerConnsForReadErrors(t, chOnErr)
   418  	defer mconnClient.Stop()
   419  	defer mconnServer.Stop()
   420  
   421  	client := mconnClient.conn
   422  
   423  	// send badly encoded msgPacket
   424  	bz := cdc.MustMarshalBinaryLengthPrefixed(PacketMsg{})
   425  	bz[4] += 0x01 // Invalid prefix bytes.
   426  
   427  	// Write it.
   428  	_, err := client.Write(bz)
   429  	assert.Nil(t, err)
   430  	assert.True(t, expectSend(chOnErr), "badly encoded msgPacket")
   431  }
   432  
   433  func TestMConnectionReadErrorUnknownChannel(t *testing.T) {
   434  	chOnErr := make(chan struct{})
   435  	mconnClient, mconnServer := newClientAndServerConnsForReadErrors(t, chOnErr)
   436  	defer mconnClient.Stop()
   437  	defer mconnServer.Stop()
   438  
   439  	msg := []byte("Ant-Man")
   440  
   441  	// fail to send msg on channel unknown by client
   442  	assert.False(t, mconnClient.Send(0x03, msg))
   443  
   444  	// send msg on channel unknown by the server.
   445  	// should cause an error
   446  	assert.True(t, mconnClient.Send(0x02, msg))
   447  	assert.True(t, expectSend(chOnErr), "unknown channel")
   448  }
   449  
   450  func TestMConnectionReadErrorLongMessage(t *testing.T) {
   451  	chOnErr := make(chan struct{})
   452  	chOnRcv := make(chan struct{})
   453  
   454  	mconnClient, mconnServer := newClientAndServerConnsForReadErrors(t, chOnErr)
   455  	defer mconnClient.Stop()
   456  	defer mconnServer.Stop()
   457  
   458  	mconnServer.onReceive = func(chID byte, msgBytes []byte) {
   459  		chOnRcv <- struct{}{}
   460  	}
   461  
   462  	client := mconnClient.conn
   463  
   464  	// send msg thats just right
   465  	var err error
   466  	var buf = new(bytes.Buffer)
   467  	var packet = PacketMsg{
   468  		ChannelID: 0x01,
   469  		EOF:       1,
   470  		Bytes:     make([]byte, mconnClient.config.MaxPacketMsgPayloadSize),
   471  	}
   472  	_, err = cdc.MarshalBinaryLengthPrefixedWriter(buf, packet)
   473  	assert.Nil(t, err)
   474  	_, err = client.Write(buf.Bytes())
   475  	assert.Nil(t, err)
   476  	assert.True(t, expectSend(chOnRcv), "msg just right")
   477  
   478  	// send msg thats too long
   479  	buf = new(bytes.Buffer)
   480  	packet = PacketMsg{
   481  		ChannelID: 0x01,
   482  		EOF:       1,
   483  		Bytes:     make([]byte, mconnClient.config.MaxPacketMsgPayloadSize+100),
   484  	}
   485  	_, err = cdc.MarshalBinaryLengthPrefixedWriter(buf, packet)
   486  	assert.Nil(t, err)
   487  	_, err = client.Write(buf.Bytes())
   488  	assert.NotNil(t, err)
   489  	assert.True(t, expectSend(chOnErr), "msg too long")
   490  }
   491  
   492  func TestMConnectionReadErrorUnknownMsgType(t *testing.T) {
   493  	chOnErr := make(chan struct{})
   494  	mconnClient, mconnServer := newClientAndServerConnsForReadErrors(t, chOnErr)
   495  	defer mconnClient.Stop()
   496  	defer mconnServer.Stop()
   497  
   498  	// send msg with unknown msg type
   499  	err := amino.EncodeUvarint(mconnClient.conn, 4)
   500  	assert.Nil(t, err)
   501  	_, err = mconnClient.conn.Write([]byte{0xFF, 0xFF, 0xFF, 0xFF})
   502  	assert.Nil(t, err)
   503  	assert.True(t, expectSend(chOnErr), "unknown msg type")
   504  }
   505  
   506  func TestMConnectionTrySend(t *testing.T) {
   507  	server, client := NetPipe()
   508  	defer server.Close()
   509  	defer client.Close()
   510  
   511  	mconn := createTestMConnection(client)
   512  	err := mconn.Start()
   513  	require.Nil(t, err)
   514  	defer mconn.Stop()
   515  
   516  	msg := []byte("Semicolon-Woman")
   517  	resultCh := make(chan string, 2)
   518  	assert.True(t, mconn.TrySend(0x01, msg))
   519  	server.Read(make([]byte, len(msg)))
   520  	assert.True(t, mconn.CanSend(0x01))
   521  	assert.True(t, mconn.TrySend(0x01, msg))
   522  	assert.False(t, mconn.CanSend(0x01))
   523  	go func() {
   524  		mconn.TrySend(0x01, msg)
   525  		resultCh <- "TrySend"
   526  	}()
   527  	assert.False(t, mconn.CanSend(0x01))
   528  	assert.False(t, mconn.TrySend(0x01, msg))
   529  	assert.Equal(t, "TrySend", <-resultCh)
   530  }