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 }