瀏覽代碼

maildir: add mailbox creation tests

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
Manos Pitsidianakis 7 月之前
父節點
當前提交
fd243fa5ab
共有 1 個文件被更改,包括 316 次插入3 次删除
  1. 316 3
      melib/src/maildir/tests.rs

+ 316 - 3
melib/src/maildir/tests.rs

@@ -20,15 +20,19 @@
 //
 //
 // SPDX-License-Identifier: EUPL-1.2 OR GPL-3.0-or-later
 // SPDX-License-Identifier: EUPL-1.2 OR GPL-3.0-or-later
 
 
-use std::path::{Path, PathBuf};
+use std::{
+    path::{Path, PathBuf},
+    sync::Arc,
+};
 
 
 use regex::Regex;
 use regex::Regex;
+use tempfile::TempDir;
 
 
 use crate::{
 use crate::{
-    backends::FlagOp,
+    backends::prelude::*,
     email::Flag,
     email::Flag,
     error::Result,
     error::Result,
-    maildir::{move_to_cur, Configuration, MaildirPathTrait},
+    maildir::{move_to_cur, Configuration, MaildirMailbox, MaildirPathTrait, MaildirType},
 };
 };
 
 
 fn set_flags(config: &Configuration, path: &Path, flag_ops: &[FlagOp]) -> Result<PathBuf> {
 fn set_flags(config: &Configuration, path: &Path, flag_ops: &[FlagOp]) -> Result<PathBuf> {
@@ -232,3 +236,312 @@ fn test_maildir_place_in_dir_regexp() {
         "place_in_dir() should add missing `:2,` substring"
         "place_in_dir() should add missing `:2,` substring"
     );
     );
 }
 }
