| use super::*; |
| use crate::test_utils::TestContext; |
| use crate::transport::add_pseudo_transport; |
|
|
| #[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); |
|
|
| |
| 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); |
| 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); |
| 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(()) |
| } |
|
|
| |
| |
| 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"), |
| ("Spam", false, true, "INBOX"), |
| ("Spam", true, false, "INBOX"), |
| ("Spam", true, true, "DeltaChat"), |
| ]; |
|
|
| |
| 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<()> { |
| |
| 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<()> { |
| |
| 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 }, |
| false, |
| true, |
| true, |
| ) |
| .await?; |
| } |
| Ok(()) |
| } |
|
|
| #[tokio::test(flavor = "multi_thread", worker_threads = 2)] |
| async fn test_get_imap_search_command() -> Result<()> { |
| let t = TestContext::new_alice().await; |
| assert_eq!( |
| get_imap_self_sent_search_command(&t.ctx).await?, |
| r#"FROM "alice@example.org""# |
| ); |
|
|
| add_pseudo_transport(&t, "alice@another.com").await?; |
| t.ctx.set_primary_self_addr("alice@another.com").await?; |
| assert_eq!( |
| get_imap_self_sent_search_command(&t.ctx).await?, |
| r#"OR (FROM "alice@another.com") (FROM "alice@example.org")"# |
| ); |
|
|
| add_pseudo_transport(&t, "alice@third.com").await?; |
| t.ctx.set_primary_self_addr("alice@third.com").await?; |
| assert_eq!( |
| get_imap_self_sent_search_command(&t.ctx).await?, |
| r#"OR (OR (FROM "alice@third.com") (FROM "alice@another.com")) (FROM "alice@example.org")"# |
| ); |
|
|
| Ok(()) |
| } |
|
|
| #[test] |
| fn test_uid_grouper() { |
| |
| |
| 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)" |
| ); |
| } |
|
|