You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

494 lines
14 KiB

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