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.

212 lines
5.5 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package p2p
  2. import (
  3. "bytes"
  4. "io"
  5. "testing"
  6. "github.com/tendermint/go-crypto"
  7. cmn "github.com/tendermint/tmlibs/common"
  8. )
  9. type dummyConn struct {
  10. *io.PipeReader
  11. *io.PipeWriter
  12. }
  13. func (drw dummyConn) Close() (err error) {
  14. err2 := drw.PipeWriter.CloseWithError(io.EOF)
  15. err1 := drw.PipeReader.Close()
  16. if err2 != nil {
  17. return err
  18. }
  19. return err1
  20. }
  21. // Each returned ReadWriteCloser is akin to a net.Connection
  22. func makeDummyConnPair() (fooConn, barConn dummyConn) {
  23. barReader, fooWriter := io.Pipe()
  24. fooReader, barWriter := io.Pipe()
  25. return dummyConn{fooReader, fooWriter}, dummyConn{barReader, barWriter}
  26. }
  27. func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) {
  28. fooConn, barConn := makeDummyConnPair()
  29. fooPrvKey := crypto.GenPrivKeyEd25519()
  30. fooPubKey := fooPrvKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
  31. barPrvKey := crypto.GenPrivKeyEd25519()
  32. barPubKey := barPrvKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
  33. cmn.Parallel(
  34. func() {
  35. var err error
  36. fooSecConn, err = MakeSecretConnection(fooConn, fooPrvKey)
  37. if err != nil {
  38. tb.Errorf("Failed to establish SecretConnection for foo: %v", err)
  39. return
  40. }
  41. remotePubBytes := fooSecConn.RemotePubKey()
  42. if !bytes.Equal(remotePubBytes[:], barPubKey[:]) {
  43. tb.Errorf("Unexpected fooSecConn.RemotePubKey. Expected %v, got %v",
  44. barPubKey, fooSecConn.RemotePubKey())
  45. }
  46. },
  47. func() {
  48. var err error
  49. barSecConn, err = MakeSecretConnection(barConn, barPrvKey)
  50. if barSecConn == nil {
  51. tb.Errorf("Failed to establish SecretConnection for bar: %v", err)
  52. return
  53. }
  54. remotePubBytes := barSecConn.RemotePubKey()
  55. if !bytes.Equal(remotePubBytes[:], fooPubKey[:]) {
  56. tb.Errorf("Unexpected barSecConn.RemotePubKey. Expected %v, got %v",
  57. fooPubKey, barSecConn.RemotePubKey())
  58. }
  59. })
  60. return
  61. }
  62. func TestSecretConnectionHandshake(t *testing.T) {
  63. fooSecConn, barSecConn := makeSecretConnPair(t)
  64. if err := fooSecConn.Close(); err != nil {
  65. t.Error(err)
  66. }
  67. if err := barSecConn.Close(); err != nil {
  68. t.Error(err)
  69. }
  70. }
  71. func TestSecretConnectionReadWrite(t *testing.T) {
  72. fooConn, barConn := makeDummyConnPair()
  73. fooWrites, barWrites := []string{}, []string{}
  74. fooReads, barReads := []string{}, []string{}
  75. // Pre-generate the things to write (for foo & bar)
  76. for i := 0; i < 100; i++ {
  77. fooWrites = append(fooWrites, cmn.RandStr((cmn.RandInt()%(dataMaxSize*5))+1))
  78. barWrites = append(barWrites, cmn.RandStr((cmn.RandInt()%(dataMaxSize*5))+1))
  79. }
  80. // A helper that will run with (fooConn, fooWrites, fooReads) and vice versa
  81. genNodeRunner := func(nodeConn dummyConn, nodeWrites []string, nodeReads *[]string) func() {
  82. return func() {
  83. // Node handskae
  84. nodePrvKey := crypto.GenPrivKeyEd25519()
  85. nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey)
  86. if err != nil {
  87. t.Errorf("Failed to establish SecretConnection for node: %v", err)
  88. return
  89. }
  90. // In parallel, handle reads and writes
  91. cmn.Parallel(
  92. func() {
  93. // Node writes
  94. for _, nodeWrite := range nodeWrites {
  95. n, err := nodeSecretConn.Write([]byte(nodeWrite))
  96. if err != nil {
  97. t.Errorf("Failed to write to nodeSecretConn: %v", err)
  98. return
  99. }
  100. if n != len(nodeWrite) {
  101. t.Errorf("Failed to write all bytes. Expected %v, wrote %v", len(nodeWrite), n)
  102. return
  103. }
  104. }
  105. if err := nodeConn.PipeWriter.Close(); err != nil {
  106. t.Error(err)
  107. }
  108. },
  109. func() {
  110. // Node reads
  111. readBuffer := make([]byte, dataMaxSize)
  112. for {
  113. n, err := nodeSecretConn.Read(readBuffer)
  114. if err == io.EOF {
  115. return
  116. } else if err != nil {
  117. t.Errorf("Failed to read from nodeSecretConn: %v", err)
  118. return
  119. }
  120. *nodeReads = append(*nodeReads, string(readBuffer[:n]))
  121. }
  122. if err := nodeConn.PipeReader.Close(); err != nil {
  123. t.Error(err)
  124. }
  125. })
  126. }
  127. }
  128. // Run foo & bar in parallel
  129. cmn.Parallel(
  130. genNodeRunner(fooConn, fooWrites, &fooReads),
  131. genNodeRunner(barConn, barWrites, &barReads),
  132. )
  133. // A helper to ensure that the writes and reads match.
  134. // Additionally, small writes (<= dataMaxSize) must be atomically read.
  135. compareWritesReads := func(writes []string, reads []string) {
  136. for {
  137. // Pop next write & corresponding reads
  138. var read, write string = "", writes[0]
  139. var readCount = 0
  140. for _, readChunk := range reads {
  141. read += readChunk
  142. readCount += 1
  143. if len(write) <= len(read) {
  144. break
  145. }
  146. if len(write) <= dataMaxSize {
  147. break // atomicity of small writes
  148. }
  149. }
  150. // Compare
  151. if write != read {
  152. t.Errorf("Expected to read %X, got %X", write, read)
  153. }
  154. // Iterate
  155. writes = writes[1:]
  156. reads = reads[readCount:]
  157. if len(writes) == 0 {
  158. break
  159. }
  160. }
  161. }
  162. compareWritesReads(fooWrites, barReads)
  163. compareWritesReads(barWrites, fooReads)
  164. }
  165. func BenchmarkSecretConnection(b *testing.B) {
  166. b.StopTimer()
  167. fooSecConn, barSecConn := makeSecretConnPair(b)
  168. fooWriteText := cmn.RandStr(dataMaxSize)
  169. // Consume reads from bar's reader
  170. go func() {
  171. readBuffer := make([]byte, dataMaxSize)
  172. for {
  173. _, err := barSecConn.Read(readBuffer)
  174. if err == io.EOF {
  175. return
  176. } else if err != nil {
  177. b.Fatalf("Failed to read from barSecConn: %v", err)
  178. }
  179. }
  180. }()
  181. b.StartTimer()
  182. for i := 0; i < b.N; i++ {
  183. _, err := fooSecConn.Write([]byte(fooWriteText))
  184. if err != nil {
  185. b.Fatalf("Failed to write to fooSecConn: %v", err)
  186. }
  187. }
  188. b.StopTimer()
  189. if err := fooSecConn.Close(); err != nil {
  190. b.Error(err)
  191. }
  192. //barSecConn.Close() race condition
  193. }