8 "github.com/tendermint/go-crypto"
9 cmn "github.com/tendermint/tmlibs/common"
12 type dummyConn struct {
17 func (drw dummyConn) Close() (err error) {
18 err2 := drw.PipeWriter.CloseWithError(io.EOF)
19 err1 := drw.PipeReader.Close()
26 // Each returned ReadWriteCloser is akin to a net.Connection
27 func makeDummyConnPair() (fooConn, barConn dummyConn) {
28 barReader, fooWriter := io.Pipe()
29 fooReader, barWriter := io.Pipe()
30 return dummyConn{fooReader, fooWriter}, dummyConn{barReader, barWriter}
33 func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) {
34 fooConn, barConn := makeDummyConnPair()
35 fooPrvKey := crypto.GenPrivKeyEd25519()
36 fooPubKey := fooPrvKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
37 barPrvKey := crypto.GenPrivKeyEd25519()
38 barPubKey := barPrvKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
43 fooSecConn, err = MakeSecretConnection(fooConn, fooPrvKey)
45 tb.Errorf("Failed to establish SecretConnection for foo: %v", err)
48 remotePubBytes := fooSecConn.RemotePubKey()
49 if !bytes.Equal(remotePubBytes[:], barPubKey[:]) {
50 tb.Errorf("Unexpected fooSecConn.RemotePubKey. Expected %v, got %v",
51 barPubKey, fooSecConn.RemotePubKey())
56 barSecConn, err = MakeSecretConnection(barConn, barPrvKey)
57 if barSecConn == nil {
58 tb.Errorf("Failed to establish SecretConnection for bar: %v", err)
61 remotePubBytes := barSecConn.RemotePubKey()
62 if !bytes.Equal(remotePubBytes[:], fooPubKey[:]) {
63 tb.Errorf("Unexpected barSecConn.RemotePubKey. Expected %v, got %v",
64 fooPubKey, barSecConn.RemotePubKey())
71 func TestSecretConnectionHandshake(t *testing.T) {
72 fooSecConn, barSecConn := makeSecretConnPair(t)
77 func TestSecretConnectionReadWrite(t *testing.T) {
78 fooConn, barConn := makeDummyConnPair()
79 fooWrites, barWrites := []string{}, []string{}
80 fooReads, barReads := []string{}, []string{}
82 // Pre-generate the things to write (for foo & bar)
83 for i := 0; i < 100; i++ {
84 fooWrites = append(fooWrites, cmn.RandStr((cmn.RandInt()%(dataMaxSize*5))+1))
85 barWrites = append(barWrites, cmn.RandStr((cmn.RandInt()%(dataMaxSize*5))+1))
88 // A helper that will run with (fooConn, fooWrites, fooReads) and vice versa
89 genNodeRunner := func(nodeConn dummyConn, nodeWrites []string, nodeReads *[]string) func() {
92 nodePrvKey := crypto.GenPrivKeyEd25519()
93 nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey)
95 t.Errorf("Failed to establish SecretConnection for node: %v", err)
98 // In parallel, handle reads and writes
102 for _, nodeWrite := range nodeWrites {
103 n, err := nodeSecretConn.Write([]byte(nodeWrite))
105 t.Errorf("Failed to write to nodeSecretConn: %v", err)
108 if n != len(nodeWrite) {
109 t.Errorf("Failed to write all bytes. Expected %v, wrote %v", len(nodeWrite), n)
113 nodeConn.PipeWriter.Close()
117 readBuffer := make([]byte, dataMaxSize)
119 n, err := nodeSecretConn.Read(readBuffer)
122 } else if err != nil {
123 t.Errorf("Failed to read from nodeSecretConn: %v", err)
126 *nodeReads = append(*nodeReads, string(readBuffer[:n]))
128 nodeConn.PipeReader.Close()
133 // Run foo & bar in parallel
135 genNodeRunner(fooConn, fooWrites, &fooReads),
136 genNodeRunner(barConn, barWrites, &barReads),
139 // A helper to ensure that the writes and reads match.
140 // Additionally, small writes (<= dataMaxSize) must be atomically read.
141 compareWritesReads := func(writes []string, reads []string) {
143 // Pop next write & corresponding reads
144 var read, write string = "", writes[0]
146 for _, readChunk := range reads {
149 if len(write) <= len(read) {
152 if len(write) <= dataMaxSize {
153 break // atomicity of small writes
158 t.Errorf("Expected to read %X, got %X", write, read)
162 reads = reads[readCount:]
163 if len(writes) == 0 {
169 compareWritesReads(fooWrites, barReads)
170 compareWritesReads(barWrites, fooReads)
174 func BenchmarkSecretConnection(b *testing.B) {
176 fooSecConn, barSecConn := makeSecretConnPair(b)
177 fooWriteText := cmn.RandStr(dataMaxSize)
178 // Consume reads from bar's reader
180 readBuffer := make([]byte, dataMaxSize)
182 _, err := barSecConn.Read(readBuffer)
185 } else if err != nil {
186 b.Fatalf("Failed to read from barSecConn: %v", err)
192 for i := 0; i < b.N; i++ {
193 _, err := fooSecConn.Write([]byte(fooWriteText))
195 b.Fatalf("Failed to write to fooSecConn: %v", err)
201 //barSecConn.Close() race condition