github.com/status-im/status-go@v1.1.0/protocol/messenger_mailserver_processMailserverBatch_test.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "crypto/rand" 6 "encoding/hex" 7 "errors" 8 "math/big" 9 "testing" 10 "time" 11 12 "github.com/google/uuid" 13 "github.com/libp2p/go-libp2p/core/peer" 14 "github.com/stretchr/testify/require" 15 16 "github.com/status-im/status-go/eth-node/types" 17 "github.com/status-im/status-go/protocol/tt" 18 ) 19 20 type queryResponse struct { 21 topics []types.TopicType 22 err error // Indicates if this response will simulate an error returned by SendMessagesRequestForTopics 23 cursor []byte 24 } 25 26 type mockTransport struct { 27 queryResponses map[string]queryResponse 28 } 29 30 func newMockTransport() *mockTransport { 31 return &mockTransport{ 32 queryResponses: make(map[string]queryResponse), 33 } 34 } 35 36 func getInitialResponseKey(topics []types.TopicType) string { 37 return hex.EncodeToString(append([]byte("start"), topics[0][:]...)) 38 } 39 40 func (t *mockTransport) SendMessagesRequestForTopics( 41 ctx context.Context, 42 peerID peer.ID, 43 from, to uint32, 44 prevCursor types.StoreRequestCursor, 45 pubsubTopic string, 46 contentTopics []types.TopicType, 47 limit uint32, 48 waitForResponse bool, 49 processEnvelopes bool, 50 ) (cursor types.StoreRequestCursor, envelopesCount int, err error) { 51 var response queryResponse 52 if prevCursor == nil { 53 initialResponse := getInitialResponseKey(contentTopics) 54 response = t.queryResponses[initialResponse] 55 } else { 56 response = t.queryResponses[hex.EncodeToString(prevCursor)] 57 } 58 return response.cursor, 0, response.err 59 } 60 61 func (t *mockTransport) Populate(topics []types.TopicType, responses int, includeRandomError bool) error { 62 if responses <= 0 || len(topics) == 0 { 63 return errors.New("invalid input parameters") 64 } 65 66 var topicBatches [][]types.TopicType 67 68 for i := 0; i < len(topics); i += maxTopicsPerRequest { 69 // Split batch in 10-contentTopic subbatches 70 j := i + maxTopicsPerRequest 71 if j > len(topics) { 72 j = len(topics) 73 } 74 topicBatches = append(topicBatches, topics[i:j]) 75 } 76 77 randomErrIdx, err := rand.Int(rand.Reader, big.NewInt(int64(len(topicBatches)))) 78 if err != nil { 79 return err 80 } 81 randomErrIdxInt := int(randomErrIdx.Int64()) 82 83 for i, topicBatch := range topicBatches { 84 // Setup initial response 85 initialResponseKey := getInitialResponseKey(topicBatch) 86 t.queryResponses[initialResponseKey] = queryResponse{ 87 topics: topicBatch, 88 err: nil, 89 } 90 91 prevKey := initialResponseKey 92 for x := 0; x < responses-1; x++ { 93 newResponseCursor := []byte(uuid.New().String()) 94 newResponseKey := hex.EncodeToString(newResponseCursor) 95 96 var err error 97 if includeRandomError && i == randomErrIdxInt && x == responses-2 { // Include an error in last request 98 err = errors.New("random error") 99 } 100 101 t.queryResponses[newResponseKey] = queryResponse{ 102 topics: topicBatch, 103 err: err, 104 } 105 106 // Updating prev response cursor to point to the new response 107 prevResponse := t.queryResponses[prevKey] 108 prevResponse.cursor = newResponseCursor 109 t.queryResponses[prevKey] = prevResponse 110 111 prevKey = newResponseKey 112 } 113 114 } 115 116 return nil 117 } 118 119 func TestProcessMailserverBatchHappyPath(t *testing.T) { 120 ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) 121 defer cancel() 122 123 logger := tt.MustCreateTestLogger() 124 125 mailserverID, err := peer.Decode("16Uiu2HAkw3x97MbbZSWHbdF5bob45vcZvPPK4s4Mjyv2mxyB9GS3") 126 require.NoError(t, err) 127 topics := []types.TopicType{} 128 for i := 0; i < 22; i++ { 129 topics = append(topics, types.BytesToTopic([]byte{0, 0, 0, byte(i)})) 130 } 131 132 testTransport := newMockTransport() 133 err = testTransport.Populate(topics, 10, false) 134 require.NoError(t, err) 135 136 testBatch := MailserverBatch{ 137 Topics: topics, 138 } 139 140 err = processMailserverBatch(ctx, testTransport, testBatch, mailserverID, logger, defaultStoreNodeRequestPageSize, nil, false) 141 require.NoError(t, err) 142 } 143 144 func TestProcessMailserverBatchFailure(t *testing.T) { 145 ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) 146 defer cancel() 147 148 logger := tt.MustCreateTestLogger() 149 150 mailserverID, err := peer.Decode("16Uiu2HAkw3x97MbbZSWHbdF5bob45vcZvPPK4s4Mjyv2mxyB9GS3") 151 require.NoError(t, err) 152 topics := []types.TopicType{} 153 for i := 0; i < 5; i++ { 154 topics = append(topics, types.BytesToTopic([]byte{0, 0, 0, byte(i)})) 155 } 156 157 testTransport := newMockTransport() 158 err = testTransport.Populate(topics, 4, true) 159 require.NoError(t, err) 160 161 testBatch := MailserverBatch{ 162 Topics: topics, 163 } 164 165 err = processMailserverBatch(ctx, testTransport, testBatch, mailserverID, logger, defaultStoreNodeRequestPageSize, nil, false) 166 require.Error(t, err) 167 }