github.com/status-im/status-go@v1.1.0/protocol/messenger_contact_requests_test.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 "github.com/stretchr/testify/suite" 9 "go.uber.org/zap" 10 11 "github.com/status-im/status-go/deprecation" 12 "github.com/status-im/status-go/eth-node/crypto" 13 "github.com/status-im/status-go/eth-node/types" 14 multiaccountscommon "github.com/status-im/status-go/multiaccounts/common" 15 "github.com/status-im/status-go/multiaccounts/settings" 16 "github.com/status-im/status-go/protocol/common" 17 "github.com/status-im/status-go/protocol/protobuf" 18 "github.com/status-im/status-go/protocol/requests" 19 v1protocol "github.com/status-im/status-go/protocol/v1" 20 ) 21 22 func TestMessengerContactRequestSuite(t *testing.T) { 23 suite.Run(t, new(MessengerContactRequestSuite)) 24 } 25 26 type MessengerContactRequestSuite struct { 27 MessengerBaseTestSuite 28 } 29 30 func (s *MessengerContactRequestSuite) findFirstByContentType(messages []*common.Message, contentType protobuf.ChatMessage_ContentType) *common.Message { 31 return FindFirstByContentType(messages, contentType) 32 } 33 34 func (s *MessengerContactRequestSuite) sendContactRequest(request *requests.SendContactRequest, messenger *Messenger) { 35 s.logger.Info("sendContactRequest", zap.String("sender", messenger.IdentityPublicKeyString()), zap.String("receiver", request.ID)) 36 37 // Send contact request 38 resp, err := messenger.SendContactRequest(context.Background(), request) 39 s.Require().NoError(err) 40 s.Require().NotNil(resp) 41 42 // Check CR and mutual state update messages 43 s.Require().Len(resp.Messages(), 2) 44 45 mutualStateUpdate := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_SENT) 46 s.Require().NotNil(mutualStateUpdate) 47 48 s.Require().NotNil(mutualStateUpdate.ID) 49 s.Require().Equal(mutualStateUpdate.From, messenger.myHexIdentity()) 50 s.Require().Equal(mutualStateUpdate.ChatId, request.ID) 51 s.Require().Equal(mutualStateUpdate.Text, fmt.Sprintf(outgoingMutualStateEventSentDefaultText, request.ID)) 52 53 contactRequest := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 54 s.Require().NotNil(contactRequest) 55 56 s.Require().Equal(common.ContactRequestStatePending, contactRequest.ContactRequestState) 57 s.Require().Equal(request.Message, contactRequest.Text) 58 59 // Check pending notification 60 s.Require().Len(resp.ActivityCenterNotifications(), 1) 61 s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type) 62 s.Require().Equal(contactRequest.ID, resp.ActivityCenterNotifications()[0].Message.ID) 63 s.Require().Equal(contactRequest.ContactRequestState, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 64 s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, true) 65 66 // Check contacts 67 s.Require().Len(resp.Contacts, 1) 68 contact := resp.Contacts[0] 69 s.Require().False(contact.mutual()) 70 71 // Make sure it's not returned as coming from us 72 contactRequests, _, err := messenger.PendingContactRequests("", 10) 73 s.Require().NoError(err) 74 s.Require().Len(contactRequests, 0) 75 76 // Make sure contact is added on the sender side 77 contacts := messenger.AddedContacts() 78 s.Require().Len(contacts, 1) 79 s.Require().Equal(ContactRequestStateSent, contacts[0].ContactRequestLocalState) 80 s.Require().NotNil(contacts[0].DisplayName) 81 82 // Check contact's primary name matches notification's name 83 s.Require().Equal(resp.ActivityCenterNotifications()[0].Name, contacts[0].PrimaryName()) 84 } 85 86 func (s *MessengerContactRequestSuite) receiveContactRequest(messageText string, theirMessenger *Messenger) *common.Message { 87 s.logger.Info("receiveContactRequest", zap.String("receiver", theirMessenger.IdentityPublicKeyString())) 88 89 // Wait for the message to reach its destination 90 resp, err := WaitOnMessengerResponse( 91 theirMessenger, 92 func(r *MessengerResponse) bool { 93 return len(r.Contacts) == 1 && len(r.Messages()) >= 2 && len(r.ActivityCenterNotifications()) == 1 94 }, 95 "no messages", 96 ) 97 98 // Check contact request has been received 99 s.Require().NoError(err) 100 s.Require().NotNil(resp) 101 102 // Check CR and mutual state update messages 103 s.Require().Len(resp.Messages(), 2) 104 105 contactRequest := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 106 s.Require().NotNil(contactRequest) 107 108 s.Require().Equal(common.ContactRequestStatePending, contactRequest.ContactRequestState) 109 s.Require().Equal(messageText, contactRequest.Text) 110 111 mutualStateUpdate := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_SENT) 112 s.Require().NotNil(mutualStateUpdate) 113 114 s.Require().Equal(mutualStateUpdate.From, contactRequest.From) 115 s.Require().Equal(mutualStateUpdate.ChatId, contactRequest.From) 116 s.Require().Equal(mutualStateUpdate.Text, fmt.Sprintf(incomingMutualStateEventSentDefaultText, contactRequest.From)) 117 118 // Check activity center notification is of the right type 119 s.Require().Len(resp.ActivityCenterNotifications(), 1) 120 s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type) 121 s.Require().Equal(contactRequest.ID, resp.ActivityCenterNotifications()[0].Message.ID) 122 s.Require().Equal(contactRequest.ContactRequestState, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 123 s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, false) 124 s.Require().Equal(resp.ActivityCenterNotifications()[0].Accepted, false) 125 s.Require().Equal(resp.ActivityCenterNotifications()[0].Dismissed, false) 126 127 notifications, err := theirMessenger.ActivityCenterNotifications(ActivityCenterNotificationsRequest{ 128 Cursor: "", 129 Limit: 10, 130 ActivityTypes: []ActivityCenterType{ActivityCenterNotificationTypeContactRequest}, 131 ReadType: ActivityCenterQueryParamsReadUnread, 132 }, 133 ) 134 s.Require().NoError(err) 135 s.Require().Len(notifications.Notifications, 1) 136 s.Require().Equal(contactRequest.ID, notifications.Notifications[0].Message.ID) 137 s.Require().Equal(contactRequest.ContactRequestState, notifications.Notifications[0].Message.ContactRequestState) 138 139 // Check the contact state is correctly set 140 s.Require().Len(resp.Contacts, 1) 141 contact := resp.Contacts[0] 142 s.Require().Equal(ContactRequestStateReceived, contact.ContactRequestRemoteState) 143 144 // Check contact's primary name matches notification's name 145 s.Require().Equal(resp.ActivityCenterNotifications()[0].Name, contact.PrimaryName()) 146 147 // Make sure it's the latest pending contact requests 148 contactRequests, _, err := theirMessenger.PendingContactRequests("", 10) 149 s.Require().NoError(err) 150 s.Require().Greater(len(contactRequests), 0) 151 s.Require().Equal(contactRequests[0].ID, contactRequest.ID) 152 153 // Confirm latest pending contact request 154 resp, err = theirMessenger.GetLatestContactRequestForContact(contactRequest.From) 155 s.Require().NoError(err) 156 s.Require().Len(resp.Messages(), 1) 157 s.Require().Equal(contactRequest.ID, resp.Messages()[0].ID) 158 s.Require().Equal(common.ContactRequestStatePending, resp.Messages()[0].ContactRequestState) 159 160 return contactRequest 161 } 162 163 // This function partially logs given MessengerResponse with description. 164 // This is helpful for testing response content during long tests. 165 // Logged contents: Messages, Contacts, ActivityCenterNotifications 166 func (s *MessengerContactRequestSuite) logResponse(response *MessengerResponse, description string) { 167 s.logger.Debug("MessengerResponse", zap.String("description", description)) 168 169 for i, message := range response.Messages() { 170 s.logger.Debug("message", 171 zap.Int("index", i), 172 zap.String("Text", message.Text), 173 zap.Any("ContentType", message.ContentType), 174 ) 175 } 176 177 for i, contact := range response.Contacts { 178 s.logger.Debug("contact", 179 zap.Int("index", i), 180 zap.Bool("Blocked", contact.Blocked), 181 zap.Bool("Removed", contact.Removed), 182 zap.Any("crRemoteState", contact.ContactRequestLocalState), 183 zap.Any("crLocalState", contact.ContactRequestRemoteState), 184 ) 185 } 186 187 for i, notification := range response.ActivityCenterNotifications() { 188 messageText := "" 189 if notification.Message != nil { 190 messageText = notification.Message.Text 191 } 192 s.logger.Debug("acNotification", 193 zap.Int("index", i), 194 zap.Any("id", notification.ID), 195 zap.Any("Type", notification.Type), 196 zap.String("Message", messageText), 197 zap.String("Name", notification.Name), 198 zap.String("Author", notification.Author), 199 ) 200 } 201 } 202 203 func (s *MessengerContactRequestSuite) acceptContactRequest( 204 contactRequest *common.Message, sender *Messenger, receiver *Messenger) { 205 s.logger.Info("acceptContactRequest", 206 zap.String("sender", sender.IdentityPublicKeyString()), 207 zap.String("receiver", receiver.IdentityPublicKeyString())) 208 209 // Accept contact request, receiver side 210 resp, err := receiver.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: types.Hex2Bytes(contactRequest.ID)}) 211 s.Require().NoError(err) 212 213 // Chack updated contact request message and mutual state update 214 s.Require().NotNil(resp) 215 s.Require().Len(resp.Messages(), 2) 216 217 contactRequestMsg := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 218 s.Require().NotNil(contactRequestMsg) 219 220 mutualStateUpdate := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_ACCEPTED) 221 s.Require().NotNil(mutualStateUpdate) 222 223 s.Require().Equal(contactRequestMsg.ID, contactRequest.ID) 224 s.Require().Equal(common.ContactRequestStateAccepted, contactRequestMsg.ContactRequestState) 225 226 s.Require().Equal(mutualStateUpdate.ChatId, contactRequestMsg.From) 227 s.Require().Equal(mutualStateUpdate.From, contactRequestMsg.ChatId) 228 s.Require().Equal(mutualStateUpdate.Text, fmt.Sprintf(outgoingMutualStateEventAcceptedDefaultText, contactRequestMsg.From)) 229 230 s.Require().Len(resp.ActivityCenterNotifications(), 1) 231 s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequest.ID) 232 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 233 s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 234 235 // Check the contact state is correctly set 236 s.Require().Len(resp.Contacts, 1) 237 s.Require().True(resp.Contacts[0].mutual()) 238 239 // Check contact's primary name matches notification's name 240 s.Require().Equal(resp.ActivityCenterNotifications()[0].Name, resp.Contacts[0].PrimaryName()) 241 242 // Check we have active chat in the response 243 s.Require().Len(resp.Chats(), 1) 244 s.Require().True(resp.Chats()[0].Active) 245 246 // Make sure the sender is added to our contacts 247 contacts := receiver.AddedContacts() 248 s.Require().Len(contacts, 1) 249 250 // Make sure we consider them a mutual contact, receiver side 251 mutualContacts := receiver.MutualContacts() 252 s.Require().Len(mutualContacts, 1) 253 254 // Confirm latest pending contact request 255 resp, err = receiver.GetLatestContactRequestForContact(sender.IdentityPublicKeyString()) 256 s.Require().NoError(err) 257 s.Require().Len(resp.Messages(), 1) 258 s.Require().Equal(contactRequest.ID, resp.Messages()[0].ID) 259 s.Require().Equal(common.ContactRequestStateAccepted, resp.Messages()[0].ContactRequestState) 260 261 // Wait for the message to reach its destination 262 resp, err = WaitOnMessengerResponse(sender, 263 func(r *MessengerResponse) bool { 264 return len(r.Contacts) == 1 && len(r.Messages()) == 2 265 }, 266 "contact request acceptance not received", 267 ) 268 s.logResponse(resp, "acceptContactRequest") 269 s.Require().NoError(err) 270 s.Require().NotNil(resp) 271 272 // Check activity center notification is of the right type 273 s.Require().Len(resp.ActivityCenterNotifications(), 1) 274 s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type) 275 s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 276 s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, true) 277 s.Require().Equal(resp.ActivityCenterNotifications()[0].Accepted, true) 278 s.Require().Equal(resp.ActivityCenterNotifications()[0].Dismissed, false) 279 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 280 281 // Make sure the message is updated, sender side 282 s.Require().Len(resp.Messages(), 2) 283 284 contactRequestMsg = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 285 s.Require().NotNil(contactRequestMsg) 286 287 mutualStateUpdate = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_ACCEPTED) 288 s.Require().NotNil(mutualStateUpdate) 289 290 s.Require().Equal(contactRequest.ID, contactRequestMsg.ID) 291 s.Require().Equal(contactRequest.Text, contactRequestMsg.Text) 292 s.Require().Equal(common.ContactRequestStateAccepted, contactRequestMsg.ContactRequestState) 293 294 s.Require().Equal(mutualStateUpdate.From, contactRequestMsg.ChatId) 295 s.Require().Equal(mutualStateUpdate.ChatId, contactRequestMsg.ChatId) 296 s.Require().Equal(mutualStateUpdate.Text, fmt.Sprintf(incomingMutualStateEventAcceptedDefaultText, contactRequestMsg.ChatId)) 297 298 // Make sure we consider them a mutual contact, sender side 299 mutualContacts = s.m.MutualContacts() 300 s.Require().Len(mutualContacts, 1) 301 302 // Check the contact state is correctly set 303 s.Require().Len(resp.Contacts, 1) 304 contact := resp.Contacts[0] 305 s.Require().True(contact.mutual()) 306 307 // Check contact's primary name matches notification's name 308 s.Require().Equal(resp.ActivityCenterNotifications()[0].Name, contact.PrimaryName()) 309 310 // Sender's side chat should be active after the accepting the CR 311 chat, ok := s.m.allChats.Load(contact.ID) 312 s.Require().True(ok) 313 s.Require().NotNil(chat) 314 s.Require().True(chat.Active) 315 316 // Receiver's side chat should be also active after the accepting the CR 317 myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 318 chat, ok = receiver.allChats.Load(myID) 319 s.Require().True(ok) 320 s.Require().NotNil(chat) 321 s.Require().True(chat.Active) 322 } 323 324 func (s *MessengerContactRequestSuite) checkMutualContact(messenger *Messenger, contactPublicKey string) { 325 contacts := messenger.AddedContacts() 326 s.Require().Len(contacts, 1) 327 contact := contacts[0] 328 s.Require().Equal(contactPublicKey, contact.ID) 329 s.Require().True(contact.mutual()) 330 } 331 332 func (s *MessengerContactRequestSuite) createContactRequest(contactPublicKey string, messageText string) *requests.SendContactRequest { 333 return &requests.SendContactRequest{ 334 ID: contactPublicKey, 335 Message: messageText, 336 } 337 } 338 339 func (s *MessengerContactRequestSuite) declineContactRequest(contactRequest *common.Message, theirMessenger *Messenger) { 340 // Dismiss contact request, receiver side 341 resp, err := theirMessenger.DeclineContactRequest(context.Background(), &requests.DeclineContactRequest{ID: types.Hex2Bytes(contactRequest.ID)}) 342 s.Require().NoError(err) 343 344 // Check the contact state is correctly set 345 s.Require().Len(resp.Contacts, 1) 346 s.Require().Equal(ContactRequestStateDismissed, resp.Contacts[0].ContactRequestLocalState) 347 348 // Make sure the message is updated 349 s.Require().NotNil(resp) 350 s.Require().Len(resp.Messages(), 1) 351 s.Require().Equal(resp.Messages()[0].ID, contactRequest.ID) 352 s.Require().Equal(common.ContactRequestStateDismissed, resp.Messages()[0].ContactRequestState) 353 354 s.Require().Len(resp.ActivityCenterNotifications(), 1) 355 s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequest.ID) 356 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 357 s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, true) 358 s.Require().Equal(resp.ActivityCenterNotifications()[0].Accepted, false) 359 s.Require().Equal(resp.ActivityCenterNotifications()[0].Dismissed, true) 360 s.Require().Equal(common.ContactRequestStateDismissed, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 361 362 // Check contact's primary name matches notification's name 363 s.Require().Equal(resp.ActivityCenterNotifications()[0].Name, resp.Contacts[0].PrimaryName()) 364 365 // Make sure the sender is not added to our contacts 366 contacts := theirMessenger.AddedContacts() 367 s.Require().Len(contacts, 0) 368 } 369 370 func (s *MessengerContactRequestSuite) retractContactRequest(contactID string, theirMessenger *Messenger) { 371 resp, err := s.m.RetractContactRequest(&requests.RetractContactRequest{ID: types.Hex2Bytes(contactID)}) 372 s.Require().NoError(err) 373 s.Require().NotNil(resp) 374 s.Require().Len(resp.Contacts, 1) 375 s.Require().False(resp.Contacts[0].hasAddedUs()) 376 s.Require().False(resp.Contacts[0].added()) 377 378 // Check the contact state is correctly set 379 s.Require().Len(resp.Contacts, 1) 380 s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState) 381 s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState) 382 383 // Check outgoing mutual state message 384 s.Require().Len(resp.Messages(), 1) 385 mutualStateUpdate := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_REMOVED) 386 s.Require().NotNil(mutualStateUpdate) 387 388 myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 389 s.Require().Equal(mutualStateUpdate.From, myID) 390 s.Require().Equal(mutualStateUpdate.ChatId, contactID) 391 s.Require().Equal(mutualStateUpdate.Text, fmt.Sprintf(outgoingMutualStateEventRemovedDefaultText, contactID)) 392 393 // Wait for the message to reach its destination 394 resp, err = WaitOnMessengerResponse( 395 theirMessenger, 396 func(r *MessengerResponse) bool { 397 return len(r.Contacts) > 0 && len(r.ActivityCenterNotifications()) == 1 398 }, 399 "no messages", 400 ) 401 s.Require().NoError(err) 402 s.Require().NotNil(resp) 403 s.Require().Len(resp.Contacts, 1) 404 405 s.Require().Equal(myID, resp.Contacts[0].ID) 406 407 s.Require().False(resp.Contacts[0].added()) 408 s.Require().False(resp.Contacts[0].hasAddedUs()) 409 s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState) 410 s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState) 411 412 // Check pending notification 413 s.Require().Len(resp.ActivityCenterNotifications(), 1) 414 s.Require().Equal(ActivityCenterNotificationTypeContactRemoved, resp.ActivityCenterNotifications()[0].Type) 415 s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, false) 416 417 // Check incoming mutual state message 418 s.Require().Len(resp.Messages(), 1) 419 mutualStateUpdate = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_REMOVED) 420 s.Require().NotNil(mutualStateUpdate) 421 422 s.Require().Equal(mutualStateUpdate.From, myID) 423 s.Require().Equal(mutualStateUpdate.ChatId, myID) 424 s.Require().Equal(mutualStateUpdate.Text, fmt.Sprintf(incomingMutualStateEventRemovedDefaultText, myID)) 425 } 426 427 func (s *MessengerContactRequestSuite) syncInstallationContactV2FromContact(contact *Contact) protobuf.SyncInstallationContactV2 { 428 return protobuf.SyncInstallationContactV2{ 429 LastUpdatedLocally: contact.LastUpdatedLocally, 430 LastUpdated: contact.LastUpdated, 431 Id: contact.ID, 432 DisplayName: contact.DisplayName, 433 EnsName: contact.EnsName, 434 LocalNickname: contact.LocalNickname, 435 Added: contact.added(), 436 Blocked: contact.Blocked, 437 Muted: false, 438 HasAddedUs: contact.hasAddedUs(), 439 Removed: contact.Removed, 440 ContactRequestLocalState: int64(contact.ContactRequestLocalState), 441 ContactRequestRemoteState: int64(contact.ContactRequestRemoteState), 442 ContactRequestRemoteClock: int64(contact.ContactRequestRemoteClock), 443 ContactRequestLocalClock: int64(contact.ContactRequestLocalClock), 444 VerificationStatus: int64(contact.VerificationStatus), 445 TrustStatus: int64(contact.TrustStatus), 446 } 447 } 448 449 func (s *MessengerContactRequestSuite) TestReceiveAndAcceptContactRequest() { //nolint: unused 450 messageText := "hello!" 451 452 theirMessenger := s.newMessenger() 453 defer TearDownMessenger(&s.Suite, theirMessenger) 454 455 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 456 request := &requests.SendContactRequest{ 457 ID: contactID, 458 Message: messageText, 459 } 460 s.sendContactRequest(request, s.m) 461 contactRequest := s.receiveContactRequest(messageText, theirMessenger) 462 s.acceptContactRequest(contactRequest, s.m, theirMessenger) 463 } 464 465 func (s *MessengerContactRequestSuite) TestReceiveAndDismissContactRequest() { 466 messageText := "hello!" 467 468 theirMessenger := s.newMessenger() 469 defer TearDownMessenger(&s.Suite, theirMessenger) 470 471 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 472 request := &requests.SendContactRequest{ 473 ID: contactID, 474 Message: messageText, 475 } 476 s.sendContactRequest(request, s.m) 477 contactRequest := s.receiveContactRequest(messageText, theirMessenger) 478 s.declineContactRequest(contactRequest, theirMessenger) 479 } 480 481 func (s *MessengerContactRequestSuite) TestReceiveAcceptAndRetractContactRequest() { //nolint: unused 482 messageText := "hello!" 483 484 theirMessenger := s.newMessenger() 485 defer TearDownMessenger(&s.Suite, theirMessenger) 486 487 s.Require().NoError(theirMessenger.settings.SaveSettingField(settings.MutualContactEnabled, true)) 488 489 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 490 request := &requests.SendContactRequest{ 491 ID: contactID, 492 Message: messageText, 493 } 494 s.sendContactRequest(request, s.m) 495 contactRequest := s.receiveContactRequest(messageText, theirMessenger) 496 s.acceptContactRequest(contactRequest, s.m, theirMessenger) 497 s.retractContactRequest(contactID, theirMessenger) 498 } 499 500 // The scenario tested is as follow: 501 // 1. Repeat 5 times: 502 // 2.1) Alice sends a contact request to Bob 503 // 2.2) Bob accepts the contact request 504 // 2.3) Alice removes bob from contacts 505 func (s *MessengerContactRequestSuite) TestAcceptCRRemoveAndRepeat() { 506 theirMessenger := s.newMessenger() 507 defer TearDownMessenger(&s.Suite, theirMessenger) 508 509 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 510 511 for i := 0; i < 5; i++ { 512 messageText := fmt.Sprintf("hello %d", i) 513 request := &requests.SendContactRequest{ 514 ID: contactID, 515 Message: messageText, 516 } 517 s.sendContactRequest(request, s.m) 518 contactRequest := s.receiveContactRequest(messageText, theirMessenger) 519 s.acceptContactRequest(contactRequest, s.m, theirMessenger) 520 s.retractContactRequest(contactID, theirMessenger) 521 } 522 } 523 524 // The scenario tested is as follow: 525 // 1) Alice sends a contact request to Bob 526 // 2) Bob declines the contact request 527 // 3) Alice fails to send a new contact request to Bob 528 func (s *MessengerContactRequestSuite) TestAliceTriesToSpamBobWithContactRequests() { 529 messageTextAlice := "You wanna play with fire, Bobby?!" 530 alice := s.m 531 532 bob := s.newMessenger() 533 defer TearDownMessenger(&s.Suite, bob) 534 535 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 536 537 // Alice sends a contact request to Bob 538 request := &requests.SendContactRequest{ 539 ID: bobID, 540 Message: messageTextAlice, 541 } 542 s.sendContactRequest(request, alice) 543 544 contactRequest := s.receiveContactRequest(messageTextAlice, bob) 545 s.Require().NotNil(contactRequest) 546 547 // Bob declines the contact request 548 s.declineContactRequest(contactRequest, bob) 549 550 // Alice sends a new contact request 551 resp, err := alice.SendContactRequest(context.Background(), request) 552 s.Require().NoError(err) 553 s.Require().NotNil(resp) 554 555 // Check CR and mutual state update messages 556 s.Require().Len(resp.Messages(), 2) 557 558 contactRequest = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 559 s.Require().NotNil(contactRequest) 560 561 s.Require().Equal(common.ContactRequestStatePending, contactRequest.ContactRequestState) 562 s.Require().Equal(request.Message, contactRequest.Text) 563 564 // We should not receive a CR from a rejected contact 565 _, err = WaitOnMessengerResponse( 566 bob, 567 func(r *MessengerResponse) bool { 568 return len(r.Messages()) > 0 && 569 s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) != nil 570 }, 571 "no messages", 572 ) 573 s.Require().Error(err) 574 s.Require().ErrorContains(err, "no messages") 575 } 576 577 // The scenario tested is as follow: 578 // 1) Alice sends a contact request to Bob 579 // 2) Bob accepts the contact 580 // 3) Bob accepts the contact request (again!) 581 // 4) No extra mesages on Alice's side 582 func (s *MessengerContactRequestSuite) TestAliceSeesOnlyOneAcceptFromBob() { 583 messageTextAlice := "You wanna play with fire, Bobby?!" 584 alice := s.m 585 586 bob := s.newMessenger() 587 defer TearDownMessenger(&s.Suite, bob) 588 589 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 590 591 // Alice sends a contact request to Bob 592 request := &requests.SendContactRequest{ 593 ID: bobID, 594 Message: messageTextAlice, 595 } 596 s.sendContactRequest(request, alice) 597 598 contactRequest := s.receiveContactRequest(messageTextAlice, bob) 599 s.Require().NotNil(contactRequest) 600 601 // Bob accepts the contact request 602 s.acceptContactRequest(contactRequest, alice, bob) 603 604 // Accept contact request again 605 _, err := bob.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: types.Hex2Bytes(contactRequest.ID)}) 606 s.Require().NoError(err) 607 608 // Check we don't have extra messages on Alice's side 609 resp, err := WaitOnMessengerResponse(alice, 610 func(r *MessengerResponse) bool { 611 return len(r.ActivityCenterNotifications()) == 1 && len(r.Messages()) == 1 612 }, 613 "contact request acceptance not received", 614 ) 615 s.Require().NoError(err) 616 s.Require().NotNil(resp) 617 618 // Check activity center notification is of the right type 619 s.Require().Len(resp.ActivityCenterNotifications(), 1) 620 s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type) 621 s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 622 s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, true) 623 s.Require().Equal(resp.ActivityCenterNotifications()[0].Accepted, true) 624 s.Require().Equal(resp.ActivityCenterNotifications()[0].Dismissed, false) 625 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 626 627 // Make sure the message is updated, sender side 628 s.Require().Len(resp.Messages(), 1) 629 630 contactRequest = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 631 s.Require().NotNil(contactRequest) 632 633 s.Require().Equal(common.ContactRequestStateAccepted, contactRequest.ContactRequestState) 634 s.Require().Equal(request.Message, contactRequest.Text) 635 } 636 637 func (s *MessengerContactRequestSuite) TestReceiveAndAcceptContactRequestTwice() { //nolint: unused 638 messageText := "hello!" 639 640 theirMessenger := s.newMessenger() 641 defer TearDownMessenger(&s.Suite, theirMessenger) 642 643 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 644 request := &requests.SendContactRequest{ 645 ID: contactID, 646 Message: messageText, 647 } 648 s.sendContactRequest(request, s.m) 649 contactRequest := s.receiveContactRequest(messageText, theirMessenger) 650 s.acceptContactRequest(contactRequest, s.m, theirMessenger) 651 652 // Resend contact request with higher clock value 653 resp, err := s.m.SendContactRequest(context.Background(), request) 654 s.Require().NoError(err) 655 s.Require().NotNil(resp) 656 657 // Check CR and mutual state update messages 658 s.Require().Len(resp.Messages(), 2) 659 660 contactRequest = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 661 s.Require().NotNil(contactRequest) 662 663 s.Require().Equal(common.ContactRequestStateAccepted, contactRequest.ContactRequestState) 664 s.Require().Equal(request.Message, contactRequest.Text) 665 666 // We should not receive a CR from a mutual contact 667 _, err = WaitOnMessengerResponse( 668 theirMessenger, 669 func(r *MessengerResponse) bool { 670 return len(r.Messages()) > 0 && 671 s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) != nil 672 }, 673 "no messages", 674 ) 675 s.Require().Error(err) 676 s.Require().ErrorContains(err, "no messages") 677 } 678 679 func (s *MessengerContactRequestSuite) TestAcceptLatestContactRequestForContact() { 680 messageText := "hello!" 681 682 theirMessenger := s.newMessenger() 683 defer TearDownMessenger(&s.Suite, theirMessenger) 684 685 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 686 request := &requests.SendContactRequest{ 687 ID: contactID, 688 Message: messageText, 689 } 690 s.sendContactRequest(request, s.m) 691 contactRequest := s.receiveContactRequest(messageText, theirMessenger) 692 693 // Accept latest contact request, receiver side 694 myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 695 resp, err := theirMessenger.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(myID)}) 696 s.Require().NoError(err) 697 698 // Make sure the message is updated 699 s.Require().NotNil(resp) 700 s.Require().Len(resp.Messages(), 2) 701 702 contactRequestMsg := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 703 s.Require().NotNil(contactRequestMsg) 704 705 mutualStateUpdate := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_ACCEPTED) 706 s.Require().NotNil(mutualStateUpdate) 707 708 s.Require().Equal(contactRequestMsg.ID, contactRequest.ID) 709 s.Require().Equal(common.ContactRequestStateAccepted, contactRequestMsg.ContactRequestState) 710 711 s.Require().Equal(mutualStateUpdate.From, contactRequest.ChatId) 712 s.Require().Equal(mutualStateUpdate.ChatId, contactRequest.From) 713 714 s.Require().Len(resp.ActivityCenterNotifications(), 1) 715 s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequest.ID) 716 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 717 s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 718 719 // Check the contact state is correctly set 720 s.Require().Len(resp.Contacts, 1) 721 s.Require().True(resp.Contacts[0].mutual()) 722 723 // Make sure the sender is added to our contacts 724 contacts := theirMessenger.AddedContacts() 725 s.Require().Len(contacts, 1) 726 727 // Make sure we consider them a mutual contact, receiver side 728 mutualContacts := theirMessenger.MutualContacts() 729 s.Require().Len(mutualContacts, 1) 730 731 // Wait for the message to reach its destination 732 resp, err = WaitOnMessengerResponse( 733 s.m, 734 func(r *MessengerResponse) bool { 735 return len(r.Contacts) == 1 && len(r.Messages()) == 2 && len(r.ActivityCenterNotifications()) == 1 736 }, 737 "no messages", 738 ) 739 s.Require().NoError(err) 740 741 // Make sure the message is updated, sender side 742 s.Require().NotNil(resp) 743 744 s.Require().Len(resp.Messages(), 2) 745 746 contactRequestMsg = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 747 s.Require().NotNil(contactRequestMsg) 748 749 mutualStateUpdate = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_ACCEPTED) 750 s.Require().NotNil(mutualStateUpdate) 751 752 s.Require().Equal(common.ContactRequestStateAccepted, contactRequestMsg.ContactRequestState) 753 754 s.Require().Equal(mutualStateUpdate.From, contactRequest.ChatId) 755 s.Require().Equal(mutualStateUpdate.ChatId, contactRequest.ChatId) 756 757 // Check activity center notification is of the right type 758 s.Require().Len(resp.ActivityCenterNotifications(), 1) 759 s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type) 760 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 761 s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 762 763 // Make sure we consider them a mutual contact, sender side 764 mutualContacts = s.m.MutualContacts() 765 s.Require().Len(mutualContacts, 1) 766 767 // Check the contact state is correctly set 768 s.Require().Len(resp.Contacts, 1) 769 s.Require().True(resp.Contacts[0].mutual()) 770 } 771 772 func (s *MessengerContactRequestSuite) TestDismissLatestContactRequestForContact() { 773 messageText := "hello!" 774 775 theirMessenger := s.newMessenger() 776 defer TearDownMessenger(&s.Suite, theirMessenger) 777 778 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 779 request := &requests.SendContactRequest{ 780 ID: contactID, 781 Message: messageText, 782 } 783 s.sendContactRequest(request, s.m) 784 contactRequest := s.receiveContactRequest(messageText, theirMessenger) 785 786 // Dismiss latest contact request, receiver side 787 myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 788 resp, err := theirMessenger.DismissLatestContactRequestForContact(context.Background(), &requests.DismissLatestContactRequestForContact{ID: types.Hex2Bytes(myID)}) 789 s.Require().NoError(err) 790 791 // Make sure the message is updated 792 s.Require().NotNil(resp) 793 s.Require().Len(resp.Messages(), 1) 794 s.Require().Equal(resp.Messages()[0].ID, contactRequest.ID) 795 s.Require().Equal(common.ContactRequestStateDismissed, resp.Messages()[0].ContactRequestState) 796 797 s.Require().Len(resp.ActivityCenterNotifications(), 1) 798 s.Require().Equal(resp.ActivityCenterNotifications()[0].ID.String(), contactRequest.ID) 799 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 800 s.Require().Equal(common.ContactRequestStateDismissed, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 801 } 802 803 func (s *MessengerContactRequestSuite) TestPairedDevicesRemoveContact() { 804 messageText := "hello!" 805 806 alice1 := s.m 807 alice2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, nil) 808 s.Require().NoError(err) 809 defer TearDownMessenger(&s.Suite, alice2) 810 811 prepAliceMessengersForPairing(&s.Suite, alice1, alice2) 812 813 PairDevices(&s.Suite, alice1, alice2) 814 PairDevices(&s.Suite, alice2, alice1) 815 816 bob := s.newMessenger() 817 defer TearDownMessenger(&s.Suite, bob) 818 819 // Alice sends a contact request to bob 820 contactID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 821 request := &requests.SendContactRequest{ 822 ID: contactID, 823 Message: messageText, 824 } 825 s.sendContactRequest(request, alice1) 826 contactRequest := s.receiveContactRequest(messageText, bob) 827 s.acceptContactRequest(contactRequest, alice1, bob) 828 829 // Wait for the message to reach its destination 830 resp, err := WaitOnMessengerResponse( 831 alice2, 832 func(r *MessengerResponse) bool { 833 return len(r.Contacts) > 0 834 }, 835 "no messages", 836 ) 837 s.Require().NoError(err) 838 839 // Make sure we consider them a mutual contact, sender side 840 mutualContacts := alice2.MutualContacts() 841 s.Require().Len(mutualContacts, 1) 842 843 // Check the contact state is correctly set 844 s.Require().Len(resp.Contacts, 1) 845 s.Require().True(resp.Contacts[0].mutual()) 846 847 s.retractContactRequest(contactID, bob) 848 849 // Check on alice2 side 850 resp, err = WaitOnMessengerResponse( 851 alice2, 852 func(r *MessengerResponse) bool { 853 return len(r.Contacts) > 0 854 }, 855 "no messages", 856 ) 857 s.Require().NoError(err) 858 s.Require().NotNil(resp) 859 s.Require().Len(resp.Contacts, 1) 860 861 // Check the contact state is correctly set 862 s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState) 863 s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestRemoteState) 864 } 865 866 // The scenario tested is as follow: 867 // 1) Alice sends a contact request to Bob 868 // 2) Bob accepts the contact request 869 // 3) Alice restores state on a different device 870 // 4) Alice sends a contact request to bob 871 // Bob will need to help Alice recover her state, since as far as he can see 872 // that's an already accepted contact request 873 func (s *MessengerContactRequestSuite) TestAliceRecoverStateSendContactRequest() { 874 messageText := "hello!" 875 876 alice1 := s.m 877 878 bob := s.newMessenger() 879 defer TearDownMessenger(&s.Suite, bob) 880 881 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 882 883 // Alice sends a contact request to bob 884 request := &requests.SendContactRequest{ 885 ID: bobID, 886 Message: messageText, 887 } 888 s.sendContactRequest(request, alice1) 889 890 contactRequest := s.receiveContactRequest(messageText, bob) 891 s.Require().NotNil(contactRequest) 892 893 // Bob accepts the contact request 894 s.acceptContactRequest(contactRequest, alice1, bob) 895 896 // Alice resets her device 897 alice2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, nil) 898 s.Require().NoError(err) 899 defer TearDownMessenger(&s.Suite, alice2) 900 901 // adds bob again to her device 902 s.sendContactRequest(request, alice2) 903 904 // Wait for the message to reach its destination 905 _, err = WaitOnMessengerResponse( 906 bob, 907 func(r *MessengerResponse) bool { 908 return len(r.Contacts) > 0 909 }, 910 "no messages", 911 ) 912 s.Require().NoError(err) 913 914 // Bob should be a mutual contact with alice, nothing has changed 915 s.Require().Len(bob.MutualContacts(), 1) 916 917 // Alice retrieves her messages, she should have been notified by 918 // dear bobby that they were contacts 919 resp, err := WaitOnMessengerResponse( 920 alice2, 921 func(r *MessengerResponse) bool { 922 return len(r.Contacts) > 0 923 }, 924 "no messages", 925 ) 926 s.Require().NoError(err) 927 s.Require().NotNil(resp) 928 s.Require().Len(resp.Contacts, 1) 929 930 // Check the contact state is correctly set 931 s.Require().True(resp.Contacts[0].mutual()) 932 } 933 934 // The scenario tested is as follow: 935 // 1) Alice sends a contact request to Bob 936 // 2) Bob accepts the contact request 937 // 3) Alice restores state on a different device 938 // 4) Bob sends a message to alice 939 // Alice will show a contact request from bob 940 func (s *MessengerContactRequestSuite) TestAliceRecoverStateReceiveContactRequest() { 941 messageText := "hello!" 942 943 alice1 := s.m 944 945 bob := s.newMessenger() 946 defer TearDownMessenger(&s.Suite, bob) 947 948 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 949 950 // Alice sends a contact request to bob 951 request := &requests.SendContactRequest{ 952 ID: bobID, 953 Message: messageText, 954 } 955 s.sendContactRequest(request, alice1) 956 957 contactRequest := s.receiveContactRequest(messageText, bob) 958 s.Require().NotNil(contactRequest) 959 960 // Bob accepts the contact request 961 s.acceptContactRequest(contactRequest, alice1, bob) 962 963 // Alice resets her device 964 alice2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, nil) 965 s.Require().NoError(err) 966 defer TearDownMessenger(&s.Suite, alice2) 967 968 // We want to facilitate the discovery of the x3dh bundl here, since bob does not know about alice device 969 970 alice2Bundle, err := alice2.encryptor.GetBundle(alice2.identity) 971 s.Require().NoError(err) 972 973 _, err = bob.encryptor.ProcessPublicBundle(bob.identity, alice2Bundle) 974 s.Require().NoError(err) 975 976 // Bob sends a chat message to alice 977 978 var chat Chat 979 chats := bob.Chats() 980 for i, c := range chats { 981 if c.ID == alice1.myHexIdentity() && c.OneToOne() { 982 chat = *chats[i] 983 } 984 } 985 s.Require().NotNil(chat) 986 987 inputMessage := buildTestMessage(chat) 988 _, err = bob.SendChatMessage(context.Background(), inputMessage) 989 s.NoError(err) 990 991 // Alice retrieves the chat message, it should be 992 resp, err := WaitOnMessengerResponse( 993 alice2, 994 func(r *MessengerResponse) bool { 995 return len(r.ActivityCenterNotifications()) == 1 996 }, 997 "no messages", 998 ) 999 s.Require().NoError(err) 1000 s.Require().NotNil(resp) 1001 s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type) 1002 s.Require().Len(resp.Contacts, 1) 1003 1004 // Check the contact state is correctly set 1005 s.Require().Equal(ContactRequestStateNone, resp.Contacts[0].ContactRequestLocalState) 1006 s.Require().Equal(ContactRequestStateReceived, resp.Contacts[0].ContactRequestRemoteState) 1007 } 1008 1009 // The scenario tested is as follow: 1010 // 1) Alice sends a contact request to Bob 1011 // 2) Bob accepts the contact request 1012 // 3) Bob goes offline 1013 // 4) Alice retracts the contact request 1014 // 5) Alice adds bob back to her contacts 1015 // 6) Bob goes online, they receive 4 and 5 in the correct order 1016 func (s *MessengerContactRequestSuite) TestAliceOfflineRetractsAndAddsCorrectOrder() { 1017 messageText := "hello!" 1018 1019 alice1 := s.m 1020 1021 bob := s.newMessenger() 1022 defer TearDownMessenger(&s.Suite, bob) 1023 1024 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 1025 1026 // Alice sends a contact request to bob 1027 request := &requests.SendContactRequest{ 1028 ID: bobID, 1029 Message: messageText, 1030 } 1031 s.sendContactRequest(request, alice1) 1032 1033 contactRequest := s.receiveContactRequest(messageText, bob) 1034 s.Require().NotNil(contactRequest) 1035 1036 // Bob accepts the contact request 1037 s.acceptContactRequest(contactRequest, alice1, bob) 1038 1039 // Alice removes Bob from contacts 1040 _, err := alice1.RetractContactRequest(&requests.RetractContactRequest{ID: types.Hex2Bytes(bob.myHexIdentity())}) 1041 s.Require().NoError(err) 1042 1043 // Adds bob again to her device 1044 s.sendContactRequest(request, alice1) 1045 1046 // Wait for the message to reach its destination 1047 _, err = WaitOnMessengerResponse( 1048 bob, 1049 func(r *MessengerResponse) bool { 1050 return len(r.ActivityCenterNotifications()) > 0 1051 }, 1052 "no messages", 1053 ) 1054 s.Require().NoError(err) 1055 } 1056 1057 // The scenario tested is as follow: 1058 // 1) Alice sends a contact request to Bob 1059 // 2) Bob accepts the contact request 1060 // 3) Bob goes offline 1061 // 4) Alice retracts the contact request 1062 // 5) Alice adds bob back to her contacts 1063 // 6) Bob goes online, they receive 4 and 5 in the wrong order 1064 func (s *MessengerContactRequestSuite) TestAliceOfflineRetractsAndAddsWrongOrder() { 1065 messageText := "hello!" 1066 1067 alice1 := s.m 1068 1069 bob := s.newMessenger() 1070 defer TearDownMessenger(&s.Suite, bob) 1071 1072 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 1073 1074 // Alice sends a contact request to bob 1075 request := &requests.SendContactRequest{ 1076 ID: bobID, 1077 Message: messageText, 1078 } 1079 s.sendContactRequest(request, alice1) 1080 1081 contactRequest := s.receiveContactRequest(messageText, bob) 1082 s.Require().NotNil(contactRequest) 1083 1084 // Bob accepts the contact request 1085 s.acceptContactRequest(contactRequest, alice1, bob) 1086 1087 // Alice removes Bob from contacts 1088 _, err := alice1.RetractContactRequest(&requests.RetractContactRequest{ID: types.Hex2Bytes(bob.myHexIdentity())}) 1089 s.Require().NoError(err) 1090 1091 // Adds bob again to her device 1092 s.sendContactRequest(request, alice1) 1093 1094 // Get alice perspective of bob 1095 bobFromAlice := alice1.AddedContacts()[0] 1096 1097 // Get bob perspective of alice 1098 aliceFromBob := bob.MutualContacts()[0] 1099 1100 s.Require().NotNil(bobFromAlice) 1101 s.Require().NotNil(aliceFromBob) 1102 1103 // We can't simulate out-of-order messages easily, so we need to do 1104 // things manually here 1105 result := aliceFromBob.ContactRequestPropagatedStateReceived(bobFromAlice.ContactRequestPropagatedState()) 1106 s.Require().True(result.newContactRequestReceived) 1107 } 1108 1109 // The scenario tested is as follow: 1110 // 1) Alice sends a contact request to Bob 1111 // 2) Bob accepts the contact request 1112 // 3) Alice removes Bob from contacts 1113 // 4) Make sure Alice and Bob are not mutual contacts 1114 // 5) Alice sends new contact request 1115 // 6) Bob accepts new contact request 1116 func (s *MessengerContactRequestSuite) TestAliceResendsContactRequestAfterRemovingBobFromContacts() { 1117 messageTextFirst := "hello 1!" 1118 1119 theirMessenger := s.newMessenger() 1120 defer TearDownMessenger(&s.Suite, theirMessenger) 1121 1122 contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 1123 1124 // Alice sends a contact request to Bob 1125 request := &requests.SendContactRequest{ 1126 ID: contactID, 1127 Message: messageTextFirst, 1128 } 1129 s.sendContactRequest(request, s.m) 1130 1131 // Bob accepts the contact request 1132 contactRequest := s.receiveContactRequest(messageTextFirst, theirMessenger) 1133 s.Require().NotNil(contactRequest) 1134 s.acceptContactRequest(contactRequest, s.m, theirMessenger) 1135 1136 // Alice removes Bob from contacts 1137 s.retractContactRequest(contactID, theirMessenger) 1138 1139 // Send new contact request 1140 messageTextSecond := "hello 2!" 1141 1142 // Alice sends new contact request 1143 request = &requests.SendContactRequest{ 1144 ID: contactID, 1145 Message: messageTextSecond, 1146 } 1147 s.sendContactRequest(request, s.m) 1148 1149 // Make sure bob and alice are not mutual after sending CR 1150 s.Require().Len(s.m.MutualContacts(), 0) 1151 s.Require().Len(theirMessenger.MutualContacts(), 0) 1152 1153 // Bob accepts new contact request 1154 contactRequest = s.receiveContactRequest(messageTextSecond, theirMessenger) 1155 s.Require().NotNil(contactRequest) 1156 s.acceptContactRequest(contactRequest, s.m, theirMessenger) 1157 1158 // Make sure bob and alice are not mutual after sending CR 1159 s.Require().Len(s.m.MutualContacts(), 1) 1160 s.Require().Len(theirMessenger.MutualContacts(), 1) 1161 } 1162 1163 // The scenario tested is as follow: 1164 // 1) Alice sends a contact request to Bob 1165 // 2) Bob declines the contact request from Alice 1166 // 3) Bob sends a contact request to Alice 1167 // 4) Alice and Bob are mutual contacts (because Alice's CR is "pending" on her side), Both CRs are accepted 1168 func (s *MessengerContactRequestSuite) TestBobSendsContactRequestAfterDecliningOneFromAlice() { 1169 messageTextAlice := "hello, Bobby!" 1170 1171 alice := s.m 1172 1173 bob := s.newMessenger() 1174 defer TearDownMessenger(&s.Suite, bob) 1175 1176 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 1177 1178 // Alice sends a contact request to bob 1179 requestFromAlice := &requests.SendContactRequest{ 1180 ID: bobID, 1181 Message: messageTextAlice, 1182 } 1183 s.sendContactRequest(requestFromAlice, alice) 1184 1185 contactRequest := s.receiveContactRequest(messageTextAlice, bob) 1186 s.Require().NotNil(contactRequest) 1187 1188 // Bob declines the contact request 1189 s.declineContactRequest(contactRequest, bob) 1190 1191 messageTextBob := "hello, Alice!" 1192 1193 aliceID := types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey)) 1194 1195 // Bob sends a contact request to Alice 1196 requestFromBob := &requests.SendContactRequest{ 1197 ID: aliceID, 1198 Message: messageTextBob, 1199 } 1200 1201 // Send contact request 1202 resp, err := bob.SendContactRequest(context.Background(), requestFromBob) 1203 s.Require().NoError(err) 1204 s.Require().NotNil(resp) 1205 1206 // Check CR message, it should be accepted 1207 s.Require().Len(resp.Messages(), 2) 1208 1209 contactRequest = s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 1210 s.Require().NotNil(contactRequest) 1211 1212 s.Require().Equal(common.ContactRequestStateAccepted, contactRequest.ContactRequestState) 1213 s.Require().Equal(requestFromBob.Message, contactRequest.Text) 1214 1215 // Check pending notification 1216 s.Require().Len(resp.ActivityCenterNotifications(), 1) 1217 s.Require().Equal(ActivityCenterNotificationTypeContactRequest, resp.ActivityCenterNotifications()[0].Type) 1218 s.Require().Equal(contactRequest.ID, resp.ActivityCenterNotifications()[0].Message.ID) 1219 s.Require().Equal(contactRequest.ContactRequestState, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 1220 s.Require().Equal(resp.ActivityCenterNotifications()[0].Read, true) 1221 1222 // Check contacts Bob's side 1223 s.Require().Len(resp.Contacts, 1) 1224 contact := resp.Contacts[0] 1225 s.Require().True(contact.mutual()) 1226 } 1227 1228 func (s *MessengerContactRequestSuite) TestBuildContact() { 1229 contactKey, err := crypto.GenerateKey() 1230 s.Require().NoError(err) 1231 contactID := types.EncodeHex(crypto.FromECDSAPub(&contactKey.PublicKey)) 1232 1233 contact, err := s.m.BuildContact(&requests.BuildContact{PublicKey: contactID}) 1234 s.Require().NoError(err) 1235 1236 s.Require().Equal(contact.EnsName, "") 1237 s.Require().False(contact.ENSVerified) 1238 1239 contact, err = s.m.BuildContact(&requests.BuildContact{PublicKey: contactID, ENSName: "foobar"}) 1240 s.Require().NoError(err) 1241 1242 s.Require().Equal(contact.EnsName, "foobar") 1243 s.Require().True(contact.ENSVerified) 1244 } 1245 1246 func (s *MessengerContactRequestSuite) TestReceiveAcceptAndRetractContactRequestOutOfOrder() { 1247 message := protobuf.ChatMessage{ 1248 Clock: 4, 1249 Timestamp: 1, 1250 Text: "some text", 1251 ChatId: common.PubkeyToHex(&s.m.identity.PublicKey), 1252 MessageType: protobuf.MessageType_ONE_TO_ONE, 1253 ContentType: protobuf.ChatMessage_CONTACT_REQUEST, 1254 } 1255 1256 contactKey, err := crypto.GenerateKey() 1257 s.Require().NoError(err) 1258 1259 contact, err := BuildContactFromPublicKey(&contactKey.PublicKey) 1260 s.Require().NoError(err) 1261 1262 state := s.m.buildMessageState() 1263 1264 state.CurrentMessageState = &CurrentMessageState{ 1265 PublicKey: &contactKey.PublicKey, 1266 MessageID: "0xa", 1267 StatusMessage: &v1protocol.StatusMessage{TransportLayer: v1protocol.TransportLayer{Message: &types.Message{Timestamp: 1}}, ApplicationLayer: v1protocol.ApplicationLayer{ID: []byte("test-id")}}, 1268 Contact: contact, 1269 WhisperTimestamp: 1, 1270 } 1271 1272 response := state.Response 1273 err = s.m.HandleChatMessage(state, &message, nil, false) 1274 s.Require().NoError(err) 1275 s.Require().Len(response.ActivityCenterNotifications(), 1) 1276 contacts := s.m.Contacts() 1277 s.Require().Len(contacts, 1) 1278 s.Require().Equal(ContactRequestStateReceived, contacts[0].ContactRequestRemoteState) 1279 1280 retract := protobuf.RetractContactRequest{ 1281 Clock: 2, 1282 } 1283 err = s.m.HandleRetractContactRequest(state, &retract, nil) 1284 s.Require().NoError(err) 1285 1286 // Nothing should have changed 1287 contacts = s.m.Contacts() 1288 s.Require().Len(contacts, 1) 1289 s.Require().Equal(ContactRequestStateReceived, contacts[0].ContactRequestRemoteState) 1290 } 1291 1292 // The scenario tested is as follow: 1293 // 1) Alice sends a contact request to Bob 1294 // 2) Bob receives CR from Alice 1295 // 3) Bob resets his device 1296 // 4) Bob restores Alice's contact from backup, CR is created 1297 // 5) Bob succesefully accepts restored contact request 1298 // 6) Alice get notified properly 1299 func (s *MessengerContactRequestSuite) TestBobRestoresIncomingContactRequestFromSyncInstallationContactV2() { 1300 messageText := "hello, Bobby!" 1301 1302 alice := s.m 1303 alice.account.CustomizationColor = multiaccountscommon.CustomizationColorBeige 1304 1305 bob1 := s.newMessenger() 1306 defer TearDownMessenger(&s.Suite, bob1) 1307 1308 aliceID := types.EncodeHex(crypto.FromECDSAPub(&alice.identity.PublicKey)) 1309 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob1.identity.PublicKey)) 1310 1311 // Alice sends a contact request to bob 1312 requestFromAlice := &requests.SendContactRequest{ 1313 ID: bobID, 1314 Message: messageText, 1315 } 1316 s.sendContactRequest(requestFromAlice, alice) 1317 1318 // Bob receives CR from Alice 1319 contactRequest := s.receiveContactRequest(messageText, bob1) 1320 s.Require().NotNil(contactRequest) 1321 1322 // Bob resets his device 1323 bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil) 1324 s.Require().NoError(err) 1325 defer TearDownMessenger(&s.Suite, bob2) 1326 1327 // Get bob perspective of alice for backup 1328 aliceFromBob := bob1.Contacts()[0] 1329 s.Require().Equal(aliceFromBob.CustomizationColor, alice.account.GetCustomizationColor()) 1330 state := bob2.buildMessageState() 1331 1332 // Restore alice's contact from backup 1333 sync := s.syncInstallationContactV2FromContact(aliceFromBob) 1334 err = bob2.HandleSyncInstallationContactV2(state, &sync, nil) 1335 s.Require().NoError(err) 1336 1337 // Accept latest CR for a contact 1338 resp, err := bob2.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(aliceID)}) 1339 s.Require().NoError(err) 1340 s.Require().Len(resp.Contacts, 1) 1341 1342 // Make sure the message is updated 1343 s.Require().NotNil(resp) 1344 s.Require().Len(resp.Messages(), 2) 1345 1346 contactRequestMsg := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 1347 s.Require().NotNil(contactRequestMsg) 1348 1349 // NOTE: We don't restore CR message 1350 // s.Require().Equal(resp.Messages()[0].ID, contactRequest.ID) 1351 s.Require().Equal(common.ContactRequestStateAccepted, contactRequestMsg.ContactRequestState) 1352 1353 s.Require().Len(resp.ActivityCenterNotifications(), 1) 1354 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 1355 s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 1356 1357 // Check the contact state is correctly set 1358 s.Require().Len(resp.Contacts, 1) 1359 s.Require().True(resp.Contacts[0].mutual()) 1360 1361 // Make sure the sender is added to our contacts 1362 contacts := bob2.AddedContacts() 1363 s.Require().Len(contacts, 1) 1364 1365 // Make sure we consider them a mutual contact, receiver side 1366 mutualContacts := bob2.MutualContacts() 1367 s.Require().Len(mutualContacts, 1) 1368 } 1369 1370 // The scenario tested is as follow: 1371 // 1) Alice sends a contact request to Bob 1372 // 2) Bob receives CR from Alice 1373 // 3) Alice resets her device 1374 // 4) Alice restores Bob's contact from backup, CR is created 1375 // 5) Bob accepts contact request 1376 // 6) Alice get notified properly 1377 func (s *MessengerContactRequestSuite) TestAliceRestoresOutgoingContactRequestFromSyncInstallationContactV2() { 1378 messageText := "hello, Bobby!" 1379 1380 alice1 := s.m 1381 1382 bob := s.newMessenger() 1383 defer TearDownMessenger(&s.Suite, bob) 1384 1385 aliceID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey)) 1386 bobID := types.EncodeHex(crypto.FromECDSAPub(&bob.identity.PublicKey)) 1387 1388 // Alice sends a contact request to bob 1389 requestFromAlice := &requests.SendContactRequest{ 1390 ID: bobID, 1391 Message: messageText, 1392 } 1393 s.sendContactRequest(requestFromAlice, alice1) 1394 1395 // Bob receives CR from Alice 1396 contactRequest := s.receiveContactRequest(messageText, bob) 1397 s.Require().NotNil(contactRequest) 1398 1399 // Bob resets his device 1400 alice2, err := newMessengerWithKey(s.shh, alice1.identity, s.logger, nil) 1401 s.Require().NoError(err) 1402 defer TearDownMessenger(&s.Suite, alice2) 1403 1404 // Get bob perspective of alice for backup 1405 bobFromAlice := alice1.Contacts()[0] 1406 state := alice2.buildMessageState() 1407 1408 // Restore alice's contact from backup 1409 sync := s.syncInstallationContactV2FromContact(bobFromAlice) 1410 err = alice2.HandleSyncInstallationContactV2(state, &sync, nil) 1411 s.Require().NoError(err) 1412 1413 // Accept latest CR for a contact 1414 resp, err := bob.AcceptLatestContactRequestForContact(context.Background(), &requests.AcceptLatestContactRequestForContact{ID: types.Hex2Bytes(aliceID)}) 1415 s.Require().NoError(err) 1416 1417 // Make sure the message is updated 1418 s.Require().NotNil(resp) 1419 s.Require().Len(resp.Messages(), 2) 1420 1421 contactRequestMsg := s.findFirstByContentType(resp.Messages(), protobuf.ChatMessage_CONTACT_REQUEST) 1422 s.Require().NotNil(contactRequestMsg) 1423 1424 // NOTE: We don't restore CR message 1425 // s.Require().Equal(resp.Messages()[0].ID, contactRequest.ID) 1426 s.Require().Equal(common.ContactRequestStateAccepted, contactRequestMsg.ContactRequestState) 1427 1428 s.Require().Len(resp.ActivityCenterNotifications(), 1) 1429 s.Require().NotNil(resp.ActivityCenterNotifications()[0].Message) 1430 s.Require().Equal(common.ContactRequestStateAccepted, resp.ActivityCenterNotifications()[0].Message.ContactRequestState) 1431 1432 // Check the contact state is correctly set 1433 s.Require().Len(resp.Contacts, 1) 1434 s.Require().True(resp.Contacts[0].mutual()) 1435 1436 // Make sure the sender is added to our contacts 1437 contacts := bob.AddedContacts() 1438 s.Require().Len(contacts, 1) 1439 1440 // Make sure we consider them a mutual contact, receiver side 1441 mutualContacts := bob.MutualContacts() 1442 s.Require().Len(mutualContacts, 1) 1443 } 1444 1445 /* 1446 Makes Alice and Bob mutual contacts. 1447 Verifies that Alice device-2 receives mutual contact information. 1448 Contact request is sent from Alice device 1. 1449 */ 1450 func (s *MessengerContactRequestSuite) makeMutualContactsAndSync(alice1 *Messenger, alice2 *Messenger, bob *Messenger, messageText string) { 1451 bobPublicKey := bob.IdentityPublicKeyString() 1452 1453 cr := s.createContactRequest(bobPublicKey, messageText) 1454 s.sendContactRequest(cr, alice1) 1455 receivedCR := s.receiveContactRequest(cr.Message, bob) 1456 s.acceptContactRequest(receivedCR, alice1, bob) 1457 s.checkMutualContact(alice1, bobPublicKey) 1458 1459 // Wait for Alice-2 to sync new contact 1460 resp, _ := WaitOnMessengerResponse(alice2, func(r *MessengerResponse) bool { 1461 // FIXME: https://github.com/status-im/status-go/issues/3803 1462 // No condition here. There are randomly received 1-3 messages. 1463 return false // len(r.Contacts) == 1 && len(r.Messages()) == 3 1464 }, "alice-2 didn't receive bob contact") 1465 s.logResponse(resp, "Wait for Alice-2 to sync new contact") 1466 s.Require().NotNil(resp) 1467 //s.Require().NoError(err) // WARNING: Uncomment when bug fixed. https://github.com/status-im/status-go/issues/3803 1468 1469 // Check that Alice-2 has Bob as a contact 1470 s.Require().Len(alice2.Contacts(), 1) 1471 s.Require().Equal(bobPublicKey, alice2.Contacts()[0].ID) 1472 1473 // TODO: https://github.com/status-im/status-go/issues/3803 1474 // Check response messages and AC notifications when 1475 } 1476 1477 func (s *MessengerContactRequestSuite) blockContactAndSync(alice1 *Messenger, alice2 *Messenger, bob *Messenger) { 1478 bobPublicKey := bob.IdentityPublicKeyString() 1479 bobDisplayName, err := bob.settings.DisplayName() 1480 s.Require().NoError(err) 1481 1482 // Alice-1 blocks Bob 1483 _, err = alice1.BlockContact(context.Background(), bobPublicKey, false) 1484 s.Require().NoError(err) 1485 s.Require().Len(alice1.BlockedContacts(), 1) 1486 s.Require().Equal(bobPublicKey, alice1.BlockedContacts()[0].ID) 1487 1488 // Wait for Bob to receive message that he was removed as contact 1489 resp, err := WaitOnMessengerResponse(bob, func(r *MessengerResponse) bool { 1490 return len(r.Contacts) == 1 && len(r.Messages()) == 1 1491 }, "Bob didn't receive a message that he was removed as contact") 1492 1493 s.Require().NoError(err) 1494 s.Require().NotNil(resp) 1495 s.logResponse(resp, "Wait for Bob to receive message that he was removed as contact") 1496 1497 // Check response contacts 1498 s.Require().Len(resp.Contacts, 1) 1499 respContact := resp.Contacts[0] 1500 s.Require().Equal(respContact.ID, alice1.IdentityPublicKeyString()) 1501 s.Require().Equal(ContactRequestStateNone, respContact.ContactRequestLocalState) 1502 s.Require().Equal(ContactRequestStateNone, respContact.ContactRequestRemoteState) 1503 1504 // Check response messages 1505 s.Require().Len(resp.Messages(), 1) 1506 s.Require().Equal(resp.Messages()[0].Text, fmt.Sprintf(incomingMutualStateEventRemovedDefaultText, alice1.IdentityPublicKeyString())) 1507 1508 // Check response AC notifications 1509 s.Require().Len(resp.ActivityCenterNotifications(), 1) 1510 s.Require().Equal(resp.ActivityCenterNotifications()[0].Type, ActivityCenterNotificationTypeContactRemoved) 1511 1512 alice2.logger.Info("STARTING") 1513 // Wait for Alice-2 to sync Bob blocked state 1514 resp, err = WaitOnMessengerResponse(alice2, func(r *MessengerResponse) bool { 1515 return len(r.Contacts) == 1 1516 }, "Alice-2 didn't receive blocking bob") 1517 s.logResponse(resp, "Wait for Alice-2 to sync Bob blocked state") 1518 s.Require().NoError(err) 1519 s.Require().NotNil(resp) 1520 1521 // Check that Bob contact is synced with correct display name and blocked 1522 s.Require().Len(alice2.Contacts(), 1) 1523 respContact = alice2.Contacts()[0] 1524 s.Require().True(respContact.Blocked) 1525 s.Require().True(respContact.Removed) 1526 s.Require().Equal(bobPublicKey, respContact.ID) 1527 s.Require().Equal(bobDisplayName, respContact.DisplayName) 1528 s.Require().Equal(ContactRequestStateDismissed, respContact.ContactRequestLocalState) 1529 s.Require().Equal(ContactRequestStateReceived, respContact.ContactRequestRemoteState) 1530 1531 // Check chats list 1532 s.Require().Len(alice2.Chats(), deprecation.AddChatsCount(2)) 1533 } 1534 1535 func (s *MessengerContactRequestSuite) unblockContactAndSync(alice1 *Messenger, alice2 *Messenger, bob *Messenger) { 1536 bobPublicKey := bob.IdentityPublicKeyString() 1537 1538 _, err := alice1.UnblockContact(bobPublicKey) 1539 s.Require().NoError(err) 1540 s.Require().Len(alice1.BlockedContacts(), 0) 1541 1542 // Bob doesn't receive any message on blocking. 1543 // No response wait here. 1544 1545 // Wait for Alice-2 to receive Bob unblocked state 1546 resp, err := WaitOnMessengerResponse(alice2, func(r *MessengerResponse) bool { 1547 return len(r.Contacts) == 1 1548 }, "Alice-2 didn't receive Bob unblocked state") 1549 s.logResponse(resp, "Wait for Alice-2 to receive Bob unblocked state") 1550 s.Require().NoError(err) 1551 s.Require().NotNil(resp) 1552 1553 // Check that Alice-2 has Bob unblocked and removed 1554 s.Require().Len(alice2.Contacts(), 1) 1555 respContact := alice2.Contacts()[0] 1556 s.Require().Equal(bobPublicKey, respContact.ID) 1557 s.Require().False(respContact.Blocked) 1558 s.Require().True(respContact.Removed) 1559 s.Require().Equal(respContact.ContactRequestLocalState, ContactRequestStateNone) 1560 s.Require().Equal(respContact.ContactRequestRemoteState, ContactRequestStateNone) 1561 1562 // Check chats list 1563 s.Require().Len(alice2.Chats(), deprecation.AddChatsCount(2)) 1564 } 1565 1566 func (s *MessengerContactRequestSuite) TestBlockedContactSyncing() { 1567 // Setup Bob 1568 bob := s.newMessenger() 1569 defer TearDownMessenger(&s.Suite, bob) 1570 _ = bob.SetDisplayName("bob-1") 1571 s.logger.Info("Bob account set up", zap.String("publicKey", bob.IdentityPublicKeyString())) 1572 1573 // Setup Alice-1 1574 alice1 := s.m 1575 s.logger.Info("Alice account set up", zap.String("publicKey", alice1.IdentityPublicKeyString())) 1576 1577 // Setup Alice-2 1578 alice2, err := newMessengerWithKey(s.shh, s.m.identity, s.logger, nil) 1579 s.Require().NoError(err) 1580 defer TearDownMessenger(&s.Suite, alice2) 1581 1582 // Pair alice-1 <-> alice-2 1583 // NOTE: This doesn't include initial data sync. Local pairing could be used. 1584 s.logger.Info("pairing Alice-1 and Alice-2") 1585 prepAliceMessengersForPairing(&s.Suite, alice1, alice2) 1586 PairDevices(&s.Suite, alice1, alice2) 1587 PairDevices(&s.Suite, alice2, alice1) 1588 s.logger.Info("pairing Alice-1 and Alice-2 finished") 1589 1590 // Loop cr-block-unblock. Some bugs happen at second iteration. 1591 for i := 0; i < 2; i++ { 1592 crText := fmt.Sprintf("hello-%d", i) 1593 s.makeMutualContactsAndSync(alice1, alice2, bob, crText) 1594 s.blockContactAndSync(alice1, alice2, bob) 1595 s.unblockContactAndSync(alice1, alice2, bob) 1596 } 1597 }