10 "github.com/tendermint/go-crypto"
11 cmn "github.com/tendermint/tmlibs/common"
14 type dummyConn struct {
19 func (drw dummyConn) Close() (err error) {
20 err2 := drw.PipeWriter.CloseWithError(io.EOF)
21 err1 := drw.PipeReader.Close()
28 // Each returned ReadWriteCloser is akin to a net.Connection
29 func makeDummyConnPair() (fooConn, barConn dummyConn) {
30 barReader, fooWriter := io.Pipe()
31 fooReader, barWriter := io.Pipe()
32 return dummyConn{fooReader, fooWriter}, dummyConn{barReader, barWriter}
35 func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) {
36 fooConn, barConn := makeDummyConnPair()
37 fooPrvKey := crypto.GenPrivKeyEd25519()
38 fooPubKey := fooPrvKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
39 barPrvKey := crypto.GenPrivKeyEd25519()
40 barPubKey := barPrvKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
45 fooSecConn, err = MakeSecretConnection(fooConn, fooPrvKey)
47 tb.Errorf("Failed to establish SecretConnection for foo: %v", err)
50 remotePubBytes := fooSecConn.RemotePubKey()
51 if !bytes.Equal(remotePubBytes[:], barPubKey[:]) {
52 tb.Errorf("Unexpected fooSecConn.RemotePubKey. Expected %v, got %v",
53 barPubKey, fooSecConn.RemotePubKey())
58 barSecConn, err = MakeSecretConnection(barConn, barPrvKey)
59 if barSecConn == nil {
60 tb.Errorf("Failed to establish SecretConnection for bar: %v", err)
63 remotePubBytes := barSecConn.RemotePubKey()
64 if !bytes.Equal(remotePubBytes[:], fooPubKey[:]) {
65 tb.Errorf("Unexpected barSecConn.RemotePubKey. Expected %v, got %v",
66 fooPubKey, barSecConn.RemotePubKey())
73 func TestSecretConnectionHandshake(t *testing.T) {
74 fooSecConn, barSecConn := makeSecretConnPair(t)
79 func TestSecretConnectionReadWrite(t *testing.T) {
80 fooConn, barConn := makeDummyConnPair()
81 fooWrites, barWrites := []string{}, []string{}
82 fooReads, barReads := []string{}, []string{}
84 // Pre-generate the things to write (for foo & bar)
85 for i := 0; i < 100; i++ {
86 fooWrites = append(fooWrites, cmn.RandStr((cmn.RandInt()%(dataMaxSize*5))+1))
87 barWrites = append(barWrites, cmn.RandStr((cmn.RandInt()%(dataMaxSize*5))+1))
90 // A helper that will run with (fooConn, fooWrites, fooReads) and vice versa
91 genNodeRunner := func(nodeConn dummyConn, nodeWrites []string, nodeReads *[]string) func() {
94 nodePrvKey := crypto.GenPrivKeyEd25519()
95 nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey)
97 t.Errorf("Failed to establish SecretConnection for node: %v", err)
100 // In parallel, handle reads and writes
104 for _, nodeWrite := range nodeWrites {
105 n, err := nodeSecretConn.Write([]byte(nodeWrite))
107 t.Errorf("Failed to write to nodeSecretConn: %v", err)
110 if n != len(nodeWrite) {
111 t.Errorf("Failed to write all bytes. Expected %v, wrote %v", len(nodeWrite), n)
115 nodeConn.PipeWriter.Close()
119 readBuffer := make([]byte, dataMaxSize)
121 n, err := nodeSecretConn.Read(readBuffer)
124 } else if err != nil {
125 t.Errorf("Failed to read from nodeSecretConn: %v", err)
128 *nodeReads = append(*nodeReads, string(readBuffer[:n]))
130 nodeConn.PipeReader.Close()
135 // Run foo & bar in parallel
137 genNodeRunner(fooConn, fooWrites, &fooReads),
138 genNodeRunner(barConn, barWrites, &barReads),
141 // A helper to ensure that the writes and reads match.
142 // Additionally, small writes (<= dataMaxSize) must be atomically read.
143 compareWritesReads := func(writes []string, reads []string) {
145 // Pop next write & corresponding reads
146 var read, write string = "", writes[0]
148 for _, readChunk := range reads {
151 if len(write) <= len(read) {
154 if len(write) <= dataMaxSize {
155 break // atomicity of small writes
160 t.Errorf("Expected to read %X, got %X", write, read)
164 reads = reads[readCount:]
165 if len(writes) == 0 {
171 compareWritesReads(fooWrites, barReads)
172 compareWritesReads(barWrites, fooReads)
176 func BenchmarkSecretConnection(b *testing.B) {
178 fooSecConn, barSecConn := makeSecretConnPair(b)
179 fooWriteText := cmn.RandStr(dataMaxSize)
180 // Consume reads from bar's reader
182 readBuffer := make([]byte, dataMaxSize)
184 _, err := barSecConn.Read(readBuffer)
187 } else if err != nil {
188 b.Fatalf("Failed to read from barSecConn: %v", err)
194 for i := 0; i < b.N; i++ {
195 _, err := fooSecConn.Write([]byte(fooWriteText))
197 b.Fatalf("Failed to write to fooSecConn: %v", err)
203 //barSecConn.Close() race condition