status-im/status-go

View on GitHub
protocol/messenger_pin_message_test.go

Summary

Maintainability
A
0 mins
Test Coverage
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()
    defer TearDownMessenger(&s.Suite, theirMessenger)

    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.NewPinMessage()
    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()
    defer TearDownMessenger(&s.Suite, theirMessenger)

    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)
    s.Require().Equal(response.Chats()[0].UnviewedMessagesCount, uint(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,
        false,
    )
    s.Require().NoError(err)

    s.Require().Len(handlePinMessageResponse.PinMessages(), 1)
    s.Require().False(handlePinMessageResponse.PinMessages()[0].Pinned)
    s.Require().Len(handlePinMessageResponse.Chats(), 1)
    s.Require().Equal(handlePinMessageResponse.Chats()[0].UnviewedMessagesCount, uint(0))

    // 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,
        false,
    )
    s.Require().NoError(err)

    s.Require().Len(handlePinMessageResponse.PinMessages(), 1)
    s.Require().False(handlePinMessageResponse.PinMessages()[0].Pinned)
    s.Require().Len(handlePinMessageResponse.Chats(), 1)
    s.Require().Equal(handlePinMessageResponse.Chats()[0].UnviewedMessagesCount, uint(0))

    // 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,
        false,
    )
    s.Require().NoError(err)

    s.Require().Len(handlePinMessageResponse.PinMessages(), 0)
}