github.com/status-im/status-go@v1.1.0/protocol/messenger_raw_message_resend_test.go (about) 1 package protocol 2 3 import ( 4 "errors" 5 "testing" 6 7 "github.com/golang/protobuf/proto" 8 "github.com/stretchr/testify/suite" 9 "go.uber.org/zap" 10 11 gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" 12 "github.com/status-im/status-go/eth-node/types" 13 "github.com/status-im/status-go/protocol/common" 14 "github.com/status-im/status-go/protocol/communities" 15 "github.com/status-im/status-go/protocol/protobuf" 16 "github.com/status-im/status-go/protocol/tt" 17 ) 18 19 func TestMessengerRawMessageResendTestSuite(t *testing.T) { 20 suite.Run(t, new(MessengerRawMessageResendTest)) 21 } 22 23 type MessengerRawMessageResendTest struct { 24 suite.Suite 25 logger *zap.Logger 26 27 aliceMessenger *Messenger 28 bobMessenger *Messenger 29 30 aliceWaku types.Waku 31 bobWaku types.Waku 32 33 mockedBalances communities.BalancesByChain 34 } 35 36 func (s *MessengerRawMessageResendTest) SetupTest() { 37 s.logger = tt.MustCreateTestLogger() 38 s.mockedBalances = make(communities.BalancesByChain) 39 40 wakuNodes := CreateWakuV2Network(&s.Suite, s.logger, []string{"alice", "bob"}) 41 42 s.aliceWaku = wakuNodes[0] 43 s.aliceMessenger = newTestCommunitiesMessenger(&s.Suite, s.aliceWaku, testCommunitiesMessengerConfig{ 44 testMessengerConfig: testMessengerConfig{ 45 name: "alice", 46 logger: s.logger, 47 }, 48 walletAddresses: []string{aliceAddress1}, 49 password: accountPassword, 50 mockedBalances: &s.mockedBalances, 51 }) 52 53 _, err := s.aliceMessenger.Start() 54 s.Require().NoError(err) 55 56 s.bobWaku = wakuNodes[1] 57 s.bobMessenger = newTestCommunitiesMessenger(&s.Suite, s.bobWaku, testCommunitiesMessengerConfig{ 58 testMessengerConfig: testMessengerConfig{ 59 name: "bob", 60 logger: s.logger, 61 }, 62 walletAddresses: []string{bobAddress}, 63 password: bobPassword, 64 mockedBalances: &s.mockedBalances, 65 }) 66 67 _, err = s.bobMessenger.Start() 68 s.Require().NoError(err) 69 70 community, _ := createOnRequestCommunity(&s.Suite, s.aliceMessenger) 71 advertiseCommunityToUserOldWay(&s.Suite, community, s.aliceMessenger, s.bobMessenger) 72 joinOnRequestCommunity(&s.Suite, community.ID(), s.aliceMessenger, s.bobMessenger, bobPassword, []string{bobAddress}) 73 } 74 75 func (s *MessengerRawMessageResendTest) TearDownTest() { 76 TearDownMessenger(&s.Suite, s.aliceMessenger) 77 TearDownMessenger(&s.Suite, s.bobMessenger) 78 if s.aliceWaku != nil { 79 s.Require().NoError(gethbridge.GetGethWakuV2From(s.aliceWaku).Stop()) 80 } 81 if s.bobWaku != nil { 82 s.Require().NoError(gethbridge.GetGethWakuV2From(s.bobWaku).Stop()) 83 } 84 _ = s.logger.Sync() 85 } 86 87 func (s *MessengerRawMessageResendTest) waitForMessageSent(messageID string) { 88 err := tt.RetryWithBackOff(func() error { 89 rawMessage, err := s.bobMessenger.RawMessageByID(messageID) 90 s.Require().NoError(err) 91 s.Require().NotNil(rawMessage) 92 if rawMessage.SendCount > 0 { 93 return nil 94 } 95 return errors.New("raw message should be sent finally") 96 }) 97 s.Require().NoError(err) 98 } 99 100 // TestMessageSent tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is in state `sent` without resending 101 func (s *MessengerRawMessageResendTest) TestMessageSent() { 102 ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) 103 s.Require().NoError(err) 104 // one request to join to control node 105 s.Require().Len(ids, 1) 106 107 s.waitForMessageSent(ids[0]) 108 } 109 110 // TestMessageResend tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is resent 111 func (s *MessengerRawMessageResendTest) TestMessageResend() { 112 ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) 113 s.Require().NoError(err) 114 s.Require().Len(ids, 1) 115 // wait for Sent status for already sent message to make sure that sent message was delivered 116 // before testing resend 117 s.waitForMessageSent(ids[0]) 118 119 rawMessage := s.GetRequestToJoinToControlNodeRawMessage(ids) 120 s.Require().NotNil(rawMessage) 121 s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false)) 122 s.Require().NoError(s.bobMessenger.UpdateRawMessageLastSent(rawMessage.ID, 0)) 123 124 err = tt.RetryWithBackOff(func() error { 125 msg, err := s.bobMessenger.RawMessageByID(rawMessage.ID) 126 s.Require().NoError(err) 127 s.Require().NotNil(msg) 128 if msg.SendCount < 2 { 129 return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet") 130 } 131 return nil 132 }) 133 s.Require().NoError(err) 134 135 waitOnMessengerResponse(&s.Suite, func(r *MessengerResponse) error { 136 if len(r.RequestsToJoinCommunity()) > 0 { 137 return nil 138 } 139 return errors.New("community request to join not received") 140 }, s.aliceMessenger) 141 } 142 143 func (s *MessengerRawMessageResendTest) TestInvalidRawMessageToWatchDoesNotProduceResendLoop() { 144 ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) 145 s.Require().NoError(err) 146 s.Require().Len(ids, 1) 147 148 s.waitForMessageSent(ids[0]) 149 150 rawMessage := s.GetRequestToJoinToControlNodeRawMessage(ids) 151 s.Require().NotNil(rawMessage) 152 153 requestToJoinProto := &protobuf.CommunityRequestToJoin{} 154 err = proto.Unmarshal(rawMessage.Payload, requestToJoinProto) 155 s.Require().NoError(err) 156 157 requestToJoinProto.DisplayName = "invalid_ID" 158 payload, err := proto.Marshal(requestToJoinProto) 159 s.Require().NoError(err) 160 rawMessage.Payload = payload 161 162 _, err = s.bobMessenger.AddRawMessageToWatch(rawMessage) 163 s.Require().Error(err, common.ErrModifiedRawMessage) 164 165 // simulate storing msg with modified payload, but old message ID 166 _, err = s.bobMessenger.UpsertRawMessageToWatch(rawMessage) 167 s.Require().NoError(err) 168 s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false)) 169 s.Require().NoError(s.bobMessenger.UpdateRawMessageLastSent(rawMessage.ID, 0)) 170 171 // check counter increased for invalid message to escape the loop 172 err = tt.RetryWithBackOff(func() error { 173 msg, err := s.bobMessenger.RawMessageByID(rawMessage.ID) 174 s.Require().NoError(err) 175 s.Require().NotNil(msg) 176 if msg.SendCount < 2 { 177 return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet") 178 } 179 return nil 180 }) 181 s.Require().NoError(err) 182 } 183 184 func (s *MessengerRawMessageResendTest) GetRequestToJoinToControlNodeRawMessage(ids []string) *common.RawMessage { 185 for _, messageID := range ids { 186 rawMessage, err := s.bobMessenger.RawMessageByID(messageID) 187 s.Require().NoError(err) 188 s.Require().NotNil(rawMessage) 189 190 if rawMessage.ResendMethod == common.ResendMethodSendCommunityMessage { 191 return rawMessage 192 } 193 } 194 195 s.Require().FailNow("rawMessage was not found") 196 return nil 197 }