mirror of
https://github.com/status-im/status-go.git
synced 2025-01-10 06:36:32 +00:00
7650f3003e
There were a couple of issues on how we handle pinned messages: 1) Clock of the message was only checked when saving, meaning that the client would receive potentially updates that were not to be processed. 2) We relied on the client to generate a notification for a pinned message by sending a normal message through the wire. This PR changes the behavior so that the notification is generated locally, either on response to a network event or client event. 3) When deleting a message, we pull all the replies/pinned notifications and send them over to the client so they know that those messages needs updating.
182 lines
5.0 KiB
Go
182 lines
5.0 KiB
Go
package protocol
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"github.com/status-im/status-go/protocol/common"
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
|
)
|
|
|
|
func TestMessengerPinMessageSuite(t *testing.T) {
|
|
suite.Run(t, new(MessengerPinMessageSuite))
|
|
}
|
|
|
|
type MessengerPinMessageSuite struct {
|
|
MessengerBaseTestSuite
|
|
}
|
|
|
|
func (s *MessengerPinMessageSuite) TestPinMessage() {
|
|
theirMessenger := s.newMessenger()
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport)
|
|
err = theirMessenger.SaveChat(theirChat)
|
|
s.Require().NoError(err)
|
|
|
|
ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport)
|
|
err = s.m.SaveChat(ourChat)
|
|
s.Require().NoError(err)
|
|
|
|
inputMessage := buildTestMessage(*theirChat)
|
|
sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
|
|
s.NoError(err)
|
|
s.Require().Len(sendResponse.Messages(), 1)
|
|
|
|
response, err := WaitOnMessengerResponse(
|
|
s.m,
|
|
func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(response.Chats(), 1)
|
|
|
|
pinMessage := &common.PinMessage{
|
|
LocalChatID: theirChat.ID,
|
|
}
|
|
pinMessage.MessageId = inputMessage.ID
|
|
pinMessage.Pinned = true
|
|
pinMessage.ChatId = theirChat.ID
|
|
sendResponse, err = theirMessenger.SendPinMessage(context.Background(), pinMessage)
|
|
s.NoError(err)
|
|
s.Require().Len(sendResponse.PinMessages(), 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
response, err = WaitOnMessengerResponse(
|
|
s.m,
|
|
func(r *MessengerResponse) bool {
|
|
// we pull as well the original pinned message
|
|
return len(r.PinMessages()) == 1 && len(r.Messages()) == 2
|
|
},
|
|
"pin message not received",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
receivedPinMessage := response.PinMessages()[0]
|
|
s.Require().True(receivedPinMessage.Pinned)
|
|
s.Require().NotNil(receivedPinMessage.Message)
|
|
s.Require().Equal(inputMessage.ID, receivedPinMessage.Message.Message.ID)
|
|
messages := response.Messages()
|
|
|
|
var originalMessage *common.Message
|
|
var notificationMessage *common.Message
|
|
|
|
if messages[0].ID == inputMessage.ID {
|
|
originalMessage = messages[0]
|
|
notificationMessage = messages[1]
|
|
} else {
|
|
originalMessage = messages[1]
|
|
notificationMessage = messages[0]
|
|
}
|
|
|
|
s.Require().Equal(theirMessenger.myHexIdentity(), notificationMessage.From)
|
|
s.Require().Equal(inputMessage.ID, notificationMessage.ResponseTo)
|
|
s.Require().Equal(protobuf.ChatMessage_SYSTEM_MESSAGE_PINNED_MESSAGE, notificationMessage.ContentType)
|
|
|
|
s.Require().Equal(inputMessage.ID, originalMessage.ID)
|
|
}
|
|
|
|
func (s *MessengerPinMessageSuite) TestPinMessageOutOfOrder() {
|
|
theirMessenger := s.newMessenger()
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport)
|
|
err = theirMessenger.SaveChat(theirChat)
|
|
s.Require().NoError(err)
|
|
|
|
ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport)
|
|
err = s.m.SaveChat(ourChat)
|
|
s.Require().NoError(err)
|
|
|
|
inputMessage := buildTestMessage(*theirChat)
|
|
sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
|
|
s.NoError(err)
|
|
s.Require().Len(sendResponse.Messages(), 1)
|
|
|
|
response, err := WaitOnMessengerResponse(
|
|
s.m,
|
|
func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(response.Chats(), 1)
|
|
|
|
// Unpin with higher clock
|
|
|
|
unpinMessage := protobuf.PinMessage{
|
|
ChatId: theirChat.ID,
|
|
MessageId: inputMessage.ID,
|
|
Pinned: false,
|
|
Clock: 3,
|
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
|
}
|
|
|
|
handlePinMessageResponse := &MessengerResponse{}
|
|
err = theirMessenger.handlePinMessage(
|
|
&Contact{ID: s.m.myHexIdentity()},
|
|
1000,
|
|
handlePinMessageResponse,
|
|
unpinMessage,
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(handlePinMessageResponse.PinMessages(), 1)
|
|
s.Require().False(handlePinMessageResponse.PinMessages()[0].Pinned)
|
|
|
|
// Pin with lower clock in response
|
|
|
|
pinMessage := protobuf.PinMessage{
|
|
ChatId: theirChat.ID,
|
|
MessageId: inputMessage.ID,
|
|
Pinned: true,
|
|
Clock: 2,
|
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
|
}
|
|
|
|
err = theirMessenger.handlePinMessage(
|
|
&Contact{ID: s.m.myHexIdentity()},
|
|
1000,
|
|
handlePinMessageResponse,
|
|
pinMessage,
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(handlePinMessageResponse.PinMessages(), 1)
|
|
s.Require().False(handlePinMessageResponse.PinMessages()[0].Pinned)
|
|
|
|
// Pin with lower clock not in response
|
|
|
|
handlePinMessageResponse = &MessengerResponse{}
|
|
pinMessage = protobuf.PinMessage{
|
|
ChatId: theirChat.ID,
|
|
MessageId: inputMessage.ID,
|
|
Pinned: true,
|
|
Clock: 1,
|
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
|
}
|
|
|
|
err = theirMessenger.handlePinMessage(
|
|
&Contact{ID: s.m.myHexIdentity()},
|
|
1000,
|
|
handlePinMessageResponse,
|
|
pinMessage,
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(handlePinMessageResponse.PinMessages(), 0)
|
|
}
|