aboutsummaryrefslogtreecommitdiffstats
path: root/tests/net/maildir/maildirStoreTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/net/maildir/maildirStoreTest.cpp')
-rw-r--r--tests/net/maildir/maildirStoreTest.cpp578
1 files changed, 578 insertions, 0 deletions
diff --git a/tests/net/maildir/maildirStoreTest.cpp b/tests/net/maildir/maildirStoreTest.cpp
new file mode 100644
index 00000000..ad61c2f9
--- /dev/null
+++ b/tests/net/maildir/maildirStoreTest.cpp
@@ -0,0 +1,578 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2007 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "tests/testUtils.hpp"
+
+#include "vmime/platform.hpp"
+
+#include "vmime/net/maildir/maildirStore.hpp"
+#include "vmime/net/maildir/maildirFormat.hpp"
+
+
+#define VMIME_TEST_SUITE maildirStoreTest
+#define VMIME_TEST_SUITE_MODULE "Net/Maildir"
+
+
+// Shortcuts and helpers
+typedef vmime::utility::file::path fspath;
+typedef vmime::utility::file::path::component fspathc;
+
+typedef vmime::net::folder::path fpath;
+typedef vmime::net::folder::path::component fpathc;
+
+
+const fpath operator/(const fpath& path, const std::string& c)
+{
+ return path / fpathc(c);
+}
+
+
+/** Test messages */
+static const vmime::string TEST_MESSAGE_1 =
+ "From: <[email protected]>\r\n"
+ "Subject: VMime Test\r\n"
+ "Date: Thu, 01 Mar 2007 09:49:35 +0100\r\n"
+ "\r\n"
+ "Hello, world!";
+
+
+/** Maildir trees used in tests.
+ * Structure:
+ *
+ * .
+ * |-- Folder
+ * | `-- SubFolder
+ * | |-- SubSubFolder1
+ * | `-- SubSubFolder2
+ * `-- Folder2
+ *
+ */
+
+// KMail format
+static const vmime::string TEST_MAILDIR_KMAIL[] = // directories to create
+{
+ "/Folder",
+ "/Folder/new",
+ "/Folder/tmp",
+ "/Folder/cur",
+ "/.Folder.directory",
+ "/.Folder.directory/SubFolder",
+ "/.Folder.directory/SubFolder/new",
+ "/.Folder.directory/SubFolder/tmp",
+ "/.Folder.directory/SubFolder/cur",
+ "/.Folder.directory/.SubFolder.directory",
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder1",
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder1/new",
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder1/tmp",
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder1/cur",
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder2",
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder2/new",
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder2/tmp",
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder2/cur",
+ "/Folder2",
+ "/Folder2/new",
+ "/Folder2/tmp",
+ "/Folder2/cur",
+ "*" // end
+};
+
+static const vmime::string TEST_MAILDIRFILES_KMAIL[] = // files to create and their contents
+{
+ "/.Folder.directory/.SubFolder.directory/SubSubFolder2/cur/1043236113.351.EmqD:S", TEST_MESSAGE_1,
+ "*" // end
+};
+
+// Courier format
+static const vmime::string TEST_MAILDIR_COURIER[] = // directories to create
+{
+ "/.Folder",
+ "/.Folder/new",
+ "/.Folder/tmp",
+ "/.Folder/cur",
+ "/.Folder.SubFolder",
+ "/.Folder.SubFolder",
+ "/.Folder.SubFolder/new",
+ "/.Folder.SubFolder/tmp",
+ "/.Folder.SubFolder/cur",
+ "/.Folder.SubFolder.SubSubFolder1",
+ "/.Folder.SubFolder.SubSubFolder1/new",
+ "/.Folder.SubFolder.SubSubFolder1/tmp",
+ "/.Folder.SubFolder.SubSubFolder1/cur",
+ "/.Folder.SubFolder.SubSubFolder2",
+ "/.Folder.SubFolder.SubSubFolder2/new",
+ "/.Folder.SubFolder.SubSubFolder2/tmp",
+ "/.Folder.SubFolder.SubSubFolder2/cur",
+ "/.Folder2",
+ "/.Folder2/new",
+ "/.Folder2/tmp",
+ "/.Folder2/cur",
+ "*" // end
+};
+
+static const vmime::string TEST_MAILDIRFILES_COURIER[] = // files to create and their contents
+{
+ "/.Folder/maildirfolder", "",
+ "/.Folder.SubFolder/maildirfolder", "",
+ "/.Folder.SubFolder.SubSubFolder1/maildirfolder", "",
+ "/.Folder.SubFolder.SubSubFolder2/maildirfolder", "",
+ "/.Folder.SubFolder.SubSubFolder2/cur/1043236113.351.EmqD:S", TEST_MESSAGE_1,
+ "/.Folder2/maildirfolder", "",
+ "*" // end
+};
+
+
+
+VMIME_TEST_SUITE_BEGIN
+
+ VMIME_TEST_LIST_BEGIN
+ VMIME_TEST(testDetectFormat_KMail)
+ VMIME_TEST(testDetectFormat_Courier)
+
+ VMIME_TEST(testListRootFolders_KMail)
+ VMIME_TEST(testListAllFolders_KMail)
+
+ VMIME_TEST(testListRootFolders_Courier)
+ VMIME_TEST(testListAllFolders_Courier)
+
+ VMIME_TEST(testListMessages_KMail)
+ VMIME_TEST(testListMessages_Courier)
+
+ VMIME_TEST(testRenameFolder_KMail)
+ VMIME_TEST(testRenameFolder_Courier)
+
+ VMIME_TEST(testDestroyFolder_KMail)
+ VMIME_TEST(testDestroyFolder_Courier)
+
+ VMIME_TEST(testFolderExists_KMail)
+ VMIME_TEST(testFolderExists_Courier)
+
+ VMIME_TEST(testCreateFolder_KMail)
+ VMIME_TEST(testCreateFolder_Courier)
+ VMIME_TEST_LIST_END
+
+
+public:
+
+ maildirStoreTest()
+ {
+ // Temporary directory
+ m_tempPath = fspath() / fspathc("tmp") // Use /tmp
+ / fspathc("vmime" + vmime::utility::stringUtils::toString(std::time(NULL))
+ + vmime::utility::stringUtils::toString(std::rand()));
+ }
+
+ void tearDown()
+ {
+ // In case of an uncaught exception
+ destroyMaildir();
+ }
+
+ void testDetectFormat_KMail()
+ {
+ createMaildir(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+
+ vmime::ref <vmime::net::maildir::maildirStore> store =
+ vmime::dynamicCast <vmime::net::maildir::maildirStore>(createAndConnectStore());
+
+ VASSERT_EQ("*", "kmail", store->getFormat()->getName());
+
+ destroyMaildir();
+ }
+
+ void testDetectFormat_Courier()
+ {
+ createMaildir(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+
+ vmime::ref <vmime::net::maildir::maildirStore> store =
+ vmime::dynamicCast <vmime::net::maildir::maildirStore>(createAndConnectStore());
+
+ VASSERT_EQ("*", "courier", store->getFormat()->getName());
+
+ destroyMaildir();
+ }
+
+
+ void testListRootFolders_KMail()
+ {
+ testListRootFoldersImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+ }
+
+ void testListRootFolders_Courier()
+ {
+ testListRootFoldersImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+ }
+
+ void testListRootFoldersImpl(const vmime::string* const dirs, const vmime::string* const files)
+ {
+ createMaildir(dirs, files);
+
+ // Connect to store
+ vmime::ref <vmime::net::store> store = createAndConnectStore();
+ vmime::ref <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ // Get root folders, not recursive
+ const std::vector <vmime::ref <vmime::net::folder> >
+ rootFolders = rootFolder->getFolders(false);
+
+ VASSERT_EQ("1", 2, rootFolders.size());
+ VASSERT("2", findFolder(rootFolders, fpath() / "Folder") != NULL);
+ VASSERT("3", findFolder(rootFolders, fpath() / "Folder2") != NULL);
+
+ destroyMaildir();
+ }
+
+
+ void testListAllFolders_KMail()
+ {
+ testListAllFoldersImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+ }
+
+ void testListAllFolders_Courier()
+ {
+ testListAllFoldersImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+ }
+
+ void testListAllFoldersImpl(const vmime::string* const dirs, const vmime::string* const files)
+ {
+ createMaildir(dirs, files);
+
+ // Connect to store
+ vmime::ref <vmime::net::store> store = createAndConnectStore();
+ vmime::ref <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ // Get all folders, recursive
+ const std::vector <vmime::ref <vmime::net::folder> >
+ allFolders = rootFolder->getFolders(true);
+
+ VASSERT_EQ("1", 5, allFolders.size());
+ VASSERT("2", findFolder(allFolders, fpath() / "Folder") != NULL);
+ VASSERT("3", findFolder(allFolders, fpath() / "Folder" / "SubFolder") != NULL);
+ VASSERT("4", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder1") != NULL);
+ VASSERT("5", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder2") != NULL);
+ VASSERT("6", findFolder(allFolders, fpath() / "Folder2") != NULL);
+
+ destroyMaildir();
+ }
+
+
+ void testListMessages_KMail()
+ {
+ testListMessagesImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+ }
+
+ void testListMessages_Courier()
+ {
+ testListMessagesImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+ }
+
+ void testListMessagesImpl(const vmime::string* const dirs, const vmime::string* const files)
+ {
+ createMaildir(dirs, files);
+
+ vmime::ref <vmime::net::store> store = createAndConnectStore();
+ vmime::ref <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ vmime::ref <vmime::net::folder> folder = store->getFolder
+ (fpath() / "Folder" / "SubFolder" / "SubSubFolder2");
+
+ int count, unseen;
+ folder->status(count, unseen);
+
+ VASSERT_EQ("Message count", 1, count);
+
+ folder->open(vmime::net::folder::MODE_READ_ONLY);
+
+ vmime::ref <vmime::net::message> msg = folder->getMessage(1);
+
+ folder->fetchMessage(msg, vmime::net::folder::FETCH_SIZE);
+
+ VASSERT_EQ("Message size", TEST_MESSAGE_1.length(), msg->getSize());
+
+ std::ostringstream oss;
+ vmime::utility::outputStreamAdapter os(oss);
+ msg->extract(os);
+
+ VASSERT_EQ("Message contents", TEST_MESSAGE_1, oss.str());
+
+ folder->close(false);
+
+ destroyMaildir();
+ }
+
+
+ void testRenameFolder_KMail()
+ {
+ testRenameFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+ }
+
+ void testRenameFolder_Courier()
+ {
+ testRenameFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+ }
+
+ void testRenameFolderImpl(const vmime::string* const dirs, const vmime::string* const files)
+ {
+ createMaildir(dirs, files);
+
+ vmime::ref <vmime::net::store> store = createAndConnectStore();
+ vmime::ref <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ // Rename "Folder/SubFolder" to "Folder/foo"
+ vmime::ref <vmime::net::folder> folder = store->getFolder
+ (fpath() / "Folder" / "SubFolder");
+
+ folder->rename(fpath() / "Folder" / "foo");
+
+ // Ensure folder and its subfolders have been renamed
+ const std::vector <vmime::ref <vmime::net::folder> >
+ allFolders = rootFolder->getFolders(true);
+
+ VASSERT_EQ("1", 5, allFolders.size());
+ VASSERT("2", findFolder(allFolders, fpath() / "Folder") != NULL);
+ VASSERT("3", findFolder(allFolders, fpath() / "Folder" / "SubFolder") == NULL);
+ VASSERT("4", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder1") == NULL);
+ VASSERT("5", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder2") == NULL);
+ VASSERT("6", findFolder(allFolders, fpath() / "Folder2") != NULL);
+ VASSERT("7", findFolder(allFolders, fpath() / "Folder" / "foo") != NULL);
+ VASSERT("8", findFolder(allFolders, fpath() / "Folder" / "foo" / "SubSubFolder1") != NULL);
+ VASSERT("9", findFolder(allFolders, fpath() / "Folder" / "foo" / "SubSubFolder2") != NULL);
+
+ destroyMaildir();
+ }
+
+
+ void testDestroyFolder_KMail()
+ {
+ testDestroyFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+ }
+
+ void testDestroyFolder_Courier()
+ {
+ testDestroyFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+ }
+
+ void testDestroyFolderImpl(const vmime::string* const dirs, const vmime::string* const files)
+ {
+ createMaildir(dirs, files);
+
+ vmime::ref <vmime::net::store> store = createAndConnectStore();
+ vmime::ref <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ // Destroy "Folder/SubFolder" (total: 3 folders)
+ vmime::ref <vmime::net::folder> folder = store->getFolder
+ (fpath() / "Folder" / "SubFolder");
+
+ folder->destroy();
+
+ // Ensure folder and its subfolders have been deleted and other folders still exist
+ const std::vector <vmime::ref <vmime::net::folder> >
+ allFolders = rootFolder->getFolders(true);
+
+ VASSERT_EQ("1", 2, allFolders.size());
+ VASSERT("2", findFolder(allFolders, fpath() / "Folder") != NULL);
+ VASSERT("3", findFolder(allFolders, fpath() / "Folder" / "SubFolder") == NULL);
+ VASSERT("4", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder1") == NULL);
+ VASSERT("5", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder2") == NULL);
+ VASSERT("6", findFolder(allFolders, fpath() / "Folder2") != NULL);
+
+ destroyMaildir();
+ }
+
+
+ void testFolderExists_KMail()
+ {
+ testFolderExistsImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+ }
+
+ void testFolderExists_Courier()
+ {
+ testFolderExistsImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+ }
+
+ void testFolderExistsImpl(const vmime::string* const dirs, const vmime::string* const files)
+ {
+ createMaildir(dirs, files);
+
+ vmime::ref <vmime::net::store> store = createAndConnectStore();
+ vmime::ref <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ VASSERT("1", store->getFolder(fpath() / "Folder" / "SubFolder")->exists());
+ VASSERT("2", !store->getFolder(fpath() / "Folder" / "SubSubFolder1")->exists());
+ VASSERT("3", store->getFolder(fpath() / "Folder2")->exists());
+ VASSERT("4", store->getFolder(fpath() / "Folder" / "SubFolder" / "SubSubFolder2")->exists());
+
+ destroyMaildir();
+ }
+
+
+ void testCreateFolder_KMail()
+ {
+ testCreateFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+ }
+
+ void testCreateFolder_Courier()
+ {
+ testCreateFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+ }
+
+ void testCreateFolderImpl(const vmime::string* const dirs, const vmime::string* const files)
+ {
+ createMaildir(dirs, files);
+
+ vmime::ref <vmime::net::store> store = createAndConnectStore();
+ vmime::ref <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ VASSERT("Before", !store->getFolder(fpath() / "Folder" / "NewFolder")->exists());
+
+ VASSERT_NO_THROW("Creation", store->getFolder(fpath() / "Folder" / "NewFolder")->
+ create(vmime::net::folder::TYPE_CONTAINS_MESSAGES));
+
+ VASSERT("After", store->getFolder(fpath() / "Folder" / "NewFolder")->exists());
+
+ destroyMaildir();
+ }
+
+private:
+
+ vmime::utility::file::path m_tempPath;
+
+
+ vmime::ref <vmime::net::store> createAndConnectStore()
+ {
+ vmime::ref <vmime::net::session> session =
+ vmime::create <vmime::net::session>();
+
+ vmime::ref <vmime::net::store> store =
+ session->getStore(getStoreURL());
+
+ store->connect();
+
+ return store;
+ }
+
+ const vmime::ref <vmime::net::folder> findFolder
+ (const std::vector <vmime::ref <vmime::net::folder> >& folders,
+ const vmime::net::folder::path& path)
+ {
+ for (unsigned int i = 0, n = folders.size() ; i < n ; ++i)
+ {
+ if (folders[i]->getFullPath() == path)
+ return folders[i];
+ }
+
+ return NULL;
+ }
+
+ const vmime::utility::url getStoreURL()
+ {
+ vmime::utility::fileSystemFactory* fsf =
+ vmime::platform::getHandler()->getFileSystemFactory();
+
+ vmime::utility::url url(std::string("maildir://localhost")
+ + fsf->pathToString(m_tempPath));
+
+ return url;
+ }
+
+ void createMaildir(const vmime::string* const dirs, const vmime::string* const files)
+ {
+ vmime::utility::fileSystemFactory* fsf =
+ vmime::platform::getHandler()->getFileSystemFactory();
+
+ vmime::ref <vmime::utility::file> rootDir = fsf->create(m_tempPath);
+ rootDir->createDirectory(false);
+
+ for (vmime::string const* dir = dirs ; *dir != "*" ; ++dir)
+ {
+ vmime::ref <vmime::utility::file> fdir = fsf->create(m_tempPath / fsf->stringToPath(*dir));
+ fdir->createDirectory(false);
+ }
+
+ for (vmime::string const* file = files ; *file != "*" ; file += 2)
+ {
+ const vmime::string& contents = *(file + 1);
+
+ vmime::ref <vmime::utility::file> ffile = fsf->create(m_tempPath / fsf->stringToPath(*file));
+ ffile->createFile();
+
+ vmime::ref <vmime::utility::fileWriter> fileWriter = ffile->getFileWriter();
+ vmime::ref <vmime::utility::outputStream> os = fileWriter->getOutputStream();
+
+ os->write(contents.data(), contents.length());
+ os->flush();
+
+ fileWriter = NULL;
+ }
+
+ }
+
+ void destroyMaildir()
+ {
+ vmime::utility::fileSystemFactory* fsf =
+ vmime::platform::getHandler()->getFileSystemFactory();
+
+ recursiveDelete(fsf->create(m_tempPath));
+ }
+
+ void recursiveDelete(vmime::ref <vmime::utility::file> dir)
+ {
+ if (!dir->exists() || !dir->isDirectory())
+ return;
+
+ vmime::ref <vmime::utility::fileIterator> files = dir->getFiles();
+
+ // First, delete files and subdirectories in this directory
+ while (files->hasMoreElements())
+ {
+ vmime::ref <vmime::utility::file> file = files->nextElement();
+
+ if (file->isDirectory())
+ {
+ recursiveDelete(file);
+ }
+ else
+ {
+ try
+ {
+ file->remove();
+ }
+ catch (vmime::exceptions::filesystem_exception&)
+ {
+ // Ignore
+ }
+ }
+ }
+
+ // Then, delete this (empty) directory
+ try
+ {
+ dir->remove();
+ }
+ catch (vmime::exceptions::filesystem_exception&)
+ {
+ // Ignore
+ }
+ }
+
+VMIME_TEST_SUITE_END
+