package p2p_test import ( "net" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" p2p "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tmlibs/log" ) func createMConnection(conn net.Conn) *p2p.MConnection { onReceive := func(chID byte, msgBytes []byte) { } onError := func(r interface{}) { } c := createMConnectionWithCallbacks(conn, onReceive, onError) c.SetLogger(log.TestingLogger()) return c } func createMConnectionWithCallbacks(conn net.Conn, onReceive func(chID byte, msgBytes []byte), onError func(r interface{})) *p2p.MConnection { chDescs := []*p2p.ChannelDescriptor{&p2p.ChannelDescriptor{ID: 0x01, Priority: 1, SendQueueCapacity: 1}} c := p2p.NewMConnection(conn, chDescs, onReceive, onError) c.SetLogger(log.TestingLogger()) return c } func TestMConnectionSend(t *testing.T) { assert, require := assert.New(t), require.New(t) server, client := net.Pipe() defer server.Close() defer client.Close() mconn := createMConnection(client) _, err := mconn.Start() require.Nil(err) defer mconn.Stop() msg := "Ant-Man" assert.True(mconn.Send(0x01, msg)) // Note: subsequent Send/TrySend calls could pass because we are reading from // the send queue in a separate goroutine. server.Read(make([]byte, len(msg))) assert.True(mconn.CanSend(0x01)) msg = "Spider-Man" assert.True(mconn.TrySend(0x01, msg)) server.Read(make([]byte, len(msg))) assert.False(mconn.CanSend(0x05), "CanSend should return false because channel is unknown") assert.False(mconn.Send(0x05, "Absorbing Man"), "Send should return false because channel is unknown") } func TestMConnectionReceive(t *testing.T) { assert, require := assert.New(t), require.New(t) server, client := net.Pipe() defer server.Close() defer client.Close() receivedCh := make(chan []byte) errorsCh := make(chan interface{}) onReceive := func(chID byte, msgBytes []byte) { receivedCh <- msgBytes } onError := func(r interface{}) { errorsCh <- r } mconn1 := createMConnectionWithCallbacks(client, onReceive, onError) _, err := mconn1.Start() require.Nil(err) defer mconn1.Stop() mconn2 := createMConnection(server) _, err = mconn2.Start() require.Nil(err) defer mconn2.Stop() msg := "Cyclops" assert.True(mconn2.Send(0x01, msg)) select { case receivedBytes := <-receivedCh: assert.Equal([]byte(msg), receivedBytes[2:]) // first 3 bytes are internal case err := <-errorsCh: t.Fatalf("Expected %s, got %+v", msg, err) case <-time.After(500 * time.Millisecond): t.Fatalf("Did not receive %s message in 500ms", msg) } } func TestMConnectionStatus(t *testing.T) { assert, require := assert.New(t), require.New(t) server, client := net.Pipe() defer server.Close() defer client.Close() mconn := createMConnection(client) _, err := mconn.Start() require.Nil(err) defer mconn.Stop() status := mconn.Status() assert.NotNil(status) assert.Zero(status.Channels[0].SendQueueSize) } func TestMConnectionStopsAndReturnsError(t *testing.T) { assert, require := assert.New(t), require.New(t) server, client := net.Pipe() defer server.Close() defer client.Close() receivedCh := make(chan []byte) errorsCh := make(chan interface{}) onReceive := func(chID byte, msgBytes []byte) { receivedCh <- msgBytes } onError := func(r interface{}) { errorsCh <- r } mconn := createMConnectionWithCallbacks(client, onReceive, onError) _, err := mconn.Start() require.Nil(err) defer mconn.Stop() client.Close() select { case receivedBytes := <-receivedCh: t.Fatalf("Expected error, got %v", receivedBytes) case err := <-errorsCh: assert.NotNil(err) assert.False(mconn.IsRunning()) case <-time.After(500 * time.Millisecond): t.Fatal("Did not receive error in 500ms") } }