aboutsummaryrefslogtreecommitdiff
path: root/vmime-master/tests/net/maildir/maildirStoreTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vmime-master/tests/net/maildir/maildirStoreTest.cpp')
-rw-r--r--vmime-master/tests/net/maildir/maildirStoreTest.cpp584
1 files changed, 584 insertions, 0 deletions
diff --git a/vmime-master/tests/net/maildir/maildirStoreTest.cpp b/vmime-master/tests/net/maildir/maildirStoreTest.cpp
new file mode 100644
index 0000000..1f418e8
--- /dev/null
+++ b/vmime-master/tests/net/maildir/maildirStoreTest.cpp
@@ -0,0 +1,584 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
+//
+// 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 3 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"
+
+
+// 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: <test@vmime.org>\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(maildirStoreTest)
+
+ 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::shared_ptr <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::shared_ptr <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::shared_ptr <vmime::net::store> store = createAndConnectStore();
+ vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ // Get root folders, not recursive
+ const std::vector <vmime::shared_ptr <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::shared_ptr <vmime::net::store> store = createAndConnectStore();
+ vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ // Get all folders, recursive
+ const std::vector <vmime::shared_ptr <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::shared_ptr <vmime::net::store> store = createAndConnectStore();
+ vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ vmime::shared_ptr <vmime::net::folder> folder = store->getFolder(
+ fpath() / "Folder" / "SubFolder" / "SubSubFolder2"
+ );
+
+ vmime::size_t count, unseen;
+ folder->status(count, unseen);
+
+ VASSERT_EQ("Message count", 1, count);
+
+ folder->open(vmime::net::folder::MODE_READ_ONLY);
+
+ vmime::shared_ptr <vmime::net::message> msg = folder->getMessage(1);
+
+ folder->fetchMessage(msg, vmime::net::fetchAttributes::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() {
+
+ try {
+
+ testRenameFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL);
+
+ } catch (vmime::exception& e) {
+
+ std::cerr << e;
+ throw e;
+ }
+ }
+
+ void testRenameFolder_Courier()
+ {
+ try {
+
+ testRenameFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER);
+
+ } catch (vmime::exception& e) {
+
+ std::cerr << e;
+ throw e;
+ }
+ }
+
+ void testRenameFolderImpl(const vmime::string* const dirs, const vmime::string* const files) {
+
+ createMaildir(dirs, files);
+
+ vmime::shared_ptr <vmime::net::store> store = createAndConnectStore();
+ vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ // Rename "Folder/SubFolder" to "Folder/foo"
+ vmime::shared_ptr <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::shared_ptr <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::shared_ptr <vmime::net::store> store = createAndConnectStore();
+ vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ // Destroy "Folder/SubFolder" (total: 3 folders)
+ vmime::shared_ptr <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::shared_ptr <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::shared_ptr <vmime::net::store> store = createAndConnectStore();
+ vmime::shared_ptr <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::shared_ptr <vmime::net::store> store = createAndConnectStore();
+ vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder();
+
+ VASSERT("Before", !store->getFolder(fpath() / "Folder" / "NewFolder")->exists());
+
+ vmime::net::folderAttributes attribs;
+ attribs.setType(vmime::net::folderAttributes::TYPE_CONTAINS_MESSAGES);
+
+ VASSERT_NO_THROW("Creation", store->getFolder(fpath() / "Folder" / "NewFolder")->create(attribs));
+
+ VASSERT("After", store->getFolder(fpath() / "Folder" / "NewFolder")->exists());
+
+ destroyMaildir();
+ }
+
+private:
+
+ vmime::utility::file::path m_tempPath;
+
+
+ vmime::shared_ptr <vmime::net::store> createAndConnectStore() {
+
+ vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create();
+
+ vmime::shared_ptr <vmime::net::store> store =
+ session->getStore(getStoreURL());
+
+ store->connect();
+
+ return store;
+ }
+
+ const vmime::shared_ptr <vmime::net::folder> findFolder(
+ const std::vector <vmime::shared_ptr <vmime::net::folder> >& folders,
+ const vmime::net::folder::path& path
+ ) {
+
+ for (size_t i = 0, n = folders.size() ; i < n ; ++i) {
+
+ if (folders[i]->getFullPath() == path) {
+ return folders[i];
+ }
+ }
+
+ return vmime::null;
+ }
+
+ const vmime::utility::url getStoreURL() {
+
+ vmime::shared_ptr <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::shared_ptr <vmime::utility::fileSystemFactory> fsf =
+ vmime::platform::getHandler()->getFileSystemFactory();
+
+ vmime::shared_ptr <vmime::utility::file> rootDir = fsf->create(m_tempPath);
+ rootDir->createDirectory(false);
+
+ for (vmime::string const* dir = dirs ; *dir != "*" ; ++dir) {
+
+ vmime::shared_ptr <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::shared_ptr <vmime::utility::file> ffile = fsf->create(m_tempPath / fsf->stringToPath(*file));
+ ffile->createFile();
+
+ vmime::shared_ptr <vmime::utility::fileWriter> fileWriter = ffile->getFileWriter();
+ vmime::shared_ptr <vmime::utility::outputStream> os = fileWriter->getOutputStream();
+
+ os->write(contents.data(), contents.length());
+ os->flush();
+
+ fileWriter = vmime::null;
+ }
+
+ }
+
+ void destroyMaildir() {
+
+ vmime::shared_ptr <vmime::utility::fileSystemFactory> fsf =
+ vmime::platform::getHandler()->getFileSystemFactory();
+
+ recursiveDelete(fsf->create(m_tempPath));
+ }
+
+ void recursiveDelete(vmime::shared_ptr <vmime::utility::file> dir) {
+
+ if (!dir->exists() || !dir->isDirectory()) {
+ return;
+ }
+
+ vmime::shared_ptr <vmime::utility::fileIterator> files = dir->getFiles();
+
+ // First, delete files and subdirectories in this directory
+ while (files->hasMoreElements()) {
+
+ vmime::shared_ptr <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