github.com/aergoio/aergo@v1.3.1/p2p/v030/v030io_test.go (about) 1 /* 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package v030 7 8 import ( 9 "bufio" 10 "bytes" 11 "fmt" 12 "github.com/aergoio/aergo/internal/enc" 13 "io/ioutil" 14 "testing" 15 "time" 16 17 "github.com/aergoio/aergo/p2p/p2pcommon" 18 "github.com/aergoio/aergo/types" 19 "github.com/gofrs/uuid" 20 "github.com/golang/protobuf/proto" 21 "github.com/stretchr/testify/assert" 22 ) 23 24 var sampleTxsB58 = []string{ 25 "4H4zAkAyRV253K5SNBJtBxqUgHEbZcXbWFFc6cmQHY45", 26 "6xfk39kuyDST7NwCu8tx3wqwFZ5dwKPDjxUS14tU7NZb8", 27 "E8dbBGe9Hnuhk35cJoekPjL3VoL4xAxtnRuP47UoxzHd", 28 "HB7Hg5GUbHuxwe8Lp5PcYUoAaQ7EZjRNG6RuvS6DnDRf", 29 "BxKmDg9VbWHxrWnStEeTzJ2Ze7RF7YK4rpyjcsWSsnxs", 30 "DwmGqFU4WgADpYN36FXKsYxMjeppvh9Najg4KxJ8gtX3", 31 } 32 33 var sampleTxs [][]byte 34 var sampleTxHashes []types.TxID 35 36 var sampleBlksB58 = []string{ 37 "v6zbuQ4aVSdbTwQhaiZGp5pcL5uL55X3kt2wfxor5W6", 38 "2VEPg4MqJUoaS3EhZ6WWSAUuFSuD4oSJ645kSQsGV7H9", 39 "AtzTZ2CZS45F1276RpTdLfYu2DLgRcd9HL3aLqDT1qte", 40 "2n9QWNDoUvML756X7xdHWCFLZrM4CQEtnVH2RzG5FYAw", 41 "6cy7U7XKYtDTMnF3jNkcJvJN5Rn85771NSKjc5Tfo2DM", 42 "3bmB8D37XZr4DNPs64NiGRa2Vw3i8VEgEy6Xc2XBmRXC", 43 } 44 var sampleBlks [][]byte 45 var sampleBlksHashes []types.BlockID 46 47 func init() { 48 sampleTxs = make([][]byte, len(sampleTxsB58)) 49 sampleTxHashes = make([]types.TxID, len(sampleTxsB58)) 50 for i, hashb58 := range sampleTxsB58 { 51 hash, _ := enc.ToBytes(hashb58) 52 sampleTxs[i] = hash 53 copy(sampleTxHashes[i][:], hash) 54 } 55 56 sampleBlks = make([][]byte, len(sampleBlksB58)) 57 sampleBlksHashes = make([]types.BlockID, len(sampleBlksB58)) 58 for i, hashb58 := range sampleTxsB58 { 59 hash, _ := enc.ToBytes(hashb58) 60 sampleBlks[i] = hash 61 copy(sampleBlksHashes[i][:], hash) 62 } 63 } 64 65 func Test_ReadWrite(t *testing.T) { 66 var sampleID p2pcommon.MsgID 67 sampleUUID, _ := uuid.NewV4() 68 copy(sampleID[:], sampleUUID[:]) 69 70 tests := []struct { 71 name string 72 ids [][]byte 73 }{ 74 {"TEmpty", nil}, 75 {"TSingle", sampleTxs[:1]}, 76 {"TSmall", sampleTxs}, 77 {"TBig", func() [][]byte { 78 toreturn := make([][]byte, 0, len(sampleTxs)*1000) 79 for i := 0; i < 1000; i++ { 80 toreturn = append(toreturn, sampleTxs...) 81 } 82 return toreturn 83 }()}, 84 } 85 for _, test := range tests { 86 t.Run(test.name, func(t *testing.T) { 87 sizeChecker, sizeChecker2 := ioSum{}, ioSum{} 88 samplePData := &types.NewTransactionsNotice{TxHashes: test.ids} 89 payload, _ := proto.Marshal(samplePData) 90 sample := p2pcommon.NewMessageValue(p2pcommon.NewTxNotice, sampleID, p2pcommon.EmptyID, time.Now().UnixNano(), payload) 91 92 buf := bytes.NewBuffer(nil) 93 target := NewV030ReadWriter(nil, buf, nil) 94 target.AddIOListener(&sizeChecker) 95 96 target.WriteMsg(sample) 97 98 actual := buf.Bytes() 99 assert.Equal(t, len(payload)+msgHeaderLength, len(actual)) 100 assert.Equal(t, len(actual), sizeChecker.writeN) 101 102 rd := NewV030ReadWriter(bufio.NewReader(buf), ioutil.Discard, nil) 103 rd.AddIOListener(&sizeChecker2) 104 105 readMsg, err := rd.ReadMsg() 106 107 assert.Nil(t, err) 108 assert.NotNil(t, readMsg) 109 assert.Equal(t, sample, readMsg) 110 assert.True(t, bytes.Equal(sample.Payload(), readMsg.Payload())) 111 assert.Equal(t, sizeChecker.writeN, sizeChecker2.readN) 112 113 // read error test 114 buf2 := bytes.NewBuffer(actual) 115 buf2.Truncate(buf2.Len() - 1) 116 rd2 := NewV030ReadWriter(bufio.NewReader(buf), ioutil.Discard, nil) 117 readMsg, err = rd2.ReadMsg() 118 assert.NotNil(t, err) 119 }) 120 } 121 } 122 123 type ioSum struct { 124 readN int 125 writeN int 126 } 127 128 func (s *ioSum) OnRead(protocol p2pcommon.SubProtocol, read int) { 129 s.readN += read 130 } 131 132 func (s *ioSum) OnWrite(protocol p2pcommon.SubProtocol, write int) { 133 s.writeN += write 134 } 135 136 func TestV030Writer_WriteError(t *testing.T) { 137 //var sampleID MsgID 138 //sampleUUID, _ := uuid.NewRandom() 139 //copy(sampleID[:], sampleUUID[:]) 140 //samplePData := &types.NewTransactionsNotice{TxHashes:sampleTxs} 141 //payload, _ := proto.Marshal(samplePData) 142 //sample := &MessageValue{subProtocol: subproto.NewTxNotice, id: sampleID, timestamp: time.Now().UnixNano(), length: uint32(len(payload)), payload: payload} 143 //mockWriter := make(MockWriter) 144 //mockWriter.On("Write", mock.Anything).Return(fmt.Errorf("writer error")) 145 //target := NewV030Writer(bufio.NewWriter(mockWriter)) 146 //err := target.WriteMsg(sample) 147 //assert.NotNil(t, err) 148 } 149 150 func BenchmarkV030Writer_WriteMsg(b *testing.B) { 151 var sampleID p2pcommon.MsgID 152 sampleUUID, _ := uuid.NewV4() 153 copy(sampleID[:], sampleUUID[:]) 154 timestamp := time.Now().UnixNano() 155 156 smallPData := &types.NewTransactionsNotice{} 157 payload, _ := proto.Marshal(smallPData) 158 smallMsg := p2pcommon.NewMessageValue(p2pcommon.NewTxNotice, sampleID, p2pcommon.EmptyID, timestamp, payload) 159 bigHashes := make([][]byte, 0, len(sampleTxs)*10000) 160 for i := 0; i < 10000; i++ { 161 bigHashes = append(bigHashes, sampleTxs...) 162 } 163 bigPData := &types.NewTransactionsNotice{TxHashes: bigHashes} 164 payload, _ = proto.Marshal(bigPData) 165 bigMsg := p2pcommon.NewMessageValue(p2pcommon.NewTxNotice, sampleID, p2pcommon.EmptyID, timestamp, payload) 166 167 benchmarks := []struct { 168 name string 169 rw p2pcommon.MsgReadWriter 170 input *p2pcommon.MessageValue 171 repeatCount int 172 }{ 173 // write small 174 {"BWSmall", NewV030ReadWriter(nil,ioutil.Discard, nil), smallMsg, 100}, 175 // write big 176 {"BWBig", NewV030ReadWriter(nil, ioutil.Discard,nil), bigMsg, 100}, 177 ////write small with rw 178 //{"BWSmallRW", NewV030ReadWriter(nil, ioutil.Discard, nil), smallMsg, 100}, 179 //// write big with rw 180 //{"BWBigRW", NewV030ReadWriter(nil, ioutil.Discard, nil), bigMsg, 100}, 181 } 182 for _, bm := range benchmarks { 183 b.Run(bm.name, func(b *testing.B) { 184 for i := 0; i < b.N; i++ { 185 target := bm.rw 186 for j := 0; j < bm.repeatCount; j++ { 187 target.WriteMsg(bm.input) 188 } 189 } 190 }) 191 } 192 } 193 194 func BenchmarkV030Reader_ReadMsg(b *testing.B) { 195 var sampleID p2pcommon.MsgID 196 sampleUUID, _ := uuid.NewV4() 197 copy(sampleID[:], sampleUUID[:]) 198 timestamp := time.Now().UnixNano() 199 200 smallPData := &types.NewTransactionsNotice{} 201 payload, _ := proto.Marshal(smallPData) 202 smallMsg := p2pcommon.NewMessageValue(p2pcommon.NewTxNotice, sampleID, p2pcommon.EmptyID, timestamp, payload) 203 smallBytes := getMarshaledV030(smallMsg, 1) 204 bigHashes := make([][]byte, 0, len(sampleTxs)*10000) 205 for i := 0; i < 10000; i++ { 206 bigHashes = append(bigHashes, sampleTxs...) 207 } 208 bigPData := &types.NewTransactionsNotice{TxHashes: bigHashes} 209 payload, _ = proto.Marshal(bigPData) 210 bigMsg := p2pcommon.NewMessageValue(p2pcommon.NewTxNotice, sampleID, p2pcommon.EmptyID, timestamp, payload) 211 bigBytes := getMarshaledV030(bigMsg, 1) 212 213 fmt.Printf("small : %d , big : %d \n", len(smallBytes), len(bigBytes)) 214 215 benchmarks := []struct { 216 name string 217 rd p2pcommon.MsgReadWriter 218 repeatCount int 219 }{ 220 // read big with rw 221 {"BRBigRW", NewV030ReadWriter(NewRepeatedBuffer(bigBytes), nil, nil), 100}, 222 // read small with rw 223 {"BRSmallRW", NewV030ReadWriter(NewRepeatedBuffer(smallBytes), nil, nil), 100}, 224 //// read small 225 //{"BRSmall", NewV030Reader(NewRepeatedBuffer(smallBytes)), 100}, 226 //// read big 227 //{"BRBig", NewV030Reader(NewRepeatedBuffer(bigBytes)), 100}, 228 } 229 for _, bm := range benchmarks { 230 b.Run(bm.name, func(b *testing.B) { 231 for i := 0; i < b.N; i++ { 232 target := bm.rd 233 for j := 0; j < bm.repeatCount; j++ { 234 actual, err := target.ReadMsg() 235 if err != nil { 236 b.Fatal("err while reading on lap",j, err.Error()) 237 } else if actual.ID() != sampleID { 238 b.Fatal() 239 } 240 } 241 } 242 }) 243 } 244 } 245 246 func getMarshaledV030(m *p2pcommon.MessageValue, repeat int) []byte { 247 unitbuf := &bytes.Buffer{} 248 writer := NewV030ReadWriter(nil, bufio.NewWriter(unitbuf), nil) 249 writer.WriteMsg(m) 250 unitbytes := unitbuf.Bytes() 251 buf := make([]byte, 0, len(unitbytes)*repeat) 252 for i := 0; i < repeat; i++ { 253 buf = append(buf, unitbytes...) 254 } 255 return buf 256 } 257 258 type RepeatedBuffer struct { 259 offset, size int 260 buf []byte 261 } 262 263 func (r *RepeatedBuffer) Read(p []byte) (n int, err error) { 264 copied := copy(p, r.buf[r.offset:]) 265 r.offset+=copied 266 if r.offset >= r.size { 267 r.offset = 0 268 } 269 return copied, nil 270 } 271 272 func NewRepeatedBuffer(buf []byte) *RepeatedBuffer { 273 return &RepeatedBuffer{buf: buf, size:len(buf)} 274 }