8 cmn "github.com/tendermint/tmlibs/common"
10 "github.com/vapor/crypto/ed25519/chainkd"
13 type dummyConn struct {
18 func (drw dummyConn) Close() (err error) {
19 err2 := drw.PipeWriter.CloseWithError(io.EOF)
20 err1 := drw.PipeReader.Close()
27 // Each returned ReadWriteCloser is akin to a net.Connection
28 func makeDummyConnPair() (fooConn, barConn dummyConn) {
29 barReader, fooWriter := io.Pipe()
30 fooReader, barWriter := io.Pipe()
31 return dummyConn{fooReader, fooWriter}, dummyConn{barReader, barWriter}
34 func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) {
35 fooConn, barConn := makeDummyConnPair()
36 fooPrvKey, _ := chainkd.NewXPrv(nil)
37 fooPubKey := fooPrvKey.XPub()
38 barPrvKey, _ := chainkd.NewXPrv(nil)
39 barPubKey := barPrvKey.XPub()
44 fooSecConn, err = MakeSecretConnection(fooConn, fooPrvKey)
46 tb.Errorf("Failed to establish SecretConnection for foo: %v", err)
49 remotePubBytes := fooSecConn.RemotePubKey()
50 if !bytes.Equal(remotePubBytes.Bytes()[:], barPubKey[:]) {
51 tb.Errorf("Unexpected fooSecConn.RemotePubKey. Expected %v, got %v",
52 barPubKey, fooSecConn.RemotePubKey())
57 barSecConn, err = MakeSecretConnection(barConn, barPrvKey)
58 if barSecConn == nil {
59 tb.Errorf("Failed to establish SecretConnection for bar: %v", err)
62 remotePubBytes := barSecConn.RemotePubKey()
63 if !bytes.Equal(remotePubBytes.Bytes()[:], fooPubKey[:]) {
64 tb.Errorf("Unexpected barSecConn.RemotePubKey. Expected %v, got %v",
65 fooPubKey, barSecConn.RemotePubKey())
72 func TestSecretConnectionHandshake(t *testing.T) {
73 fooSecConn, barSecConn := makeSecretConnPair(t)
78 func TestSecretConnectionReadWrite(t *testing.T) {
79 fooConn, barConn := makeDummyConnPair()
80 fooWrites, barWrites := []string{}, []string{}
81 fooReads, barReads := []string{}, []string{}
83 // Pre-generate the things to write (for foo & bar)
84 for i := 0; i < 100; i++ {
85 fooWrites = append(fooWrites, cmn.RandStr((cmn.RandInt()%(dataMaxSize*5))+1))
86 barWrites = append(barWrites, cmn.RandStr((cmn.RandInt()%(dataMaxSize*5))+1))
89 // A helper that will run with (fooConn, fooWrites, fooReads) and vice versa
90 genNodeRunner := func(nodeConn dummyConn, nodeWrites []string, nodeReads *[]string) func() {
93 nodePrvKey, _ := chainkd.NewXPrv(nil)
94 nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey)
96 t.Errorf("Failed to establish SecretConnection for node: %v", err)
99 // In parallel, handle reads and writes
103 for _, nodeWrite := range nodeWrites {
104 n, err := nodeSecretConn.Write([]byte(nodeWrite))
106 t.Errorf("Failed to write to nodeSecretConn: %v", err)
109 if n != len(nodeWrite) {
110 t.Errorf("Failed to write all bytes. Expected %v, wrote %v", len(nodeWrite), n)
114 nodeConn.PipeWriter.Close()
118 readBuffer := make([]byte, dataMaxSize)
120 n, err := nodeSecretConn.Read(readBuffer)
123 } else if err != nil {
124 t.Errorf("Failed to read from nodeSecretConn: %v", err)
127 *nodeReads = append(*nodeReads, string(readBuffer[:n]))
129 nodeConn.PipeReader.Close()
134 // Run foo & bar in parallel
136 genNodeRunner(fooConn, fooWrites, &fooReads),
137 genNodeRunner(barConn, barWrites, &barReads),
140 // A helper to ensure that the writes and reads match.
141 // Additionally, small writes (<= dataMaxSize) must be atomically read.
142 compareWritesReads := func(writes []string, reads []string) {
144 // Pop next write & corresponding reads
145 var read, write string = "", writes[0]
147 for _, readChunk := range reads {
150 if len(write) <= len(read) {
153 if len(write) <= dataMaxSize {
154 break // atomicity of small writes
159 t.Errorf("Expected to read %X, got %X", write, read)
163 reads = reads[readCount:]
164 if len(writes) == 0 {
170 compareWritesReads(fooWrites, barReads)
171 compareWritesReads(barWrites, fooReads)
175 func BenchmarkSecretConnection(b *testing.B) {
177 fooSecConn, barSecConn := makeSecretConnPair(b)
178 fooWriteText := cmn.RandStr(dataMaxSize)
179 // Consume reads from bar's reader
181 readBuffer := make([]byte, dataMaxSize)
183 _, err := barSecConn.Read(readBuffer)
186 } else if err != nil {
187 b.Fatalf("Failed to read from barSecConn: %v", err)
193 for i := 0; i < b.N; i++ {
194 _, err := fooSecConn.Write([]byte(fooWriteText))
196 b.Fatalf("Failed to write to fooSecConn: %v", err)
202 //barSecConn.Close() race condition