github.com/status-im/status-go@v1.1.0/protocol/messenger_pin_message_test.go (about)

     1  package protocol
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/suite"
     8  
     9  	"github.com/status-im/status-go/protocol/common"
    10  	"github.com/status-im/status-go/protocol/protobuf"
    11  )
    12  
    13  func TestMessengerPinMessageSuite(t *testing.T) {
    14  	suite.Run(t, new(MessengerPinMessageSuite))
    15  }
    16  
    17  type MessengerPinMessageSuite struct {
    18  	MessengerBaseTestSuite
    19  }
    20  
    21  func (s *MessengerPinMessageSuite) TestPinMessage() {
    22  	theirMessenger := s.newMessenger()
    23  	defer TearDownMessenger(&s.Suite, theirMessenger)
    24  
    25  	theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport)
    26  	err := theirMessenger.SaveChat(theirChat)
    27  	s.Require().NoError(err)
    28  
    29  	ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport)
    30  	err = s.m.SaveChat(ourChat)
    31  	s.Require().NoError(err)
    32  
    33  	inputMessage := buildTestMessage(*theirChat)
    34  	sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
    35  	s.NoError(err)
    36  	s.Require().Len(sendResponse.Messages(), 1)
    37  
    38  	response, err := WaitOnMessengerResponse(
    39  		s.m,
    40  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
    41  		"no messages",
    42  	)
    43  	s.Require().NoError(err)
    44  	s.Require().Len(response.Chats(), 1)
    45  
    46  	pinMessage := common.NewPinMessage()
    47  	pinMessage.LocalChatID = theirChat.ID
    48  	pinMessage.MessageId = inputMessage.ID
    49  	pinMessage.Pinned = true
    50  	pinMessage.ChatId = theirChat.ID
    51  	sendResponse, err = theirMessenger.SendPinMessage(context.Background(), pinMessage)
    52  	s.NoError(err)
    53  	s.Require().Len(sendResponse.PinMessages(), 1)
    54  
    55  	// Wait for the message to reach its destination
    56  	response, err = WaitOnMessengerResponse(
    57  		s.m,
    58  		func(r *MessengerResponse) bool {
    59  			// we pull as well the original pinned message
    60  			return len(r.PinMessages()) == 1 && len(r.Messages()) == 2
    61  		},
    62  		"pin message not received",
    63  	)
    64  	s.Require().NoError(err)
    65  
    66  	receivedPinMessage := response.PinMessages()[0]
    67  	s.Require().True(receivedPinMessage.Pinned)
    68  	s.Require().NotNil(receivedPinMessage.Message)
    69  	s.Require().Equal(inputMessage.ID, receivedPinMessage.Message.Message.ID)
    70  	messages := response.Messages()
    71  
    72  	var originalMessage *common.Message
    73  	var notificationMessage *common.Message
    74  
    75  	if messages[0].ID == inputMessage.ID {
    76  		originalMessage = messages[0]
    77  		notificationMessage = messages[1]
    78  	} else {
    79  		originalMessage = messages[1]
    80  		notificationMessage = messages[0]
    81  	}
    82  
    83  	s.Require().Equal(theirMessenger.myHexIdentity(), notificationMessage.From)
    84  	s.Require().Equal(inputMessage.ID, notificationMessage.ResponseTo)
    85  	s.Require().Equal(protobuf.ChatMessage_SYSTEM_MESSAGE_PINNED_MESSAGE, notificationMessage.ContentType)
    86  
    87  	s.Require().Equal(inputMessage.ID, originalMessage.ID)
    88  }
    89  
    90  func (s *MessengerPinMessageSuite) TestPinMessageOutOfOrder() {
    91  	theirMessenger := s.newMessenger()
    92  	defer TearDownMessenger(&s.Suite, theirMessenger)
    93  
    94  	theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport)
    95  	err := theirMessenger.SaveChat(theirChat)
    96  	s.Require().NoError(err)
    97  
    98  	ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport)
    99  	err = s.m.SaveChat(ourChat)
   100  	s.Require().NoError(err)
   101  
   102  	inputMessage := buildTestMessage(*theirChat)
   103  	sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
   104  	s.NoError(err)
   105  	s.Require().Len(sendResponse.Messages(), 1)
   106  
   107  	response, err := WaitOnMessengerResponse(
   108  		s.m,
   109  		func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
   110  		"no messages",
   111  	)
   112  	s.Require().NoError(err)
   113  	s.Require().Len(response.Chats(), 1)
   114  	s.Require().Equal(response.Chats()[0].UnviewedMessagesCount, uint(1))
   115  
   116  	// Unpin with higher clock
   117  
   118  	unpinMessage := protobuf.PinMessage{
   119  		ChatId:      theirChat.ID,
   120  		MessageId:   inputMessage.ID,
   121  		Pinned:      false,
   122  		Clock:       3,
   123  		MessageType: protobuf.MessageType_ONE_TO_ONE,
   124  	}
   125  
   126  	handlePinMessageResponse := &MessengerResponse{}
   127  	err = theirMessenger.handlePinMessage(
   128  		&Contact{ID: s.m.myHexIdentity()},
   129  		1000,
   130  		handlePinMessageResponse,
   131  		&unpinMessage,
   132  		false,
   133  	)
   134  	s.Require().NoError(err)
   135  
   136  	s.Require().Len(handlePinMessageResponse.PinMessages(), 1)
   137  	s.Require().False(handlePinMessageResponse.PinMessages()[0].Pinned)
   138  	s.Require().Len(handlePinMessageResponse.Chats(), 1)
   139  	s.Require().Equal(handlePinMessageResponse.Chats()[0].UnviewedMessagesCount, uint(0))
   140  
   141  	// Pin with lower clock in response
   142  
   143  	pinMessage := protobuf.PinMessage{
   144  		ChatId:      theirChat.ID,
   145  		MessageId:   inputMessage.ID,
   146  		Pinned:      true,
   147  		Clock:       2,
   148  		MessageType: protobuf.MessageType_ONE_TO_ONE,
   149  	}
   150  
   151  	err = theirMessenger.handlePinMessage(
   152  		&Contact{ID: s.m.myHexIdentity()},
   153  		1000,
   154  		handlePinMessageResponse,
   155  		&pinMessage,
   156  		false,
   157  	)
   158  	s.Require().NoError(err)
   159  
   160  	s.Require().Len(handlePinMessageResponse.PinMessages(), 1)
   161  	s.Require().False(handlePinMessageResponse.PinMessages()[0].Pinned)
   162  	s.Require().Len(handlePinMessageResponse.Chats(), 1)
   163  	s.Require().Equal(handlePinMessageResponse.Chats()[0].UnviewedMessagesCount, uint(0))
   164  
   165  	// Pin with lower clock not in response
   166  
   167  	handlePinMessageResponse = &MessengerResponse{}
   168  	pinMessage = protobuf.PinMessage{
   169  		ChatId:      theirChat.ID,
   170  		MessageId:   inputMessage.ID,
   171  		Pinned:      true,
   172  		Clock:       1,
   173  		MessageType: protobuf.MessageType_ONE_TO_ONE,
   174  	}
   175  
   176  	err = theirMessenger.handlePinMessage(
   177  		&Contact{ID: s.m.myHexIdentity()},
   178  		1000,
   179  		handlePinMessageResponse,
   180  		&pinMessage,
   181  		false,
   182  	)
   183  	s.Require().NoError(err)
   184  
   185  	s.Require().Len(handlePinMessageResponse.PinMessages(), 0)
   186  }