mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
This can only result in adding unencrypted email-contacts and we do not want to encourage creating unencrypted chats.
305 lines
10 KiB
Rust
305 lines
10 KiB
Rust
use super::*;
|
|
use crate::contact::Contact;
|
|
use crate::test_utils::TestContext;
|
|
|
|
#[test]
|
|
fn test_get_folder_meaning_by_name() {
|
|
assert_eq!(get_folder_meaning_by_name("xxx"), FolderMeaning::Unknown);
|
|
assert_eq!(get_folder_meaning_by_name("SPAM"), FolderMeaning::Spam);
|
|
assert_eq!(get_folder_meaning_by_name("Trash"), FolderMeaning::Trash);
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_set_uid_next_validity() {
|
|
let t = TestContext::new_alice().await;
|
|
assert_eq!(get_uid_next(&t.ctx, 1, "Inbox").await.unwrap(), 0);
|
|
assert_eq!(get_uidvalidity(&t.ctx, 1, "Inbox").await.unwrap(), 0);
|
|
|
|
set_uidvalidity(&t.ctx, 1, "Inbox", 7).await.unwrap();
|
|
assert_eq!(get_uidvalidity(&t.ctx, 1, "Inbox").await.unwrap(), 7);
|
|
assert_eq!(get_uid_next(&t.ctx, 1, "Inbox").await.unwrap(), 0);
|
|
|
|
// For another transport there is still no UIDVALIDITY set.
|
|
assert_eq!(get_uidvalidity(&t.ctx, 2, "Inbox").await.unwrap(), 0);
|
|
|
|
set_uid_next(&t.ctx, 1, "Inbox", 5).await.unwrap();
|
|
set_uidvalidity(&t.ctx, 1, "Inbox", 6).await.unwrap();
|
|
assert_eq!(get_uid_next(&t.ctx, 1, "Inbox").await.unwrap(), 5);
|
|
assert_eq!(get_uidvalidity(&t.ctx, 1, "Inbox").await.unwrap(), 6);
|
|
|
|
assert_eq!(get_uid_next(&t.ctx, 2, "Inbox").await.unwrap(), 0);
|
|
assert_eq!(get_uidvalidity(&t.ctx, 2, "Inbox").await.unwrap(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_build_sequence_sets() {
|
|
assert_eq!(build_sequence_sets(&[]).unwrap(), vec![]);
|
|
|
|
let cases = vec![
|
|
(vec![1], "1"),
|
|
(vec![3291], "3291"),
|
|
(vec![1, 3, 5, 7, 9, 11], "1,3,5,7,9,11"),
|
|
(vec![1, 2, 3], "1:3"),
|
|
(vec![1, 4, 5, 6], "1,4:6"),
|
|
((1..=500).collect(), "1:500"),
|
|
(vec![3, 4, 8, 9, 10, 11, 39, 50, 2], "3:4,8:11,39,50,2"),
|
|
];
|
|
for (input, s) in cases {
|
|
assert_eq!(
|
|
build_sequence_sets(&input).unwrap(),
|
|
vec![(input, s.into())]
|
|
);
|
|
}
|
|
|
|
let has_number = |(uids, s): &(Vec<u32>, String), number| {
|
|
uids.contains(&number) && s.split(',').any(|n| n.parse::<u32>().unwrap() == number)
|
|
};
|
|
|
|
let numbers: Vec<_> = (2..=500).step_by(2).collect();
|
|
let result = build_sequence_sets(&numbers).unwrap();
|
|
for (_, set) in &result {
|
|
assert!(set.len() < 1010);
|
|
assert!(!set.ends_with(','));
|
|
assert!(!set.starts_with(','));
|
|
}
|
|
assert!(result.len() == 1); // these UIDs fit in one set
|
|
for &number in &numbers {
|
|
assert!(result.iter().any(|r| has_number(r, number)));
|
|
}
|
|
|
|
let numbers: Vec<_> = (1..=1000).step_by(3).collect();
|
|
let result = build_sequence_sets(&numbers).unwrap();
|
|
for (_, set) in &result {
|
|
assert!(set.len() < 1010);
|
|
assert!(!set.ends_with(','));
|
|
assert!(!set.starts_with(','));
|
|
}
|
|
let (last_uids, last_str) = result.last().unwrap();
|
|
assert_eq!(
|
|
last_uids.get((last_uids.len() - 2)..).unwrap(),
|
|
&[997, 1000]
|
|
);
|
|
assert!(last_str.ends_with("997,1000"));
|
|
assert!(result.len() == 2); // This time we need 2 sets
|
|
for &number in &numbers {
|
|
assert!(result.iter().any(|r| has_number(r, number)));
|
|
}
|
|
|
|
let numbers: Vec<_> = (30000000..=30002500).step_by(4).collect();
|
|
let result = build_sequence_sets(&numbers).unwrap();
|
|
for (_, set) in &result {
|
|
assert!(set.len() < 1010);
|
|
assert!(!set.ends_with(','));
|
|
assert!(!set.starts_with(','));
|
|
}
|
|
assert_eq!(result.len(), 6);
|
|
for &number in &numbers {
|
|
assert!(result.iter().any(|r| has_number(r, number)));
|
|
}
|
|
}
|
|
|
|
async fn check_target_folder_combination(
|
|
folder: &str,
|
|
mvbox_move: bool,
|
|
chat_msg: bool,
|
|
expected_destination: &str,
|
|
accepted_chat: bool,
|
|
outgoing: bool,
|
|
setupmessage: bool,
|
|
) -> Result<()> {
|
|
println!(
|
|
"Testing: For folder {folder}, mvbox_move {mvbox_move}, chat_msg {chat_msg}, accepted {accepted_chat}, outgoing {outgoing}, setupmessage {setupmessage}"
|
|
);
|
|
|
|
let t = TestContext::new_alice().await;
|
|
t.ctx
|
|
.set_config(Config::ConfiguredMvboxFolder, Some("DeltaChat"))
|
|
.await?;
|
|
t.ctx
|
|
.set_config(Config::MvboxMove, Some(if mvbox_move { "1" } else { "0" }))
|
|
.await?;
|
|
|
|
if accepted_chat {
|
|
let contact_id = Contact::create(&t.ctx, "", "bob@example.net").await?;
|
|
ChatId::create_for_contact(&t.ctx, contact_id).await?;
|
|
}
|
|
let temp;
|
|
|
|
let bytes = if setupmessage {
|
|
include_bytes!("../../test-data/message/AutocryptSetupMessage.eml")
|
|
} else {
|
|
temp = format!(
|
|
"Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
|
|
{}\
|
|
Subject: foo\n\
|
|
Message-ID: <abc@example.com>\n\
|
|
{}\
|
|
Date: Sun, 22 Mar 2020 22:37:57 +0000\n\
|
|
\n\
|
|
hello\n",
|
|
if outgoing {
|
|
"From: alice@example.org\nTo: bob@example.net\n"
|
|
} else {
|
|
"From: bob@example.net\nTo: alice@example.org\n"
|
|
},
|
|
if chat_msg { "Chat-Version: 1.0\n" } else { "" },
|
|
);
|
|
temp.as_bytes()
|
|
};
|
|
|
|
let (headers, _) = mailparse::parse_headers(bytes)?;
|
|
let actual = if let Some(config) =
|
|
target_folder_cfg(&t, folder, get_folder_meaning_by_name(folder), &headers).await?
|
|
{
|
|
t.get_config(config).await?
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let expected = if expected_destination == folder {
|
|
None
|
|
} else {
|
|
Some(expected_destination)
|
|
};
|
|
assert_eq!(
|
|
expected,
|
|
actual.as_deref(),
|
|
"For folder {folder}, mvbox_move {mvbox_move}, chat_msg {chat_msg}, accepted {accepted_chat}, outgoing {outgoing}, setupmessage {setupmessage}: expected {expected:?}, got {actual:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
// chat_msg means that the message was sent by Delta Chat
|
|
// The tuples are (folder, mvbox_move, chat_msg, expected_destination)
|
|
const COMBINATIONS_ACCEPTED_CHAT: &[(&str, bool, bool, &str)] = &[
|
|
("INBOX", false, false, "INBOX"),
|
|
("INBOX", false, true, "INBOX"),
|
|
("INBOX", true, false, "INBOX"),
|
|
("INBOX", true, true, "DeltaChat"),
|
|
("Spam", false, false, "INBOX"), // Move classical emails in accepted chats from Spam to Inbox, not 100% sure on this, we could also just never move non-chat-msgs
|
|
("Spam", false, true, "INBOX"),
|
|
("Spam", true, false, "INBOX"), // Move classical emails in accepted chats from Spam to Inbox, not 100% sure on this, we could also just never move non-chat-msgs
|
|
("Spam", true, true, "DeltaChat"),
|
|
];
|
|
|
|
// These are the same as above, but non-chat messages in Spam stay in Spam
|
|
const COMBINATIONS_REQUEST: &[(&str, bool, bool, &str)] = &[
|
|
("INBOX", false, false, "INBOX"),
|
|
("INBOX", false, true, "INBOX"),
|
|
("INBOX", true, false, "INBOX"),
|
|
("INBOX", true, true, "DeltaChat"),
|
|
("Spam", false, false, "Spam"),
|
|
("Spam", false, true, "INBOX"),
|
|
("Spam", true, false, "Spam"),
|
|
("Spam", true, true, "DeltaChat"),
|
|
];
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_target_folder_incoming_accepted() -> Result<()> {
|
|
for (folder, mvbox_move, chat_msg, expected_destination) in COMBINATIONS_ACCEPTED_CHAT {
|
|
check_target_folder_combination(
|
|
folder,
|
|
*mvbox_move,
|
|
*chat_msg,
|
|
expected_destination,
|
|
true,
|
|
false,
|
|
false,
|
|
)
|
|
.await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_target_folder_incoming_request() -> Result<()> {
|
|
for (folder, mvbox_move, chat_msg, expected_destination) in COMBINATIONS_REQUEST {
|
|
check_target_folder_combination(
|
|
folder,
|
|
*mvbox_move,
|
|
*chat_msg,
|
|
expected_destination,
|
|
false,
|
|
false,
|
|
false,
|
|
)
|
|
.await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_target_folder_outgoing() -> Result<()> {
|
|
// Test outgoing emails
|
|
for (folder, mvbox_move, chat_msg, expected_destination) in COMBINATIONS_ACCEPTED_CHAT {
|
|
check_target_folder_combination(
|
|
folder,
|
|
*mvbox_move,
|
|
*chat_msg,
|
|
expected_destination,
|
|
true,
|
|
true,
|
|
false,
|
|
)
|
|
.await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
async fn test_target_folder_setupmsg() -> Result<()> {
|
|
// Test setupmessages
|
|
for (folder, mvbox_move, chat_msg, _expected_destination) in COMBINATIONS_ACCEPTED_CHAT {
|
|
check_target_folder_combination(
|
|
folder,
|
|
*mvbox_move,
|
|
*chat_msg,
|
|
if folder == &"Spam" { "INBOX" } else { folder }, // Never move setup messages, except if they are in "Spam"
|
|
false,
|
|
true,
|
|
true,
|
|
)
|
|
.await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_uid_grouper() {
|
|
// Input: sequence of (rowid: i64, uid: u32, target: String)
|
|
// Output: sequence of (target: String, rowid_set: Vec<i64>, uid_set: String)
|
|
let grouper = UidGrouper::from([(1, 2, "INBOX".to_string())]);
|
|
let res: Vec<(String, Vec<i64>, String)> = grouper.into_iter().collect();
|
|
assert_eq!(res, vec![("INBOX".to_string(), vec![1], "2".to_string())]);
|
|
|
|
let grouper = UidGrouper::from([(1, 2, "INBOX".to_string()), (2, 3, "INBOX".to_string())]);
|
|
let res: Vec<(String, Vec<i64>, String)> = grouper.into_iter().collect();
|
|
assert_eq!(
|
|
res,
|
|
vec![("INBOX".to_string(), vec![1, 2], "2:3".to_string())]
|
|
);
|
|
|
|
let grouper = UidGrouper::from([
|
|
(1, 2, "INBOX".to_string()),
|
|
(2, 2, "INBOX".to_string()),
|
|
(3, 3, "INBOX".to_string()),
|
|
]);
|
|
let res: Vec<(String, Vec<i64>, String)> = grouper.into_iter().collect();
|
|
assert_eq!(
|
|
res,
|
|
vec![("INBOX".to_string(), vec![1, 2, 3], "2:3".to_string())]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_setmetadata_device_token() {
|
|
assert_eq!(
|
|
format_setmetadata("INBOX", "foobarbaz"),
|
|
"SETMETADATA \"INBOX\" (/private/devicetoken {9+}\r\nfoobarbaz)"
|
|
);
|
|
assert_eq!(
|
|
format_setmetadata("INBOX", "foo\r\nbar\r\nbaz\r\n"),
|
|
"SETMETADATA \"INBOX\" (/private/devicetoken {15+}\r\nfoo\r\nbar\r\nbaz\r\n)"
|
|
);
|
|
}
|