237 lines
7.6 KiB
Go
237 lines
7.6 KiB
Go
package protocol
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
"github.com/status-im/status-go/eth-node/types"
|
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
|
"github.com/status-im/status-go/multiaccounts/settings"
|
|
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
|
"github.com/status-im/status-go/protocol/requests"
|
|
"github.com/status-im/status-go/protocol/tt"
|
|
)
|
|
|
|
func TestMessengerPairingTest(t *testing.T) {
|
|
suite.Run(t, new(MessengerPairingSuite))
|
|
}
|
|
|
|
type MessengerPairingSuite struct {
|
|
MessengerBaseTestSuite
|
|
}
|
|
|
|
func (s *MessengerPairingSuite) TestEnableNonExistingInstallation() {
|
|
installationID := uuid.New().String()
|
|
_, err := s.m.EnableInstallationAndPair(&requests.EnableInstallationAndPair{InstallationID: installationID})
|
|
s.Require().NoError(err)
|
|
|
|
installations := s.m.Installations()
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Len(installations, 2)
|
|
var theirInstallation *multidevice.Installation
|
|
for _, i := range installations {
|
|
if i.ID == installationID {
|
|
theirInstallation = i
|
|
break
|
|
} else {
|
|
s.Require().NotNil(i.InstallationMetadata)
|
|
}
|
|
}
|
|
s.Require().NotNil(theirInstallation)
|
|
s.Require().True(theirInstallation.Enabled)
|
|
|
|
installationsFromDB, err := s.m.encryptor.GetOurActiveInstallations(&s.m.identity.PublicKey)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(installationsFromDB, 2)
|
|
for _, i := range installationsFromDB {
|
|
s.Require().True(i.Enabled)
|
|
if i.ID == installationID {
|
|
theirInstallation = i
|
|
break
|
|
}
|
|
}
|
|
s.Require().NotNil(theirInstallation)
|
|
s.Require().True(theirInstallation.Enabled)
|
|
|
|
}
|
|
|
|
type stubEnableInstallationAndPair struct {
|
|
installationID string
|
|
getInstallationIDInvokedFirst bool
|
|
}
|
|
|
|
func (m *stubEnableInstallationAndPair) GetInstallationID() string {
|
|
if !m.getInstallationIDInvokedFirst {
|
|
m.getInstallationIDInvokedFirst = true
|
|
return m.installationID
|
|
}
|
|
return "wrong installation ID"
|
|
}
|
|
|
|
func (m *stubEnableInstallationAndPair) Validate() error {
|
|
return nil
|
|
}
|
|
|
|
// TestNewInstallationReceivedIsNotCreated tests the scenario where alice2 wants to pair with alice1
|
|
// but the target installation ID is wrong so no AC notification(ActivityCenterNotificationTypeNewInstallationReceived)
|
|
// should be created for alice1
|
|
func (s *MessengerPairingSuite) TestNewInstallationReceivedIsNotCreated() {
|
|
alice1 := s.m
|
|
alice2, err := newMessengerWithKey(s.shh, s.privateKey, s.logger, nil)
|
|
s.Require().NoError(err)
|
|
defer TearDownMessenger(&s.Suite, alice2)
|
|
|
|
mockRequest := &stubEnableInstallationAndPair{installationID: alice1.installationID}
|
|
_, err = alice2.EnableInstallationAndPair(mockRequest)
|
|
s.Require().NoError(err)
|
|
|
|
resp, err := WaitOnMessengerResponse(
|
|
alice1,
|
|
func(r *MessengerResponse) bool {
|
|
for _, i := range r.Installations() {
|
|
if i.ID == alice2.installationID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
},
|
|
"no messages",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 0)
|
|
}
|
|
|
|
// TestNewInstallationCreatedIsNotDeleted tests the scenario
|
|
// 1. prepare AC NewInstallationCreated for alice2
|
|
// 2. prepare AC NewInstallationCreated for alice3
|
|
// 3. alice1.EnableInstallationAndSync
|
|
// 4. check AC NewInstallationCreated for alice3 is not deleted
|
|
func (s *MessengerPairingSuite) TestNewInstallationCreatedIsNotDeleted() {
|
|
alice1 := s.m
|
|
alice2, err := newMessengerWithKey(s.shh, s.privateKey, s.logger, nil)
|
|
s.Require().NoError(err)
|
|
alice3, err := newMessengerWithKey(s.shh, s.privateKey, s.logger, nil)
|
|
s.Require().NoError(err)
|
|
defer TearDownMessenger(&s.Suite, alice2)
|
|
defer TearDownMessenger(&s.Suite, alice3)
|
|
|
|
// prepare AC NewInstallationCreated for alice2
|
|
_, err = alice2.EnableInstallationAndPair(&requests.EnableInstallationAndPair{InstallationID: alice1.installationID})
|
|
s.Require().NoError(err)
|
|
|
|
// alice1 should get the installationID2 from alice2
|
|
s.expectInstallationReceived(alice1, alice2.installationID)
|
|
|
|
// prepare AC NewInstallationCreated for alice3
|
|
_, err = alice3.EnableInstallationAndPair(&requests.EnableInstallationAndPair{InstallationID: alice1.installationID})
|
|
s.Require().NoError(err)
|
|
|
|
// alice1 should get the installationID3 from alice3
|
|
s.expectInstallationReceived(alice1, alice3.installationID)
|
|
|
|
_, err = alice1.EnableInstallationAndSync(&requests.EnableInstallationAndSync{InstallationID: alice2.installationID})
|
|
s.Require().NoError(err)
|
|
|
|
_, err = WaitOnMessengerResponse(
|
|
alice3,
|
|
func(r *MessengerResponse) bool {
|
|
for _, i := range r.Installations() {
|
|
if i.ID == alice1.installationID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
},
|
|
"alice3 should get the installationID from alice1",
|
|
)
|
|
s.Require().NoError(err)
|
|
|
|
ac, err := alice3.ActivityCenterNotification(types.FromHex(alice1.installationID))
|
|
s.Require().NoError(err)
|
|
s.Require().Equal(ActivityCenterNotificationTypeNewInstallationCreated, ac.Type)
|
|
s.Require().False(ac.Deleted)
|
|
}
|
|
|
|
func (s *MessengerPairingSuite) expectInstallationReceived(m *Messenger, installationID string) {
|
|
resp, err := WaitOnMessengerResponse(
|
|
m,
|
|
func(r *MessengerResponse) bool {
|
|
for _, i := range r.Installations() {
|
|
if i.ID == installationID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
},
|
|
"installation not received",
|
|
)
|
|
s.Require().NoError(err)
|
|
s.Require().Len(resp.ActivityCenterNotifications(), 1)
|
|
s.Require().Equal(ActivityCenterNotificationTypeNewInstallationReceived, resp.ActivityCenterNotifications()[0].Type)
|
|
}
|
|
|
|
// TestMessengerSyncFallback tests the scenario where alice2 wants to sync with alice1
|
|
// alice1 generated the connection string for bootstraping alice2
|
|
// alice2 failed to connect to alice1 and restored from seed phrase
|
|
// alice2 get the installationID1 from alice1 via parsing the connection string
|
|
// alice2 should get the display name from alice1 after pairing
|
|
func (s *MessengerPairingSuite) TestMessengerSyncFallback() {
|
|
alice1 := s.m
|
|
alice2, err := newMessengerWithKey(s.shh, s.privateKey, s.logger, nil)
|
|
s.Require().NoError(err)
|
|
defer TearDownMessenger(&s.Suite, alice2)
|
|
|
|
alice1ProfileKp := accounts.GetProfileKeypairForTest(true, false, false)
|
|
alice1ProfileKp.KeyUID = alice1.account.KeyUID
|
|
alice1ProfileKp.Accounts[0].KeyUID = alice1.account.KeyUID
|
|
err = alice1.settings.SaveOrUpdateKeypair(alice1ProfileKp)
|
|
s.Require().NoError(err)
|
|
|
|
expectedDisplayName := "alice1"
|
|
s.Require().NoError(alice1.SetDisplayName(expectedDisplayName))
|
|
ss, err := alice2.getSettings()
|
|
s.Require().NoError(err)
|
|
s.Require().NotEqual(expectedDisplayName, ss.DisplayName)
|
|
installationID1 := alice1.installationID
|
|
installationID2 := alice2.installationID
|
|
s.Require().NotEqual(installationID1, installationID2)
|
|
|
|
_, err = alice2.EnableInstallationAndPair(&requests.EnableInstallationAndPair{InstallationID: installationID1})
|
|
s.Require().NoError(err)
|
|
|
|
// alice1 should get the installationID2 from alice2
|
|
s.expectInstallationReceived(alice1, installationID2)
|
|
|
|
// check response from alice1
|
|
resp, err := alice1.EnableInstallationAndSync(&requests.EnableInstallationAndSync{InstallationID: installationID2})
|
|
s.Require().NoError(err)
|
|
installationID2Exist := false
|
|
for _, i := range resp.Installations() {
|
|
if i.ID == installationID2 {
|
|
installationID2Exist = true
|
|
break
|
|
}
|
|
}
|
|
s.Require().True(installationID2Exist)
|
|
|
|
// check if the display name is synced
|
|
err = tt.RetryWithBackOff(func() error {
|
|
r, err := alice2.RetrieveAll()
|
|
s.Require().NoError(err)
|
|
for _, ss := range r.Settings {
|
|
if ss.GetDBName() == settings.DisplayName.GetDBName() {
|
|
return nil
|
|
}
|
|
}
|
|
return errors.New("display name setting not received yet")
|
|
})
|
|
s.Require().NoError(err)
|
|
ss, err = alice2.getSettings()
|
|
s.Require().NoError(err)
|
|
s.Require().Equal(expectedDisplayName, ss.DisplayName)
|
|
}
|