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  }