chore: cover community events eventual consistency with test
It proves eventual consistency is broken for contact request events. iterates: status-im/status-desktop#13387
This commit is contained in:
parent
a0e7b1374e
commit
87199a8c99
|
@ -0,0 +1,178 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/status-im/status-go/protocol/communities"
|
||||
"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 TestCommunityEventsEventualConsistencySuite(t *testing.T) {
|
||||
suite.Run(t, new(CommunityEventsEventualConsistencySuite))
|
||||
}
|
||||
|
||||
type CommunityEventsEventualConsistencySuite struct {
|
||||
AdminCommunityEventsSuite
|
||||
|
||||
messagesOrderController *MessagesOrderController
|
||||
}
|
||||
|
||||
func (s *CommunityEventsEventualConsistencySuite) SetupTest() {
|
||||
s.logger = tt.MustCreateTestLogger()
|
||||
s.collectiblesServiceMock = &CollectiblesServiceMock{}
|
||||
|
||||
config := waku.DefaultConfig
|
||||
config.MinimumAcceptedPoW = 0
|
||||
shh := waku.New(&config, s.logger)
|
||||
wakuWrapper, err := newTestWakuWrapper(&config, s.logger)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(shh.Start())
|
||||
s.shh = wakuWrapper
|
||||
|
||||
s.messagesOrderController = NewMessagesOrderController(messagesOrderRandom)
|
||||
s.messagesOrderController.Start(wakuWrapper.SubscribePostEvents())
|
||||
|
||||
s.owner = s.newMessenger("", []string{})
|
||||
s.admin = s.newMessenger(accountPassword, []string{eventsSenderAccountAddress})
|
||||
s.alice = s.newMessenger(accountPassword, []string{aliceAccountAddress})
|
||||
_, err = s.owner.Start()
|
||||
s.Require().NoError(err)
|
||||
_, err = s.admin.Start()
|
||||
s.Require().NoError(err)
|
||||
_, err = s.alice.Start()
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.mockedBalances = createMockedWalletBalance(&s.Suite)
|
||||
}
|
||||
|
||||
func (s *CommunityEventsEventualConsistencySuite) TearDownTest() {
|
||||
s.AdminCommunityEventsSuite.TearDownTest()
|
||||
s.messagesOrderController.Stop()
|
||||
}
|
||||
|
||||
func (s *CommunityEventsEventualConsistencySuite) newMessenger(password string, walletAddresses []string) *Messenger {
|
||||
return newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{
|
||||
testMessengerConfig: testMessengerConfig{
|
||||
logger: s.logger,
|
||||
messagesOrderController: s.messagesOrderController,
|
||||
},
|
||||
password: password,
|
||||
walletAddresses: walletAddresses,
|
||||
mockedBalances: &s.mockedBalances,
|
||||
collectiblesService: s.collectiblesServiceMock,
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: remove once eventual consistency is implemented
|
||||
var communityRequestsEventualConsistencyFixed = false
|
||||
|
||||
func (s *CommunityEventsEventualConsistencySuite) TestAdminAcceptRejectRequestToJoin() {
|
||||
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{})
|
||||
|
||||
// set up additional user that will send request to join
|
||||
user := s.newMessenger("", []string{})
|
||||
s.SetupAdditionalMessengers([]*Messenger{user})
|
||||
|
||||
advertiseCommunityToUserOldWay(&s.Suite, community, s.owner, user)
|
||||
|
||||
// user sends request to join
|
||||
requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID(), ENSName: "testName"}
|
||||
response, err := user.RequestToJoinCommunity(requestToJoin)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(response)
|
||||
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
||||
|
||||
sentRequest := response.RequestsToJoinCommunity[0]
|
||||
|
||||
checkRequestToJoin := func(r *MessengerResponse) bool {
|
||||
for _, request := range r.RequestsToJoinCommunity {
|
||||
if request.ENSName == requestToJoin.ENSName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// admin receives request to join
|
||||
response, err = WaitOnMessengerResponse(
|
||||
s.admin,
|
||||
checkRequestToJoin,
|
||||
"event sender did not receive community request to join",
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.RequestsToJoinCommunity, 1)
|
||||
|
||||
// accept request to join
|
||||
acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID}
|
||||
_, err = s.admin.AcceptRequestToJoinCommunity(acceptRequestToJoin)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// then reject request to join
|
||||
rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID}
|
||||
_, err = s.admin.DeclineRequestToJoinCommunity(rejectRequestToJoin)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// ensure both messages are pushed to waku
|
||||
/*
|
||||
FIXME: we should do it smarter, as follows:
|
||||
```
|
||||
hashes1, err := admin.SendEvent()
|
||||
hashes2, err := admin.SendEvent()
|
||||
WaitForHashes([][]byte{hashes1, hashes2}, admin.waku)
|
||||
s.messagesOrderController.setCustomOrder([][]{hashes1, hashes2})
|
||||
```
|
||||
*/
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// ensure events are received in order
|
||||
s.messagesOrderController.order = messagesOrderAsPosted
|
||||
|
||||
waitForAcceptedRequestToJoin := waitOnCommunitiesEvent(s.owner, func(sub *communities.Subscription) bool {
|
||||
return len(sub.AcceptedRequestsToJoin) == 1
|
||||
})
|
||||
|
||||
waitOnAdminEventsRejection := waitOnCommunitiesEvent(s.owner, func(s *communities.Subscription) bool {
|
||||
return s.CommunityEventsMessageInvalidClock != nil
|
||||
})
|
||||
|
||||
_, err = s.owner.RetrieveAll()
|
||||
s.Require().NoError(err)
|
||||
|
||||
// first owner handles AcceptRequestToJoinCommunity event
|
||||
err = <-waitForAcceptedRequestToJoin
|
||||
s.Require().NoError(err)
|
||||
|
||||
// then owner rejects DeclineRequestToJoinCommunity event due to invalid clock
|
||||
err = <-waitOnAdminEventsRejection
|
||||
s.Require().NoError(err)
|
||||
|
||||
if communityRequestsEventualConsistencyFixed {
|
||||
// admin receives rejected DeclineRequestToJoinCommunity event and re-applies it,
|
||||
// there is no signal whatsoever, we just wait for admin to process all incoming messages
|
||||
_, _ = WaitOnMessengerResponse(s.admin, func(response *MessengerResponse) bool {
|
||||
return false
|
||||
}, "")
|
||||
|
||||
waitForRejectedRequestToJoin := waitOnCommunitiesEvent(s.owner, func(sub *communities.Subscription) bool {
|
||||
return len(sub.RejectedRequestsToJoin) == 1
|
||||
})
|
||||
|
||||
_, err = s.owner.RetrieveAll()
|
||||
s.Require().NoError(err)
|
||||
|
||||
// owner handles DeclineRequestToJoinCommunity event eventually
|
||||
err = <-waitForRejectedRequestToJoin
|
||||
s.Require().NoError(err)
|
||||
|
||||
// user should be removed from community
|
||||
community, err = s.owner.GetCommunityByID(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().False(community.HasMember(&user.identity.PublicKey))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue