api: don't load trashed messages with Message::load_from_db

API now pretends that trashed messages don't exist.
This way callers don't have to check if loaded message
belongs to trash chat.
If message may be trashed by the time it is attempted to be loaded,
callers should use Message::load_from_db_optional.

Most changes are around receive_status_update() function
because previously it relied on loading trashed status update
messages immediately after adding them to the database.
This commit is contained in:
link2xt
2024-04-13 23:34:09 +00:00
parent 94ac2b1097
commit c069190b68
11 changed files with 161 additions and 116 deletions

View File

@@ -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(())
}

View File

@@ -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;

View File

@@ -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.

View File

@@ -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<Option<Message>> {
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<Option<Message>> {
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));
}
}

View File

@@ -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)

View File

@@ -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;
}
}
}

View File

@@ -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(())
}

View File

@@ -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 =

View File

@@ -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);

View File

@@ -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

View File

@@ -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?,