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  }