fix: self-contact related flaky tests (#4312)

This commit is contained in:
Igor Sirotin 2023-11-13 20:07:35 +00:00 committed by GitHub
parent 57e370e7b9
commit 010afb4b39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 102 additions and 40 deletions

View File

@ -126,6 +126,7 @@ type Messenger struct {
systemMessagesTranslations *systemMessageTranslationsMap
allChats *chatMap
selfContact *Contact
selfContactSubscriptions []chan *SelfContactChangeEvent
allContacts *contactMap
allInstallations *installationMap
modifiedInstallations *stringBoolMap
@ -1592,6 +1593,7 @@ func (m *Messenger) watchIdentityImageChanges() {
identityImagesMap[img.Name] = *img
}
m.selfContact.Images = identityImagesMap
m.publishSelfContactSubscriptions(&SelfContactChangeEvent{ImagesChanged: true})
if change.PublishExpected {
err = m.syncProfilePictures(m.dispatchMessage, identityImages)

View File

@ -10,6 +10,8 @@ import (
"github.com/golang/protobuf/proto"
"go.uber.org/zap"
"github.com/ethereum/go-ethereum/log"
"github.com/status-im/status-go/deprecation"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
@ -26,6 +28,14 @@ const incomingMutualStateEventSentDefaultText = "@%s sent you a contact request"
const incomingMutualStateEventAcceptedDefaultText = "@%s accepted your contact request"
const incomingMutualStateEventRemovedDefaultText = "@%s removed you as a contact"
type SelfContactChangeEvent struct {
DisplayNameChanged bool
PreferredNameChanged bool
BioChanged bool
SocialLinksChanged bool
ImagesChanged bool
}
func (m *Messenger) prepareMutualStateUpdateMessage(contactID string, updateType MutualStateUpdateType, clock uint64, timestamp uint64, outgoing bool) (*common.Message, error) {
var text string
var to string
@ -766,6 +776,10 @@ func (m *Messenger) GetContactByID(pubKey string) *Contact {
return contact
}
func (m *Messenger) GetSelfContact() *Contact {
return m.selfContact
}
func (m *Messenger) SetContactLocalNickname(request *requests.SetContactLocalNickname) (*MessengerResponse, error) {
if err := request.Validate(); err != nil {
@ -1291,3 +1305,19 @@ func (m *Messenger) forgetContactInfoRequest(publicKey string) {
delete(m.requestedContacts, publicKey)
}
func (m *Messenger) SubscribeToSelfContactChanges() chan *SelfContactChangeEvent {
s := make(chan *SelfContactChangeEvent, 10)
m.selfContactSubscriptions = append(m.selfContactSubscriptions, s)
return s
}
func (m *Messenger) publishSelfContactSubscriptions(event *SelfContactChangeEvent) {
for _, s := range m.selfContactSubscriptions {
select {
case s <- event:
default:
log.Warn("self contact subscription channel full, dropping message")
}
}
}

View File

@ -46,7 +46,8 @@ func (s *MessengerContactsTestSuite) Test_SelfContact() {
// Set values stored in settings
settingsList := []string{settings.DisplayName.GetReactName(), settings.PreferredName.GetReactName(), settings.Bio.GetReactName()}
changesLatch := SelfContactChangeEvent{}
setSettingsValues := func() {
err := s.m.SetDisplayName(displayName)
s.Require().NoError(err)
@ -58,7 +59,20 @@ func (s *MessengerContactsTestSuite) Test_SelfContact() {
s.Require().NoError(err)
}
SetSettingsAndWaitForChange(&s.Suite, s.m, settingsList, timeout, setSettingsValues)
eventHandler := func(event *SelfContactChangeEvent) bool {
if event.DisplayNameChanged {
changesLatch.DisplayNameChanged = true
}
if event.BioChanged {
changesLatch.BioChanged = true
}
if event.PreferredNameChanged {
changesLatch.PreferredNameChanged = true
}
return changesLatch.DisplayNameChanged && changesLatch.BioChanged && changesLatch.PreferredNameChanged
}
SetSettingsAndWaitForChange(&s.Suite, s.m, timeout, setSettingsValues, eventHandler)
// Set values stored in multiaccounts
@ -67,7 +81,7 @@ func (s *MessengerContactsTestSuite) Test_SelfContact() {
s.Require().NoError(err)
}
SetIdentityImagesAndWaitForChange(&s.Suite, s.m.multiAccounts, timeout, setIdentityImages)
SetIdentityImagesAndWaitForChange(&s.Suite, s.m, timeout, setIdentityImages)
// Set social links. They are applied immediately, no need to wait.

View File

@ -181,6 +181,9 @@ func (m *Messenger) AddOrReplaceSocialLinks(socialLinks identity.SocialLinks) er
return err
}
m.selfContact.SocialLinks = socialLinks
m.publishSelfContactSubscriptions(&SelfContactChangeEvent{
SocialLinksChanged: true,
})
err = m.syncSocialLinks(context.Background(), m.dispatchMessage)
return err

View File

@ -445,22 +445,38 @@ func (s *MessengerLinkPreviewsTestSuite) Test_UnfurlURLs_StatusContactAdded() {
func (s *MessengerLinkPreviewsTestSuite) setProfileParameters(messenger *Messenger, displayName string, bio string, identityImages []images.IdentityImage) {
const timeout = 1 * time.Second
settingsList := []string{
settings.DisplayName.GetReactName(),
settings.Bio.GetReactName(),
}
changes := SelfContactChangeEvent{}
SetSettingsAndWaitForChange(&s.Suite, messenger, settingsList, timeout, func() {
SetSettingsAndWaitForChange(&s.Suite, messenger, timeout, func() {
err := messenger.SetDisplayName(displayName)
s.Require().NoError(err)
err = messenger.SetBio(bio)
s.Require().NoError(err)
}, func(event *SelfContactChangeEvent) bool {
if event.DisplayNameChanged {
changes.DisplayNameChanged = true
}
if event.BioChanged {
changes.BioChanged = true
}
return changes.DisplayNameChanged && changes.BioChanged
})
SetIdentityImagesAndWaitForChange(&s.Suite, messenger.multiAccounts, timeout, func() {
SetIdentityImagesAndWaitForChange(&s.Suite, messenger, timeout, func() {
err := messenger.multiAccounts.StoreIdentityImages(messenger.account.KeyUID, identityImages, false)
s.Require().NoError(err)
})
selfContact := messenger.GetSelfContact()
s.Require().Equal(selfContact.DisplayName, displayName)
s.Require().Equal(selfContact.Bio, bio)
for _, image := range identityImages {
saved, ok := selfContact.Images[image.Name]
s.Require().True(ok)
s.Require().Equal(saved, image)
}
s.Require().Equal(selfContact.DisplayName, displayName)
}
func (s *MessengerLinkPreviewsTestSuite) Test_UnfurlURLs_SelfLink() {

View File

@ -169,10 +169,13 @@ func (m *Messenger) startSettingsChangesLoop() {
switch s.GetReactName() {
case settings.DisplayName.GetReactName():
m.selfContact.DisplayName = s.Value.(string)
m.publishSelfContactSubscriptions(&SelfContactChangeEvent{DisplayNameChanged: true})
case settings.PreferredName.GetReactName():
m.selfContact.EnsName = s.Value.(string)
m.publishSelfContactSubscriptions(&SelfContactChangeEvent{PreferredNameChanged: true})
case settings.Bio.GetReactName():
m.selfContact.Bio = s.Value.(string)
m.publishSelfContactSubscriptions(&SelfContactChangeEvent{BioChanged: true})
}
case <-m.quit:
return

View File

@ -8,7 +8,6 @@ import (
"github.com/stretchr/testify/suite"
"github.com/status-im/status-go/multiaccounts"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/tt"
@ -135,43 +134,35 @@ func PairDevices(s *suite.Suite, device1, device2 *Messenger) {
s.Require().NoError(err)
}
func SetSettingsAndWaitForChange(s *suite.Suite, messenger *Messenger, settingsReactNames []string, timeout time.Duration, actionCallback func()) {
changedSettings := map[string]struct{}{}
wg := sync.WaitGroup{}
func SetSettingsAndWaitForChange(s *suite.Suite, messenger *Messenger, timeout time.Duration,
actionCallback func(), eventCallback func(*SelfContactChangeEvent) bool) {
for _, reactName := range settingsReactNames {
wg.Add(1)
settingReactName := reactName // Loop variables captured by 'func' literals in 'go' statements might have unexpected values
channel := messenger.settings.SubscribeToChanges()
go func() {
defer wg.Done()
for {
select {
case setting := <-channel:
if setting.GetReactName() == settingReactName {
changedSettings[settingReactName] = struct{}{}
return
}
case <-time.After(timeout):
return
}
allEventsReceived := false
channel := messenger.SubscribeToSelfContactChanges()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
for !allEventsReceived {
select {
case event := <-channel:
allEventsReceived = eventCallback(event)
case <-time.After(timeout):
return
}
}()
}
}
}()
actionCallback()
wg.Wait()
s.Require().Len(changedSettings, len(settingsReactNames))
for _, reactName := range settingsReactNames {
_, ok := changedSettings[reactName]
s.Require().True(ok)
}
s.Require().True(allEventsReceived)
}
func SetIdentityImagesAndWaitForChange(s *suite.Suite, multiAccounts *multiaccounts.Database, timeout time.Duration, actionCallback func()) {
channel := multiAccounts.SubscribeToIdentityImageChanges()
func SetIdentityImagesAndWaitForChange(s *suite.Suite, messenger *Messenger, timeout time.Duration, actionCallback func()) {
channel := messenger.SubscribeToSelfContactChanges()
ok := false
wg := sync.WaitGroup{}
wg.Add(1)
@ -179,8 +170,10 @@ func SetIdentityImagesAndWaitForChange(s *suite.Suite, multiAccounts *multiaccou
go func() {
defer wg.Done()
select {
case <-channel:
ok = true
case event := <-channel:
if event.ImagesChanged {
ok = true
}
case <-time.After(timeout):
return
}
@ -189,5 +182,6 @@ func SetIdentityImagesAndWaitForChange(s *suite.Suite, multiAccounts *multiaccou
actionCallback()
wg.Wait()
s.Require().True(ok)
}