peer_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package p2p
  2. import (
  3. "errors"
  4. "fmt"
  5. "math/rand"
  6. "net"
  7. "reflect"
  8. "testing"
  9. "time"
  10. )
  11. var discard = Protocol{
  12. Name: "discard",
  13. Length: 1,
  14. Run: func(p *Peer, rw MsgReadWriter) error {
  15. for {
  16. msg, err := rw.ReadMsg()
  17. if err != nil {
  18. return err
  19. }
  20. fmt.Printf("discarding %d\n", msg.Code)
  21. if err = msg.Discard(); err != nil {
  22. return err
  23. }
  24. }
  25. },
  26. }
  27. func testPeer(protos []Protocol) (func(), *conn, *Peer, <-chan DiscReason) {
  28. fd1, fd2 := net.Pipe()
  29. c1 := &conn{fd: fd1, transport: newTestTransport(randomID(), fd1)}
  30. c2 := &conn{fd: fd2, transport: newTestTransport(randomID(), fd2)}
  31. for _, p := range protos {
  32. c1.caps = append(c1.caps, p.cap())
  33. c2.caps = append(c2.caps, p.cap())
  34. }
  35. peer := newPeer(c1, protos)
  36. errc := make(chan DiscReason, 1)
  37. go func() { errc <- peer.run() }()
  38. closer := func() { c2.close(errors.New("close func called")) }
  39. return closer, c2, peer, errc
  40. }
  41. func TestPeerProtoReadMsg(t *testing.T) {
  42. done := make(chan struct{})
  43. proto := Protocol{
  44. Name: "a",
  45. Length: 5,
  46. Run: func(peer *Peer, rw MsgReadWriter) error {
  47. if err := ExpectMsg(rw, 2, []uint{1}); err != nil {
  48. t.Error(err)
  49. }
  50. if err := ExpectMsg(rw, 3, []uint{2}); err != nil {
  51. t.Error(err)
  52. }
  53. if err := ExpectMsg(rw, 4, []uint{3}); err != nil {
  54. t.Error(err)
  55. }
  56. close(done)
  57. return nil
  58. },
  59. }
  60. closer, rw, _, errc := testPeer([]Protocol{proto})
  61. defer closer()
  62. Send(rw, baseProtocolLength+2, []uint{1})
  63. Send(rw, baseProtocolLength+3, []uint{2})
  64. Send(rw, baseProtocolLength+4, []uint{3})
  65. select {
  66. case <-done:
  67. case err := <-errc:
  68. t.Errorf("peer returned: %v", err)
  69. case <-time.After(2 * time.Second):
  70. t.Errorf("receive timeout")
  71. }
  72. }
  73. func TestPeerProtoEncodeMsg(t *testing.T) {
  74. proto := Protocol{
  75. Name: "a",
  76. Length: 2,
  77. Run: func(peer *Peer, rw MsgReadWriter) error {
  78. if err := SendItems(rw, 2); err == nil {
  79. t.Error("expected error for out-of-range msg code, got nil")
  80. }
  81. if err := SendItems(rw, 1, "foo", "bar"); err != nil {
  82. t.Errorf("write error: %v", err)
  83. }
  84. return nil
  85. },
  86. }
  87. closer, rw, _, _ := testPeer([]Protocol{proto})
  88. defer closer()
  89. if err := ExpectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
  90. t.Error(err)
  91. }
  92. }
  93. func TestPeerPing(t *testing.T) {
  94. closer, rw, _, _ := testPeer(nil)
  95. defer closer()
  96. if err := SendItems(rw, pingMsg); err != nil {
  97. t.Fatal(err)
  98. }
  99. if err := ExpectMsg(rw, pongMsg, nil); err != nil {
  100. t.Error(err)
  101. }
  102. }
  103. func TestPeerDisconnect(t *testing.T) {
  104. closer, rw, _, disc := testPeer(nil)
  105. defer closer()
  106. if err := SendItems(rw, discMsg, DiscQuitting); err != nil {
  107. t.Fatal(err)
  108. }
  109. select {
  110. case reason := <-disc:
  111. if reason != DiscRequested {
  112. t.Errorf("run returned wrong reason: got %v, want %v", reason, DiscRequested)
  113. }
  114. case <-time.After(500 * time.Millisecond):
  115. t.Error("peer did not return")
  116. }
  117. }
  118. // This test is supposed to verify that Peer can reliably handle
  119. // multiple causes of disconnection occurring at the same time.
  120. func TestPeerDisconnectRace(t *testing.T) {
  121. maybe := func() bool { return rand.Intn(1) == 1 }
  122. for i := 0; i < 1000; i++ {
  123. protoclose := make(chan error)
  124. protodisc := make(chan DiscReason)
  125. closer, rw, p, disc := testPeer([]Protocol{
  126. {
  127. Name: "closereq",
  128. Run: func(p *Peer, rw MsgReadWriter) error { return <-protoclose },
  129. Length: 1,
  130. },
  131. {
  132. Name: "disconnect",
  133. Run: func(p *Peer, rw MsgReadWriter) error { p.Disconnect(<-protodisc); return nil },
  134. Length: 1,
  135. },
  136. })
  137. // Simulate incoming messages.
  138. go SendItems(rw, baseProtocolLength+1)
  139. go SendItems(rw, baseProtocolLength+2)
  140. // Close the network connection.
  141. go closer()
  142. // Make protocol "closereq" return.
  143. protoclose <- errors.New("protocol closed")
  144. // Make protocol "disconnect" call peer.Disconnect
  145. protodisc <- DiscAlreadyConnected
  146. // In some cases, simulate something else calling peer.Disconnect.
  147. if maybe() {
  148. go p.Disconnect(DiscInvalidIdentity)
  149. }
  150. // In some cases, simulate remote requesting a disconnect.
  151. if maybe() {
  152. go SendItems(rw, discMsg, DiscQuitting)
  153. }
  154. select {
  155. case <-disc:
  156. case <-time.After(2 * time.Second):
  157. // Peer.run should return quickly. If it doesn't the Peer
  158. // goroutines are probably deadlocked. Call panic in order to
  159. // show the stacks.
  160. panic("Peer.run took to long to return.")
  161. }
  162. }
  163. }
  164. func TestNewPeer(t *testing.T) {
  165. name := "nodename"
  166. caps := []Cap{{"foo", 2}, {"bar", 3}}
  167. id := randomID()
  168. p := NewPeer(id, name, caps)
  169. if p.ID() != id {
  170. t.Errorf("ID mismatch: got %v, expected %v", p.ID(), id)
  171. }
  172. if p.Name() != name {
  173. t.Errorf("Name mismatch: got %v, expected %v", p.Name(), name)
  174. }
  175. if !reflect.DeepEqual(p.Caps(), caps) {
  176. t.Errorf("Caps mismatch: got %v, expected %v", p.Caps(), caps)
  177. }
  178. p.Disconnect(DiscAlreadyConnected) // Should not hang
  179. }