diff --git a/src/chat.rs b/src/chat.rs index e95363e9f..f09f117fb 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -3598,6 +3598,49 @@ mod tests { Ok(()) } + /// Test that group updates are robust to lost messages and eventual out of order arrival. + #[async_std::test] + async fn test_modify_chat_lost() -> Result<()> { + let alice = TestContext::new_alice().await; + + let bob_id = Contact::create(&alice, "", "bob@example.net").await?; + let claire_id = Contact::create(&alice, "", "claire@foo.de").await?; + let daisy_id = Contact::create(&alice, "", "daisy@bar.de").await?; + + let alice_chat_id = create_group_chat(&alice, ProtectionStatus::Unprotected, "foo").await?; + add_contact_to_chat(&alice, alice_chat_id, bob_id).await?; + add_contact_to_chat(&alice, alice_chat_id, claire_id).await?; + add_contact_to_chat(&alice, alice_chat_id, daisy_id).await?; + + send_text_msg(&alice, alice_chat_id, "populate".to_string()).await?; + let add = alice.pop_sent_msg().await; + async_std::task::sleep(std::time::Duration::from_millis(1100)).await; + + remove_contact_from_chat(&alice, alice_chat_id, claire_id).await?; + let remove1 = alice.pop_sent_msg().await; + async_std::task::sleep(std::time::Duration::from_millis(1100)).await; + + remove_contact_from_chat(&alice, alice_chat_id, daisy_id).await?; + let remove2 = alice.pop_sent_msg().await; + + let bob = TestContext::new_bob().await; + + bob.recv_msg(&add).await; + let bob_chat_id = bob.get_last_msg().await.chat_id; + assert_eq!(get_chat_contacts(&bob, bob_chat_id).await?.len(), 4); + + // First removal message is lost. + // Nevertheless, two members are removed. + bob.recv_msg(&remove2).await; + assert_eq!(get_chat_contacts(&bob, bob_chat_id).await?.len(), 2); + + // Eventually, first removal message arrives. + // This has no effect. + bob.recv_msg(&remove1).await; + assert_eq!(get_chat_contacts(&bob, bob_chat_id).await?.len(), 2); + Ok(()) + } + #[async_std::test] async fn test_add_remove_contact_for_single() { let ctx = TestContext::new_alice().await;