github.com/status-im/status-go@v1.1.0/protocol/messenger_test.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "encoding/hex" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io" 10 "math/big" 11 "os" 12 "strings" 13 "testing" 14 "time" 15 16 _ "github.com/mutecomm/go-sqlcipher/v4" // require go-sqlcipher that overrides default implementation 17 "github.com/stretchr/testify/suite" 18 "go.uber.org/zap" 19 20 "github.com/status-im/status-go/deprecation" 21 coretypes "github.com/status-im/status-go/eth-node/core/types" 22 "github.com/status-im/status-go/eth-node/crypto" 23 "github.com/status-im/status-go/eth-node/types" 24 enstypes "github.com/status-im/status-go/eth-node/types/ens" 25 "github.com/status-im/status-go/images" 26 "github.com/status-im/status-go/multiaccounts/settings" 27 "github.com/status-im/status-go/protocol/common" 28 "github.com/status-im/status-go/protocol/protobuf" 29 "github.com/status-im/status-go/protocol/requests" 30 "github.com/status-im/status-go/protocol/tt" 31 v1protocol "github.com/status-im/status-go/protocol/v1" 32 "github.com/status-im/status-go/server" 33 ) 34 35 const ( 36 testPK = "0x0424a68f89ba5fcd5e0640c1e1f591d561fa4125ca4e2a43592bc4123eca10ce064e522c254bb83079ba404327f6eafc01ec90a1444331fe769d3f3a7f90b0dde1" 37 testPublicChatID = "super-chat" 38 testContract = "0x314159265dd8dbb310642f98f50c066173c1259b" 39 testValue = "2000" 40 testTransactionHash = "0x412a851ac2ae51cad34a56c8a9cfee55d577ac5e1ac71cf488a2f2093a373799" 41 newEnsName = "new-name" 42 ) 43 44 func TestMessengerSuite(t *testing.T) { 45 suite.Run(t, new(MessengerSuite)) 46 } 47 48 type MessengerSuite struct { 49 MessengerBaseTestSuite 50 } 51 52 type testNode struct { 53 shh types.Waku 54 } 55 56 func (n *testNode) NewENSVerifier(_ *zap.Logger) enstypes.ENSVerifier { 57 panic("not implemented") 58 } 59 60 func (n *testNode) AddPeer(_ string) error { 61 panic("not implemented") 62 } 63 64 func (n *testNode) RemovePeer(_ string) error { 65 panic("not implemented") 66 } 67 68 func (n *testNode) GetWaku(_ interface{}) (types.Waku, error) { 69 return n.shh, nil 70 } 71 72 func (n *testNode) GetWakuV2(_ interface{}) (types.Waku, error) { 73 return nil, errors.New("No waku v2 support") 74 } 75 76 func (n *testNode) GetWhisper(_ interface{}) (types.Whisper, error) { 77 return nil, nil 78 } 79 80 func (n *testNode) PeersCount() int { 81 return 1 82 } 83 84 func (s *MessengerSuite) TestInitFilters() { 85 testCases := []struct { 86 Name string 87 Prep func() 88 AddedFilters int 89 }{ 90 { 91 Name: "no chats and contacts", 92 Prep: func() {}, 93 AddedFilters: 3, 94 }, 95 { 96 Name: "active public chat", 97 Prep: func() { 98 publicChat := Chat{ 99 ChatType: ChatTypePublic, 100 ID: "some-public-chat", 101 Active: true, 102 } 103 err := s.m.SaveChat(&publicChat) 104 s.Require().NoError(err) 105 }, 106 AddedFilters: 1, 107 }, 108 { 109 Name: "active one-to-one chat", 110 Prep: func() { 111 key, err := crypto.GenerateKey() 112 s.Require().NoError(err) 113 privateChat := Chat{ 114 ID: types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey)), 115 ChatType: ChatTypeOneToOne, 116 Active: true, 117 } 118 err = s.m.SaveChat(&privateChat) 119 s.Require().NoError(err) 120 }, 121 AddedFilters: 1, 122 }, 123 { 124 Name: "active group chat", 125 Prep: func() { 126 key1, err := crypto.GenerateKey() 127 s.Require().NoError(err) 128 key2, err := crypto.GenerateKey() 129 s.Require().NoError(err) 130 groupChat := Chat{ 131 ID: "some-id", 132 ChatType: ChatTypePrivateGroupChat, 133 Active: true, 134 Members: []ChatMember{ 135 { 136 ID: types.EncodeHex(crypto.FromECDSAPub(&key1.PublicKey)), 137 }, 138 { 139 ID: types.EncodeHex(crypto.FromECDSAPub(&key2.PublicKey)), 140 }, 141 }, 142 } 143 err = s.m.SaveChat(&groupChat) 144 s.Require().NoError(err) 145 }, 146 AddedFilters: 2, 147 }, 148 { 149 Name: "inactive chat", 150 Prep: func() { 151 publicChat := Chat{ 152 ChatType: ChatTypePublic, 153 ID: "some-public-chat-2", 154 Active: false, 155 } 156 err := s.m.SaveChat(&publicChat) 157 s.Require().NoError(err) 158 }, 159 AddedFilters: 0, 160 }, 161 { 162 Name: "added contact", 163 Prep: func() { 164 key, err := crypto.GenerateKey() 165 s.Require().NoError(err) 166 _, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey))}) 167 s.Require().NoError(err) 168 }, 169 AddedFilters: deprecation.AddProfileFiltersCount(1), 170 }, 171 } 172 173 expectedFilters := 0 174 for _, tc := range testCases { 175 s.Run(tc.Name, func() { 176 tc.Prep() 177 err := s.m.InitFilters() 178 s.Require().NoError(err) 179 filters := s.m.transport.Filters() 180 expectedFilters += tc.AddedFilters 181 s.Equal(deprecation.AddTimelineFiltersCount(expectedFilters), len(filters)) 182 }) 183 } 184 } 185 186 func buildAudioMessage(s *MessengerSuite, chat Chat) *common.Message { 187 clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{}) 188 message := common.NewMessage() 189 message.Text = "text-input-message" 190 message.ChatId = chat.ID 191 message.Clock = clock 192 message.Timestamp = timestamp 193 message.WhisperTimestamp = clock 194 message.LocalChatID = chat.ID 195 message.MessageType = protobuf.MessageType_PUBLIC_GROUP 196 message.ContentType = protobuf.ChatMessage_AUDIO 197 message.Payload = &protobuf.ChatMessage_Audio{ 198 Audio: &protobuf.AudioMessage{ 199 Type: 1, 200 Payload: []byte("some-payload"), 201 }, 202 } 203 204 return message 205 } 206 207 func buildTestMessage(chat Chat) *common.Message { 208 clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{}) 209 message := common.NewMessage() 210 message.Text = "text-input-message" 211 message.ChatId = chat.ID 212 message.Clock = clock 213 message.Timestamp = timestamp 214 message.WhisperTimestamp = clock 215 message.LocalChatID = chat.ID 216 message.ContentType = protobuf.ChatMessage_TEXT_PLAIN 217 switch chat.ChatType { 218 case ChatTypePublic, ChatTypeProfile: 219 message.MessageType = protobuf.MessageType_PUBLIC_GROUP 220 case ChatTypeOneToOne: 221 message.MessageType = protobuf.MessageType_ONE_TO_ONE 222 case ChatTypePrivateGroupChat: 223 message.MessageType = protobuf.MessageType_PRIVATE_GROUP 224 } 225 226 return message 227 } 228 229 func buildTestGapMessage(chat Chat) *common.Message { 230 clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{}) 231 message := common.NewMessage() 232 message.ChatId = chat.ID 233 message.Clock = clock 234 message.Timestamp = timestamp 235 message.WhisperTimestamp = clock 236 message.LocalChatID = chat.ID 237 message.ContentType = protobuf.ChatMessage_SYSTEM_MESSAGE_GAP 238 switch chat.ChatType { 239 case ChatTypePublic, ChatTypeProfile: 240 message.MessageType = protobuf.MessageType_PUBLIC_GROUP 241 case ChatTypeOneToOne: 242 message.MessageType = protobuf.MessageType_ONE_TO_ONE 243 case ChatTypePrivateGroupChat: 244 message.MessageType = protobuf.MessageType_PRIVATE_GROUP 245 } 246 247 return message 248 } 249 250 func (s *MessengerSuite) TestMarkMessagesSeen() { 251 chat := CreatePublicChat("test-chat", s.m.transport) 252 chat.UnviewedMessagesCount = 2 253 chat.UnviewedMentionsCount = 3 254 chat.Highlight = true 255 err := s.m.SaveChat(chat) 256 s.Require().NoError(err) 257 inputMessage1 := buildTestMessage(*chat) 258 inputMessage1.ID = "1" 259 inputMessage1.Seen = false 260 inputMessage1.Text = "hey @" + common.PubkeyToHex(&s.m.identity.PublicKey) 261 inputMessage1.Mentioned = true 262 inputMessage2 := buildTestMessage(*chat) 263 inputMessage2.ID = "2" 264 inputMessage2.Text = "hey @" + common.PubkeyToHex(&s.m.identity.PublicKey) 265 inputMessage2.Mentioned = true 266 inputMessage2.Seen = false 267 268 err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2}) 269 s.Require().NoError(err) 270 271 response, err := s.m.MarkMessagesRead(chat.ID, []string{inputMessage1.ID}) 272 s.Require().NoError(err) 273 274 s.Require().Len(response.GetSeenAndUnseenMessages(), 1) 275 s.Require().Equal(chat.ID, response.GetSeenAndUnseenMessages()[0].ChatID) 276 s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].Count) 277 s.Require().Equal(uint64(1), response.GetSeenAndUnseenMessages()[0].CountWithMentions) 278 s.Require().Equal(true, response.GetSeenAndUnseenMessages()[0].Seen) 279 s.Require().Len(response.ActivityCenterNotifications(), 0) 280 281 // Make sure that if it's not seen, it does not return a count of 1 282 response, err = s.m.MarkMessagesRead(chat.ID, []string{inputMessage1.ID}) 283 s.Require().NoError(err) 284 s.Require().Len(response.GetSeenAndUnseenMessages(), 1) 285 s.Require().Equal(chat.ID, response.GetSeenAndUnseenMessages()[0].ChatID) 286 s.Require().Equal(uint64(0), response.GetSeenAndUnseenMessages()[0].Count) 287 s.Require().Equal(uint64(0), response.GetSeenAndUnseenMessages()[0].CountWithMentions) 288 s.Require().Equal(true, response.GetSeenAndUnseenMessages()[0].Seen) 289 s.Require().Len(response.ActivityCenterNotifications(), 0) 290 291 chats := s.m.Chats() 292 for _, c := range chats { 293 if c.ID == chat.ID { 294 s.Require().Equal(uint(1), c.UnviewedMessagesCount) 295 s.Require().Equal(uint(1), c.UnviewedMentionsCount) 296 s.Require().Equal(false, c.Highlight) 297 } 298 } 299 } 300 301 func (s *MessengerSuite) TestMarkAllRead() { 302 chat := CreatePublicChat("test-chat", s.m.transport) 303 chat.UnviewedMessagesCount = 2 304 chat.Highlight = true 305 err := s.m.SaveChat(chat) 306 s.Require().NoError(err) 307 inputMessage1 := buildTestMessage(*chat) 308 inputMessage1.ID = "1" 309 inputMessage1.Seen = false 310 inputMessage2 := buildTestMessage(*chat) 311 inputMessage2.ID = "2" 312 inputMessage2.Seen = false 313 314 err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2}) 315 s.Require().NoError(err) 316 317 _, err = s.m.MarkAllRead(context.Background(), chat.ID) 318 s.Require().NoError(err) 319 320 chats := s.m.Chats() 321 s.Require().Len(chats, deprecation.AddChatsCount(1)) 322 for idx := range chats { 323 if chats[idx].ID == chat.ID { 324 s.Require().Equal(uint(0), chats[idx].UnviewedMessagesCount) 325 s.Require().Equal(false, chats[idx].Highlight) 326 } 327 } 328 } 329 330 func (s *MessengerSuite) TestSendPublic() { 331 chat := CreatePublicChat("test-chat", s.m.transport) 332 chat.LastClockValue = uint64(100000000000000) 333 err := s.m.SaveChat(chat) 334 s.NoError(err) 335 inputMessage := buildTestMessage(*chat) 336 response, err := s.m.SendChatMessage(context.Background(), inputMessage) 337 s.NoError(err) 338 339 s.Require().Equal(1, len(response.Messages()), "it returns the message") 340 outputMessage := response.Messages()[0] 341 342 s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock") 343 s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value") 344 s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp") 345 s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field") 346 s.Require().True(outputMessage.Seen, "it marks the message as seen") 347 s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending") 348 s.Require().NotEmpty(outputMessage.ID, "it sets the ID field") 349 s.Require().Equal(protobuf.MessageType_PUBLIC_GROUP, outputMessage.MessageType) 350 351 savedMessages, _, err := s.m.MessageByChatID(chat.ID, "", 10) 352 s.Require().NoError(err) 353 s.Require().Equal(1, len(savedMessages), "it saves the message") 354 } 355 356 func (s *MessengerSuite) TestSendProfile() { 357 // Early exit to skip testing deprecated code 358 if deprecation.ChatProfileDeprecated { 359 return 360 } 361 362 chat := CreateProfileChat("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), s.m.transport) 363 chat.LastClockValue = uint64(100000000000000) 364 err := s.m.SaveChat(chat) 365 s.NoError(err) 366 inputMessage := buildTestMessage(*chat) 367 response, err := s.m.SendChatMessage(context.Background(), inputMessage) 368 s.NoError(err) 369 370 s.Require().Equal(1, len(response.Messages()), "it returns the message") 371 outputMessage := response.Messages()[0] 372 373 s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock") 374 s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value") 375 s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp") 376 s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field") 377 s.Require().Equal(chat.Profile, outputMessage.From, "From equal to chat Profile") 378 s.Require().True(outputMessage.Seen, "it marks the message as seen") 379 s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending") 380 s.Require().NotEmpty(outputMessage.ID, "it sets the ID field") 381 s.Require().Equal(protobuf.MessageType_PUBLIC_GROUP, outputMessage.MessageType) 382 383 savedMessages, _, err := s.m.MessageByChatID(chat.ID, "", 10) 384 s.Require().NoError(err) 385 s.Require().Equal(1, len(savedMessages), "it saves the message") 386 } 387 388 func (s *MessengerSuite) TestSendPrivateOneToOne() { 389 recipientKey, err := crypto.GenerateKey() 390 s.NoError(err) 391 pkString := hex.EncodeToString(crypto.FromECDSAPub(&recipientKey.PublicKey)) 392 chat := CreateOneToOneChat(pkString, &recipientKey.PublicKey, s.m.transport) 393 394 inputMessage := common.NewMessage() 395 inputMessage.ChatId = chat.ID 396 chat.LastClockValue = uint64(100000000000000) 397 err = s.m.SaveChat(chat) 398 s.NoError(err) 399 response, err := s.m.SendChatMessage(context.Background(), inputMessage) 400 s.NoError(err) 401 s.Require().Equal(1, len(response.Messages()), "it returns the message") 402 outputMessage := response.Messages()[0] 403 404 s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock") 405 s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value") 406 407 s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp") 408 s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field") 409 s.Require().True(outputMessage.Seen, "it marks the message as seen") 410 s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending") 411 s.Require().NotEmpty(outputMessage.ID, "it sets the ID field") 412 s.Require().Equal(protobuf.MessageType_ONE_TO_ONE, outputMessage.MessageType) 413 } 414 415 func (s *MessengerSuite) TestSendPrivateGroup() { 416 response, err := s.m.CreateGroupChatWithMembers(context.Background(), "test", []string{}) 417 s.NoError(err) 418 s.Require().Len(response.Chats(), 1) 419 420 chat := response.Chats()[0] 421 key, err := crypto.GenerateKey() 422 s.NoError(err) 423 424 s.Require().NoError(makeMutualContact(s.m, &key.PublicKey)) 425 426 members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey))} 427 _, err = s.m.AddMembersToGroupChat(context.Background(), chat.ID, members) 428 s.NoError(err) 429 430 inputMessage := common.NewMessage() 431 inputMessage.ChatId = chat.ID 432 chat.LastClockValue = uint64(100000000000000) 433 err = s.m.SaveChat(chat) 434 s.NoError(err) 435 response, err = s.m.SendChatMessage(context.Background(), inputMessage) 436 s.Require().NoError(err) 437 s.Require().Equal(1, len(response.Messages()), "it returns the message") 438 outputMessage := response.Messages()[0] 439 440 s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock") 441 s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value") 442 443 s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp") 444 s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field") 445 s.Require().True(outputMessage.Seen, "it marks the message as seen") 446 s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSending, "it marks the message as sending") 447 s.Require().NotEmpty(outputMessage.ID, "it sets the ID field") 448 s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType) 449 } 450 451 func (s *MessengerSuite) TestSendPrivateEmptyGroup() { 452 response, err := s.m.CreateGroupChatWithMembers(context.Background(), "test", []string{}) 453 s.NoError(err) 454 s.Require().Len(response.Chats(), 1) 455 456 chat := response.Chats()[0] 457 458 inputMessage := common.NewMessage() 459 inputMessage.ChatId = chat.ID 460 chat.LastClockValue = uint64(100000000000000) 461 err = s.m.SaveChat(chat) 462 s.NoError(err) 463 response, err = s.m.SendChatMessage(context.Background(), inputMessage) 464 s.NoError(err) 465 s.Require().Equal(1, len(response.Messages()), "it returns the message") 466 outputMessage := response.Messages()[0] 467 468 s.Require().Equal(uint64(100000000000001), outputMessage.Clock, "it correctly sets the clock") 469 s.Require().Equal(uint64(100000000000001), chat.LastClockValue, "it correctly sets the last-clock-value") 470 471 s.Require().NotEqual(uint64(0), chat.Timestamp, "it sets the timestamp") 472 s.Require().Equal("0x"+hex.EncodeToString(crypto.FromECDSAPub(&s.privateKey.PublicKey)), outputMessage.From, "it sets the From field") 473 s.Require().True(outputMessage.Seen, "it marks the message as seen") 474 s.Require().Equal(outputMessage.OutgoingStatus, common.OutgoingStatusSent, "it marks the message as sent") 475 s.Require().NotEmpty(outputMessage.ID, "it sets the ID field") 476 s.Require().Equal(protobuf.MessageType_PRIVATE_GROUP, outputMessage.MessageType) 477 } 478 479 // Make sure public messages sent by us are not 480 func (s *MessengerSuite) TestRetrieveOwnPublic() { 481 chat := CreatePublicChat("status", s.m.transport) 482 err := s.m.SaveChat(chat) 483 s.NoError(err) 484 // Right-to-left text 485 text := "پيل اندر خانه يي تاريک بود عرضه را آورده بودندش هنود i\nاز براي ديدنش مردم بسي اندر آن ظلمت همي شد هر کسي" 486 487 inputMessage := buildTestMessage(*chat) 488 inputMessage.ChatId = chat.ID 489 inputMessage.Text = text 490 491 response, err := s.m.SendChatMessage(context.Background(), inputMessage) 492 s.NoError(err) 493 494 s.Require().Len(response.Messages(), 1) 495 496 textMessage := response.Messages()[0] 497 498 s.Equal(textMessage.Text, text) 499 s.NotNil(textMessage.ParsedText) 500 s.True(textMessage.RTL) 501 s.Equal(1, textMessage.LineCount) 502 503 s.Require().Len(response.Chats(), 1) 504 actualChat := response.Chats()[0] 505 // It does not set the unviewed messages count 506 s.Require().Equal(uint(0), actualChat.UnviewedMessagesCount) 507 // It updates the last message clock value 508 s.Require().Equal(textMessage.Clock, actualChat.LastClockValue) 509 // It sets the last message 510 s.Require().NotNil(actualChat.LastMessage) 511 } 512 513 // Retrieve their public message 514 func (s *MessengerSuite) TestRetrieveTheirPublic() { 515 theirMessenger := s.newMessenger() 516 defer TearDownMessenger(&s.Suite, theirMessenger) 517 theirChat := CreatePublicChat("status", s.m.transport) 518 err := theirMessenger.SaveChat(theirChat) 519 s.Require().NoError(err) 520 521 chat := CreatePublicChat("status", s.m.transport) 522 err = s.m.SaveChat(chat) 523 s.Require().NoError(err) 524 525 _, err = s.m.Join(chat) 526 s.Require().NoError(err) 527 528 inputMessage := buildTestMessage(*chat) 529 530 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 531 s.NoError(err) 532 533 sentMessage := sendResponse.Messages()[0] 534 535 // Wait for the message to reach its destination 536 response, err := WaitOnMessengerResponse( 537 s.m, 538 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 539 "no messages", 540 ) 541 542 s.Require().NoError(err) 543 544 s.Require().Len(response.Messages(), 1) 545 s.Require().Len(response.Chats(), 1) 546 actualChat := response.Chats()[0] 547 // It sets the unviewed messages count 548 s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount) 549 // It updates the last message clock value 550 s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue) 551 // It sets the last message 552 s.Require().NotNil(actualChat.LastMessage) 553 } 554 555 // Drop audio message in public group 556 func (s *MessengerSuite) TestDropAudioMessageInPublicGroup() { 557 theirMessenger := s.newMessenger() 558 defer TearDownMessenger(&s.Suite, theirMessenger) 559 theirChat := CreatePublicChat("status", s.m.transport) 560 err := theirMessenger.SaveChat(theirChat) 561 s.Require().NoError(err) 562 563 chat := CreatePublicChat("status", s.m.transport) 564 err = s.m.SaveChat(chat) 565 s.Require().NoError(err) 566 567 _, err = s.m.Join(chat) 568 s.Require().NoError(err) 569 570 inputMessage := buildAudioMessage(s, *chat) 571 572 _, err = theirMessenger.SendChatMessage(context.Background(), inputMessage) 573 s.NoError(err) 574 575 time.Sleep(100 * time.Millisecond) 576 response, err := s.m.RetrieveAll() 577 s.Require().NoError(err) 578 s.Require().Len(response.Messages(), 0) 579 } 580 581 func (s *MessengerSuite) TestDeletedAtClockValue() { 582 theirMessenger := s.newMessenger() 583 defer TearDownMessenger(&s.Suite, theirMessenger) 584 theirChat := CreatePublicChat("status", s.m.transport) 585 err := theirMessenger.SaveChat(theirChat) 586 s.Require().NoError(err) 587 588 chat := CreatePublicChat("status", s.m.transport) 589 err = s.m.SaveChat(chat) 590 s.Require().NoError(err) 591 592 _, err = s.m.Join(chat) 593 s.Require().NoError(err) 594 595 inputMessage := buildTestMessage(*chat) 596 597 sentResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 598 s.NoError(err) 599 600 chat.DeletedAtClockValue = sentResponse.Messages()[0].Clock 601 err = s.m.SaveChat(chat) 602 s.Require().NoError(err) 603 604 // Wait for the message to reach its destination 605 time.Sleep(100 * time.Millisecond) 606 response, err := s.m.RetrieveAll() 607 s.Require().NoError(err) 608 s.Require().Len(response.Messages(), 0) 609 } 610 611 func (s *MessengerSuite) TestRetrieveBlockedContact() { 612 theirMessenger := s.newMessenger() 613 defer TearDownMessenger(&s.Suite, theirMessenger) 614 615 theirChat := CreatePublicChat("status", s.m.transport) 616 err := theirMessenger.SaveChat(theirChat) 617 s.Require().NoError(err) 618 _, err = theirMessenger.Join(theirChat) 619 s.Require().NoError(err) 620 621 chat := CreatePublicChat("status", s.m.transport) 622 err = s.m.SaveChat(chat) 623 s.Require().NoError(err) 624 _, err = s.m.Join(chat) 625 s.Require().NoError(err) 626 627 publicKeyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 628 blockedContact := Contact{ 629 ID: publicKeyHex, 630 EnsName: "contact-name", 631 LastUpdated: 20, 632 Blocked: false, 633 } 634 635 requireMessageArrival := func(receiver *Messenger, require bool) { 636 // Wait for the message to reach its destination 637 time.Sleep(100 * time.Millisecond) 638 response, err := receiver.RetrieveAll() 639 s.Require().NoError(err) 640 if require { 641 containTextMsg := false 642 for _, msg := range response.Messages() { 643 if msg.ContentType == protobuf.ChatMessage_TEXT_PLAIN && msg.Text == "text-input-message" { 644 containTextMsg = true 645 break 646 } 647 } 648 s.Require().True(containTextMsg) 649 } else { 650 s.Require().Len(response.Messages(), 0) 651 } 652 } 653 654 // Block contact 655 _, err = s.m.BlockContact(context.Background(), blockedContact.ID, false) 656 s.Require().NoError(err) 657 658 // Blocked contact sends message, we should not receive it 659 theirMessage := buildTestMessage(*theirChat) 660 _, err = theirMessenger.SendChatMessage(context.Background(), theirMessage) 661 s.NoError(err) 662 requireMessageArrival(s.m, false) 663 664 // We send a message, blocked contact should still receive it 665 ourMessage := buildTestMessage(*chat) 666 _, err = s.m.SendChatMessage(context.Background(), ourMessage) 667 s.NoError(err) 668 requireMessageArrival(theirMessenger, true) 669 670 // Unblock contact 671 response, err := s.m.UnblockContact(blockedContact.ID) 672 s.Require().NoError(err) 673 s.Require().NotNil(response) 674 s.Require().Equal(false, response.Contacts[0].Blocked) 675 s.Require().Equal(true, response.Contacts[0].Removed) 676 677 // Unblocked contact sends message, we should receive it 678 _, err = theirMessenger.SendChatMessage(context.Background(), theirMessage) 679 s.Require().NoError(err) 680 requireMessageArrival(s.m, true) 681 682 // We send a message, unblocked contact should receive it 683 _, err = s.m.SendChatMessage(context.Background(), ourMessage) 684 s.NoError(err) 685 requireMessageArrival(theirMessenger, true) 686 } 687 688 // Resend their public message, receive only once 689 func (s *MessengerSuite) TestResendPublicMessage() { 690 theirMessenger := s.newMessenger() 691 defer TearDownMessenger(&s.Suite, theirMessenger) 692 theirChat := CreatePublicChat("status", s.m.transport) 693 err := theirMessenger.SaveChat(theirChat) 694 s.Require().NoError(err) 695 696 chat := CreatePublicChat("status", s.m.transport) 697 err = s.m.SaveChat(chat) 698 s.Require().NoError(err) 699 700 _, err = s.m.Join(chat) 701 s.Require().NoError(err) 702 703 inputMessage := buildTestMessage(*chat) 704 705 sendResponse1, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 706 s.Require().NoError(err) 707 708 sentMessage := sendResponse1.Messages()[0] 709 710 err = theirMessenger.ReSendChatMessage(context.Background(), sentMessage.ID) 711 s.Require().NoError(err) 712 713 // Wait for the message to reach its destination 714 response, err := WaitOnMessengerResponse( 715 s.m, 716 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 717 "no messages", 718 ) 719 s.Require().NoError(err) 720 721 s.Require().Len(response.Messages(), 1) 722 s.Require().Len(response.Chats(), 1) 723 actualChat := response.Chats()[0] 724 // It sets the unviewed messages count 725 s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount) 726 // It updates the last message clock value 727 s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue) 728 // It sets the last message 729 s.Require().NotNil(actualChat.LastMessage) 730 731 // We send the messag again 732 err = theirMessenger.ReSendChatMessage(context.Background(), sentMessage.ID) 733 s.Require().NoError(err) 734 735 // It should not be retrieved anymore 736 time.Sleep(100 * time.Millisecond) 737 response, err = s.m.RetrieveAll() 738 s.Require().NoError(err) 739 s.Require().Len(response.Messages(), 0) 740 } 741 742 // Test receiving a message on an existing private chat 743 func (s *MessengerSuite) TestRetrieveTheirPrivateChatExisting() { 744 theirMessenger := s.newMessenger() 745 defer TearDownMessenger(&s.Suite, theirMessenger) 746 theirChat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey, s.m.transport) 747 err := theirMessenger.SaveChat(theirChat) 748 s.Require().NoError(err) 749 750 ourChat := CreateOneToOneChat("our-chat", &theirMessenger.identity.PublicKey, s.m.transport) 751 ourChat.UnviewedMessagesCount = 1 752 // Make chat inactive 753 ourChat.Active = false 754 err = s.m.SaveChat(ourChat) 755 s.Require().NoError(err) 756 757 inputMessage := buildTestMessage(*theirChat) 758 759 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 760 s.NoError(err) 761 s.Require().Len(sendResponse.Messages(), 1) 762 763 sentMessage := sendResponse.Messages()[0] 764 765 response, err := WaitOnMessengerResponse( 766 s.m, 767 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 768 "no messages", 769 ) 770 s.Require().NoError(err) 771 772 s.Require().Len(response.Chats(), 1) 773 actualChat := response.Chats()[0] 774 // It updates the unviewed messages count 775 s.Require().Equal(uint(2), actualChat.UnviewedMessagesCount) 776 // It updates the last message clock value 777 s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue) 778 // It sets the last message 779 s.Require().NotNil(actualChat.LastMessage) 780 s.Require().False(actualChat.Active) 781 } 782 783 // Test receiving a message on an non-existing private chat 784 func (s *MessengerSuite) TestRetrieveTheirPrivateChatNonExisting() { 785 theirMessenger := s.newMessenger() 786 defer TearDownMessenger(&s.Suite, theirMessenger) 787 chat := CreateOneToOneChat("XXX", &s.privateKey.PublicKey, s.m.transport) 788 err := theirMessenger.SaveChat(chat) 789 s.NoError(err) 790 791 inputMessage := buildTestMessage(*chat) 792 793 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 794 s.NoError(err) 795 s.Require().Len(sendResponse.Messages(), 1) 796 797 sentMessage := sendResponse.Messages()[0] 798 799 // Wait for the message to reach its destination 800 response, err := WaitOnMessengerResponse( 801 s.m, 802 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 803 "no messages", 804 ) 805 806 s.Require().NoError(err) 807 808 s.Require().Len(response.Chats(), 1) 809 actualChat := response.Chats()[0] 810 // It updates the unviewed messages count 811 s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount) 812 // It updates the last message clock value 813 s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue) 814 // It sets the last message 815 s.Require().NotNil(actualChat.LastMessage) 816 // It does not set the chat as active 817 s.Require().False(actualChat.Active) 818 } 819 820 // Test receiving a message on an non-existing public chat 821 func (s *MessengerSuite) TestRetrieveTheirPublicChatNonExisting() { 822 theirMessenger := s.newMessenger() 823 defer TearDownMessenger(&s.Suite, theirMessenger) 824 chat := CreatePublicChat("test-chat", s.m.transport) 825 err := theirMessenger.SaveChat(chat) 826 s.NoError(err) 827 828 inputMessage := buildTestMessage(*chat) 829 830 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 831 s.NoError(err) 832 s.Require().Len(sendResponse.Messages(), 1) 833 834 // Wait for the message to reach its destination 835 time.Sleep(100 * time.Millisecond) 836 response, err := s.m.RetrieveAll() 837 s.NoError(err) 838 839 s.Require().Equal(len(response.Messages()), 0) 840 s.Require().Equal(len(response.Chats()), 0) 841 } 842 843 // Test receiving a message on an existing private group chat 844 func (s *MessengerSuite) TestRetrieveTheirPrivateGroupChat() { 845 var response *MessengerResponse 846 theirMessenger := s.newMessenger() 847 defer TearDownMessenger(&s.Suite, theirMessenger) 848 response, err := s.m.CreateGroupChatWithMembers(context.Background(), "id", []string{}) 849 s.NoError(err) 850 s.Require().Len(response.Chats(), 1) 851 852 ourChat := response.Chats()[0] 853 854 err = s.m.SaveChat(ourChat) 855 s.NoError(err) 856 857 s.Require().NoError(makeMutualContact(s.m, &theirMessenger.identity.PublicKey)) 858 859 members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))} 860 _, err = s.m.AddMembersToGroupChat(context.Background(), ourChat.ID, members) 861 s.NoError(err) 862 863 // Retrieve their messages so that the chat is created 864 response, err = WaitOnMessengerResponse( 865 theirMessenger, 866 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 867 "chat invitation not received", 868 ) 869 s.Require().NoError(err) 870 s.Require().Len(response.Chats(), 1) 871 s.Require().Len(response.ActivityCenterNotifications(), 1) 872 s.Require().False(response.Chats()[0].Active) 873 874 _, err = theirMessenger.ConfirmJoiningGroup(context.Background(), ourChat.ID) 875 s.NoError(err) 876 877 // Wait for the message to reach its destination 878 _, err = WaitOnMessengerResponse( 879 s.m, 880 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 881 "no joining group event received", 882 ) 883 s.Require().NoError(err) 884 885 inputMessage := buildTestMessage(*ourChat) 886 887 sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage) 888 s.NoError(err) 889 s.Require().Len(sendResponse.Messages(), 1) 890 891 sentMessage := sendResponse.Messages()[0] 892 893 response, err = WaitOnMessengerResponse( 894 s.m, 895 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 896 "no messages", 897 ) 898 s.Require().NoError(err) 899 900 s.Require().Len(response.Chats(), 1) 901 actualChat := response.Chats()[0] 902 // It updates the unviewed messages count 903 s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount) 904 // It updates the last message clock value 905 s.Require().Equal(sentMessage.Clock, actualChat.LastClockValue) 906 // It sets the last message 907 s.Require().NotNil(actualChat.LastMessage) 908 } 909 910 // Test receiving a message on an existing private group chat 911 func (s *MessengerSuite) TestChangeNameGroupChat() { 912 var response *MessengerResponse 913 theirMessenger := s.newMessenger() 914 defer TearDownMessenger(&s.Suite, theirMessenger) 915 response, err := s.m.CreateGroupChatWithMembers(context.Background(), "old-name", []string{}) 916 s.NoError(err) 917 s.Require().Len(response.Chats(), 1) 918 919 ourChat := response.Chats()[0] 920 921 err = s.m.SaveChat(ourChat) 922 s.NoError(err) 923 924 s.Require().NoError(makeMutualContact(s.m, &theirMessenger.identity.PublicKey)) 925 926 members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))} 927 _, err = s.m.AddMembersToGroupChat(context.Background(), ourChat.ID, members) 928 s.NoError(err) 929 930 // Retrieve their messages so that the chat is created 931 _, err = WaitOnMessengerResponse( 932 theirMessenger, 933 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 934 "chat invitation not received", 935 ) 936 s.Require().NoError(err) 937 938 _, err = theirMessenger.ConfirmJoiningGroup(context.Background(), ourChat.ID) 939 s.NoError(err) 940 941 // Wait for join group event 942 _, err = WaitOnMessengerResponse( 943 s.m, 944 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 945 "no joining group event received", 946 ) 947 s.Require().NoError(err) 948 949 _, err = s.m.ChangeGroupChatName(context.Background(), ourChat.ID, newEnsName) 950 s.NoError(err) 951 952 // Retrieve their messages so that the chat is created 953 response, err = WaitOnMessengerResponse( 954 theirMessenger, 955 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 956 "chat invitation not received", 957 ) 958 s.Require().NoError(err) 959 960 s.Require().Len(response.Chats(), 1) 961 actualChat := response.Chats()[0] 962 s.Require().Equal(newEnsName, actualChat.Name) 963 } 964 965 // Test being re-invited to a group chat 966 func (s *MessengerSuite) TestReInvitedToGroupChat() { 967 var response *MessengerResponse 968 theirMessenger := s.newMessenger() 969 defer TearDownMessenger(&s.Suite, theirMessenger) 970 response, err := s.m.CreateGroupChatWithMembers(context.Background(), "old-name", []string{}) 971 s.NoError(err) 972 s.Require().Len(response.Chats(), 1) 973 974 ourChat := response.Chats()[0] 975 976 err = s.m.SaveChat(ourChat) 977 s.NoError(err) 978 979 s.Require().NoError(makeMutualContact(s.m, &theirMessenger.identity.PublicKey)) 980 981 members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey))} 982 _, err = s.m.AddMembersToGroupChat(context.Background(), ourChat.ID, members) 983 s.NoError(err) 984 985 // Retrieve their messages so that the chat is created 986 response, err = WaitOnMessengerResponse( 987 theirMessenger, 988 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 989 "chat invitation not received", 990 ) 991 s.Require().NoError(err) 992 s.Require().Len(response.ActivityCenterNotifications(), 1) 993 s.Require().False(response.Chats()[0].Active) 994 995 _, err = theirMessenger.ConfirmJoiningGroup(context.Background(), ourChat.ID) 996 s.NoError(err) 997 998 // Wait for join group event 999 _, err = WaitOnMessengerResponse( 1000 s.m, 1001 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 1002 "no joining group event received", 1003 ) 1004 s.Require().NoError(err) 1005 1006 response, err = theirMessenger.LeaveGroupChat(context.Background(), ourChat.ID, true) 1007 s.NoError(err) 1008 1009 s.Require().Len(response.Chats(), 1) 1010 s.Require().False(response.Chats()[0].Active) 1011 1012 // Retrieve messages so user is removed 1013 _, err = WaitOnMessengerResponse( 1014 s.m, 1015 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 && len(r.Chats()[0].Members) == 1 }, 1016 "leave group chat not received", 1017 ) 1018 1019 s.Require().NoError(err) 1020 1021 // And we get re-invited 1022 _, err = s.m.AddMembersToGroupChat(context.Background(), ourChat.ID, members) 1023 s.NoError(err) 1024 1025 // Retrieve their messages so that the chat is created 1026 response, err = WaitOnMessengerResponse( 1027 theirMessenger, 1028 func(r *MessengerResponse) bool { return len(r.Chats()) > 0 }, 1029 "chat invitation not received", 1030 ) 1031 1032 s.Require().NoError(err) 1033 1034 s.Require().Len(response.Chats(), 1) 1035 s.Require().False(response.Chats()[0].Active) 1036 } 1037 1038 func (s *MessengerSuite) TestChatPersistencePublic() { 1039 chat := &Chat{ 1040 ID: "chat-name", 1041 Name: "chat-name", 1042 Color: "#fffff", 1043 Active: true, 1044 ChatType: ChatTypePublic, 1045 Timestamp: 10, 1046 LastClockValue: 20, 1047 DeletedAtClockValue: 30, 1048 UnviewedMessagesCount: 40, 1049 LastMessage: common.NewMessage(), 1050 Highlight: false, 1051 } 1052 1053 s.Require().NoError(s.m.SaveChat(chat)) 1054 savedChats := s.m.Chats() 1055 s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats)) 1056 } 1057 1058 func (s *MessengerSuite) TestDeleteChat() { 1059 chatID := "chatid" 1060 chat := &Chat{ 1061 ID: chatID, 1062 Name: "chat-name", 1063 Color: "#fffff", 1064 Active: true, 1065 ChatType: ChatTypePublic, 1066 Timestamp: 10, 1067 LastClockValue: 20, 1068 DeletedAtClockValue: 30, 1069 UnviewedMessagesCount: 40, 1070 LastMessage: common.NewMessage(), 1071 Highlight: false, 1072 } 1073 1074 s.Require().NoError(s.m.SaveChat(chat)) 1075 savedChats := s.m.Chats() 1076 s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats)) 1077 1078 s.Require().NoError(s.m.DeleteChat(chatID)) 1079 savedChats = s.m.Chats() 1080 s.Require().Equal(deprecation.AddChatsCount(0), len(savedChats)) 1081 } 1082 1083 func (s *MessengerSuite) TestChatPersistenceUpdate() { 1084 chat := &Chat{ 1085 ID: "chat-name", 1086 Name: "chat-name", 1087 Color: "#fffff", 1088 Active: true, 1089 ChatType: ChatTypePublic, 1090 Timestamp: 10, 1091 LastClockValue: 20, 1092 DeletedAtClockValue: 30, 1093 UnviewedMessagesCount: 40, 1094 LastMessage: common.NewMessage(), 1095 Highlight: false, 1096 } 1097 1098 s.Require().NoError(s.m.SaveChat(chat)) 1099 savedChats := s.m.Chats() 1100 s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats)) 1101 1102 var actualChat *Chat 1103 for idx := range savedChats { 1104 if savedChats[idx].ID == chat.ID { 1105 actualChat = chat 1106 } 1107 } 1108 1109 s.Require().NotNil(actualChat) 1110 s.Require().Equal(chat, actualChat) 1111 1112 chat.Name = "updated-name-1" 1113 s.Require().NoError(s.m.SaveChat(chat)) 1114 1115 var actualUpdatedChat *Chat 1116 updatedChats := s.m.Chats() 1117 1118 for idx := range updatedChats { 1119 if updatedChats[idx].ID == chat.ID { 1120 actualUpdatedChat = chat 1121 } 1122 } 1123 1124 s.Require().Equal(chat, actualUpdatedChat) 1125 } 1126 1127 func (s *MessengerSuite) TestChatPersistenceOneToOne() { 1128 chat := &Chat{ 1129 ID: testPK, 1130 Name: testPK, 1131 Color: "#fffff", 1132 Active: true, 1133 ChatType: ChatTypeOneToOne, 1134 Timestamp: 10, 1135 LastClockValue: 20, 1136 DeletedAtClockValue: 30, 1137 UnviewedMessagesCount: 40, 1138 LastMessage: common.NewMessage(), 1139 Highlight: false, 1140 } 1141 1142 publicKeyBytes, err := hex.DecodeString(testPK[2:]) 1143 s.Require().NoError(err) 1144 1145 pk, err := crypto.UnmarshalPubkey(publicKeyBytes) 1146 s.Require().NoError(err) 1147 1148 s.Require().NoError(s.m.SaveChat(chat)) 1149 savedChats := s.m.Chats() 1150 s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats)) 1151 1152 var actualChat *Chat 1153 for idx := range savedChats { 1154 if chat.ID == savedChats[idx].ID { 1155 actualChat = savedChats[idx] 1156 } 1157 1158 } 1159 1160 actualPk, err := actualChat.PublicKey() 1161 s.Require().NoError(err) 1162 1163 s.Require().Equal(pk, actualPk) 1164 1165 s.Require().Equal(chat, actualChat) 1166 s.Require().NotEmpty(actualChat.Identicon) 1167 s.Require().NotEmpty(actualChat.Alias) 1168 } 1169 1170 func (s *MessengerSuite) TestChatPersistencePrivateGroupChat() { 1171 1172 member1Key, err := crypto.GenerateKey() 1173 s.Require().NoError(err) 1174 member1ID := types.EncodeHex(crypto.FromECDSAPub(&member1Key.PublicKey)) 1175 1176 member2Key, err := crypto.GenerateKey() 1177 s.Require().NoError(err) 1178 member2ID := types.EncodeHex(crypto.FromECDSAPub(&member2Key.PublicKey)) 1179 1180 member3Key, err := crypto.GenerateKey() 1181 s.Require().NoError(err) 1182 member3ID := types.EncodeHex(crypto.FromECDSAPub(&member3Key.PublicKey)) 1183 1184 chat := &Chat{ 1185 ID: "chat-id", 1186 Name: "chat-id", 1187 Color: "#fffff", 1188 Active: true, 1189 ChatType: ChatTypePrivateGroupChat, 1190 Timestamp: 10, 1191 Members: []ChatMember{ 1192 { 1193 ID: member1ID, 1194 Admin: false, 1195 }, 1196 { 1197 ID: member2ID, 1198 Admin: true, 1199 }, 1200 { 1201 ID: member3ID, 1202 Admin: true, 1203 }, 1204 }, 1205 MembershipUpdates: []v1protocol.MembershipUpdateEvent{ 1206 { 1207 Type: protobuf.MembershipUpdateEvent_CHAT_CREATED, 1208 Name: "name-1", 1209 ClockValue: 1, 1210 Signature: []byte("signature-1"), 1211 From: "from-1", 1212 Members: []string{"member-1", "member-2"}, 1213 }, 1214 { 1215 Type: protobuf.MembershipUpdateEvent_MEMBERS_ADDED, 1216 Name: "name-2", 1217 ClockValue: 2, 1218 Signature: []byte("signature-2"), 1219 From: "from-2", 1220 Members: []string{"member-2", "member-3"}, 1221 }, 1222 }, 1223 LastClockValue: 20, 1224 DeletedAtClockValue: 30, 1225 UnviewedMessagesCount: 40, 1226 LastMessage: common.NewMessage(), 1227 Highlight: false, 1228 } 1229 s.Require().NoError(s.m.SaveChat(chat)) 1230 savedChats := s.m.Chats() 1231 s.Require().Equal(deprecation.AddChatsCount(1), len(savedChats)) 1232 1233 var actualChat *Chat 1234 for idx := range savedChats { 1235 if savedChats[idx].ID == chat.ID { 1236 actualChat = savedChats[idx] 1237 } 1238 1239 } 1240 1241 s.Require().Equal(chat, actualChat) 1242 } 1243 1244 func (s *MessengerSuite) TestBlockContact() { 1245 contact := Contact{ 1246 ID: testPK, 1247 EnsName: "contact-name", 1248 LastUpdated: 20, 1249 ContactRequestLocalState: ContactRequestStateSent, 1250 } 1251 1252 key2, err := crypto.GenerateKey() 1253 s.Require().NoError(err) 1254 1255 contact2 := Contact{ 1256 ID: common.PubkeyToHex(&key2.PublicKey), 1257 EnsName: "contact-name", 1258 LastUpdated: 20, 1259 ContactRequestLocalState: ContactRequestStateSent, 1260 } 1261 1262 chat1 := &Chat{ 1263 ID: contact.ID, 1264 Name: "chat-name", 1265 Color: "#fffff", 1266 Active: true, 1267 ChatType: ChatTypeOneToOne, 1268 Timestamp: 1, 1269 LastClockValue: 20, 1270 DeletedAtClockValue: 30, 1271 UnviewedMessagesCount: 40, 1272 Highlight: false, 1273 } 1274 1275 chat2 := &Chat{ 1276 ID: "chat-2", 1277 Name: "chat-name", 1278 Color: "#fffff", 1279 Active: true, 1280 ChatType: ChatTypePublic, 1281 Timestamp: 2, 1282 LastClockValue: 20, 1283 DeletedAtClockValue: 30, 1284 UnviewedMessagesCount: 40, 1285 Highlight: false, 1286 } 1287 1288 chat3 := &Chat{ 1289 ID: "chat-3", 1290 Name: "chat-name", 1291 Color: "#fffff", 1292 Active: true, 1293 ChatType: ChatTypePublic, 1294 Timestamp: 3, 1295 LastClockValue: 20, 1296 DeletedAtClockValue: 30, 1297 UnviewedMessagesCount: 40, 1298 Highlight: false, 1299 } 1300 1301 s.Require().NoError(s.m.SaveChat(chat1)) 1302 s.Require().NoError(s.m.SaveChat(chat2)) 1303 s.Require().NoError(s.m.SaveChat(chat3)) 1304 1305 _, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: contact.ID}) 1306 s.Require().NoError(err) 1307 1308 messages := []*common.Message{ 1309 { 1310 ID: "test-1", 1311 LocalChatID: chat2.ID, 1312 ChatMessage: &protobuf.ChatMessage{ 1313 ContentType: 1, 1314 Text: "test-1", 1315 Clock: 1, 1316 }, 1317 From: contact.ID, 1318 }, 1319 { 1320 ID: "test-2", 1321 LocalChatID: chat2.ID, 1322 ChatMessage: &protobuf.ChatMessage{ 1323 ContentType: 2, 1324 Text: "test-2", 1325 Clock: 2, 1326 }, 1327 From: contact.ID, 1328 }, 1329 { 1330 ID: "test-3", 1331 LocalChatID: chat2.ID, 1332 ChatMessage: &protobuf.ChatMessage{ 1333 ContentType: 3, 1334 Text: "test-3", 1335 Clock: 3, 1336 }, 1337 Seen: false, 1338 From: contact2.ID, 1339 }, 1340 { 1341 ID: "test-4", 1342 LocalChatID: chat2.ID, 1343 ChatMessage: &protobuf.ChatMessage{ 1344 ContentType: 4, 1345 Text: "test-4", 1346 Clock: 4, 1347 }, 1348 Seen: false, 1349 From: contact2.ID, 1350 }, 1351 { 1352 ID: "test-5", 1353 LocalChatID: chat2.ID, 1354 ChatMessage: &protobuf.ChatMessage{ 1355 ContentType: 5, 1356 Text: "test-5", 1357 Clock: 5, 1358 }, 1359 Seen: true, 1360 From: contact2.ID, 1361 }, 1362 { 1363 ID: "test-6", 1364 LocalChatID: chat3.ID, 1365 ChatMessage: &protobuf.ChatMessage{ 1366 ContentType: 6, 1367 Text: "test-6", 1368 Clock: 6, 1369 }, 1370 Seen: false, 1371 From: contact.ID, 1372 }, 1373 { 1374 ID: "test-7", 1375 LocalChatID: chat3.ID, 1376 ChatMessage: &protobuf.ChatMessage{ 1377 ContentType: 7, 1378 Text: "test-7", 1379 Clock: 7, 1380 }, 1381 Seen: false, 1382 From: contact2.ID, 1383 }, 1384 } 1385 1386 err = s.m.SaveMessages(messages) 1387 s.Require().NoError(err) 1388 1389 response, err := s.m.BlockContact(context.Background(), contact.ID, false) 1390 s.Require().NoError(err) 1391 1392 blockedContacts := s.m.BlockedContacts() 1393 s.Require().True(blockedContacts[0].Removed) 1394 1395 chats := response.Chats() 1396 1397 var actualChat2, actualChat3 *Chat 1398 for idx := range chats { 1399 if chats[idx].ID == chat2.ID { 1400 actualChat2 = chats[idx] 1401 } else if chats[idx].ID == chat3.ID { 1402 actualChat3 = chats[idx] 1403 } 1404 } 1405 // The new unviewed count is updated 1406 s.Require().Equal(uint(1), actualChat3.UnviewedMessagesCount) 1407 s.Require().Equal(uint(2), actualChat2.UnviewedMessagesCount) 1408 1409 // The new message content is updated 1410 s.Require().NotNil(actualChat3.LastMessage) 1411 1412 s.Require().Equal("test-7", actualChat3.LastMessage.ID) 1413 1414 s.Require().NotNil(actualChat2.LastMessage) 1415 s.Require().Equal("test-5", actualChat2.LastMessage.ID) 1416 1417 // The contact is updated 1418 savedContacts := s.m.Contacts() 1419 s.Require().Equal(1, len(savedContacts)) 1420 1421 // The chat is deleted 1422 actualChats := s.m.Chats() 1423 s.Require().Equal(deprecation.AddChatsCount(3), len(actualChats)) 1424 1425 // The messages have been deleted 1426 chat2Messages, _, err := s.m.MessageByChatID(chat2.ID, "", 20) 1427 s.Require().NoError(err) 1428 s.Require().Equal(3, len(chat2Messages)) 1429 1430 chat3Messages, _, err := s.m.MessageByChatID(chat3.ID, "", 20) 1431 s.Require().NoError(err) 1432 s.Require().Equal(1, len(chat3Messages)) 1433 1434 } 1435 1436 func (s *MessengerSuite) TestContactPersistence() { 1437 _, err := s.m.AddContact(context.Background(), &requests.AddContact{ID: testPK}) 1438 s.Require().NoError(err) 1439 savedContacts := s.m.Contacts() 1440 1441 s.Require().Equal(1, len(savedContacts)) 1442 1443 s.Require().True(savedContacts[0].added()) 1444 } 1445 1446 func (s *MessengerSuite) TestSharedSecretHandler() { 1447 err := s.m.handleSharedSecrets(nil) 1448 s.NoError(err) 1449 } 1450 1451 func (s *MessengerSuite) TestCreateGroupChatWithMembers() { 1452 members := []string{testPK} 1453 1454 pubKey, err := common.HexToPubkey(testPK) 1455 s.Require().NoError(err) 1456 s.Require().NoError(makeMutualContact(s.m, pubKey)) 1457 1458 response, err := s.m.CreateGroupChatWithMembers(context.Background(), "test", members) 1459 s.NoError(err) 1460 s.Require().Len(response.Chats(), 1) 1461 1462 chat := response.Chats()[0] 1463 1464 s.Require().Equal("test", chat.Name) 1465 publicKeyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 1466 s.Require().Contains(chat.ID, publicKeyHex) 1467 s.EqualValues([]string{publicKeyHex}, []string{chat.Members[0].ID}) 1468 s.Equal(members[0], chat.Members[1].ID) 1469 } 1470 1471 func (s *MessengerSuite) TestAddMembersToChat() { 1472 response, err := s.m.CreateGroupChatWithMembers(context.Background(), "test", []string{}) 1473 s.Require().NoError(err) 1474 s.Require().Len(response.Chats(), 1) 1475 1476 chat := response.Chats()[0] 1477 1478 key, err := crypto.GenerateKey() 1479 s.Require().NoError(err) 1480 members := []string{"0x" + hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey))} 1481 1482 s.Require().NoError(makeMutualContact(s.m, &key.PublicKey)) 1483 1484 response, err = s.m.AddMembersToGroupChat(context.Background(), chat.ID, members) 1485 s.Require().NoError(err) 1486 s.Require().Len(response.Chats(), 1) 1487 s.Require().Len(response.Messages(), 1) 1488 1489 chat = response.Chats()[0] 1490 1491 publicKeyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 1492 keyHex := "0x" + hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey)) 1493 s.EqualValues([]string{publicKeyHex, keyHex}, []string{chat.Members[0].ID, chat.Members[1].ID}) 1494 } 1495 1496 func (s *MessengerSuite) TestDeclineRequestAddressForTransaction() { 1497 value := testValue 1498 contract := testContract 1499 theirMessenger := s.newMessenger() 1500 defer TearDownMessenger(&s.Suite, theirMessenger) 1501 theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 1502 myPkString := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 1503 1504 chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport) 1505 err := s.m.SaveChat(chat) 1506 s.Require().NoError(err) 1507 1508 myAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey) 1509 1510 response, err := s.m.RequestAddressForTransaction(context.Background(), theirPkString, myAddress.Hex(), value, contract) 1511 s.Require().NoError(err) 1512 s.Require().NotNil(response) 1513 s.Require().Len(response.Chats(), 1) 1514 s.Require().Len(response.Messages(), 1) 1515 1516 senderMessage := response.Messages()[0] 1517 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1518 initialCommandID := senderMessage.ID 1519 1520 s.Require().Equal("Request address for transaction", senderMessage.Text) 1521 s.Require().NotNil(senderMessage.CommandParameters) 1522 s.Require().Equal(value, senderMessage.CommandParameters.Value) 1523 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 1524 s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID) 1525 s.Require().Equal(common.CommandStateRequestAddressForTransaction, senderMessage.CommandParameters.CommandState) 1526 1527 // Wait for the message to reach its destination 1528 response, err = WaitOnMessengerResponse( 1529 theirMessenger, 1530 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 1531 "no messages", 1532 ) 1533 s.Require().NoError(err) 1534 1535 s.Require().NotNil(response) 1536 s.Require().Len(response.Chats(), 1) 1537 s.Require().Len(response.Messages(), 1) 1538 1539 receiverMessage := response.Messages()[0] 1540 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 1541 s.Require().Equal("Request address for transaction", receiverMessage.Text) 1542 s.Require().NotNil(receiverMessage.CommandParameters) 1543 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 1544 s.Require().Equal(contract, receiverMessage.CommandParameters.Contract) 1545 s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID) 1546 s.Require().Equal(theirPkString, receiverMessage.ChatId) 1547 s.Require().Equal(common.CommandStateRequestAddressForTransaction, receiverMessage.CommandParameters.CommandState) 1548 1549 // We decline the request 1550 response, err = theirMessenger.DeclineRequestAddressForTransaction(context.Background(), receiverMessage.ID) 1551 s.Require().NoError(err) 1552 s.Require().Len(response.Chats(), 1) 1553 s.Require().Len(response.Messages(), 1) 1554 1555 senderMessage = response.Messages()[0] 1556 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1557 s.Require().Equal("Request address for transaction declined", senderMessage.Text) 1558 s.Require().NotNil(senderMessage.CommandParameters) 1559 s.Require().Equal(value, senderMessage.CommandParameters.Value) 1560 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 1561 s.Require().Equal(common.CommandStateRequestAddressForTransactionDeclined, senderMessage.CommandParameters.CommandState) 1562 s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID) 1563 s.Require().Equal(receiverMessage.ID, senderMessage.Replace) 1564 1565 // Wait for the message to reach its destination 1566 response, err = WaitOnMessengerResponse( 1567 s.m, 1568 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 1569 "no messages", 1570 ) 1571 s.Require().NoError(err) 1572 1573 s.Require().Len(response.Chats(), 1) 1574 s.Require().Len(response.Messages(), 1) 1575 1576 receiverMessage = response.Messages()[0] 1577 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 1578 s.Require().Equal("Request address for transaction declined", receiverMessage.Text) 1579 s.Require().NotNil(receiverMessage.CommandParameters) 1580 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 1581 s.Require().Equal(contract, receiverMessage.CommandParameters.Contract) 1582 s.Require().Equal(common.CommandStateRequestAddressForTransactionDeclined, receiverMessage.CommandParameters.CommandState) 1583 s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID) 1584 s.Require().Equal(myPkString, receiverMessage.ChatId) 1585 s.Require().Equal(initialCommandID, receiverMessage.Replace) 1586 } 1587 1588 func (s *MessengerSuite) TestSendEthTransaction() { 1589 value := testValue 1590 contract := testContract 1591 1592 theirMessenger := s.newMessenger() 1593 defer TearDownMessenger(&s.Suite, theirMessenger) 1594 theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 1595 1596 receiverAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey) 1597 receiverAddressString := strings.ToLower(receiverAddress.Hex()) 1598 1599 chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport) 1600 err := s.m.SaveChat(chat) 1601 s.Require().NoError(err) 1602 1603 transactionHash := testTransactionHash 1604 signature, err := buildSignature(s.m.identity, &s.m.identity.PublicKey, transactionHash) 1605 s.Require().NoError(err) 1606 1607 response, err := s.m.SendTransaction(context.Background(), theirPkString, value, contract, transactionHash, signature) 1608 s.Require().NoError(err) 1609 s.Require().NotNil(response) 1610 s.Require().Len(response.Chats(), 1) 1611 s.Require().Len(response.Messages(), 1) 1612 1613 senderMessage := response.Messages()[0] 1614 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1615 s.Require().Equal("Transaction sent", senderMessage.Text) 1616 s.Require().NotNil(senderMessage.CommandParameters) 1617 s.Require().Equal(transactionHash, senderMessage.CommandParameters.TransactionHash) 1618 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 1619 s.Require().Equal(value, senderMessage.CommandParameters.Value) 1620 s.Require().Equal(signature, senderMessage.CommandParameters.Signature) 1621 s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState) 1622 s.Require().NotEmpty(senderMessage.ID) 1623 s.Require().Equal("", senderMessage.Replace) 1624 1625 var transactions []*TransactionToValidate 1626 // Wait for the message to reach its destination 1627 err = tt.RetryWithBackOff(func() error { 1628 var err error 1629 1630 _, err = theirMessenger.RetrieveAll() 1631 if err != nil { 1632 return err 1633 } 1634 transactions, err = theirMessenger.persistence.TransactionsToValidate() 1635 if err == nil && len(transactions) == 0 { 1636 err = errors.New("no transactions") 1637 } 1638 return err 1639 }) 1640 s.Require().NoError(err) 1641 1642 actualTransaction := transactions[0] 1643 1644 s.Require().Equal(&s.m.identity.PublicKey, actualTransaction.From) 1645 s.Require().Equal(transactionHash, actualTransaction.TransactionHash) 1646 s.Require().True(actualTransaction.Validate) 1647 1648 senderAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey) 1649 1650 client := MockEthClient{} 1651 valueBig, ok := big.NewInt(0).SetString(value, 10) 1652 s.Require().True(ok) 1653 client.messages = make(map[string]MockTransaction) 1654 client.messages[transactionHash] = MockTransaction{ 1655 Status: coretypes.TransactionStatusSuccess, 1656 Message: coretypes.NewMessage( 1657 senderAddress, 1658 &receiverAddress, 1659 1, 1660 valueBig, 1661 0, 1662 nil, 1663 nil, 1664 false, 1665 ), 1666 } 1667 theirMessenger.verifyTransactionClient = client 1668 response, err = theirMessenger.ValidateTransactions(context.Background(), []types.Address{receiverAddress}) 1669 s.Require().NoError(err) 1670 1671 s.Require().NotNil(response) 1672 s.Require().Len(response.Chats(), 1) 1673 s.Require().Len(response.Messages(), 1) 1674 1675 receiverMessage := response.Messages()[0] 1676 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 1677 1678 s.Require().Equal("Transaction received", receiverMessage.Text) 1679 s.Require().NotNil(receiverMessage.CommandParameters) 1680 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 1681 s.Require().Equal(strings.ToLower(receiverAddress.Hex()), receiverMessage.CommandParameters.Address) 1682 s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash) 1683 s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address) 1684 s.Require().Equal("", receiverMessage.CommandParameters.ID) 1685 s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState) 1686 s.Require().Equal(senderMessage.ID, receiverMessage.ID) 1687 s.Require().Equal("", receiverMessage.Replace) 1688 } 1689 1690 func (s *MessengerSuite) TestSendTokenTransaction() { 1691 value := testValue 1692 contract := testContract 1693 1694 theirMessenger := s.newMessenger() 1695 defer TearDownMessenger(&s.Suite, theirMessenger) 1696 theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 1697 1698 receiverAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey) 1699 receiverAddressString := strings.ToLower(receiverAddress.Hex()) 1700 1701 chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport) 1702 err := s.m.SaveChat(chat) 1703 s.Require().NoError(err) 1704 1705 transactionHash := testTransactionHash 1706 signature, err := buildSignature(s.m.identity, &s.m.identity.PublicKey, transactionHash) 1707 s.Require().NoError(err) 1708 1709 response, err := s.m.SendTransaction(context.Background(), theirPkString, value, contract, transactionHash, signature) 1710 s.Require().NoError(err) 1711 s.Require().NotNil(response) 1712 s.Require().Len(response.Chats(), 1) 1713 s.Require().Len(response.Messages(), 1) 1714 1715 senderMessage := response.Messages()[0] 1716 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1717 s.Require().Equal("Transaction sent", senderMessage.Text) 1718 s.Require().NotNil(senderMessage.CommandParameters) 1719 s.Require().Equal(transactionHash, senderMessage.CommandParameters.TransactionHash) 1720 s.Require().Equal(value, senderMessage.CommandParameters.Value) 1721 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 1722 s.Require().Equal(signature, senderMessage.CommandParameters.Signature) 1723 s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState) 1724 s.Require().NotEmpty(senderMessage.ID) 1725 1726 var transactions []*TransactionToValidate 1727 // Wait for the message to reach its destination 1728 err = tt.RetryWithBackOff(func() error { 1729 var err error 1730 1731 _, err = theirMessenger.RetrieveAll() 1732 if err != nil { 1733 return err 1734 } 1735 transactions, err = theirMessenger.persistence.TransactionsToValidate() 1736 if err == nil && len(transactions) == 0 { 1737 err = errors.New("no transactions") 1738 } 1739 return err 1740 }) 1741 s.Require().NoError(err) 1742 1743 actualTransaction := transactions[0] 1744 1745 s.Require().Equal(&s.m.identity.PublicKey, actualTransaction.From) 1746 s.Require().Equal(transactionHash, actualTransaction.TransactionHash) 1747 s.Require().True(actualTransaction.Validate) 1748 1749 senderAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey) 1750 1751 contractAddress := types.HexToAddress(contract) 1752 client := MockEthClient{} 1753 valueBig, ok := big.NewInt(0).SetString(value, 10) 1754 s.Require().True(ok) 1755 client.messages = make(map[string]MockTransaction) 1756 client.messages[transactionHash] = MockTransaction{ 1757 Status: coretypes.TransactionStatusSuccess, 1758 Message: coretypes.NewMessage( 1759 senderAddress, 1760 &contractAddress, 1761 1, 1762 nil, 1763 0, 1764 nil, 1765 buildData(transferFunction, receiverAddress, valueBig), 1766 false, 1767 ), 1768 } 1769 theirMessenger.verifyTransactionClient = client 1770 response, err = theirMessenger.ValidateTransactions(context.Background(), []types.Address{receiverAddress}) 1771 s.Require().NoError(err) 1772 1773 s.Require().NotNil(response) 1774 s.Require().Len(response.Chats(), 1) 1775 s.Require().Len(response.Messages(), 1) 1776 1777 receiverMessage := response.Messages()[0] 1778 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 1779 1780 s.Require().Equal("Transaction received", receiverMessage.Text) 1781 s.Require().NotNil(receiverMessage.CommandParameters) 1782 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 1783 s.Require().Equal(contract, receiverMessage.CommandParameters.Contract) 1784 s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash) 1785 s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address) 1786 s.Require().Equal("", receiverMessage.CommandParameters.ID) 1787 s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState) 1788 s.Require().Equal(senderMessage.ID, receiverMessage.ID) 1789 s.Require().Equal(senderMessage.Replace, senderMessage.Replace) 1790 } 1791 1792 func (s *MessengerSuite) TestAcceptRequestAddressForTransaction() { 1793 value := testValue 1794 contract := testContract 1795 theirMessenger := s.newMessenger() 1796 defer TearDownMessenger(&s.Suite, theirMessenger) 1797 theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 1798 myPkString := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) 1799 1800 myAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey) 1801 1802 chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport) 1803 err := s.m.SaveChat(chat) 1804 s.Require().NoError(err) 1805 1806 response, err := s.m.RequestAddressForTransaction(context.Background(), theirPkString, myAddress.Hex(), value, contract) 1807 s.Require().NoError(err) 1808 s.Require().NotNil(response) 1809 s.Require().Len(response.Chats(), 1) 1810 s.Require().Len(response.Messages(), 1) 1811 1812 senderMessage := response.Messages()[0] 1813 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1814 initialCommandID := senderMessage.ID 1815 1816 s.Require().Equal("Request address for transaction", senderMessage.Text) 1817 s.Require().NotNil(senderMessage.CommandParameters) 1818 s.Require().Equal(value, senderMessage.CommandParameters.Value) 1819 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 1820 s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID) 1821 s.Require().Equal(common.CommandStateRequestAddressForTransaction, senderMessage.CommandParameters.CommandState) 1822 1823 // Wait for the message to reach its destination 1824 response, err = WaitOnMessengerResponse( 1825 theirMessenger, 1826 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 1827 "no messages", 1828 ) 1829 s.Require().NoError(err) 1830 1831 s.Require().NotNil(response) 1832 s.Require().Len(response.Chats(), 1) 1833 s.Require().Len(response.Messages(), 1) 1834 1835 receiverMessage := response.Messages()[0] 1836 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 1837 s.Require().Equal("Request address for transaction", receiverMessage.Text) 1838 s.Require().NotNil(receiverMessage.CommandParameters) 1839 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 1840 s.Require().Equal(contract, receiverMessage.CommandParameters.Contract) 1841 s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID) 1842 s.Require().Equal(common.CommandStateRequestAddressForTransaction, receiverMessage.CommandParameters.CommandState) 1843 s.Require().Equal(theirPkString, receiverMessage.ChatId) 1844 1845 // We accept the request 1846 response, err = theirMessenger.AcceptRequestAddressForTransaction(context.Background(), receiverMessage.ID, "some-address") 1847 s.Require().NoError(err) 1848 s.Require().Len(response.Chats(), 1) 1849 s.Require().Len(response.Messages(), 1) 1850 1851 senderMessage = response.Messages()[0] 1852 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1853 s.Require().Equal("Request address for transaction accepted", senderMessage.Text) 1854 s.Require().NotNil(senderMessage.CommandParameters) 1855 s.Require().Equal(value, senderMessage.CommandParameters.Value) 1856 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 1857 s.Require().Equal(common.CommandStateRequestAddressForTransactionAccepted, senderMessage.CommandParameters.CommandState) 1858 s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID) 1859 s.Require().Equal("some-address", senderMessage.CommandParameters.Address) 1860 s.Require().Equal(receiverMessage.ID, senderMessage.Replace) 1861 1862 // Wait for the message to reach its destination 1863 response, err = WaitOnMessengerResponse( 1864 s.m, 1865 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 1866 "no messages", 1867 ) 1868 s.Require().NoError(err) 1869 1870 s.Require().Len(response.Chats(), 1) 1871 s.Require().Len(response.Messages(), 1) 1872 1873 receiverMessage = response.Messages()[0] 1874 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 1875 s.Require().Equal("Request address for transaction accepted", receiverMessage.Text) 1876 s.Require().NotNil(receiverMessage.CommandParameters) 1877 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 1878 s.Require().Equal(contract, receiverMessage.CommandParameters.Contract) 1879 s.Require().Equal(common.CommandStateRequestAddressForTransactionAccepted, receiverMessage.CommandParameters.CommandState) 1880 s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID) 1881 s.Require().Equal("some-address", receiverMessage.CommandParameters.Address) 1882 s.Require().Equal(initialCommandID, receiverMessage.Replace) 1883 s.Require().Equal(myPkString, receiverMessage.ChatId) 1884 } 1885 1886 func (s *MessengerSuite) TestDeclineRequestTransaction() { 1887 value := testValue 1888 contract := testContract 1889 receiverAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey) 1890 receiverAddressString := strings.ToLower(receiverAddress.Hex()) 1891 theirMessenger := s.newMessenger() 1892 defer TearDownMessenger(&s.Suite, theirMessenger) 1893 theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 1894 1895 chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport) 1896 err := s.m.SaveChat(chat) 1897 s.Require().NoError(err) 1898 1899 response, err := s.m.RequestTransaction(context.Background(), theirPkString, value, contract, receiverAddressString) 1900 s.Require().NoError(err) 1901 s.Require().NotNil(response) 1902 s.Require().Len(response.Chats(), 1) 1903 s.Require().Len(response.Messages(), 1) 1904 1905 senderMessage := response.Messages()[0] 1906 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1907 initialCommandID := senderMessage.ID 1908 1909 s.Require().Equal("Request transaction", senderMessage.Text) 1910 s.Require().NotNil(senderMessage.CommandParameters) 1911 s.Require().Equal(value, senderMessage.CommandParameters.Value) 1912 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 1913 s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address) 1914 s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID) 1915 s.Require().Equal(common.CommandStateRequestTransaction, senderMessage.CommandParameters.CommandState) 1916 1917 // Wait for the message to reach its destination 1918 response, err = WaitOnMessengerResponse( 1919 theirMessenger, 1920 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 1921 "no messages", 1922 ) 1923 s.Require().NoError(err) 1924 1925 s.Require().NotNil(response) 1926 s.Require().Len(response.Chats(), 1) 1927 s.Require().Len(response.Messages(), 1) 1928 1929 receiverMessage := response.Messages()[0] 1930 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 1931 s.Require().Equal("Request transaction", receiverMessage.Text) 1932 s.Require().NotNil(receiverMessage.CommandParameters) 1933 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 1934 s.Require().Equal(contract, receiverMessage.CommandParameters.Contract) 1935 s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address) 1936 s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID) 1937 s.Require().Equal(common.CommandStateRequestTransaction, receiverMessage.CommandParameters.CommandState) 1938 1939 response, err = theirMessenger.DeclineRequestTransaction(context.Background(), initialCommandID) 1940 s.Require().NoError(err) 1941 s.Require().NotNil(response) 1942 s.Require().Len(response.Chats(), 1) 1943 s.Require().Len(response.Messages(), 1) 1944 1945 senderMessage = response.Messages()[0] 1946 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1947 1948 s.Require().Equal("Transaction request declined", senderMessage.Text) 1949 s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID) 1950 s.Require().Equal(receiverMessage.ID, senderMessage.Replace) 1951 s.Require().Equal(common.CommandStateRequestTransactionDeclined, senderMessage.CommandParameters.CommandState) 1952 1953 // Wait for the message to reach its destination 1954 response, err = WaitOnMessengerResponse( 1955 s.m, 1956 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 1957 "no messages", 1958 ) 1959 s.Require().NoError(err) 1960 1961 s.Require().NotNil(response) 1962 s.Require().Len(response.Chats(), 1) 1963 s.Require().Len(response.Messages(), 1) 1964 1965 receiverMessage = response.Messages()[0] 1966 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 1967 1968 s.Require().Equal("Transaction request declined", receiverMessage.Text) 1969 s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID) 1970 s.Require().Equal(initialCommandID, receiverMessage.Replace) 1971 s.Require().Equal(common.CommandStateRequestTransactionDeclined, receiverMessage.CommandParameters.CommandState) 1972 } 1973 1974 func (s *MessengerSuite) TestRequestTransaction() { 1975 value := testValue 1976 contract := testContract 1977 receiverAddress := crypto.PubkeyToAddress(s.m.identity.PublicKey) 1978 receiverAddressString := strings.ToLower(receiverAddress.Hex()) 1979 theirMessenger := s.newMessenger() 1980 defer TearDownMessenger(&s.Suite, theirMessenger) 1981 theirPkString := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) 1982 1983 chat := CreateOneToOneChat(theirPkString, &theirMessenger.identity.PublicKey, s.m.transport) 1984 err := s.m.SaveChat(chat) 1985 s.Require().NoError(err) 1986 1987 response, err := s.m.RequestTransaction(context.Background(), theirPkString, value, contract, receiverAddressString) 1988 s.Require().NoError(err) 1989 s.Require().NotNil(response) 1990 s.Require().Len(response.Chats(), 1) 1991 s.Require().Len(response.Messages(), 1) 1992 1993 senderMessage := response.Messages()[0] 1994 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 1995 initialCommandID := senderMessage.ID 1996 1997 s.Require().Equal("Request transaction", senderMessage.Text) 1998 s.Require().NotNil(senderMessage.CommandParameters) 1999 s.Require().Equal(value, senderMessage.CommandParameters.Value) 2000 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 2001 s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address) 2002 s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID) 2003 s.Require().Equal(common.CommandStateRequestTransaction, senderMessage.CommandParameters.CommandState) 2004 2005 // Wait for the message to reach its destination 2006 response, err = WaitOnMessengerResponse( 2007 theirMessenger, 2008 func(r *MessengerResponse) bool { return len(r.Messages()) > 0 }, 2009 "no messages", 2010 ) 2011 s.Require().NoError(err) 2012 2013 s.Require().NotNil(response) 2014 s.Require().Len(response.Chats(), 1) 2015 s.Require().Len(response.Messages(), 1) 2016 2017 receiverMessage := response.Messages()[0] 2018 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 2019 s.Require().Equal("Request transaction", receiverMessage.Text) 2020 s.Require().NotNil(receiverMessage.CommandParameters) 2021 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 2022 s.Require().Equal(contract, receiverMessage.CommandParameters.Contract) 2023 s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address) 2024 s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID) 2025 s.Require().Equal(common.CommandStateRequestTransaction, receiverMessage.CommandParameters.CommandState) 2026 2027 transactionHash := "0x412a851ac2ae51cad34a56c8a9cfee55d577ac5e1ac71cf488a2f2093a373799" 2028 signature, err := buildSignature(theirMessenger.identity, &theirMessenger.identity.PublicKey, transactionHash) 2029 s.Require().NoError(err) 2030 response, err = theirMessenger.AcceptRequestTransaction(context.Background(), transactionHash, initialCommandID, signature) 2031 s.Require().NoError(err) 2032 s.Require().NotNil(response) 2033 s.Require().Len(response.Chats(), 1) 2034 s.Require().Len(response.Messages(), 1) 2035 2036 senderMessage = response.Messages()[0] 2037 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, senderMessage.ContentType) 2038 2039 s.Require().Equal("Transaction sent", senderMessage.Text) 2040 s.Require().NotNil(senderMessage.CommandParameters) 2041 s.Require().Equal(value, senderMessage.CommandParameters.Value) 2042 s.Require().Equal(contract, senderMessage.CommandParameters.Contract) 2043 s.Require().Equal(transactionHash, senderMessage.CommandParameters.TransactionHash) 2044 s.Require().Equal(receiverAddressString, senderMessage.CommandParameters.Address) 2045 s.Require().Equal(initialCommandID, senderMessage.CommandParameters.ID) 2046 s.Require().Equal(signature, senderMessage.CommandParameters.Signature) 2047 s.Require().NotEmpty(senderMessage.ID) 2048 s.Require().Equal(receiverMessage.ID, senderMessage.Replace) 2049 s.Require().Equal(common.CommandStateTransactionSent, senderMessage.CommandParameters.CommandState) 2050 2051 var transactions []*TransactionToValidate 2052 // Wait for the message to reach its destination 2053 err = tt.RetryWithBackOff(func() error { 2054 var err error 2055 2056 _, err = s.m.RetrieveAll() 2057 if err != nil { 2058 return err 2059 } 2060 transactions, err = s.m.persistence.TransactionsToValidate() 2061 if err == nil && len(transactions) == 0 { 2062 err = errors.New("no transactions") 2063 } 2064 return err 2065 }) 2066 s.Require().NoError(err) 2067 2068 actualTransaction := transactions[0] 2069 2070 s.Require().Equal(&theirMessenger.identity.PublicKey, actualTransaction.From) 2071 s.Require().Equal(transactionHash, actualTransaction.TransactionHash) 2072 s.Require().True(actualTransaction.Validate) 2073 s.Require().Equal(initialCommandID, actualTransaction.CommandID) 2074 2075 senderAddress := crypto.PubkeyToAddress(theirMessenger.identity.PublicKey) 2076 2077 contractAddress := types.HexToAddress(contract) 2078 client := MockEthClient{} 2079 valueBig, ok := big.NewInt(0).SetString(value, 10) 2080 s.Require().True(ok) 2081 client.messages = make(map[string]MockTransaction) 2082 client.messages[transactionHash] = MockTransaction{ 2083 Status: coretypes.TransactionStatusSuccess, 2084 Message: coretypes.NewMessage( 2085 senderAddress, 2086 &contractAddress, 2087 1, 2088 nil, 2089 0, 2090 nil, 2091 buildData(transferFunction, receiverAddress, valueBig), 2092 false, 2093 ), 2094 } 2095 s.m.verifyTransactionClient = client 2096 response, err = s.m.ValidateTransactions(context.Background(), []types.Address{receiverAddress}) 2097 s.Require().NoError(err) 2098 2099 s.Require().NotNil(response) 2100 s.Require().Len(response.Chats(), 1) 2101 s.Require().Len(response.Messages(), 1) 2102 2103 receiverMessage = response.Messages()[0] 2104 s.Require().Equal(protobuf.ChatMessage_TRANSACTION_COMMAND, receiverMessage.ContentType) 2105 2106 s.Require().Equal("Transaction received", receiverMessage.Text) 2107 s.Require().NotNil(receiverMessage.CommandParameters) 2108 s.Require().Equal(value, receiverMessage.CommandParameters.Value) 2109 s.Require().Equal(contract, receiverMessage.CommandParameters.Contract) 2110 s.Require().Equal(transactionHash, receiverMessage.CommandParameters.TransactionHash) 2111 s.Require().Equal(receiverAddressString, receiverMessage.CommandParameters.Address) 2112 s.Require().Equal(initialCommandID, receiverMessage.CommandParameters.ID) 2113 s.Require().Equal(signature, receiverMessage.CommandParameters.Signature) 2114 s.Require().Equal(common.CommandStateTransactionSent, receiverMessage.CommandParameters.CommandState) 2115 s.Require().Equal(senderMessage.ID, receiverMessage.ID) 2116 s.Require().Equal(senderMessage.Replace, senderMessage.Replace) 2117 } 2118 2119 type MockTransaction struct { 2120 Status coretypes.TransactionStatus 2121 Message coretypes.Message 2122 } 2123 2124 type MockEthClient struct { 2125 messages map[string]MockTransaction 2126 } 2127 2128 func (m MockEthClient) TransactionByHash(ctx context.Context, hash types.Hash) (coretypes.Message, coretypes.TransactionStatus, error) { 2129 mockTransaction, ok := m.messages[hash.Hex()] 2130 if !ok { 2131 return coretypes.Message{}, coretypes.TransactionStatusFailed, nil 2132 } 2133 return mockTransaction.Message, mockTransaction.Status, nil 2134 } 2135 2136 func (s *MessengerSuite) TestMessageJSON() { 2137 message := &common.Message{ 2138 ID: "test-1", 2139 LocalChatID: "local-chat-id", 2140 Alias: "alias", 2141 ChatMessage: &protobuf.ChatMessage{ 2142 ChatId: "remote-chat-id", 2143 ContentType: 0, 2144 Text: "test-1", 2145 Clock: 1, 2146 }, 2147 From: testPK, 2148 } 2149 2150 _, err := json.Marshal(message) 2151 s.Require().NoError(err) 2152 } 2153 2154 func (s *MessengerSuite) TestSentEventTracking() { 2155 2156 //when message sent, its sent field should be "false" until we got confirmation 2157 chat := CreatePublicChat("test-chat", s.m.transport) 2158 err := s.m.SaveChat(chat) 2159 s.NoError(err) 2160 inputMessage := buildTestMessage(*chat) 2161 2162 _, err = s.m.SendChatMessage(context.Background(), inputMessage) 2163 s.NoError(err) 2164 2165 rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID) 2166 s.NoError(err) 2167 s.False(rawMessage.Sent) 2168 2169 //when message sent, its sent field should be true after we got confirmation 2170 err = s.m.processSentMessage(inputMessage.ID) 2171 s.NoError(err) 2172 2173 rawMessage, err = s.m.persistence.RawMessageByID(inputMessage.ID) 2174 s.NoError(err) 2175 s.True(rawMessage.Sent) 2176 } 2177 2178 func (s *MessengerSuite) TestLastSentField() { 2179 //send message 2180 chat := CreatePublicChat("test-chat", s.m.transport) 2181 err := s.m.SaveChat(chat) 2182 s.NoError(err) 2183 inputMessage := buildTestMessage(*chat) 2184 2185 _, err = s.m.SendChatMessage(context.Background(), inputMessage) 2186 s.NoError(err) 2187 2188 rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID) 2189 s.NoError(err) 2190 s.Equal(1, rawMessage.SendCount) 2191 2192 //make sure LastSent is set 2193 s.NotEqual(uint64(0), rawMessage.LastSent, "rawMessage.LastSent should be non-zero after sending") 2194 } 2195 2196 // TODO rewrite test to use persistence calls, as shouldResendMessage does not contain 2197 // relevant logic now 2198 // func (s *MessengerSuite) TestShouldResendEmoji() { 2199 // // shouldn't try to resend non-emoji messages. 2200 // ok, err := s.m.shouldResendMessage(&common.RawMessage{ 2201 // MessageType: protobuf.ApplicationMetadataMessage_CONTACT_UPDATE, 2202 // Sent: false, 2203 // SendCount: 2, 2204 // }, s.m.getTimesource()) 2205 // s.Error(err) 2206 // s.False(ok) 2207 2208 // // shouldn't try to resend already sent message 2209 // ok, err = s.m.shouldResendMessage(&common.RawMessage{ 2210 // MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, 2211 // Sent: true, 2212 // SendCount: 1, 2213 // }, s.m.getTimesource()) 2214 // s.Error(err) 2215 // s.False(ok) 2216 2217 // // messages that already sent to many times shouldn't be resend 2218 // ok, err = s.m.shouldResendMessage(&common.RawMessage{ 2219 // MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, 2220 // Sent: false, 2221 // SendCount: s.m.config.messageResendMaxCount + 1, 2222 // }, s.m.getTimesource()) 2223 // s.NoError(err) 2224 // s.False(ok) 2225 2226 // // message sent one time CAN'T be resend in 15 seconds (only after 30) 2227 // ok, err = s.m.shouldResendMessage(&common.RawMessage{ 2228 // MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, 2229 // Sent: false, 2230 // SendCount: 1, 2231 // LastSent: s.m.getTimesource().GetCurrentTime() - 15*uint64(time.Second.Milliseconds()), 2232 // }, s.m.getTimesource()) 2233 // s.NoError(err) 2234 // s.False(ok) 2235 2236 // // message sent one time CAN be resend in 35 seconds 2237 // ok, err = s.m.shouldResendMessage(&common.RawMessage{ 2238 // MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, 2239 // Sent: false, 2240 // SendCount: 1, 2241 // LastSent: s.m.getTimesource().GetCurrentTime() - 35*uint64(time.Second.Milliseconds()), 2242 // }, s.m.getTimesource()) 2243 // s.NoError(err) 2244 // s.True(ok) 2245 2246 // // message sent three times CAN'T be resend in 100 seconds (only after 120) 2247 // ok, err = s.m.shouldResendMessage(&common.RawMessage{ 2248 // MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, 2249 // Sent: false, 2250 // SendCount: 3, 2251 // LastSent: s.m.getTimesource().GetCurrentTime() - 100*uint64(time.Second.Milliseconds()), 2252 // }, s.m.getTimesource()) 2253 // s.NoError(err) 2254 // s.False(ok) 2255 2256 // // message sent tow times CAN be resend in 65 seconds 2257 // ok, err = s.m.shouldResendMessage(&common.RawMessage{ 2258 // MessageType: protobuf.ApplicationMetadataMessage_EMOJI_REACTION, 2259 // Sent: false, 2260 // SendCount: 3, 2261 // LastSent: s.m.getTimesource().GetCurrentTime() - 125*uint64(time.Second.Milliseconds()), 2262 // }, s.m.getTimesource()) 2263 // s.NoError(err) 2264 // s.True(ok) 2265 // } 2266 2267 func (s *MessengerSuite) TestSendMessageWithPreviews() { 2268 httpServer, err := server.NewMediaServer(s.m.database, nil, nil, nil) 2269 s.Require().NoError(err) 2270 err = httpServer.SetPort(9876) 2271 s.NoError(err) 2272 s.m.SetMediaServer(httpServer) 2273 2274 chat := CreatePublicChat("test-chat", s.m.transport) 2275 err = s.m.SaveChat(chat) 2276 s.NoError(err) 2277 inputMsg := buildTestMessage(*chat) 2278 2279 contactPublicKey, err := crypto.GenerateKey() 2280 s.Require().NoError(err) 2281 compressedContactPublicKey := crypto.CompressPubkey(&contactPublicKey.PublicKey) 2282 contactID := types.EncodeHex(crypto.FromECDSAPub(&contactPublicKey.PublicKey)) 2283 2284 preview := common.LinkPreview{ 2285 Type: protobuf.UnfurledLink_LINK, 2286 URL: "https://github.com", 2287 Title: "Build software better, together", 2288 Description: "GitHub is where people build software.", 2289 Thumbnail: common.LinkPreviewThumbnail{ 2290 DataURI: "data:image/png;base64,iVBORw0KGgoAAAANSUg=", 2291 Width: 100, 2292 Height: 200, 2293 }, 2294 Favicon: common.LinkPreviewThumbnail{ 2295 DataURI: "data:image/png;base64,iVBORw0KGgoAAAANSUg=", 2296 }, 2297 } 2298 inputMsg.LinkPreviews = []common.LinkPreview{preview} 2299 2300 sentContactPreview := common.StatusLinkPreview{ 2301 URL: "https://status.app/u/TestUrl", 2302 Contact: &common.StatusContactLinkPreview{ 2303 PublicKey: contactID, 2304 DisplayName: "TestDisplayName", 2305 Description: "Test description", 2306 Icon: common.LinkPreviewThumbnail{ 2307 Width: 100, 2308 Height: 200, 2309 DataURI: "data:image/png;base64,iVBORw0KGgoAAAANSUg=", 2310 }, 2311 }, 2312 } 2313 inputMsg.StatusLinkPreviews = []common.StatusLinkPreview{sentContactPreview} 2314 2315 _, err = s.m.SendChatMessage(context.Background(), inputMsg) 2316 s.NoError(err) 2317 2318 savedMsgs, _, err := s.m.MessageByChatID(chat.ID, "", 10) 2319 s.Require().NoError(err) 2320 s.Require().Len(savedMsgs, 1) 2321 savedMsg := savedMsgs[0] 2322 2323 // Test unfurled links have been saved. 2324 s.Require().Len(savedMsg.UnfurledLinks, 1) 2325 savedLinkProto := savedMsg.UnfurledLinks[0] 2326 s.Require().Equal(preview.Type, savedLinkProto.Type) 2327 s.Require().Equal(preview.URL, savedLinkProto.Url) 2328 s.Require().Equal(preview.Title, savedLinkProto.Title) 2329 s.Require().Equal(preview.Description, savedLinkProto.Description) 2330 2331 // Test the saved link thumbnail can be encoded as a data URI. 2332 expectedDataURI, err := images.GetPayloadDataURI(savedLinkProto.ThumbnailPayload) 2333 s.Require().NoError(err) 2334 s.Require().Equal(preview.Thumbnail.DataURI, expectedDataURI) 2335 2336 s.Require().Equal( 2337 httpServer.MakeLinkPreviewThumbnailURL(inputMsg.ID, preview.URL), 2338 savedMsg.LinkPreviews[0].Thumbnail.URL, 2339 ) 2340 2341 // Check saved message protobuf fields 2342 s.Require().NotNil(savedMsg.UnfurledStatusLinks) 2343 s.Require().Len(savedMsg.UnfurledStatusLinks.UnfurledStatusLinks, 1) 2344 savedStatusLinkProto := savedMsg.UnfurledStatusLinks.UnfurledStatusLinks[0] 2345 s.Require().Equal(sentContactPreview.URL, savedStatusLinkProto.Url) 2346 s.Require().NotNil(savedStatusLinkProto.GetContact()) 2347 s.Require().Nil(savedStatusLinkProto.GetCommunity()) 2348 s.Require().Nil(savedStatusLinkProto.GetChannel()) 2349 2350 savedContactProto := savedStatusLinkProto.GetContact() 2351 s.Require().Equal(compressedContactPublicKey, savedContactProto.PublicKey) 2352 s.Require().Equal(sentContactPreview.Contact.DisplayName, savedContactProto.DisplayName) 2353 s.Require().Equal(sentContactPreview.Contact.Description, savedContactProto.Description) 2354 s.Require().NotNil(savedContactProto.Icon) 2355 s.Require().Equal(sentContactPreview.Contact.Icon.Width, int(savedContactProto.Icon.Width)) 2356 s.Require().Equal(sentContactPreview.Contact.Icon.Height, int(savedContactProto.Icon.Height)) 2357 2358 iconDataURI, err := images.GetPayloadDataURI(savedContactProto.Icon.Payload) 2359 s.Require().NoError(err) 2360 s.Require().Equal(sentContactPreview.Contact.Icon.DataURI, iconDataURI) 2361 2362 // Check message `StatusLinkPreviews` properties 2363 s.Require().Len(savedMsg.StatusLinkPreviews, 1) 2364 savedStatusLinkPreview := savedMsg.StatusLinkPreviews[0] 2365 s.Require().Equal(sentContactPreview.URL, savedStatusLinkPreview.URL) 2366 s.Require().NotNil(savedStatusLinkPreview.Contact) 2367 2368 savedContact := savedStatusLinkPreview.Contact 2369 s.Require().Equal(sentContactPreview.Contact.PublicKey, savedContact.PublicKey) 2370 s.Require().Equal(sentContactPreview.Contact.DisplayName, savedContact.DisplayName) 2371 s.Require().Equal(sentContactPreview.Contact.Description, savedContact.Description) 2372 s.Require().NotNil(savedContact.Icon) 2373 s.Require().Equal(sentContactPreview.Contact.Icon.Width, savedContact.Icon.Width) 2374 s.Require().Equal(sentContactPreview.Contact.Icon.Height, savedContact.Icon.Height) 2375 expectedIconURL := httpServer.MakeStatusLinkPreviewThumbnailURL(inputMsg.ID, sentContactPreview.URL, "contact-icon") 2376 s.Require().Equal(expectedIconURL, savedContact.Icon.URL) 2377 } 2378 2379 func (s *MessengerSuite) TestMessageSent() { 2380 //send message 2381 chat := CreatePublicChat("test-chat", s.m.transport) 2382 err := s.m.SaveChat(chat) 2383 s.NoError(err) 2384 inputMessage := buildTestMessage(*chat) 2385 2386 _, err = s.m.SendChatMessage(context.Background(), inputMessage) 2387 s.NoError(err) 2388 2389 rawMessage, err := s.m.persistence.RawMessageByID(inputMessage.ID) 2390 s.NoError(err) 2391 s.Equal(1, rawMessage.SendCount) 2392 s.False(rawMessage.Sent) 2393 2394 //imitate chat message sent 2395 err = s.m.processSentMessage(inputMessage.ID) 2396 s.NoError(err) 2397 2398 rawMessage, err = s.m.persistence.RawMessageByID(inputMessage.ID) 2399 s.NoError(err) 2400 s.Equal(1, rawMessage.SendCount) 2401 s.True(rawMessage.Sent) 2402 } 2403 2404 func (s *MessengerSuite) TestProcessSentMessages() { 2405 err := s.m.processSentMessage("a") 2406 s.Require().NoError(err) 2407 } 2408 2409 func (s *MessengerSuite) TestResendExpiredEmojis() { 2410 //send message 2411 chat := CreatePublicChat("test-chat", s.m.transport) 2412 err := s.m.SaveChat(chat) 2413 s.NoError(err) 2414 inputMessage := buildTestMessage(*chat) 2415 2416 _, err = s.m.SendChatMessage(context.Background(), inputMessage) 2417 s.NoError(err) 2418 2419 //create emoji 2420 _, err = s.m.SendEmojiReaction(context.Background(), chat.ID, inputMessage.ID, protobuf.EmojiReaction_SAD) 2421 s.Require().NoError(err) 2422 2423 ids, err := s.m.persistence.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_EMOJI_REACTION) 2424 s.Require().NoError(err) 2425 emojiID := ids[0] 2426 2427 //check that emoji was sent one time 2428 rawMessage, err := s.m.persistence.RawMessageByID(emojiID) 2429 s.NoError(err) 2430 s.False(rawMessage.Sent) 2431 s.Equal(1, rawMessage.SendCount) 2432 2433 //imitate that more than 30 seconds passed since message was sent 2434 rawMessage.LastSent = rawMessage.LastSent - 35*uint64(time.Second.Milliseconds()) 2435 err = s.m.persistence.SaveRawMessage(rawMessage) 2436 s.NoError(err) 2437 time.Sleep(2 * time.Second) 2438 2439 //make sure it was resent and SendCount incremented 2440 rawMessage, err = s.m.persistence.RawMessageByID(emojiID) 2441 s.NoError(err) 2442 s.True(rawMessage.SendCount >= 2) 2443 } 2444 2445 func buildImageWithAlbumIDMessage(chat Chat, albumID string) (*common.Message, error) { 2446 file, err := os.Open("../_assets/tests/test.jpg") 2447 if err != err { 2448 return nil, err 2449 } 2450 defer file.Close() 2451 2452 payload, err := io.ReadAll(file) 2453 if err != err { 2454 return nil, err 2455 } 2456 2457 clock, timestamp := chat.NextClockAndTimestamp(&testTimeSource{}) 2458 message := common.NewMessage() 2459 message.ChatId = chat.ID 2460 message.Clock = clock 2461 message.Timestamp = timestamp 2462 message.WhisperTimestamp = clock 2463 message.LocalChatID = chat.ID 2464 message.MessageType = protobuf.MessageType_ONE_TO_ONE 2465 message.ContentType = protobuf.ChatMessage_IMAGE 2466 2467 image := protobuf.ImageMessage{ 2468 Payload: payload, 2469 Format: protobuf.ImageFormat_JPEG, 2470 Width: 1200, 2471 Height: 1000, 2472 AlbumId: albumID, 2473 } 2474 message.Payload = &protobuf.ChatMessage_Image{Image: &image} 2475 2476 return message, nil 2477 } 2478 2479 func buildImageWithoutAlbumIDMessage(chat Chat) (*common.Message, error) { 2480 return buildImageWithAlbumIDMessage(chat, "") 2481 } 2482 2483 type testTimeSource struct{} 2484 2485 func (t *testTimeSource) GetCurrentTime() uint64 { 2486 return uint64(time.Now().Unix()) 2487 } 2488 2489 func (s *MessengerSuite) TestSendMessageMention() { 2490 // Initialize Alice and Bob's messengers 2491 alice, bob := s.m, s.newMessenger() 2492 defer TearDownMessenger(&s.Suite, bob) 2493 2494 // Set display names for Bob and Alice 2495 s.Require().NoError(bob.settings.SaveSettingField(settings.DisplayName, "bobby")) 2496 s.Require().NoError(alice.settings.SaveSettingField(settings.DisplayName, "Alice")) 2497 s.Require().NoError(alice.settings.SaveSettingField(settings.NotificationsEnabled, true)) 2498 2499 // Create one-to-one chats 2500 chat, chat2 := CreateOneToOneChat(common.PubkeyToHex(&alice.identity.PublicKey), &alice.identity.PublicKey, bob.transport), 2501 CreateOneToOneChat(common.PubkeyToHex(&bob.identity.PublicKey), &bob.identity.PublicKey, alice.transport) 2502 s.Require().NoError(bob.SaveChat(chat)) 2503 s.Require().NoError(alice.SaveChat(chat2)) 2504 2505 // Prepare the message and Send the message from Bob to Alice 2506 inputMessage := common.NewMessage() 2507 inputMessage.ChatId = chat.ID 2508 inputMessage.Text = fmt.Sprintf("@%s talk to @%s", alice.myHexIdentity(), bob.myHexIdentity()) 2509 inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN 2510 _, err := bob.SendChatMessage(context.Background(), inputMessage) 2511 s.Require().NoError(err) 2512 2513 // Wait for Alice to receive the message and make sure it's properly formatted 2514 response, err := WaitOnMessengerResponse(alice, func(r *MessengerResponse) bool { return len(r.Notifications()) >= 1 }, "no messages") 2515 s.Require().NoError(err) 2516 s.Require().Equal("Alice talk to bobby", response.Notifications()[0].Message) 2517 }