status-go/protocol/messenger_raw_message_resen...

198 lines
6.4 KiB
Go

package protocol
import (
"errors"
"testing"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/communities"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/tt"
)
func TestMessengerRawMessageResendTestSuite(t *testing.T) {
suite.Run(t, new(MessengerRawMessageResendTest))
}
type MessengerRawMessageResendTest struct {
suite.Suite
logger *zap.Logger
aliceMessenger *Messenger
bobMessenger *Messenger
aliceWaku types.Waku
bobWaku types.Waku
mockedBalances communities.BalancesByChain
}
func (s *MessengerRawMessageResendTest) SetupTest() {
s.logger = tt.MustCreateTestLogger()
s.mockedBalances = make(communities.BalancesByChain)
wakuNodes := CreateWakuV2Network(&s.Suite, s.logger, []string{"alice", "bob"})
s.aliceWaku = wakuNodes[0]
s.aliceMessenger = newTestCommunitiesMessenger(&s.Suite, s.aliceWaku, testCommunitiesMessengerConfig{
testMessengerConfig: testMessengerConfig{
name: "alice",
logger: s.logger,
},
walletAddresses: []string{aliceAddress1},
password: accountPassword,
mockedBalances: &s.mockedBalances,
})
_, err := s.aliceMessenger.Start()
s.Require().NoError(err)
s.bobWaku = wakuNodes[1]
s.bobMessenger = newTestCommunitiesMessenger(&s.Suite, s.bobWaku, testCommunitiesMessengerConfig{
testMessengerConfig: testMessengerConfig{
name: "bob",
logger: s.logger,
},
walletAddresses: []string{bobAddress},
password: bobPassword,
mockedBalances: &s.mockedBalances,
})
_, err = s.bobMessenger.Start()
s.Require().NoError(err)
community, _ := createOnRequestCommunity(&s.Suite, s.aliceMessenger)
advertiseCommunityToUserOldWay(&s.Suite, community, s.aliceMessenger, s.bobMessenger)
joinOnRequestCommunity(&s.Suite, community.ID(), s.aliceMessenger, s.bobMessenger, bobPassword, []string{bobAddress})
}
func (s *MessengerRawMessageResendTest) TearDownTest() {
TearDownMessenger(&s.Suite, s.aliceMessenger)
TearDownMessenger(&s.Suite, s.bobMessenger)
if s.aliceWaku != nil {
s.Require().NoError(gethbridge.GetGethWakuV2From(s.aliceWaku).Stop())
}
if s.bobWaku != nil {
s.Require().NoError(gethbridge.GetGethWakuV2From(s.bobWaku).Stop())
}
_ = s.logger.Sync()
}
func (s *MessengerRawMessageResendTest) waitForMessageSent(messageID string) {
err := tt.RetryWithBackOff(func() error {
rawMessage, err := s.bobMessenger.RawMessageByID(messageID)
s.Require().NoError(err)
s.Require().NotNil(rawMessage)
if rawMessage.SendCount > 0 {
return nil
}
return errors.New("raw message should be sent finally")
})
s.Require().NoError(err)
}
// TestMessageSent tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is in state `sent` without resending
func (s *MessengerRawMessageResendTest) TestMessageSent() {
ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN)
s.Require().NoError(err)
// one request to join to control node
s.Require().Len(ids, 1)
s.waitForMessageSent(ids[0])
}
// TestMessageResend tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is resent
func (s *MessengerRawMessageResendTest) TestMessageResend() {
ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN)
s.Require().NoError(err)
s.Require().Len(ids, 1)
// wait for Sent status for already sent message to make sure that sent message was delivered
// before testing resend
s.waitForMessageSent(ids[0])
rawMessage := s.GetRequestToJoinToControlNodeRawMessage(ids)
s.Require().NotNil(rawMessage)
s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false))
s.Require().NoError(s.bobMessenger.UpdateRawMessageLastSent(rawMessage.ID, 0))
err = tt.RetryWithBackOff(func() error {
msg, err := s.bobMessenger.RawMessageByID(rawMessage.ID)
s.Require().NoError(err)
s.Require().NotNil(msg)
if msg.SendCount < 2 {
return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet")
}
return nil
})
s.Require().NoError(err)
waitOnMessengerResponse(&s.Suite, func(r *MessengerResponse) error {
if len(r.RequestsToJoinCommunity()) > 0 {
return nil
}
return errors.New("community request to join not received")
}, s.aliceMessenger)
}
func (s *MessengerRawMessageResendTest) TestInvalidRawMessageToWatchDoesNotProduceResendLoop() {
ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN)
s.Require().NoError(err)
s.Require().Len(ids, 1)
s.waitForMessageSent(ids[0])
rawMessage := s.GetRequestToJoinToControlNodeRawMessage(ids)
s.Require().NotNil(rawMessage)
requestToJoinProto := &protobuf.CommunityRequestToJoin{}
err = proto.Unmarshal(rawMessage.Payload, requestToJoinProto)
s.Require().NoError(err)
requestToJoinProto.DisplayName = "invalid_ID"
payload, err := proto.Marshal(requestToJoinProto)
s.Require().NoError(err)
rawMessage.Payload = payload
_, err = s.bobMessenger.AddRawMessageToWatch(rawMessage)
s.Require().Error(err, common.ErrModifiedRawMessage)
// simulate storing msg with modified payload, but old message ID
_, err = s.bobMessenger.UpsertRawMessageToWatch(rawMessage)
s.Require().NoError(err)
s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false))
s.Require().NoError(s.bobMessenger.UpdateRawMessageLastSent(rawMessage.ID, 0))
// check counter increased for invalid message to escape the loop
err = tt.RetryWithBackOff(func() error {
msg, err := s.bobMessenger.RawMessageByID(rawMessage.ID)
s.Require().NoError(err)
s.Require().NotNil(msg)
if msg.SendCount < 2 {
return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet")
}
return nil
})
s.Require().NoError(err)
}
func (s *MessengerRawMessageResendTest) GetRequestToJoinToControlNodeRawMessage(ids []string) *common.RawMessage {
for _, messageID := range ids {
rawMessage, err := s.bobMessenger.RawMessageByID(messageID)
s.Require().NoError(err)
s.Require().NotNil(rawMessage)
if rawMessage.ResendMethod == common.ResendMethodSendCommunityMessage {
return rawMessage
}
}
s.Require().FailNow("rawMessage was not found")
return nil
}