mirror of
https://github.com/status-im/status-go.git
synced 2025-01-09 14:16:21 +00:00
b69042e7d7
This commit fixes an issue where when accepting a contact request the other end would display an extra notification. It also changes WaitOnResponse to collect results. This should make tests less flaky, since sometimes messages are processed in different batches. Now we need to be though exact on what we expect from the response (i.e use == instead of >, otherwise the same behavior applies) This uncovered a couple of issues with messenger.Merge, so I have moved the struct to use a map based collection instead of an array.
1709 lines
58 KiB
Go
1709 lines
58 KiB
Go
package protocol
|
|
|
|
import (
|
|
"context"
|
|
"crypto/ecdsa"
|
|
"testing"
|
|
|
|
"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/crypto"
|
|
"github.com/status-im/status-go/eth-node/types"
|
|
"github.com/status-im/status-go/multiaccounts/settings"
|
|
"github.com/status-im/status-go/protocol/common"
|
|
"github.com/status-im/status-go/protocol/protobuf"
|
|
"github.com/status-im/status-go/protocol/requests"
|
|
"github.com/status-im/status-go/protocol/tt"
|
|
"github.com/status-im/status-go/waku"
|
|
)
|
|
|
|
func TestMessengerContactRequestSuite(t *testing.T) {
|
|
suite.Run(t, new(MessengerContactRequestSuite))
|
|
}
|
|
|
|
type MessengerContactRequestSuite struct {
|
|
suite.Suite
|
|
m *Messenger // main instance of Messenger
|
|
privateKey *ecdsa.PrivateKey // private key for the main instance of Messenger
|
|
// If one wants to send messages between different instances of Messenger,
|
|
// a single waku service should be shared.
|
|
shh types.Waku
|
|
logger *zap.Logger
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) SetupTest() {
|
|
s.logger = tt.MustCreateTestLogger()
|
|
|
|
config := waku.DefaultConfig
|
|
config.MinimumAcceptedPoW = 0
|
|
shh := waku.New(&config, s.logger)
|
|
s.shh = gethbridge.NewGethWakuWrapper(shh)
|
|
s.Require().NoError(shh.Start())
|
|
|
|
s.m = s.newMessenger(s.shh)
|
|
s.privateKey = s.m.identity
|
|
_, err := s.m.Start()
|
|
s.Require().NoError(err)
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TearDownTest() {
|
|
s.Require().NoError(s.m.Shutdown())
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) newMessenger(shh types.Waku) *Messenger {
|
|
privateKey, err := crypto.GenerateKey()
|
|
s.Require().NoError(err)
|
|
|
|
messenger, err := newMessengerWithKey(s.shh, privateKey, s.logger, nil)
|
|
s.Require().NoError(err)
|
|
return messenger
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestReceiveAndAcceptContactRequest() { //nolint: unused
|
|
|
|
messageText := "hello!"
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
request := &requests.SendContactRequest{
|
|
ID: types.Hex2Bytes(contactID),
|
|
Message: messageText,
|
|
}
|
|
|
|
// Send contact request
|
|
resp, err := s.m.SendContactRequest(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.Messages()[0].ContactRequestState)
|
|
|
|
// Make sure it's not returned as coming from us
|
|
contactRequests, _, err := s.m.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 0)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, contacts[0].ContactRequestLocalState)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, false)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Accepted, false)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Dismissed, false)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Make sure it's the pending contact requests
|
|
contactRequests, _, err = theirMessenger.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 1)
|
|
s.Require().Equal(contactRequests[0].ContactRequestState, common.ContactRequestStatePending)
|
|
|
|
// Accept contact request, receiver side
|
|
resp, err = theirMessenger.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: types.Hex2Bytes(contactRequests[0].ID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure the message is updated
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(resp.Messages()[0].ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.Messages()[0].ContactRequestState)
|
|
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequests[0].ID)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Make sure the sender is added to our contacts
|
|
contacts = theirMessenger.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Make sure we consider them a mutual contact, receiver side
|
|
mutualContacts := theirMessenger.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
s.m,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) == 1 && len(r.Messages()) == 2 && len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, true)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Accepted, true)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Dismissed, false)
|
|
|
|
// Make sure the message is updated, sender s2de
|
|
s.Require().NotNil(resp)
|
|
|
|
var message *common.Message
|
|
|
|
for _, m := range resp.Messages() {
|
|
if m.ID == contactRequests[0].ID {
|
|
message = m
|
|
}
|
|
}
|
|
s.Require().NotNil(message)
|
|
|
|
s.Require().Equal(message.ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, message.ContactRequestState)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts = s.m.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestReceiveAndDismissContactRequest() {
|
|
|
|
messageText := "hello!"
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
request := &requests.SendContactRequest{
|
|
ID: types.Hex2Bytes(contactID),
|
|
Message: messageText,
|
|
}
|
|
|
|
// Send contact request
|
|
resp, err := s.m.SendContactRequest(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.Messages()[0].ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, resp.Contacts[0].ContactRequestLocalState)
|
|
|
|
// Make sure it's not returned as coming from us
|
|
contactRequests, _, err := s.m.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 0)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, false)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Accepted, false)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Dismissed, false)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure it's the pending contact requests
|
|
contactRequests, _, err = theirMessenger.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 1)
|
|
s.Require().Equal(contactRequests[0].ContactRequestState, common.ContactRequestStatePending)
|
|
|
|
// Dismiss contact request, receiver side
|
|
resp, err = theirMessenger.DismissContactRequest(context.Background(), &requests.DismissContactRequest{ID: types.Hex2Bytes(contactRequests[0].ID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateDismissed, resp.Contacts[0].ContactRequestLocalState)
|
|
|
|
// Make sure the message is updated
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(resp.Messages()[0].ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateDismissed, resp.Messages()[0].ContactRequestState)
|
|
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequests[0].ID)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, true)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Accepted, false)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].Dismissed, true)
|
|
s.Require().Equal(common.ContactRequestStateDismissed, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Make sure the sender is not added to our contacts
|
|
contacts = theirMessenger.AddedContacts()
|
|
s.Require().Len(contacts, 0)
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestReceiveAcceptAndRetractContactRequest() { //nolint: unused
|
|
|
|
messageText := "hello!"
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(theirMessenger.settings.SaveSettingField(settings.MutualContactEnabled, true))
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
request := &requests.SendContactRequest{
|
|
ID: types.Hex2Bytes(contactID),
|
|
Message: messageText,
|
|
}
|
|
|
|
// Send contact request
|
|
resp, err := s.m.SendContactRequest(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, resp.Contacts[0].ContactRequestLocalState)
|
|
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.Messages()[0].ContactRequestState)
|
|
|
|
// Make sure it's not returned as coming from us
|
|
contactRequests, _, err := s.m.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 0)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Make sure it's the pending contact requests
|
|
contactRequests, _, err = theirMessenger.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 1)
|
|
s.Require().Equal(contactRequests[0].ContactRequestState, common.ContactRequestStatePending)
|
|
|
|
cid := resp.ActivityCenterNotifications()[0].Message.ID
|
|
// Accept contact request, receiver side
|
|
resp, err = theirMessenger.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: types.Hex2Bytes(cid)})
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure the message is updated
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(resp.Messages()[0].ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.Messages()[0].ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequests[0].ID)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Make sure the sender is added to our contacts
|
|
contacts = theirMessenger.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Make sure we consider them a mutual contact, receiver side
|
|
mutualContacts := theirMessenger.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
s.m,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Messages()) == 2 && len(r.ActivityCenterNotifications()) == 1 && len(r.Contacts) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Make sure the message is updated, sender side
|
|
s.Require().NotNil(resp)
|
|
|
|
var message *common.Message
|
|
|
|
for _, m := range resp.Messages() {
|
|
if m.ID == contactRequests[0].ID {
|
|
message = m
|
|
}
|
|
}
|
|
s.Require().NotNil(message)
|
|
|
|
s.Require().Equal(message.ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, message.ContactRequestState)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts = s.m.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
resp, err = s.m.RetractContactRequest(&requests.RetractContactRequest{ContactID: types.Hex2Bytes(contactID)})
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().False(resp.Contacts[0].hasAddedUs())
|
|
s.Require().False(resp.Contacts[0].added())
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Contacts, 1)
|
|
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
|
|
s.Require().Equal(myID, resp.Contacts[0].ID)
|
|
|
|
s.Require().False(resp.Contacts[0].added())
|
|
s.Require().False(resp.Contacts[0].hasAddedUs())
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState)
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestReceiveAcceptAndRetractContactRequestOutOfOrder() {
|
|
message := protobuf.ChatMessage{
|
|
Clock: 4,
|
|
Timestamp: 1,
|
|
Text: "some text",
|
|
ChatId: common.PubkeyToHex(&s.m.identity.PublicKey),
|
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
|
ContentType: protobuf.ChatMessage_CONTACT_REQUEST,
|
|
}
|
|
|
|
contactKey, err := crypto.GenerateKey()
|
|
s.Require().NoError(err)
|
|
|
|
contact, err := BuildContactFromPublicKey(&contactKey.PublicKey)
|
|
s.Require().NoError(err)
|
|
|
|
state := s.m.buildMessageState()
|
|
|
|
state.CurrentMessageState = &CurrentMessageState{
|
|
PublicKey: &contactKey.PublicKey,
|
|
MessageID: "0xa",
|
|
Message: message,
|
|
Contact: contact,
|
|
WhisperTimestamp: 1,
|
|
}
|
|
|
|
response := state.Response
|
|
err = s.m.HandleChatMessage(state)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(response.ActivityCenterNotifications(), 1)
|
|
contacts := s.m.Contacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, contacts[0].ContactRequestRemoteState)
|
|
|
|
retract := protobuf.RetractContactRequest{
|
|
Clock: 2,
|
|
}
|
|
err = s.m.HandleRetractContactRequest(state, retract)
|
|
s.Require().NoError(err)
|
|
|
|
// Nothing should have changed
|
|
contacts = s.m.Contacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, contacts[0].ContactRequestRemoteState)
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestReceiveAndAcceptContactRequestTwice() { //nolint: unused
|
|
|
|
messageText := "hello!"
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
request := &requests.SendContactRequest{
|
|
ID: types.Hex2Bytes(contactID),
|
|
Message: messageText,
|
|
}
|
|
|
|
// Send contact request
|
|
resp, err := s.m.SendContactRequest(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.Messages()[0].ContactRequestState)
|
|
|
|
// Make sure it's not returned as coming from us
|
|
contactRequests, _, err := s.m.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 0)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, contacts[0].ContactRequestLocalState)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Make sure it's the pending contact requests
|
|
contactRequests, _, err = theirMessenger.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 1)
|
|
s.Require().Equal(contactRequests[0].ContactRequestState, common.ContactRequestStatePending)
|
|
|
|
// Accept contact request, receiver side
|
|
resp, err = theirMessenger.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: types.Hex2Bytes(contactRequests[0].ID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure the message is updated
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(resp.Messages()[0].ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.Messages()[0].ContactRequestState)
|
|
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequests[0].ID)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Make sure the sender is added to our contacts
|
|
contacts = theirMessenger.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Make sure we consider them a mutual contact, receiver side
|
|
mutualContacts := theirMessenger.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
s.m,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) == 1 && len(r.Messages()) == 2 && len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Make sure the message is updated, sender s2de
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 2)
|
|
|
|
var message *common.Message
|
|
|
|
for _, m := range resp.Messages() {
|
|
if m.ID == contactRequests[0].ID {
|
|
message = m
|
|
}
|
|
}
|
|
s.Require().NotNil(message)
|
|
|
|
s.Require().Equal(message.ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, message.ContactRequestState)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts = s.m.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Resend contact request with higher clock value
|
|
resp, err = s.m.SendContactRequest(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Messages()) == 1 && r.Messages()[0].ID == resp.Messages()[0].ID
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Nothing should have changed, on both sides
|
|
mutualContacts = s.m.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
mutualContacts = theirMessenger.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestAcceptLatestContactRequestForContact() {
|
|
|
|
messageText := "hello!"
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
|
|
|
|
request := &requests.SendContactRequest{
|
|
ID: types.Hex2Bytes(contactID),
|
|
Message: messageText,
|
|
}
|
|
|
|
// Send contact request
|
|
resp, err := s.m.SendContactRequest(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.Messages()[0].ContactRequestState)
|
|
|
|
// Make sure it's not returned as coming from us
|
|
contactRequests, _, err := s.m.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 0)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, contacts[0].ContactRequestLocalState)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) == 1 && len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Make sure it's the pending contact requests
|
|
contactRequests, _, err = theirMessenger.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 1)
|
|
s.Require().Equal(contactRequests[0].ContactRequestState, common.ContactRequestStatePending)
|
|
|
|
// Accept latest contact request, receiver side
|
|
resp, err = theirMessenger.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(myID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure the message is updated
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(resp.Messages()[0].ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.Messages()[0].ContactRequestState)
|
|
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequests[0].ID)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Make sure the sender is added to our contacts
|
|
contacts = theirMessenger.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Make sure we consider them a mutual contact, receiver side
|
|
mutualContacts := theirMessenger.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
s.m,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Messages()) == 2 && len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure the message is updated, sender side
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
// We receive two messages, one for the default contact request, that
|
|
// is dispatched for backward compatibility, and one for the updated
|
|
// contact request that we sent
|
|
s.Require().Len(resp.Messages(), 2)
|
|
var message *common.Message
|
|
|
|
for _, m := range resp.Messages() {
|
|
if m.ID == contactRequests[0].ID {
|
|
message = m
|
|
}
|
|
}
|
|
s.Require().NotNil(message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, message.ContactRequestState)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts = s.m.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestDismissLatestContactRequestForContact() {
|
|
|
|
messageText := "hello!"
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
|
|
|
|
request := &requests.SendContactRequest{
|
|
ID: types.Hex2Bytes(contactID),
|
|
Message: messageText,
|
|
}
|
|
|
|
// Send contact request
|
|
resp, err := s.m.SendContactRequest(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.Messages()[0].ContactRequestState)
|
|
|
|
// Make sure it's not returned as coming from us
|
|
contactRequests, _, err := s.m.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 0)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, contacts[0].ContactRequestLocalState)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Make sure it's the pending contact requests
|
|
contactRequests, _, err = theirMessenger.PendingContactRequests("", 10)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(contactRequests, 1)
|
|
s.Require().Equal(contactRequests[0].ContactRequestState, common.ContactRequestStatePending)
|
|
|
|
// Dismiss latest contact request, receiver side
|
|
resp, err = theirMessenger.DismissLatestContactRequestForContact(context.Background(), &requests.DismissLatestContactRequestForContact{ID: types.Hex2Bytes(myID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure the message is updated
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Messages(), 1)
|
|
s.Require().Equal(resp.Messages()[0].ID, contactRequests[0].ID)
|
|
s.Require().Equal(common.ContactRequestStateDismissed, resp.Messages()[0].ContactRequestState)
|
|
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequests[0].ID)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateDismissed, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestReceiveAndAcceptLegacyContactRequest() {
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(contactID),
|
|
}
|
|
|
|
// Send contact request
|
|
resp, err := s.m.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(resp)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, contacts[0].ContactRequestLocalState)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
notification := resp.ActivityCenterNotifications()[0]
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, notification.Type)
|
|
s.Require().NotNil(notification.Type)
|
|
s.Require().Equal(common.ContactRequestStatePending, notification.Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Accept contact request, receiver side
|
|
resp, err = theirMessenger.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: types.Hex2Bytes(notification.Message.ID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure the message is updated
|
|
s.Require().NotNil(resp)
|
|
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), notification.Message.ID)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Make sure the sender is added to our contacts
|
|
contacts = theirMessenger.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Make sure we consider them a mutual contact, receiver side
|
|
mutualContacts := theirMessenger.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestLegacyContactRequestNotifications() {
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(contactID),
|
|
}
|
|
|
|
// Send legacy contact request
|
|
resp, err := s.m.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(resp)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, contacts[0].ContactRequestLocalState)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
notification := resp.ActivityCenterNotifications()[0]
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, notification.Type)
|
|
s.Require().NotNil(notification.Type)
|
|
s.Require().Equal(common.ContactRequestStatePending, notification.Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestReceiveMultipleLegacy() {
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NoError(theirMessenger.settings.SaveSettingField(settings.MutualContactEnabled, true))
|
|
s.Require().NoError(s.m.settings.SaveSettingField(settings.MutualContactEnabled, true))
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(contactID),
|
|
}
|
|
|
|
// Send legacy contact request
|
|
resp, err := s.m.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().NotNil(resp)
|
|
|
|
// Make sure contact is added on the sender side
|
|
contacts := s.m.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
s.Require().Equal(ContactRequestStateSent, contacts[0].ContactRequestLocalState)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
notification := resp.ActivityCenterNotifications()[0]
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, notification.Type)
|
|
s.Require().NotNil(notification.Type)
|
|
s.Require().Equal(common.ContactRequestStatePending, notification.Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Remove contact
|
|
|
|
_, err = s.m.RetractContactRequest(&requests.RetractContactRequest{ContactID: types.Hex2Bytes(contactID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure it's not a contact anymore
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Re-add user
|
|
resp, err = s.m.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
s.Require().NoError(err)
|
|
|
|
notification = resp.ActivityCenterNotifications()[0]
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, notification.Type)
|
|
s.Require().NotNil(notification.Type)
|
|
s.Require().Equal(common.ContactRequestStatePending, notification.Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestAcceptLatestLegacyContactRequestForContact() { // nolint: unused
|
|
|
|
theirMessenger := s.newMessenger(s.shh)
|
|
_, err := theirMessenger.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey))
|
|
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(contactID),
|
|
}
|
|
|
|
// Send contact request
|
|
_, err = s.m.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err := WaitOnMessengerResponse(
|
|
theirMessenger,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Accept latest contact request, receiver side
|
|
resp, err = theirMessenger.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(myID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Make sure the sender is added to our contacts
|
|
contacts := theirMessenger.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Make sure we consider them a mutual contact, receiver side
|
|
mutualContacts := theirMessenger.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
s.m,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts = s.m.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
}
|
|
|
|
func (s *MessengerContactRequestSuite) TestPairedDevicesRemoveContact() {
|
|
alice1 := s.m
|
|
alice2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, nil)
|
|
s.Require().NoError(err)
|
|
|
|
_, err = alice2.Start()
|
|
s.Require().NoError(err)
|
|
|
|
prepAliceMessengersForPairing(&s.Suite, alice1, alice2)
|
|
|
|
pairTwoDevices(&s.Suite, alice1, alice2)
|
|
pairTwoDevices(&s.Suite, alice2, alice1)
|
|
|
|
bob := s.newMessenger(s.shh)
|
|
_, err = bob.Start()
|
|
s.Require().NoError(err)
|
|
|
|
contactID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey))
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey))
|
|
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(contactID),
|
|
}
|
|
|
|
// Send contact request
|
|
_, err = alice1.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// it should show up on device 2
|
|
resp, err := WaitOnMessengerResponse(
|
|
alice2,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(resp.Contacts[0].ContactRequestLocalState, ContactRequestStateSent)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
bob,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check activity center notification is of the right type
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message)
|
|
s.Require().Equal(common.ContactRequestStatePending, resp.ActivityCenterNotifications()[0].Message.ContactRequestState)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Accept latest contact request, receiver side
|
|
resp, err = bob.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(myID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Make sure the sender is added to our contacts
|
|
contacts := bob.AddedContacts()
|
|
s.Require().Len(contacts, 1)
|
|
|
|
// Make sure we consider them a mutual contact, receiver side
|
|
mutualContacts := bob.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice1,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts = alice1.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice2,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts = alice2.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
resp, err = alice1.RetractContactRequest(&requests.RetractContactRequest{ContactID: types.Hex2Bytes(bob.myHexIdentity())})
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().False(resp.Contacts[0].hasAddedUs())
|
|
s.Require().False(resp.Contacts[0].added())
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Check on bob side
|
|
resp, err = WaitOnMessengerResponse(
|
|
bob,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Contacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Check on alice2 side
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice2,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Contacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState)
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState)
|
|
}
|
|
|
|
// The scenario tested is as follow:
|
|
// 1) Alice sends a contact request to Bob
|
|
// 2) Bob accepts the contact request
|
|
// 3) Alice restores state on a different device
|
|
// 4) Alice sends a contact request to bob
|
|
// Bob will need to help Alice recover her state, since as far as he can see
|
|
// that's an already accepted contact request
|
|
func (s *MessengerContactRequestSuite) TestAliceRecoverStateSendContactRequest() {
|
|
// Alice sends a contact request to bob
|
|
alice1 := s.m
|
|
|
|
bob := s.newMessenger(s.shh)
|
|
_, err := bob.Start()
|
|
s.Require().NoError(err)
|
|
|
|
bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey))
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey))
|
|
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(bobID),
|
|
}
|
|
|
|
_, err = alice1.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err := WaitOnMessengerResponse(
|
|
bob,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Bob accepts the contact request
|
|
_, err = bob.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(myID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Alice receives the accepted confirmation
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice1,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts := alice1.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Alice resets her device
|
|
alice2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, nil)
|
|
s.Require().NoError(err)
|
|
|
|
_, err = alice2.Start()
|
|
s.Require().NoError(err)
|
|
|
|
// adds bob again to her device
|
|
request = &requests.AddContact{
|
|
ID: types.Hex2Bytes(bobID),
|
|
}
|
|
|
|
_, err = alice2.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
_, err = WaitOnMessengerResponse(
|
|
bob,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Bob should be a mutual contact with alice, nothing has changed
|
|
s.Require().Len(bob.MutualContacts(), 1)
|
|
|
|
// Alice retrieves her messages, she should have been notified by
|
|
// dear bobby that they were contacts
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice2,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
s.Require().Len(resp.Contacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
}
|
|
|
|
// The scenario tested is as follow:
|
|
// 1) Alice sends a contact request to Bob
|
|
// 2) Bob accepts the contact request
|
|
// 3) Alice restores state on a different device
|
|
// 4) Bob sends a message to alice
|
|
// Alice will show a contact request from bob
|
|
func (s *MessengerContactRequestSuite) TestAliceRecoverStateReceiveContactRequest() {
|
|
// Alice sends a contact request to bob
|
|
alice1 := s.m
|
|
|
|
bob := s.newMessenger(s.shh)
|
|
_, err := bob.Start()
|
|
s.Require().NoError(err)
|
|
|
|
bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey))
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey))
|
|
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(bobID),
|
|
}
|
|
|
|
_, err = alice1.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err := WaitOnMessengerResponse(
|
|
bob,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Bob accepts the contact request
|
|
_, err = bob.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(myID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Alice receives the accepted confirmation
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice1,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts := alice1.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
// Alice resets her device
|
|
alice2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, nil)
|
|
s.Require().NoError(err)
|
|
|
|
_, err = alice2.Start()
|
|
s.Require().NoError(err)
|
|
|
|
// We want to facilitate the discovery of the x3dh bundl here, since bob does not know about alice device
|
|
|
|
alice2Bundle, err := alice2.encryptor.GetBundle(alice2.identity)
|
|
s.Require().NoError(err)
|
|
|
|
_, err = bob.encryptor.ProcessPublicBundle(bob.identity, alice2Bundle)
|
|
s.Require().NoError(err)
|
|
|
|
// Bob sends a chat message to alice
|
|
|
|
var chat Chat
|
|
chats := bob.Chats()
|
|
for i, c := range chats {
|
|
if c.ID == alice1.myHexIdentity() && c.OneToOne() {
|
|
chat = *chats[i]
|
|
}
|
|
}
|
|
s.Require().NotNil(chat)
|
|
|
|
inputMessage := buildTestMessage(chat)
|
|
_, err = bob.SendChatMessage(context.Background(), inputMessage)
|
|
s.NoError(err)
|
|
|
|
// Alice retrieves the chat message, it should be
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice2,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.ActivityCenterNotifications()) == 1
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().NotNil(resp)
|
|
s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type)
|
|
s.Require().Len(resp.Contacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
}
|
|
|
|
// The scenario tested is as follow:
|
|
// 1) Alice sends a contact request to Bob
|
|
// 2) Bob accepts the contact request
|
|
// 3) Bob goes offline
|
|
// 4) Alice retracts the contact request
|
|
// 5) Alice adds bob back to her contacts
|
|
// 6) Bob goes online, they receive 4 and 5 in the correct order
|
|
func (s *MessengerContactRequestSuite) TestAliceOfflineRetractsAndAddsCorrectOrder() {
|
|
// Alice sends a contact request to bob
|
|
alice1 := s.m
|
|
|
|
bob := s.newMessenger(s.shh)
|
|
_, err := bob.Start()
|
|
s.Require().NoError(err)
|
|
|
|
bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey))
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey))
|
|
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(bobID),
|
|
}
|
|
|
|
_, err = alice1.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err := WaitOnMessengerResponse(
|
|
bob,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Bob accepts the contact request
|
|
_, err = bob.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(myID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Alice receives the accepted confirmation
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice1,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts := alice1.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
_, err = alice1.RetractContactRequest(&requests.RetractContactRequest{ContactID: types.Hex2Bytes(bob.myHexIdentity())})
|
|
s.Require().NoError(err)
|
|
|
|
// adds bob again to her device
|
|
request = &requests.AddContact{
|
|
ID: types.Hex2Bytes(bobID),
|
|
}
|
|
|
|
_, err = alice1.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
_, err = WaitOnMessengerResponse(
|
|
bob,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
}
|
|
|
|
// The scenario tested is as follow:
|
|
// 1) Alice sends a contact request to Bob
|
|
// 2) Bob accepts the contact request
|
|
// 3) Bob goes offline
|
|
// 4) Alice retracts the contact request
|
|
// 5) Alice adds bob back to her contacts
|
|
// 6) Bob goes online, they receive 4 and 5 in the wrong order
|
|
func (s *MessengerContactRequestSuite) TestAliceOfflineRetractsAndAddsWrongOrder() {
|
|
// Alice sends a contact request to bob
|
|
alice1 := s.m
|
|
|
|
bob := s.newMessenger(s.shh)
|
|
_, err := bob.Start()
|
|
s.Require().NoError(err)
|
|
|
|
bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey))
|
|
myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey))
|
|
|
|
request := &requests.AddContact{
|
|
ID: types.Hex2Bytes(bobID),
|
|
}
|
|
|
|
_, err = alice1.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Wait for the message to reach its destination
|
|
resp, err := WaitOnMessengerResponse(
|
|
bob,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0 && len(r.Messages()) > 0 && len(r.ActivityCenterNotifications()) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
|
|
// Check contact request has been received
|
|
s.Require().NoError(err)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState)
|
|
|
|
// Bob accepts the contact request
|
|
_, err = bob.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(myID)})
|
|
s.Require().NoError(err)
|
|
|
|
// Alice receives the accepted confirmation
|
|
resp, err = WaitOnMessengerResponse(
|
|
alice1,
|
|
func(r *MessengerResponse) bool {
|
|
return len(r.Contacts) > 0
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
// Make sure we consider them a mutual contact, sender side
|
|
mutualContacts := alice1.MutualContacts()
|
|
s.Require().Len(mutualContacts, 1)
|
|
|
|
// Check the contact state is correctly set
|
|
s.Require().Len(resp.Contacts, 1)
|
|
s.Require().True(resp.Contacts[0].mutual())
|
|
|
|
_, err = alice1.RetractContactRequest(&requests.RetractContactRequest{ContactID: types.Hex2Bytes(bob.myHexIdentity())})
|
|
s.Require().NoError(err)
|
|
|
|
// adds bob again to her device
|
|
request = &requests.AddContact{
|
|
ID: types.Hex2Bytes(bobID),
|
|
}
|
|
|
|
_, err = alice1.AddContact(context.Background(), request)
|
|
s.Require().NoError(err)
|
|
|
|
// Get alice perspective of bob
|
|
bobFromAlice := alice1.AddedContacts()[0]
|
|
|
|
// Get bob perspective of alice
|
|
aliceFromBob := bob.MutualContacts()[0]
|
|
|
|
s.Require().NotNil(bobFromAlice)
|
|
s.Require().NotNil(aliceFromBob)
|
|
|
|
// We can't simulate out-of-order messages easily, so we need to do
|
|
// things manually here
|
|
|
|
result := aliceFromBob.ContactRequestPropagatedStateReceived(bobFromAlice.ContactRequestPropagatedState())
|
|
s.Require().True(result.newContactRequestReceived)
|
|
|
|
}
|