+
+fn new_maildir_backend(
+    temp_dir: &TempDir,
+    acc_name: &str,
+    event_consumer: BackendEventConsumer,
+    with_root_mailbox: bool,
+) -> Result<(PathBuf, AccountSettings, Box<MaildirType>)> {
+    let root_mailbox = temp_dir.path().join("INBOX");
+    {
+        std::fs::create_dir(&root_mailbox).expect("Could not create root mailbox directory.");
+        if with_root_mailbox {
+            for d in &["cur", "new", "tmp"] {
+                std::fs::create_dir(root_mailbox.join(d))
+                    .expect("Could not create root mailbox directory contents.");
+            }
+        }
+    }
+    let subscribed_mailboxes = if with_root_mailbox {
+        vec!["INBOX".into()]
+    } else {
+        vec![]
+    };
+    let mailboxes = if with_root_mailbox {
+        vec![(
+            "INBOX".into(),
+            crate::conf::MailboxConf {
+                extra: indexmap::indexmap! {
+                    "path".into() => root_mailbox.display().to_string(),
+                },
+                ..Default::default()
+            },
+        )]
+        .into_iter()
+        .collect()
+    } else {
+        indexmap::indexmap! {}
+    };
+    let extra = if with_root_mailbox {
+        indexmap::indexmap! {
+            "root_mailbox".into() => root_mailbox.display().to_string(),
+        }
+    } else {
+        indexmap::indexmap! {}
+    };
+
+    let account_conf = AccountSettings {
+        name: acc_name.to_string(),
+        root_mailbox: root_mailbox.display().to_string(),
+        format: "maildir".to_string(),
+        identity: "user@localhost".to_string(),
+        extra_identities: vec![],
+        read_only: false,
+        display_name: None,
+        order: Default::default(),
+        subscribed_mailboxes,
+        mailboxes,
+        manual_refresh: true,
+        extra,
+    };
+
+    let maildir = MaildirType::new(&account_conf, Default::default(), event_consumer)?;
+    Ok((root_mailbox, account_conf, maildir))
+}
+
+#[test]
+fn test_maildir_mailbox_paths() {
+    let temp_dir = TempDir::new().unwrap();
+    let backend_event_queue = Arc::new(std::sync::Mutex::new(
+        std::collections::VecDeque::with_capacity(16),
+    ));
+
+    let backend_event_consumer = {
+        let backend_event_queue = Arc::clone(&backend_event_queue);
+
+        BackendEventConsumer::new(Arc::new(move |ah, be| {
+            backend_event_queue.lock().unwrap().push_back((ah, be));
+        }))
+    };
+
+    // Perform tests on a maildir backend where the root mailbox, is not a valid
+    // maildir mailbox (e.g. has no cur,new,tmp sub directories.
+    {
+        let (root_mailbox, _settings, maildir) =
+            new_maildir_backend(&temp_dir, "maildir", backend_event_consumer.clone(), false)
+                .unwrap();
+        assert!(!maildir.config.is_root_a_mailbox);
+        // Assert that giving a file system path to MaildirBox::new is valid
+        let new_mailbox = MaildirMailbox::new(
+            root_mailbox.join("Archive").display().to_string(),
+            "Archive".into(),
+            None,
+            vec![],
+            true,
+            &maildir.config,
+        )
+        .unwrap();
+        assert_eq!(new_mailbox.name, "Archive");
+        assert_eq!(&new_mailbox.path, &Path::new("Archive"));
+        assert_eq!(&new_mailbox.fs_path, &root_mailbox.join("Archive"));
+        // Assert that giving a mailbox path to MaildirBox::new is valid
+        let new_mailbox = MaildirMailbox::new(
+            "INBOX/Archive".into(),
+            "Archive".into(),
+            None,
+            vec![],
+            true,
+            &maildir.config,
+        )
+        .unwrap();
+        assert_eq!(new_mailbox.name, "Archive");
+        assert_eq!(&new_mailbox.path, &Path::new("Archive"));
+        assert_eq!(&new_mailbox.fs_path, &root_mailbox.join("Archive"));
+        let mut backend = maildir as Box<dyn MailBackend>;
+        let ref_mailboxes = smol::block_on(backend.mailboxes().unwrap()).unwrap();
+        // Assert that backend has no mailboxes at all");
+        assert!(
+            ref_mailboxes.is_empty(),
+            "ref_mailboxes were not empty: {:?}",
+            ref_mailboxes
+        );
+        let (new_hash, ref_mailboxes) =
+            smol::block_on(backend.create_mailbox("Archive".into()).unwrap()).unwrap();
+        assert_eq!(ref_mailboxes[&new_hash].name(), "Archive");
+        assert_eq!(ref_mailboxes[&new_hash].path(), "Archive");
+        assert_eq!(
+            ref_mailboxes[&new_hash]
+                .as_any()
+                .downcast_ref::<MaildirMailbox>()
+                .unwrap()
+                .fs_path(),
+            &root_mailbox.join("Archive")
+        );
+        // Assert that even if we accidentally give a file system path to a maildir
+        // backend's create_mailbox() method, it still does the correct thing.
+        let (new_hash, ref_mailboxes) = smol::block_on(
+            backend
+                .create_mailbox(root_mailbox.join("Archive2").display().to_string())
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(ref_mailboxes[&new_hash].name(), "Archive2");
+        assert_eq!(ref_mailboxes[&new_hash].path(), "Archive2");
+        assert_eq!(
+            ref_mailboxes[&new_hash]
+                .as_any()
+                .downcast_ref::<MaildirMailbox>()
+                .unwrap()
+                .fs_path(),
+            &root_mailbox.join("Archive2")
+        );
+        let ref_mailboxes = smol::block_on(backend.mailboxes().unwrap()).unwrap();
+        // Assert that backend has all the created mailboxes so far
+        assert_eq!(
+            ref_mailboxes.len(),
+            2,
+            "mailboxes() return value content not what expected: {:?}",
+            ref_mailboxes
+        );
+        // Assert that giving an absolute path returns an error
+        assert_eq!(
+            &smol::block_on(backend.create_mailbox("/Archive3".to_string()).unwrap())
+                .unwrap_err()
+                .to_string(),
+            "Path given (`/Archive3`) is absolute. Please provide a path relative to the \
+             account's root mailbox."
+        );
+        // Assert that attempting to create a mailbox outside of the root mailbox
+        // returns an error
+        assert_eq!(
+            &smol::block_on(
+                backend
+                    .create_mailbox(temp_dir.path().join("Archive3").display().to_string())
+                    .unwrap()
+            )
+            .unwrap_err()
+            .to_string(),
+            &format!(
+                "Path given, `{}`, is not included in the root mailbox path `{}`. A maildir \
+                 backend cannot contain mailboxes outside of its root path.",
+                temp_dir.path().join("Archive3").display(),
+                root_mailbox.display(),
+            )
+        );
+
+        std::fs::remove_dir_all(root_mailbox).unwrap();
+    }
+
+    // Perform same tests on a maildir backend where the root mailbox is a valid
+    // maildir mailbox (e.g. has cur,new,tmp sub directories.
+    {
+        let (root_mailbox, _settings, maildir) =
+            new_maildir_backend(&temp_dir, "maildir", backend_event_consumer, true).unwrap();
+        assert!(maildir.config.is_root_a_mailbox);
+        // Assert that giving a file system path to MaildirBox::new is valid
+        let new_mailbox = MaildirMailbox::new(
+            root_mailbox.join("Archive").display().to_string(),
+            "Archive".into(),
+            None,
+            vec![],
+            true,
+            &maildir.config,
+        )
+        .unwrap();
+        assert_eq!(new_mailbox.name, "Archive");
+        assert_eq!(&new_mailbox.path, &Path::new("INBOX/Archive"));
+        assert_eq!(&new_mailbox.fs_path, &root_mailbox.join("Archive"));
+        // Assert that giving a mailbox path to MaildirBox::new is valid
+        let new_mailbox = MaildirMailbox::new(
+            "INBOX/Archive".into(),
+            "Archive".into(),
+            None,
+            vec![],
+            true,
+            &maildir.config,
+        )
+        .unwrap();
+        assert_eq!(new_mailbox.name, "Archive");
+        assert_eq!(&new_mailbox.path, &Path::new("INBOX/Archive"));
+        assert_eq!(&new_mailbox.fs_path, &root_mailbox.join("Archive"));
+        let mut backend = maildir as Box<dyn MailBackend>;
+        let ref_mailboxes = smol::block_on(backend.mailboxes().unwrap()).unwrap();
+        // Assert that backend has only INBOX as a mailbox
+        assert_eq!(
+            ref_mailboxes.len(),
+            1,
+            "ref_mailboxes is not just INBOX: {:?}",
+            ref_mailboxes
+        );
+        // Assert that creating a mailbox without the root mailbox as a prefix does the
+        // correct thing.
+        let (new_hash, ref_mailboxes) =
+            smol::block_on(backend.create_mailbox("Archive".into()).unwrap()).unwrap();
+        assert_eq!(ref_mailboxes[&new_hash].name(), "Archive");
+        assert_eq!(ref_mailboxes[&new_hash].path(), "INBOX/Archive");
+        assert_eq!(
+            ref_mailboxes[&new_hash]
+                .as_any()
+                .downcast_ref::<MaildirMailbox>()
+                .unwrap()
+                .fs_path(),
+            &root_mailbox.join("Archive")
+        );
+        // Assert that creating a mailbox with the root mailbox as a prefix does the
+        // correct thing.
+        let (new_hash, ref_mailboxes) =
+            smol::block_on(backend.create_mailbox("INBOX/Archive2".into()).unwrap()).unwrap();
+        assert_eq!(ref_mailboxes[&new_hash].name(), "Archive2");
+        assert_eq!(ref_mailboxes[&new_hash].path(), "INBOX/Archive2");
+        assert_eq!(
+            ref_mailboxes[&new_hash]
+                .as_any()
+                .downcast_ref::<MaildirMailbox>()
+                .unwrap()
+                .fs_path(),
+            &root_mailbox.join("Archive2")
+        );
+        // Assert that even if we accidentally give a file system path to a maildir
+        // backend's create_mailbox() method, it still does the correct thing.
+        let (new_hash, ref_mailboxes) = smol::block_on(
+            backend
+                .create_mailbox(root_mailbox.join("Archive3").display().to_string())
+                .unwrap(),
+        )
+        .unwrap();
+        assert_eq!(ref_mailboxes[&new_hash].name(), "Archive3");
+        assert_eq!(ref_mailboxes[&new_hash].path(), "INBOX/Archive3");
+        assert_eq!(
+            ref_mailboxes[&new_hash]
+                .as_any()
+                .downcast_ref::<MaildirMailbox>()
+                .unwrap()
+                .fs_path(),
+            &root_mailbox.join("Archive3")
+        );
+        let ref_mailboxes = smol::block_on(backend.mailboxes().unwrap()).unwrap();
+        // Assert that backend has all the created mailboxes so far
+        assert_eq!(
+            ref_mailboxes.len(),
+            4,
+            "mailboxes() return value content not what expected: {:?}",
+            ref_mailboxes
+        );
+        // Assert that giving an absolute path returns an error
+        assert_eq!(
+            &smol::block_on(backend.create_mailbox("/Archive4".to_string()).unwrap())
+                .unwrap_err()
+                .to_string(),
+            "Path given (`/Archive4`) is absolute. Please provide a path relative to the \
+             account's root mailbox."
+        );
+        // Assert that attempting to create a mailbox outside of the root mailbox
+        // returns an error
+        assert_eq!(
+            &smol::block_on(
+                backend
+                    .create_mailbox(temp_dir.path().join("Archive4").display().to_string())
+                    .unwrap()
+            )
+            .unwrap_err()
+            .to_string(),
+            &format!(
+                "Path given, `{}`, is not included in the root mailbox path `{}`. A maildir \
+                 backend cannot contain mailboxes outside of its root path.",
+                temp_dir.path().join("Archive4").display(),
+                root_mailbox.display(),
+            )
+        );
+    }
+}