Don't use opt_level=1, instead box futures

This commit is contained in:
Hocuri
2022-10-15 09:41:52 +02:00
parent 86e1476dee
commit 9136f3cda7
2 changed files with 406 additions and 390 deletions

View File

@@ -9,7 +9,6 @@ rust-version = "1.56"
[profile.dev] [profile.dev]
debug = 0 debug = 0
panic = 'abort' panic = 'abort'
opt-level = 1
[profile.release] [profile.release]
lto = true lto = true

View File

@@ -695,214 +695,222 @@ mod tests {
use crate::test_utils::{TestContext, TestContextManager}; use crate::test_utils::{TestContext, TestContextManager};
use crate::tools::EmailAddress; use crate::tools::EmailAddress;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[test]
async fn test_setup_contact() { fn test_setup_contact() {
let mut tcm = TestContextManager::new(); let body = Box::pin(async {
let alice = tcm.alice().await; let mut tcm = TestContextManager::new();
let bob = tcm.bob().await; let alice = tcm.alice().await;
assert_eq!( let bob = tcm.bob().await;
Chatlist::try_load(&alice, 0, None, None) assert_eq!(
.await Chatlist::try_load(&alice, 0, None, None)
.unwrap() .await
.len(), .unwrap()
0 .len(),
); 0
assert_eq!( );
Chatlist::try_load(&bob, 0, None, None).await.unwrap().len(), assert_eq!(
0 Chatlist::try_load(&bob, 0, None, None).await.unwrap().len(),
); 0
);
// Step 1: Generate QR-code, ChatId(0) indicates setup-contact // Step 1: Generate QR-code, ChatId(0) indicates setup-contact
let qr = get_securejoin_qr(&alice.ctx, None).await.unwrap(); let qr = get_securejoin_qr(&alice.ctx, None).await.unwrap();
// Step 2: Bob scans QR-code, sends vc-request // Step 2: Bob scans QR-code, sends vc-request
join_securejoin(&bob.ctx, &qr).await.unwrap(); join_securejoin(&bob.ctx, &qr).await.unwrap();
assert_eq!( assert_eq!(
Chatlist::try_load(&bob, 0, None, None).await.unwrap().len(), Chatlist::try_load(&bob, 0, None, None).await.unwrap().len(),
1 1
); );
let sent = bob.pop_sent_msg().await; let sent = bob.pop_sent_msg().await;
assert_eq!( assert_eq!(
sent.recipient(), sent.recipient(),
EmailAddress::new("alice@example.org").unwrap() EmailAddress::new("alice@example.org").unwrap()
); );
let msg = alice.parse_msg(&sent).await; let msg = alice.parse_msg(&sent).await;
assert!(!msg.was_encrypted()); assert!(!msg.was_encrypted());
assert_eq!(msg.get_header(HeaderDef::SecureJoin).unwrap(), "vc-request"); assert_eq!(msg.get_header(HeaderDef::SecureJoin).unwrap(), "vc-request");
assert!(msg.get_header(HeaderDef::SecureJoinInvitenumber).is_some()); assert!(msg.get_header(HeaderDef::SecureJoinInvitenumber).is_some());
// Step 3: Alice receives vc-request, sends vc-auth-required // Step 3: Alice receives vc-request, sends vc-auth-required
alice.recv_msg(&sent).await; alice.recv_msg(&sent).await;
assert_eq!( assert_eq!(
Chatlist::try_load(&alice, 0, None, None) Chatlist::try_load(&alice, 0, None, None)
.await .await
.unwrap() .unwrap()
.len(), .len(),
1 1
); );
let sent = alice.pop_sent_msg().await; let sent = alice.pop_sent_msg().await;
let msg = bob.parse_msg(&sent).await; let msg = bob.parse_msg(&sent).await;
assert!(msg.was_encrypted()); assert!(msg.was_encrypted());
assert_eq!( assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(), msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vc-auth-required" "vc-auth-required"
); );
// Step 4: Bob receives vc-auth-required, sends vc-request-with-auth // Step 4: Bob receives vc-auth-required, sends vc-request-with-auth
bob.recv_msg(&sent).await; bob.recv_msg(&sent).await;
// Check Bob emitted the JoinerProgress event. // Check Bob emitted the JoinerProgress event.
let event = bob let event = bob
.evtracker .evtracker
.get_matching(|evt| matches!(evt, EventType::SecurejoinJoinerProgress { .. })) .get_matching(|evt| matches!(evt, EventType::SecurejoinJoinerProgress { .. }))
.await; .await;
match event { match event {
EventType::SecurejoinJoinerProgress { EventType::SecurejoinJoinerProgress {
contact_id, contact_id,
progress, progress,
} => { } => {
let alice_contact_id = let alice_contact_id =
Contact::lookup_id_by_addr(&bob.ctx, "alice@example.org", Origin::Unknown) Contact::lookup_id_by_addr(&bob.ctx, "alice@example.org", Origin::Unknown)
.await .await
.expect("Error looking up contact") .expect("Error looking up contact")
.expect("Contact not found"); .expect("Contact not found");
assert_eq!(contact_id, alice_contact_id); assert_eq!(contact_id, alice_contact_id);
assert_eq!(progress, 400); assert_eq!(progress, 400);
}
_ => unreachable!(),
} }
_ => unreachable!(),
}
// Check Bob sent the right message. // Check Bob sent the right message.
let sent = bob.pop_sent_msg().await; let sent = bob.pop_sent_msg().await;
let msg = alice.parse_msg(&sent).await; let msg = alice.parse_msg(&sent).await;
assert!(msg.was_encrypted()); assert!(msg.was_encrypted());
assert_eq!( assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(), msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vc-request-with-auth" "vc-request-with-auth"
); );
assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some()); assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some());
let bob_fp = SignedPublicKey::load_self(&bob.ctx) let bob_fp = SignedPublicKey::load_self(&bob.ctx)
.await
.unwrap()
.fingerprint();
assert_eq!(
*msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(),
bob_fp.hex()
);
// Alice should not yet have Bob verified
let contact_bob_id =
Contact::lookup_id_by_addr(&alice.ctx, "bob@example.net", Origin::Unknown)
.await
.expect("Error looking up contact")
.expect("Contact not found");
let contact_bob = Contact::load_from_db(&alice.ctx, contact_bob_id)
.await
.unwrap();
assert_eq!(
contact_bob.is_verified(&alice.ctx).await.unwrap(),
VerifiedStatus::Unverified
);
// Step 5+6: Alice receives vc-request-with-auth, sends vc-contact-confirm
alice.recv_msg(&sent).await;
assert_eq!(
contact_bob.is_verified(&alice.ctx).await.unwrap(),
VerifiedStatus::BidirectVerified
);
// exactly one one-to-one chat should be visible for both now
// (check this before calling alice.create_chat() explicitly below)
assert_eq!(
Chatlist::try_load(&alice, 0, None, None)
.await .await
.unwrap() .unwrap()
.len(), .fingerprint();
1 assert_eq!(
); *msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(),
assert_eq!( bob_fp.hex()
Chatlist::try_load(&bob, 0, None, None).await.unwrap().len(), );
1
);
// Check Alice got the verified message in her 1:1 chat. // Alice should not yet have Bob verified
{ let contact_bob_id =
let chat = alice.create_chat(&bob).await; Contact::lookup_id_by_addr(&alice.ctx, "bob@example.net", Origin::Unknown)
let msg_id = chat::get_chat_msgs(&alice.ctx, chat.get_id(), DC_GCM_ADDDAYMARKER) .await
.expect("Error looking up contact")
.expect("Contact not found");
let contact_bob = Contact::load_from_db(&alice.ctx, contact_bob_id)
.await .await
.unwrap() .unwrap();
.into_iter() assert_eq!(
.filter_map(|item| match item { contact_bob.is_verified(&alice.ctx).await.unwrap(),
chat::ChatItem::Message { msg_id } => Some(msg_id), VerifiedStatus::Unverified
_ => None, );
})
.max()
.expect("No messages in Alice's 1:1 chat");
let msg = Message::load_from_db(&alice.ctx, msg_id).await.unwrap();
assert!(msg.is_info());
let text = msg.get_text().unwrap();
assert!(text.contains("bob@example.net verified"));
}
// Check Alice sent the right message to Bob. // Step 5+6: Alice receives vc-request-with-auth, sends vc-contact-confirm
let sent = alice.pop_sent_msg().await; alice.recv_msg(&sent).await;
let msg = bob.parse_msg(&sent).await; assert_eq!(
assert!(msg.was_encrypted()); contact_bob.is_verified(&alice.ctx).await.unwrap(),
assert_eq!( VerifiedStatus::BidirectVerified
msg.get_header(HeaderDef::SecureJoin).unwrap(), );
"vc-contact-confirm"
);
// Bob should not yet have Alice verified // exactly one one-to-one chat should be visible for both now
let contact_alice_id = // (check this before calling alice.create_chat() explicitly below)
Contact::lookup_id_by_addr(&bob.ctx, "alice@example.org", Origin::Unknown) assert_eq!(
Chatlist::try_load(&alice, 0, None, None)
.await
.unwrap()
.len(),
1
);
assert_eq!(
Chatlist::try_load(&bob, 0, None, None).await.unwrap().len(),
1
);
// Check Alice got the verified message in her 1:1 chat.
{
let chat = alice.create_chat(&bob).await;
let msg_id = chat::get_chat_msgs(&alice.ctx, chat.get_id(), DC_GCM_ADDDAYMARKER)
.await
.unwrap()
.into_iter()
.filter_map(|item| match item {
chat::ChatItem::Message { msg_id } => Some(msg_id),
_ => None,
})
.max()
.expect("No messages in Alice's 1:1 chat");
let msg = Message::load_from_db(&alice.ctx, msg_id).await.unwrap();
assert!(msg.is_info());
let text = msg.get_text().unwrap();
assert!(text.contains("bob@example.net verified"));
}
// Check Alice sent the right message to Bob.
let sent = alice.pop_sent_msg().await;
let msg = bob.parse_msg(&sent).await;
assert!(msg.was_encrypted());
assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vc-contact-confirm"
);
// Bob should not yet have Alice verified
let contact_alice_id =
Contact::lookup_id_by_addr(&bob.ctx, "alice@example.org", Origin::Unknown)
.await
.expect("Error looking up contact")
.expect("Contact not found");
let contact_alice = Contact::load_from_db(&bob.ctx, contact_alice_id)
.await .await
.expect("Error looking up contact") .unwrap();
.expect("Contact not found"); assert_eq!(
let contact_alice = Contact::load_from_db(&bob.ctx, contact_alice_id) contact_bob.is_verified(&bob.ctx).await.unwrap(),
.await VerifiedStatus::Unverified
.unwrap(); );
assert_eq!(
contact_bob.is_verified(&bob.ctx).await.unwrap(),
VerifiedStatus::Unverified
);
// Step 7: Bob receives vc-contact-confirm, sends vc-contact-confirm-received // Step 7: Bob receives vc-contact-confirm, sends vc-contact-confirm-received
bob.recv_msg(&sent).await; bob.recv_msg(&sent).await;
assert_eq!( assert_eq!(
contact_alice.is_verified(&bob.ctx).await.unwrap(), contact_alice.is_verified(&bob.ctx).await.unwrap(),
VerifiedStatus::BidirectVerified VerifiedStatus::BidirectVerified
); );
// Check Bob got the verified message in his 1:1 chat. // Check Bob got the verified message in his 1:1 chat.
{ {
let chat = bob.create_chat(&alice).await; let chat = bob.create_chat(&alice).await;
let msg_id = chat::get_chat_msgs(&bob.ctx, chat.get_id(), DC_GCM_ADDDAYMARKER) let msg_id = chat::get_chat_msgs(&bob.ctx, chat.get_id(), DC_GCM_ADDDAYMARKER)
.await .await
.unwrap() .unwrap()
.into_iter() .into_iter()
.filter_map(|item| match item { .filter_map(|item| match item {
chat::ChatItem::Message { msg_id } => Some(msg_id), chat::ChatItem::Message { msg_id } => Some(msg_id),
_ => None, _ => None,
}) })
.max() .max()
.expect("No messages in Bob's 1:1 chat"); .expect("No messages in Bob's 1:1 chat");
let msg = Message::load_from_db(&bob.ctx, msg_id).await.unwrap(); let msg = Message::load_from_db(&bob.ctx, msg_id).await.unwrap();
assert!(msg.is_info()); assert!(msg.is_info());
let text = msg.get_text().unwrap(); let text = msg.get_text().unwrap();
assert!(text.contains("alice@example.org verified")); assert!(text.contains("alice@example.org verified"));
} }
// Check Bob sent the final message // Check Bob sent the final message
let sent = bob.pop_sent_msg().await; let sent = bob.pop_sent_msg().await;
let msg = alice.parse_msg(&sent).await; let msg = alice.parse_msg(&sent).await;
assert!(msg.was_encrypted()); assert!(msg.was_encrypted());
assert_eq!( assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(), msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vc-contact-confirm-received" "vc-contact-confirm-received"
); );
});
return tokio::runtime::Builder::new_multi_thread()
.worker_threads(2usize)
.enable_all()
.build()
.expect("Failed building the Runtime")
.block_on(body);
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -1068,231 +1076,240 @@ mod tests {
Ok(()) Ok(())
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[test]
async fn test_secure_join() -> Result<()> { fn test_secure_join() -> Result<()> {
let mut tcm = TestContextManager::new(); let body = Box::pin(async {
let alice = tcm.alice().await; let mut tcm = TestContextManager::new();
let bob = tcm.bob().await; let alice = tcm.alice().await;
let bob = tcm.bob().await;
// We start with empty chatlists. // We start with empty chatlists.
assert_eq!(Chatlist::try_load(&alice, 0, None, None).await?.len(), 0); assert_eq!(Chatlist::try_load(&alice, 0, None, None).await?.len(), 0);
assert_eq!(Chatlist::try_load(&bob, 0, None, None).await?.len(), 0); assert_eq!(Chatlist::try_load(&bob, 0, None, None).await?.len(), 0);
let alice_chatid = let alice_chatid =
chat::create_group_chat(&alice.ctx, ProtectionStatus::Protected, "the chat").await?; chat::create_group_chat(&alice.ctx, ProtectionStatus::Protected, "the chat")
.await?;
// Step 1: Generate QR-code, secure-join implied by chatid // Step 1: Generate QR-code, secure-join implied by chatid
let qr = get_securejoin_qr(&alice.ctx, Some(alice_chatid)) let qr = get_securejoin_qr(&alice.ctx, Some(alice_chatid))
.await
.unwrap();
// Step 2: Bob scans QR-code, sends vg-request
let bob_chatid = join_securejoin(&bob.ctx, &qr).await?;
assert_eq!(Chatlist::try_load(&bob, 0, None, None).await?.len(), 1);
let sent = bob.pop_sent_msg().await;
assert_eq!(
sent.recipient(),
EmailAddress::new("alice@example.org").unwrap()
);
let msg = alice.parse_msg(&sent).await;
assert!(!msg.was_encrypted());
assert_eq!(msg.get_header(HeaderDef::SecureJoin).unwrap(), "vg-request");
assert!(msg.get_header(HeaderDef::SecureJoinInvitenumber).is_some());
// Step 3: Alice receives vg-request, sends vg-auth-required
alice.recv_msg(&sent).await;
let sent = alice.pop_sent_msg().await;
let msg = bob.parse_msg(&sent).await;
assert!(msg.was_encrypted());
assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vg-auth-required"
);
// Step 4: Bob receives vg-auth-required, sends vg-request-with-auth
bob.recv_msg(&sent).await;
let sent = bob.pop_sent_msg().await;
// Check Bob emitted the JoinerProgress event.
let event = bob
.evtracker
.get_matching(|evt| matches!(evt, EventType::SecurejoinJoinerProgress { .. }))
.await;
match event {
EventType::SecurejoinJoinerProgress {
contact_id,
progress,
} => {
let alice_contact_id =
Contact::lookup_id_by_addr(&bob.ctx, "alice@example.org", Origin::Unknown)
.await
.expect("Error looking up contact")
.expect("Contact not found");
assert_eq!(contact_id, alice_contact_id);
assert_eq!(progress, 400);
}
_ => unreachable!(),
}
// Check Bob sent the right handshake message.
let msg = alice.parse_msg(&sent).await;
assert!(msg.was_encrypted());
assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vg-request-with-auth"
);
assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some());
let bob_fp = SignedPublicKey::load_self(&bob.ctx).await?.fingerprint();
assert_eq!(
*msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(),
bob_fp.hex()
);
// Alice should not yet have Bob verified
let contact_bob_id =
Contact::lookup_id_by_addr(&alice.ctx, "bob@example.net", Origin::Unknown)
.await?
.expect("Contact not found");
let contact_bob = Contact::load_from_db(&alice.ctx, contact_bob_id).await?;
assert_eq!(
contact_bob.is_verified(&alice.ctx).await?,
VerifiedStatus::Unverified
);
// Step 5+6: Alice receives vg-request-with-auth, sends vg-member-added
alice.recv_msg(&sent).await;
assert_eq!(
contact_bob.is_verified(&alice.ctx).await?,
VerifiedStatus::BidirectVerified
);
let sent = alice.pop_sent_msg().await;
let msg = bob.parse_msg(&sent).await;
assert!(msg.was_encrypted());
assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vg-member-added"
);
{
// Now Alice's chat with Bob should still be hidden, the verified message should
// appear in the group chat.
let chat = alice
.get_chat(&bob)
.await .await
.expect("Alice has no 1:1 chat with bob"); .unwrap();
// Step 2: Bob scans QR-code, sends vg-request
let bob_chatid = join_securejoin(&bob.ctx, &qr).await?;
assert_eq!(Chatlist::try_load(&bob, 0, None, None).await?.len(), 1);
let sent = bob.pop_sent_msg().await;
assert_eq!( assert_eq!(
chat.blocked, sent.recipient(),
Blocked::Yes, EmailAddress::new("alice@example.org").unwrap()
"Alice's 1:1 chat with Bob is not hidden"
); );
let msg_id = chat::get_chat_msgs(&alice.ctx, alice_chatid, DC_GCM_ADDDAYMARKER) let msg = alice.parse_msg(&sent).await;
.await assert!(!msg.was_encrypted());
.unwrap() assert_eq!(msg.get_header(HeaderDef::SecureJoin).unwrap(), "vg-request");
.into_iter() assert!(msg.get_header(HeaderDef::SecureJoinInvitenumber).is_some());
.filter_map(|item| match item {
chat::ChatItem::Message { msg_id } => Some(msg_id),
_ => None,
})
.min()
.expect("No messages in Alice's group chat");
let msg = Message::load_from_db(&alice.ctx, msg_id).await.unwrap();
assert!(msg.is_info());
let text = msg.get_text().unwrap();
assert!(text.contains("bob@example.net verified"));
}
// Bob should not yet have Alice verified // Step 3: Alice receives vg-request, sends vg-auth-required
let contact_alice_id = alice.recv_msg(&sent).await;
Contact::lookup_id_by_addr(&bob.ctx, "alice@example.org", Origin::Unknown)
.await
.expect("Error looking up contact")
.expect("Contact not found");
let contact_alice = Contact::load_from_db(&bob.ctx, contact_alice_id).await?;
assert_eq!(
contact_bob.is_verified(&bob.ctx).await?,
VerifiedStatus::Unverified
);
// Step 7: Bob receives vg-member-added, sends vg-member-added-received let sent = alice.pop_sent_msg().await;
bob.recv_msg(&sent).await; let msg = bob.parse_msg(&sent).await;
{ assert!(msg.was_encrypted());
// Bob has Alice verified, message shows up in the group chat.
assert_eq!( assert_eq!(
contact_alice.is_verified(&bob.ctx).await?, msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vg-auth-required"
);
// Step 4: Bob receives vg-auth-required, sends vg-request-with-auth
bob.recv_msg(&sent).await;
let sent = bob.pop_sent_msg().await;
// Check Bob emitted the JoinerProgress event.
let event = bob
.evtracker
.get_matching(|evt| matches!(evt, EventType::SecurejoinJoinerProgress { .. }))
.await;
match event {
EventType::SecurejoinJoinerProgress {
contact_id,
progress,
} => {
let alice_contact_id =
Contact::lookup_id_by_addr(&bob.ctx, "alice@example.org", Origin::Unknown)
.await
.expect("Error looking up contact")
.expect("Contact not found");
assert_eq!(contact_id, alice_contact_id);
assert_eq!(progress, 400);
}
_ => unreachable!(),
}
// Check Bob sent the right handshake message.
let msg = alice.parse_msg(&sent).await;
assert!(msg.was_encrypted());
assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vg-request-with-auth"
);
assert!(msg.get_header(HeaderDef::SecureJoinAuth).is_some());
let bob_fp = SignedPublicKey::load_self(&bob.ctx).await?.fingerprint();
assert_eq!(
*msg.get_header(HeaderDef::SecureJoinFingerprint).unwrap(),
bob_fp.hex()
);
// Alice should not yet have Bob verified
let contact_bob_id =
Contact::lookup_id_by_addr(&alice.ctx, "bob@example.net", Origin::Unknown)
.await?
.expect("Contact not found");
let contact_bob = Contact::load_from_db(&alice.ctx, contact_bob_id).await?;
assert_eq!(
contact_bob.is_verified(&alice.ctx).await?,
VerifiedStatus::Unverified
);
// Step 5+6: Alice receives vg-request-with-auth, sends vg-member-added
alice.recv_msg(&sent).await;
assert_eq!(
contact_bob.is_verified(&alice.ctx).await?,
VerifiedStatus::BidirectVerified VerifiedStatus::BidirectVerified
); );
let chat = bob
.get_chat(&alice) let sent = alice.pop_sent_msg().await;
.await let msg = bob.parse_msg(&sent).await;
.expect("Bob has no 1:1 chat with Alice"); assert!(msg.was_encrypted());
assert_eq!( assert_eq!(
chat.blocked, msg.get_header(HeaderDef::SecureJoin).unwrap(),
Blocked::Yes, "vg-member-added"
"Bob's 1:1 chat with Alice is not hidden"
); );
for item in chat::get_chat_msgs(&bob.ctx, bob_chatid, DC_GCM_ADDDAYMARKER)
.await
.unwrap()
{ {
if let chat::ChatItem::Message { msg_id } = item { // Now Alice's chat with Bob should still be hidden, the verified message should
let msg = Message::load_from_db(&bob.ctx, msg_id).await.unwrap(); // appear in the group chat.
let text = msg.get_text().unwrap();
println!("msg {} text: {}", msg_id, text); let chat = alice
} .get_chat(&bob)
.await
.expect("Alice has no 1:1 chat with bob");
assert_eq!(
chat.blocked,
Blocked::Yes,
"Alice's 1:1 chat with Bob is not hidden"
);
let msg_id = chat::get_chat_msgs(&alice.ctx, alice_chatid, DC_GCM_ADDDAYMARKER)
.await
.unwrap()
.into_iter()
.filter_map(|item| match item {
chat::ChatItem::Message { msg_id } => Some(msg_id),
_ => None,
})
.min()
.expect("No messages in Alice's group chat");
let msg = Message::load_from_db(&alice.ctx, msg_id).await.unwrap();
assert!(msg.is_info());
let text = msg.get_text().unwrap();
assert!(text.contains("bob@example.net verified"));
} }
let mut msg_iter = chat::get_chat_msgs(&bob.ctx, bob_chatid, DC_GCM_ADDDAYMARKER)
.await // Bob should not yet have Alice verified
.unwrap() let contact_alice_id =
.into_iter(); Contact::lookup_id_by_addr(&bob.ctx, "alice@example.org", Origin::Unknown)
loop { .await
match msg_iter.next() { .expect("Error looking up contact")
Some(chat::ChatItem::Message { msg_id }) => { .expect("Contact not found");
let contact_alice = Contact::load_from_db(&bob.ctx, contact_alice_id).await?;
assert_eq!(
contact_bob.is_verified(&bob.ctx).await?,
VerifiedStatus::Unverified
);
// Step 7: Bob receives vg-member-added, sends vg-member-added-received
bob.recv_msg(&sent).await;
{
// Bob has Alice verified, message shows up in the group chat.
assert_eq!(
contact_alice.is_verified(&bob.ctx).await?,
VerifiedStatus::BidirectVerified
);
let chat = bob
.get_chat(&alice)
.await
.expect("Bob has no 1:1 chat with Alice");
assert_eq!(
chat.blocked,
Blocked::Yes,
"Bob's 1:1 chat with Alice is not hidden"
);
for item in chat::get_chat_msgs(&bob.ctx, bob_chatid, DC_GCM_ADDDAYMARKER)
.await
.unwrap()
{
if let chat::ChatItem::Message { msg_id } = item {
let msg = Message::load_from_db(&bob.ctx, msg_id).await.unwrap(); let msg = Message::load_from_db(&bob.ctx, msg_id).await.unwrap();
let text = msg.get_text().unwrap(); let text = msg.get_text().unwrap();
match text.contains("alice@example.org verified") { println!("msg {} text: {}", msg_id, text);
true => { }
assert!(msg.is_info()); }
break; let mut msg_iter = chat::get_chat_msgs(&bob.ctx, bob_chatid, DC_GCM_ADDDAYMARKER)
} .await
false => continue, .unwrap()
} .into_iter();
loop {
match msg_iter.next() {
Some(chat::ChatItem::Message { msg_id }) => {
let msg = Message::load_from_db(&bob.ctx, msg_id).await.unwrap();
let text = msg.get_text().unwrap();
match text.contains("alice@example.org verified") {
true => {
assert!(msg.is_info());
break;
}
false => continue,
}
}
Some(_) => continue,
None => panic!("Verified message not found in Bob's group chat"),
} }
Some(_) => continue,
None => panic!("Verified message not found in Bob's group chat"),
} }
} }
}
let sent = bob.pop_sent_msg().await; let sent = bob.pop_sent_msg().await;
let msg = alice.parse_msg(&sent).await; let msg = alice.parse_msg(&sent).await;
assert!(msg.was_encrypted()); assert!(msg.was_encrypted());
assert_eq!( assert_eq!(
msg.get_header(HeaderDef::SecureJoin).unwrap(), msg.get_header(HeaderDef::SecureJoin).unwrap(),
"vg-member-added-received" "vg-member-added-received"
); );
let bob_chat = Chat::load_from_db(&bob.ctx, bob_chatid).await?; let bob_chat = Chat::load_from_db(&bob.ctx, bob_chatid).await?;
assert!(bob_chat.is_protected()); assert!(bob_chat.is_protected());
assert!(bob_chat.typ == Chattype::Group); assert!(bob_chat.typ == Chattype::Group);
// On this "happy path", Alice and Bob get only a group-chat where all information are added to. // On this "happy path", Alice and Bob get only a group-chat where all information are added to.
// The one-to-one chats are used internally for the hidden handshake messages, // The one-to-one chats are used internally for the hidden handshake messages,
// however, should not be visible in the UIs. // however, should not be visible in the UIs.
assert_eq!(Chatlist::try_load(&alice, 0, None, None).await?.len(), 1); assert_eq!(Chatlist::try_load(&alice, 0, None, None).await?.len(), 1);
assert_eq!(Chatlist::try_load(&bob, 0, None, None).await?.len(), 1); assert_eq!(Chatlist::try_load(&bob, 0, None, None).await?.len(), 1);
// If Bob then sends a direct message to alice, however, the one-to-one with Alice should appear. // If Bob then sends a direct message to alice, however, the one-to-one with Alice should appear.
let bobs_chat_with_alice = bob.create_chat(&alice).await; let bobs_chat_with_alice = bob.create_chat(&alice).await;
let sent = bob.send_text(bobs_chat_with_alice.id, "Hello").await; let sent = bob.send_text(bobs_chat_with_alice.id, "Hello").await;
alice.recv_msg(&sent).await; alice.recv_msg(&sent).await;
assert_eq!(Chatlist::try_load(&alice, 0, None, None).await?.len(), 2); assert_eq!(Chatlist::try_load(&alice, 0, None, None).await?.len(), 2);
assert_eq!(Chatlist::try_load(&bob, 0, None, None).await?.len(), 2); assert_eq!(Chatlist::try_load(&bob, 0, None, None).await?.len(), 2);
Ok(()) Ok(())
});
return tokio::runtime::Builder::new_multi_thread()
.worker_threads(2usize)
.enable_all()
.build()
.expect("Failed building the Runtime")
.block_on(body);
} }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]