diff --git a/src/download.rs b/src/download.rs index 7919722b4..d8df94d38 100644 --- a/src/download.rs +++ b/src/download.rs @@ -448,10 +448,9 @@ mod tests { ) .await?; assert_eq!(get_chat_msgs(&bob, chat_id).await?.len(), 0); - assert!(Message::load_from_db(&bob, msg.id) + assert!(Message::load_from_db_optional(&bob, msg.id) .await? - .chat_id - .is_trash()); + .is_none()); Ok(()) } @@ -507,10 +506,9 @@ mod tests { // (usually mdn are too small for not being downloaded directly) receive_imf_from_inbox(&bob, "bar@example.org", raw, false, None, false).await?; assert_eq!(get_chat_msgs(&bob, chat_id).await?.len(), 0); - assert!(Message::load_from_db(&bob, msg.id) + assert!(Message::load_from_db_optional(&bob, msg.id) .await? - .chat_id - .is_trash()); + .is_none()); Ok(()) } diff --git a/src/ephemeral.rs b/src/ephemeral.rs index 6b62e32bf..d4951ed3e 100644 --- a/src/ephemeral.rs +++ b/src/ephemeral.rs @@ -1098,8 +1098,8 @@ mod tests { }) .await; - let loaded = Message::load_from_db(t, msg_id).await?; - assert_eq!(loaded.chat_id, DC_CHAT_ID_TRASH); + let loaded = Message::load_from_db_optional(t, msg_id).await?; + assert!(loaded.is_none()); // Check that the msg was deleted locally. check_msg_is_deleted(t, chat, msg_id).await; diff --git a/src/imex.rs b/src/imex.rs index 235c97f5e..3608ae862 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -1158,7 +1158,8 @@ mod tests { // Send a message that cannot be decrypted because the keys are // not synchronized yet. let sent = alice2.send_text(msg.chat_id, "Test").await; - alice.recv_msg(&sent).await; + let trashed_message = alice.recv_msg_opt(&sent).await; + assert!(trashed_message.is_none()); assert_ne!(alice.get_last_msg().await.get_text(), "Test"); // Transfer the key. diff --git a/src/message.rs b/src/message.rs index 4a4eaa621..f6ffd8bef 100644 --- a/src/message.rs +++ b/src/message.rs @@ -506,7 +506,7 @@ impl Message { " m.location_id AS location,", " c.blocked AS blocked", " FROM msgs m LEFT JOIN chats c ON c.id=m.chat_id", - " WHERE m.id=?;" + " WHERE m.id=? AND chat_id!=3;" ), (id,), |row| { @@ -1145,13 +1145,8 @@ impl Message { pub async fn parent(&self, context: &Context) -> Result> { if let Some(in_reply_to) = &self.in_reply_to { if let Some((msg_id, _ts_sent)) = rfc724_mid_exists(context, in_reply_to).await? { - let msg = Message::load_from_db(context, msg_id).await?; - return if msg.chat_id.is_trash() { - // If message is already moved to trash chat, pretend it does not exist. - Ok(None) - } else { - Ok(Some(msg)) - }; + let msg = Message::load_from_db_optional(context, msg_id).await?; + return Ok(msg); } } Ok(None) @@ -1881,8 +1876,7 @@ pub(crate) async fn get_latest_by_rfc724_mids( ) -> Result> { for id in mids.iter().rev() { if let Some((msg_id, _)) = rfc724_mid_exists(context, id).await? { - let msg = Message::load_from_db(context, msg_id).await?; - if msg.chat_id != DC_CHAT_ID_TRASH { + if let Some(msg) = Message::load_from_db_optional(context, msg_id).await? { return Ok(Some(msg)); } } diff --git a/src/reaction.rs b/src/reaction.rs index e3e2ec893..cd0dce152 100644 --- a/src/reaction.rs +++ b/src/reaction.rs @@ -385,7 +385,6 @@ mod tests { use crate::chat::{forward_msgs, get_chat_msgs, send_text_msg}; use crate::chatlist::Chatlist; use crate::config::Config; - use crate::constants::DC_CHAT_ID_TRASH; use crate::contact::{Contact, ContactAddress, Origin}; use crate::download::DownloadState; use crate::message::{delete_msgs, MessageState}; @@ -594,8 +593,7 @@ Here's my footer -- bob@example.net" assert_eq!(get_chat_msgs(&bob, bob_msg.chat_id).await?.len(), 2); let bob_reaction_msg = bob.pop_sent_msg().await; - let alice_reaction_msg = alice.recv_msg_opt(&bob_reaction_msg).await.unwrap(); - assert_eq!(alice_reaction_msg.chat_id, DC_CHAT_ID_TRASH); + alice.recv_msg_trash(&bob_reaction_msg).await; assert_eq!(get_chat_msgs(&alice, chat_alice.id).await?.len(), 2); let reactions = get_msg_reactions(&alice, alice_msg.sender_msg_id).await?; @@ -648,8 +646,7 @@ Here's my footer -- bob@example.net" bob_msg1.chat_id.accept(&bob).await?; send_reaction(&bob, bob_msg1.id, "👍").await?; let bob_send_reaction = bob.pop_sent_msg().await; - let alice_rcvd_reaction = alice.recv_msg(&bob_send_reaction).await; - assert!(alice_rcvd_reaction.get_timestamp() > bob_msg1.get_timestamp()); + alice.recv_msg_trash(&bob_send_reaction).await; let chatlist = Chatlist::try_load(&bob, 0, None, None).await?; let summary = chatlist.get_summary(&bob, 0, None).await?; @@ -664,7 +661,7 @@ Here's my footer -- bob@example.net" SystemTime::shift(Duration::from_secs(10)); send_reaction(&alice, alice_msg1.sender_msg_id, "🍿").await?; let alice_send_reaction = alice.pop_sent_msg().await; - bob.recv_msg(&alice_send_reaction).await; + bob.recv_msg_opt(&alice_send_reaction).await; assert_summary(&alice, "You reacted 🍿 to \"Party?\"").await; assert_summary(&bob, "ALICE reacted 🍿 to \"Party?\"").await; @@ -681,7 +678,7 @@ Here's my footer -- bob@example.net" SystemTime::shift(Duration::from_secs(10)); send_reaction(&alice, alice_msg1.sender_msg_id, "🤘").await?; let alice_send_reaction = alice.pop_sent_msg().await; - bob.recv_msg(&alice_send_reaction).await; + bob.recv_msg_opt(&alice_send_reaction).await; assert_summary(&alice, "You reacted 🤘 to \"Party?\"").await; assert_summary(&bob, "ALICE reacted 🤘 to \"Party?\"").await; @@ -690,7 +687,7 @@ Here's my footer -- bob@example.net" SystemTime::shift(Duration::from_secs(10)); send_reaction(&alice, alice_msg1.sender_msg_id, "").await?; let alice_remove_reaction = alice.pop_sent_msg().await; - bob.recv_msg(&alice_remove_reaction).await; + bob.recv_msg_opt(&alice_remove_reaction).await; assert_summary(&alice, "kewl").await; assert_summary(&bob, "kewl").await; @@ -807,7 +804,7 @@ Here's my footer -- bob@example.net" let bob_reaction_msg = bob.pop_sent_msg().await; // Alice receives a reaction. - alice.recv_msg_opt(&bob_reaction_msg).await.unwrap(); + alice.recv_msg_trash(&bob_reaction_msg).await; let reactions = get_msg_reactions(&alice, alice_msg_id).await?; assert_eq!(reactions.to_string(), "👍1"); @@ -859,7 +856,7 @@ Here's my footer -- bob@example.net" { send_reaction(&alice2, alice2_msg.id, "👍").await?; let msg = alice2.pop_sent_msg().await; - alice1.recv_msg(&msg).await; + alice1.recv_msg_trash(&msg).await; } // Check that the status is still the same. @@ -881,7 +878,7 @@ Here's my footer -- bob@example.net" let alice1_msg = alice1.recv_msg(&alice0.pop_sent_msg().await).await; send_reaction(&alice0, alice0_msg_id, "👀").await?; - alice1.recv_msg(&alice0.pop_sent_msg().await).await; + alice1.recv_msg_trash(&alice0.pop_sent_msg().await).await; expect_reactions_changed_event(&alice0, chat_id, alice0_msg_id, ContactId::SELF).await?; expect_reactions_changed_event(&alice1, alice1_msg.chat_id, alice1_msg.id, ContactId::SELF) diff --git a/src/receive_imf.rs b/src/receive_imf.rs index ac1b5e4c2..512302602 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -476,11 +476,46 @@ pub(crate) async fn receive_imf_inner( } if let Some(ref status_update) = mime_parser.webxdc_status_update { - if let Err(err) = context - .receive_status_update(from_id, insert_msg_id, status_update) - .await + let can_info_msg; + let instance = if mime_parser + .parts + .first() + .filter(|part| part.typ == Viewtype::Webxdc) + .is_some() { - warn!(context, "receive_imf cannot update status: {err:#}."); + can_info_msg = false; + Some(Message::load_from_db(context, insert_msg_id).await?) + } else if let Some(field) = mime_parser.get_header(HeaderDef::InReplyTo) { + if let Some(instance) = get_rfc724_mid_in_list(context, field).await? { + can_info_msg = instance.download_state() == DownloadState::Done; + Some(instance) + } else { + can_info_msg = false; + None + } + } else { + can_info_msg = false; + None + }; + + if let Some(instance) = instance { + if let Err(err) = context + .receive_status_update( + from_id, + &instance, + received_msg.sort_timestamp, + can_info_msg, + status_update, + ) + .await + { + warn!(context, "receive_imf cannot update status: {err:#}."); + } + } else { + warn!( + context, + "Received webxdc update, but cannot assign it to message." + ); } } @@ -2694,8 +2729,6 @@ async fn mark_recipients_as_verified( /// Returns the last message referenced from `References` header if it is in the database. /// /// For Delta Chat messages it is the last message in the chat of the sender. -/// -/// Note that the returned message may be trashed. async fn get_previous_message( context: &Context, mime_parser: &MimeMessage, @@ -2703,7 +2736,7 @@ async fn get_previous_message( if let Some(field) = mime_parser.get_header(HeaderDef::References) { if let Some(rfc724mid) = parse_message_ids(field).last() { if let Some((msg_id, _)) = rfc724_mid_exists(context, rfc724mid).await? { - return Ok(Some(Message::load_from_db(context, msg_id).await?)); + return Message::load_from_db_optional(context, msg_id).await; } } } diff --git a/src/receive_imf/tests.rs b/src/receive_imf/tests.rs index 8ea32a2a6..f58d3f76b 100644 --- a/src/receive_imf/tests.rs +++ b/src/receive_imf/tests.rs @@ -4014,8 +4014,7 @@ async fn test_member_left_does_not_create_chat() -> Result<()> { // which some members simply deleted and some members left, // recreating the chat for others. remove_contact_from_chat(&alice, alice_chat_id, ContactId::SELF).await?; - let bob_chat_id = bob.recv_msg(&alice.pop_sent_msg().await).await.chat_id; - assert!(bob_chat_id.is_trash()); + bob.recv_msg_trash(&alice.pop_sent_msg().await).await; Ok(()) } @@ -4365,8 +4364,8 @@ async fn test_forged_from() -> Result<()> { .payload .replace("bob@example.net", "notbob@example.net"); - let msg = alice.recv_msg(&sent_msg).await; - assert!(msg.chat_id.is_trash()); + let msg = alice.recv_msg_opt(&sent_msg).await; + assert!(msg.is_none()); Ok(()) } diff --git a/src/securejoin.rs b/src/securejoin.rs index 0f1a7483d..35a380100 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -833,7 +833,7 @@ mod tests { assert!(msg.get_header(HeaderDef::SecureJoinInvitenumber).is_some()); // Step 3: Alice receives vc-request, sends vc-auth-required - alice.recv_msg(&sent).await; + alice.recv_msg_trash(&sent).await; assert_eq!( Chatlist::try_load(&alice, 0, None, None) .await @@ -851,7 +851,7 @@ mod tests { ); // Step 4: Bob receives vc-auth-required, sends vc-request-with-auth - bob.recv_msg(&sent).await; + bob.recv_msg_trash(&sent).await; // Check Bob emitted the JoinerProgress event. let event = bob @@ -933,7 +933,7 @@ mod tests { } // Step 5+6: Alice receives vc-request-with-auth, sends vc-contact-confirm - alice.recv_msg(&sent).await; + alice.recv_msg_trash(&sent).await; assert_eq!(contact_bob.is_verified(&alice.ctx).await.unwrap(), true); // exactly one one-to-one chat should be visible for both now @@ -982,7 +982,7 @@ mod tests { assert_eq!(contact_bob.is_verified(&bob.ctx).await.unwrap(), false); // Step 7: Bob receives vc-contact-confirm - bob.recv_msg(&sent).await; + bob.recv_msg_trash(&sent).await; assert_eq!(contact_alice.is_verified(&bob.ctx).await.unwrap(), true); // Check Bob got the verified message in his 1:1 chat. @@ -1083,7 +1083,7 @@ mod tests { assert_eq!(contact_bob.is_verified(&alice.ctx).await?, false); // Step 5+6: Alice receives vc-request-with-auth, sends vc-contact-confirm - alice.recv_msg(&sent).await; + alice.recv_msg_trash(&sent).await; assert_eq!(contact_bob.is_verified(&alice.ctx).await?, true); let sent = alice.pop_sent_msg().await; @@ -1104,7 +1104,7 @@ mod tests { assert_eq!(contact_bob.is_verified(&bob.ctx).await?, false); // Step 7: Bob receives vc-contact-confirm - bob.recv_msg(&sent).await; + bob.recv_msg_trash(&sent).await; assert_eq!(contact_alice.is_verified(&bob.ctx).await?, true); Ok(()) @@ -1182,7 +1182,7 @@ mod tests { assert!(msg.get_header(HeaderDef::SecureJoinGroup).is_none()); // Step 3: Alice receives vg-request, sends vg-auth-required - alice.recv_msg(&sent).await; + alice.recv_msg_trash(&sent).await; let sent = alice.pop_sent_msg().await; let msg = bob.parse_msg(&sent).await; @@ -1193,7 +1193,7 @@ mod tests { ); // Step 4: Bob receives vg-auth-required, sends vg-request-with-auth - bob.recv_msg(&sent).await; + bob.recv_msg_trash(&sent).await; let sent = bob.pop_sent_msg().await; // Check Bob emitted the JoinerProgress event. @@ -1240,7 +1240,7 @@ mod tests { assert_eq!(contact_bob.is_verified(&alice.ctx).await?, false); // Step 5+6: Alice receives vg-request-with-auth, sends vg-member-added - alice.recv_msg(&sent).await; + alice.recv_msg_trash(&sent).await; assert_eq!(contact_bob.is_verified(&alice.ctx).await?, true); let sent = alice.pop_sent_msg().await; @@ -1388,15 +1388,15 @@ First thread."#; // vc-request let sent = bob.pop_sent_msg().await; - alice.recv_msg(&sent).await; + alice.recv_msg_trash(&sent).await; // vc-auth-required let sent = alice.pop_sent_msg().await; - bob.recv_msg(&sent).await; + bob.recv_msg_trash(&sent).await; // vc-request-with-auth let sent = bob.pop_sent_msg().await; - alice.recv_msg(&sent).await; + alice.recv_msg_trash(&sent).await; // Alice has Bob verified now. let contact_bob_id = diff --git a/src/sync.rs b/src/sync.rs index 7cc539a28..01d0e3eb1 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -571,7 +571,7 @@ mod tests { let sent_msg = alice.pop_sent_msg().await; let alice2 = TestContext::new_alice().await; alice2.set_config_bool(Config::SyncMsgs, true).await?; - alice2.recv_msg(&sent_msg).await; + alice2.recv_msg_trash(&sent_msg).await; assert!(token::exists(&alice2, token::Namespace::Auth, "testtoken").await?); assert_eq!(Chatlist::try_load(&alice2, 0, None, None).await?.len(), 0); diff --git a/src/test_utils.rs b/src/test_utils.rs index 900fd48dd..4354976cf 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -27,8 +27,7 @@ use crate::chat::{ }; use crate::chatlist::Chatlist; use crate::config::Config; -use crate::constants::DC_GCL_NO_SPECIALS; -use crate::constants::{Blocked, Chattype}; +use crate::constants::{Blocked, Chattype, DC_CHAT_ID_TRASH, DC_GCL_NO_SPECIALS}; use crate::contact::{Contact, ContactAddress, ContactId, Modifier, Origin}; use crate::context::Context; use crate::e2ee::EncryptHelper; @@ -179,9 +178,9 @@ impl TestContextManager { loop { if let Some(sent) = scanner.pop_sent_msg_opt(Duration::ZERO).await { - scanned.recv_msg(&sent).await; + scanned.recv_msg_opt(&sent).await; } else if let Some(sent) = scanned.pop_sent_msg_opt(Duration::ZERO).await { - scanner.recv_msg(&sent).await; + scanner.recv_msg_opt(&sent).await; } else { break; } @@ -537,6 +536,16 @@ impl TestContext { receive_imf(self, msg.payload().as_bytes(), false) .await .unwrap() + .filter(|msg| msg.chat_id != DC_CHAT_ID_TRASH) + } + + /// Recevies a message and asserts that it goes to trash chat. + pub async fn recv_msg_trash(&self, msg: &SentMessage<'_>) { + let received = receive_imf(self, msg.payload().as_bytes(), false) + .await + .unwrap() + .unwrap(); + assert_eq!(received.chat_id, DC_CHAT_ID_TRASH); } /// Gets the most recent message of a chat. @@ -1069,7 +1078,8 @@ pub(crate) async fn mark_as_verified(this: &TestContext, other: &TestContext) { /// alice0's side that implies sending a sync message. pub(crate) async fn sync(alice0: &TestContext, alice1: &TestContext) { let sync_msg = alice0.pop_sent_msg().await; - alice1.recv_msg(&sync_msg).await; + let no_msg = alice1.recv_msg_opt(&sync_msg).await; + assert!(no_msg.is_none()); } /// Pretty-print an event to stdout diff --git a/src/webxdc.rs b/src/webxdc.rs index fc5f36b57..8fe7cf952 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -30,7 +30,6 @@ use crate::chat::{self, Chat}; use crate::constants::Chattype; use crate::contact::ContactId; use crate::context::Context; -use crate::download::DownloadState; use crate::events::EventType; use crate::message::{Message, MessageState, MsgId, Viewtype}; use crate::mimefactory::wrapped_base64_encode; @@ -285,7 +284,7 @@ impl Context { /// writes it to the database and handles events, info-messages, document name and summary. async fn create_status_update_record( &self, - instance: &mut Message, + instance: &Message, status_update_item: StatusUpdateItem, timestamp: i64, can_info_msg: bool, @@ -329,6 +328,7 @@ impl Context { let mut param_changed = false; + let mut instance = instance.clone(); if let Some(ref document) = status_update_item.document { if instance .param @@ -446,7 +446,7 @@ impl Context { mut status_update: StatusUpdateItem, descr: &str, ) -> Result<()> { - let mut instance = Message::load_from_db(self, instance_msg_id) + let instance = Message::load_from_db(self, instance_msg_id) .await .with_context(|| { format!("Failed to load message {instance_msg_id} from the database") @@ -474,7 +474,7 @@ impl Context { status_update.uid = Some(create_id()); let status_update_serial: StatusUpdateSerial = self .create_status_update_record( - &mut instance, + &instance, status_update, create_smeared_timestamp(self), send_now, @@ -569,33 +569,22 @@ impl Context { /// Receives status updates from receive_imf to the database /// and sends out an event. /// - /// `from_id` is the sender + /// `instance` is a webxdc instance. /// - /// `msg_id` may be an instance (in case there are initial status updates) - /// or a reply to an instance (for all other updates). + /// `from_id` is the sender. + /// + /// `timestamp` is the timestamp of the update. /// /// `json` is an array containing one or more update items as created by send_webxdc_status_update(), /// the array is parsed using serde, the single payloads are used as is. pub(crate) async fn receive_status_update( &self, from_id: ContactId, - msg_id: MsgId, + instance: &Message, + timestamp: i64, + can_info_msg: bool, json: &str, ) -> Result<()> { - let msg = Message::load_from_db(self, msg_id).await?; - let (timestamp, mut instance, can_info_msg) = if msg.viewtype == Viewtype::Webxdc { - (msg.timestamp_sort, msg, false) - } else if let Some(parent) = msg.parent(self).await? { - if parent.viewtype == Viewtype::Webxdc { - (msg.timestamp_sort, parent, true) - } else if parent.download_state() != DownloadState::Done { - (msg.timestamp_sort, parent, false) - } else { - bail!("receive_status_update: message is not the child of a webxdc message.") - } - } else { - bail!("receive_status_update: status message has no parent.") - }; let chat_id = instance.chat_id; if from_id != ContactId::SELF && !chat::is_contact_in_chat(self, chat_id, from_id).await? { @@ -612,7 +601,7 @@ impl Context { let updates: StatusUpdates = serde_json::from_str(json)?; for update_item in updates.updates { self.create_status_update_record( - &mut instance, + instance, update_item, timestamp, can_info_msg, @@ -866,9 +855,10 @@ mod tests { use crate::chatlist::Chatlist; use crate::config::Config; use crate::contact::Contact; + use crate::download::DownloadState; use crate::ephemeral; use crate::receive_imf::{receive_imf, receive_imf_from_inbox}; - use crate::test_utils::TestContext; + use crate::test_utils::{TestContext, TestContextManager}; use crate::tools::{self, SystemTime}; use crate::{message, sql}; @@ -1053,8 +1043,10 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_resend_webxdc_instance_and_info() -> Result<()> { + let mut tcm = TestContextManager::new(); + // Alice uses webxdc in a group - let alice = TestContext::new_alice().await; + let alice = tcm.alice().await; alice.set_config_bool(Config::BccSelf, false).await?; let alice_grp = create_group_chat(&alice, ProtectionStatus::Unprotected, "grp").await?; let alice_instance = send_webxdc_instance(&alice, alice_grp).await?; @@ -1069,7 +1061,7 @@ mod tests { assert_eq!(alice_grp.get_msg_cnt(&alice).await?, 2); assert!(alice.get_last_msg_in(alice_grp).await.is_info()); - // Alice adds Bob and resend already used webxdc + // Alice adds Bob and resends already used webxdc add_contact_to_chat( &alice, alice_grp, @@ -1081,7 +1073,7 @@ mod tests { let sent1 = alice.pop_sent_msg().await; // Bob received webxdc, legacy info-messages updates are received but not added to the chat - let bob = TestContext::new_bob().await; + let bob = tcm.bob().await; let bob_instance = bob.recv_msg(&sent1).await; assert_eq!(bob_instance.viewtype, Viewtype::Webxdc); assert!(!bob_instance.is_info()); @@ -1204,7 +1196,7 @@ mod tests { .await?; let bob_instance = bob.get_last_msg().await; bob_instance.chat_id.accept(&bob).await?; - bob.recv_msg(&sent2).await; + bob.recv_msg_trash(&sent2).await; assert_eq!(bob_instance.download_state, DownloadState::Available); // Bob downloads instance, updates should be assigned correctly @@ -1239,9 +1231,12 @@ mod tests { let t = TestContext::new_alice().await; let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "foo").await?; let instance = send_webxdc_instance(&t, chat_id).await?; + let now = tools::time(); t.receive_status_update( ContactId::SELF, - instance.id, + &instance, + now, + true, r#"{"updates":[{"payload":1}]}"#, ) .await?; @@ -1269,9 +1264,12 @@ mod tests { let t = TestContext::new_alice().await; let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "foo").await?; let instance = send_webxdc_instance(&t, chat_id).await?; + let now = tools::time(); t.receive_status_update( ContactId::SELF, - instance.id, + &instance, + now, + true, r#"{"updates":[{"payload":1}, {"payload":2}]}"#, ) .await?; @@ -1336,7 +1334,7 @@ mod tests { async fn test_create_status_update_record() -> Result<()> { let t = TestContext::new_alice().await; let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "foo").await?; - let mut instance = send_webxdc_instance(&t, chat_id).await?; + let instance = send_webxdc_instance(&t, chat_id).await?; assert_eq!( t.get_webxdc_status_updates(instance.id, StatusUpdateSerial(0)) @@ -1346,7 +1344,7 @@ mod tests { let update_id1 = t .create_status_update_record( - &mut instance, + &instance, StatusUpdateItem { payload: json!({"foo": "bar"}), info: None, @@ -1370,7 +1368,7 @@ mod tests { // Whatever the payload is, update should be ignored just because ID is duplicate. let update_id1_duplicate = t .create_status_update_record( - &mut instance, + &instance, StatusUpdateItem { payload: json!({"nothing": "this should be ignored"}), info: None, @@ -1403,7 +1401,7 @@ mod tests { let update_id2 = t .create_status_update_record( - &mut instance, + &instance, StatusUpdateItem { payload: json!({"foo2": "bar2"}), info: None, @@ -1422,7 +1420,7 @@ mod tests { r#"[{"payload":{"foo2":"bar2"},"serial":3,"max_serial":3}]"# ); t.create_status_update_record( - &mut instance, + &instance, StatusUpdateItem { payload: Value::Bool(true), info: None, @@ -1463,15 +1461,18 @@ mod tests { let t = TestContext::new_alice().await; let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "foo").await?; let instance = send_webxdc_instance(&t, chat_id).await?; + let now = tools::time(); assert!(t - .receive_status_update(ContactId::SELF, instance.id, r#"foo: bar"#) + .receive_status_update(ContactId::SELF, &instance, now, true, r#"foo: bar"#) .await .is_err()); // no json assert!(t .receive_status_update( ContactId::SELF, - instance.id, + &instance, + now, + true, r#"{"updada":[{"payload":{"foo":"bar"}}]}"# ) .await @@ -1479,7 +1480,9 @@ mod tests { assert!(t .receive_status_update( ContactId::SELF, - instance.id, + &instance, + now, + true, r#"{"updates":[{"foo":"bar"}]}"# ) .await @@ -1487,7 +1490,9 @@ mod tests { assert!(t .receive_status_update( ContactId::SELF, - instance.id, + &instance, + now, + true, r#"{"updates":{"payload":{"foo":"bar"}}}"# ) .await @@ -1495,7 +1500,9 @@ mod tests { t.receive_status_update( ContactId::SELF, - instance.id, + &instance, + now, + true, r#"{"updates":[{"payload":{"foo":"bar"}, "someTrash": "definitely TrAsH"}]}"#, ) .await?; @@ -1507,7 +1514,9 @@ mod tests { t.receive_status_update( ContactId::SELF, - instance.id, + &instance, + now, + true, r#" {"updates": [ {"payload" :42} , {"payload": 23} ] } "#, ) .await?; @@ -1521,7 +1530,9 @@ mod tests { t.receive_status_update( ContactId::SELF, - instance.id, + &instance, + now, + true, r#" {"updates": [ {"payload" :"ok", "future_item": "test"} ], "from": "future" } "#, ) .await?; // ignore members that may be added in the future @@ -1619,7 +1630,8 @@ mod tests { assert_eq!(bob_instance.viewtype, Viewtype::Webxdc); assert_eq!(bob_chat_id.get_msg_cnt(&bob).await?, 1); - bob.recv_msg(sent2).await; + let bob_received_update = bob.recv_msg_opt(sent2).await; + assert!(bob_received_update.is_none()); expect_status_update_event(&bob, bob_instance.id).await?; assert_eq!(bob_chat_id.get_msg_cnt(&bob).await?, 1); @@ -1632,7 +1644,7 @@ mod tests { // Alice has a second device and also receives messages there let alice2 = TestContext::new_alice().await; alice2.recv_msg(sent1).await; - alice2.recv_msg(sent2).await; + alice2.recv_msg_trash(sent2).await; let alice2_instance = alice2.get_last_msg().await; let alice2_chat_id = alice2_instance.chat_id; assert_eq!(alice2_instance.viewtype, Viewtype::Webxdc); @@ -2166,8 +2178,8 @@ sth_for_the = "future""# // Bob receives the updates let bob_instance = bob.recv_msg(sent_instance).await; - bob.recv_msg(sent_update1).await; - bob.recv_msg(sent_update2).await; + bob.recv_msg_trash(sent_update1).await; + bob.recv_msg_trash(sent_update2).await; let info = Message::load_from_db(&bob, bob_instance.id) .await? .get_webxdc_info(&bob) @@ -2177,8 +2189,8 @@ sth_for_the = "future""# // Alice has a second device and also receives the updates there let alice2 = TestContext::new_alice().await; let alice2_instance = alice2.recv_msg(sent_instance).await; - alice2.recv_msg(sent_update1).await; - alice2.recv_msg(sent_update2).await; + alice2.recv_msg_trash(sent_update1).await; + alice2.recv_msg_trash(sent_update2).await; let info = Message::load_from_db(&alice2, alice2_instance.id) .await? .get_webxdc_info(&alice2) @@ -2219,7 +2231,7 @@ sth_for_the = "future""# // Bob receives the updates let bob_instance = bob.recv_msg(sent_instance).await; - bob.recv_msg(sent_update1).await; + bob.recv_msg_trash(sent_update1).await; let info = Message::load_from_db(&bob, bob_instance.id) .await? .get_webxdc_info(&bob) @@ -2271,7 +2283,7 @@ sth_for_the = "future""# // Bob receives all messages let bob_instance = bob.recv_msg(sent1).await; let bob_chat_id = bob_instance.chat_id; - bob.recv_msg(sent2).await; + bob.recv_msg_trash(sent2).await; assert_eq!(bob_chat_id.get_msg_cnt(&bob).await?, 2); let info_msg = bob.get_last_msg().await; assert!(info_msg.is_info()); @@ -2290,7 +2302,7 @@ sth_for_the = "future""# let alice2 = TestContext::new_alice().await; let alice2_instance = alice2.recv_msg(sent1).await; let alice2_chat_id = alice2_instance.chat_id; - alice2.recv_msg(sent2).await; + alice2.recv_msg_trash(sent2).await; assert_eq!(alice2_chat_id.get_msg_cnt(&alice2).await?, 2); let info_msg = alice2.get_last_msg().await; assert!(info_msg.is_info()); @@ -2340,9 +2352,9 @@ sth_for_the = "future""# // When Bob receives the messages, they should be cleaned up as well let bob_instance = bob.recv_msg(sent1).await; let bob_chat_id = bob_instance.chat_id; - bob.recv_msg(sent2).await; + bob.recv_msg_trash(sent2).await; assert_eq!(bob_chat_id.get_msg_cnt(&bob).await?, 2); - bob.recv_msg(sent3).await; + bob.recv_msg_trash(sent3).await; assert_eq!(bob_chat_id.get_msg_cnt(&bob).await?, 2); let info_msg = bob.get_last_msg().await; assert_eq!(info_msg.get_text(), "i2"); @@ -2400,7 +2412,7 @@ sth_for_the = "future""# // Bob receives instance+update let bob_instance = bob.recv_msg(sent1).await; - bob.recv_msg(sent2).await; + bob.recv_msg_trash(sent2).await; assert!(bob_instance.get_showpadlock()); // Bob adds Claire with unknown key, update to Alice+Claire cannot be encrypted @@ -2530,7 +2542,7 @@ sth_for_the = "future""# .await?; bob.flush_status_updates().await?; let msg = bob.pop_sent_msg().await; - alice.recv_msg(&msg).await; + alice.recv_msg_trash(&msg).await; alice .get_webxdc_status_updates(alice_instance.id, StatusUpdateSerial(0)) .await @@ -2648,7 +2660,8 @@ sth_for_the = "future""# ) .await?; alice.flush_status_updates().await?; - bob.recv_msg(&alice.pop_sent_msg().await).await; + let received_update = bob.recv_msg_opt(&alice.pop_sent_msg().await).await; + assert!(received_update.is_none()); assert_eq!( bob.get_webxdc_status_updates(bob_instance.id, StatusUpdateSerial(0)) @@ -2683,7 +2696,7 @@ sth_for_the = "future""# .set(Param::Arg, r#"{"updates":[{"payload":{"foo":"bar"}}]}"#); update.set_quote(alice, Some(&alice_instance)).await?; let sent_msg = alice.send_msg(alice_chat.id, &mut update).await; - bob.recv_msg(&sent_msg).await; + bob.recv_msg_trash(&sent_msg).await; assert_eq!( bob.get_webxdc_status_updates(bob_instance.id, StatusUpdateSerial(0)) .await?,