Set the info size's properly, oops!
2000-11-28 Not Zed <NotZed@HelixCode.com> * providers/local/camel-maildir-summary.c (camel_maildir_summary_init): Set the info size's properly, oops! * tests/lib/folders.[ch]: Folder testing helpers. * tests/folder/test2.c: Test basic message ops on folders. * tests/folder/test1.c (main): Test basic folder ops on (local) stores. * providers/local/camel-local-provider.c (camel_provider_module_init): Removed some debug. * providers/local/camel-maildir-folder.c (camel_maildir_folder_class_init): fix parent class. * providers/local/camel-mh-folder.c (camel_mh_folder_class_init): Fix parent class (damn cut & paste). * providers/local/camel-maildir-store.c (get_folder): Call parent impl. (camel_maildir_store_class_init): Fix parent class setup. (delete_folder): Check the folder exists before trying to delete it. (delete_folder): Try and make the delete operation atomic/rollback failures. e.g. if one directory isn't empty, then create the other empty ones back. Also clear the tmp directory fully first. * providers/local/camel-mbox-store.c (get_folder): Call parent impl. (camel_mbox_store_class_init): parent class is camel_local_store, not camel_folder, oops. (delete_folder): Return an error if it doesn't exist, rather than covering it up. * providers/local/camel-mh-store.c (get_folder): Call parent impl. (camel_mh_store_class_init): fix parent class setup. (delete_folder): Error if it doesn't exist now. * camel-folder.c (camel_folder_move_message_to): (camel_folder_copy_message_to): Added warnings as these functions are going to be removed later. * camel-store.c (camel_store_get_root_folder): Fix for an early api change. We want CAMEL_STORE_FOLDER_CREATE, not TRUE, since its a flag. (camel_store_get_default_folder): And here too. * providers/local/camel-local-store.c (xrename): Handle renaming folders differently to renaming files. (get_default_folder_name): local stores dont have a default folder, so make it so. Or at least, it doesn't seem to make sense to have one. (get_root_folder_name): Same for root. (get_folder): Added parent implementation, that makes sure the service path exists, if we are creating a new folder (but doesn't create the folder). 2000-11-27 Not Zed <NotZed@HelixCode.com> * providers/local/camel-local-store.c (xrename): Fixed races. Use link/unlink, rather than rename, to properly detect overwriting another file. And allow some files to be missing. * providers/Makefile.am: Removed mh, mbox, added local, to the default. svn path=/trunk/; revision=6693
This commit is contained in:
@ -1,3 +1,69 @@
|
||||
2000-11-28 Not Zed <NotZed@HelixCode.com>
|
||||
|
||||
* providers/local/camel-maildir-summary.c
|
||||
(camel_maildir_summary_init): Set the info size's properly, oops!
|
||||
|
||||
* tests/lib/folders.[ch]: Folder testing helpers.
|
||||
|
||||
* tests/folder/test2.c: Test basic message ops on folders.
|
||||
|
||||
* tests/folder/test1.c (main): Test basic folder ops on (local)
|
||||
stores.
|
||||
|
||||
* providers/local/camel-local-provider.c
|
||||
(camel_provider_module_init): Removed some debug.
|
||||
|
||||
* providers/local/camel-maildir-folder.c
|
||||
(camel_maildir_folder_class_init): fix parent class.
|
||||
|
||||
* providers/local/camel-mh-folder.c (camel_mh_folder_class_init):
|
||||
Fix parent class (damn cut & paste).
|
||||
|
||||
* providers/local/camel-maildir-store.c (get_folder): Call parent
|
||||
impl.
|
||||
(camel_maildir_store_class_init): Fix parent class setup.
|
||||
(delete_folder): Check the folder exists before trying to delete
|
||||
it.
|
||||
(delete_folder): Try and make the delete operation atomic/rollback
|
||||
failures. e.g. if one directory isn't empty, then create the
|
||||
other empty ones back. Also clear the tmp directory fully first.
|
||||
|
||||
* providers/local/camel-mbox-store.c (get_folder): Call parent
|
||||
impl.
|
||||
(camel_mbox_store_class_init): parent class is camel_local_store,
|
||||
not camel_folder, oops.
|
||||
(delete_folder): Return an error if it doesn't exist, rather than
|
||||
covering it up.
|
||||
|
||||
* providers/local/camel-mh-store.c (get_folder): Call parent impl.
|
||||
(camel_mh_store_class_init): fix parent class setup.
|
||||
(delete_folder): Error if it doesn't exist now.
|
||||
|
||||
* camel-folder.c (camel_folder_move_message_to):
|
||||
(camel_folder_copy_message_to): Added warnings as these functions
|
||||
are going to be removed later.
|
||||
|
||||
* camel-store.c (camel_store_get_root_folder): Fix for an early
|
||||
api change. We want CAMEL_STORE_FOLDER_CREATE, not TRUE, since
|
||||
its a flag.
|
||||
(camel_store_get_default_folder): And here too.
|
||||
|
||||
* providers/local/camel-local-store.c (xrename): Handle renaming
|
||||
folders differently to renaming files.
|
||||
(get_default_folder_name): local stores dont have a default
|
||||
folder, so make it so. Or at least, it doesn't seem to make sense
|
||||
to have one.
|
||||
(get_root_folder_name): Same for root.
|
||||
(get_folder): Added parent implementation, that makes sure the
|
||||
service path exists, if we are creating a new folder (but doesn't
|
||||
create the folder).
|
||||
|
||||
2000-11-27 Not Zed <NotZed@HelixCode.com>
|
||||
|
||||
* providers/local/camel-local-store.c (xrename): Fixed races. Use
|
||||
link/unlink, rather than rename, to properly detect overwriting
|
||||
another file. And allow some files to be missing.
|
||||
|
||||
2000-11-28 Radek Doulik <rodo@helixcode.com>
|
||||
|
||||
* providers/local/camel-local-summary.c
|
||||
|
||||
@ -886,6 +886,9 @@ copy_message_to (CamelFolder *source, const char *uid, CamelFolder *dest,
|
||||
* This copies a message from one folder to another. If the @source and
|
||||
* @dest folders have the same parent_store, this may be more efficient
|
||||
* than a camel_folder_append_message().
|
||||
*
|
||||
* FIXME: This call should be deprecated, as append_message() can determine
|
||||
* this information for itself.
|
||||
**/
|
||||
void
|
||||
camel_folder_copy_message_to (CamelFolder *source, const char *uid,
|
||||
@ -895,6 +898,8 @@ camel_folder_copy_message_to (CamelFolder *source, const char *uid,
|
||||
g_return_if_fail (CAMEL_IS_FOLDER (dest));
|
||||
g_return_if_fail (uid != NULL);
|
||||
|
||||
g_warning("CamelFolder.copy_message_to() is a deprecated api");
|
||||
|
||||
if (source->parent_store == dest->parent_store) {
|
||||
return CF_CLASS (source)->copy_message_to (source, uid,
|
||||
dest, ex);
|
||||
@ -934,6 +939,9 @@ move_message_to (CamelFolder *source, const char *uid,
|
||||
* @dest folders have the same parent_store, this may be more efficient
|
||||
* than a camel_folder_append_message() followed by
|
||||
* camel_folder_delete_message().
|
||||
*
|
||||
* FIXME: This call should be depracated, since append_message() can
|
||||
* determine this from the message itself.
|
||||
**/
|
||||
void
|
||||
camel_folder_move_message_to (CamelFolder *source, const char *uid,
|
||||
@ -943,6 +951,8 @@ camel_folder_move_message_to (CamelFolder *source, const char *uid,
|
||||
g_return_if_fail (CAMEL_IS_FOLDER (dest));
|
||||
g_return_if_fail (uid != NULL);
|
||||
|
||||
g_warning("CamelFolder.move_message_to() is a deprecated api");
|
||||
|
||||
if (source->parent_store == dest->parent_store) {
|
||||
return CF_CLASS (source)->move_message_to (source, uid,
|
||||
dest, ex);
|
||||
|
||||
@ -354,7 +354,7 @@ camel_store_get_root_folder (CamelStore *store, CamelException *ex)
|
||||
|
||||
name = CS_CLASS (store)->get_root_folder_name (store, ex);
|
||||
if (name) {
|
||||
folder = get_folder_internal (store, name, TRUE, ex);
|
||||
folder = get_folder_internal (store, name, CAMEL_STORE_FOLDER_CREATE, ex);
|
||||
g_free (name);
|
||||
}
|
||||
return folder;
|
||||
@ -377,7 +377,7 @@ camel_store_get_default_folder (CamelStore *store, CamelException *ex)
|
||||
|
||||
name = CS_CLASS (store)->get_default_folder_name (store, ex);
|
||||
if (name) {
|
||||
folder = get_folder_internal (store, name, TRUE, ex);
|
||||
folder = get_folder_internal (store, name, CAMEL_STORE_FOLDER_CREATE, ex);
|
||||
g_free (name);
|
||||
}
|
||||
return folder;
|
||||
|
||||
@ -66,8 +66,6 @@ static CamelProvider maildir_provider = {
|
||||
|
||||
void camel_provider_module_init(CamelSession * session)
|
||||
{
|
||||
printf("Initialising local providers\n");
|
||||
|
||||
mh_provider.object_types[CAMEL_PROVIDER_STORE] = camel_mh_store_get_type();
|
||||
mh_provider.service_cache = g_hash_table_new(camel_url_hash, camel_url_equal);
|
||||
camel_session_register_provider(session, &mh_provider);
|
||||
|
||||
@ -33,11 +33,16 @@
|
||||
#include "camel-exception.h"
|
||||
#include "camel-url.h"
|
||||
|
||||
#define d(x)
|
||||
|
||||
/* Returns the class for a CamelLocalStore */
|
||||
#define CLOCALS_CLASS(so) CAMEL_LOCAL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so))
|
||||
#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
|
||||
|
||||
static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex);
|
||||
static char *get_name(CamelService *service, gboolean brief);
|
||||
static char *get_root_folder_name (CamelStore *store, CamelException *ex);
|
||||
static char *get_default_folder_name (CamelStore *store, CamelException *ex);
|
||||
static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex);
|
||||
static char *get_folder_name(CamelStore *store, const char *folder_name, CamelException *ex);
|
||||
static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top,
|
||||
@ -55,6 +60,9 @@ camel_local_store_class_init (CamelLocalStoreClass *camel_local_store_class)
|
||||
|
||||
/* virtual method overload */
|
||||
camel_service_class->get_name = get_name;
|
||||
camel_store_class->get_folder = get_folder;
|
||||
camel_store_class->get_root_folder_name = get_root_folder_name;
|
||||
camel_store_class->get_default_folder_name = get_default_folder_name;
|
||||
camel_store_class->get_folder_name = get_folder_name;
|
||||
camel_store_class->get_folder_info = get_folder_info;
|
||||
camel_store_class->free_folder_info = camel_store_free_folder_info_full;
|
||||
@ -99,6 +107,73 @@ camel_local_store_get_toplevel_dir (CamelLocalStore *store)
|
||||
return url->path;
|
||||
}
|
||||
|
||||
static CamelFolder *
|
||||
get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex)
|
||||
{
|
||||
struct stat st;
|
||||
char *path = ((CamelService *)store)->url->path;
|
||||
char *sub, *slash;
|
||||
|
||||
if (path[0] != '/') {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
|
||||
_("Store root %s is not an absolute path"), path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (stat(path, &st) == 0) {
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
|
||||
_("Store root %s is not a regular directory"), path);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (errno != ENOENT
|
||||
|| (flags & CAMEL_STORE_FOLDER_CREATE) == 0) {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
|
||||
_("Cannot get folder: %s: %s"), path, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* need to create the dir heirarchy */
|
||||
sub = alloca(strlen(path)+1);
|
||||
strcpy(sub, path);
|
||||
slash = sub;
|
||||
do {
|
||||
slash = strchr(slash+1, '/');
|
||||
if (slash)
|
||||
*slash = 0;
|
||||
if (stat(sub, &st) == -1) {
|
||||
if (errno != ENOENT
|
||||
|| mkdir(sub, 0700) == -1) {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
|
||||
_("Cannot get folder: %s: %s"), path, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (slash)
|
||||
*slash = '/';
|
||||
} while (slash);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_root_folder_name(CamelStore *store, CamelException *ex)
|
||||
{
|
||||
camel_exception_set(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
|
||||
_("Local stores do not have a root folder"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_default_folder_name(CamelStore *store, CamelException *ex)
|
||||
{
|
||||
camel_exception_set(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
|
||||
_("Local stores do not have a default folder"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex)
|
||||
{
|
||||
@ -134,25 +209,49 @@ get_folder_info (CamelStore *store, const char *top,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int xrename(const char *oldp, const char *newp, const char *prefix, const char *suffix, CamelException *ex)
|
||||
static int xrename(const char *oldp, const char *newp, const char *prefix, const char *suffix, int missingok, CamelException *ex)
|
||||
{
|
||||
struct stat st;
|
||||
char *old = g_strconcat(prefix, oldp, suffix, 0);
|
||||
char *new = g_strconcat(prefix, newp, suffix, 0);
|
||||
int ret = -1;
|
||||
int err = 0;
|
||||
|
||||
printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix);
|
||||
d(printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix));
|
||||
|
||||
/* FIXME: this has races ... */
|
||||
if (!(stat(new, &st) == -1 && errno==ENOENT)) {
|
||||
if (stat(old, &st) == -1) {
|
||||
if (missingok && errno == ENOENT) {
|
||||
ret = 0;
|
||||
} else {
|
||||
err = errno;
|
||||
ret = -1;
|
||||
}
|
||||
} else if (S_ISDIR(st.st_mode)) { /* use rename for dirs */
|
||||
if (rename(old, new) == 0
|
||||
|| stat(new, &st) == 0) {
|
||||
ret = 0;
|
||||
} else {
|
||||
err = errno;
|
||||
ret = -1;
|
||||
}
|
||||
} else if (link(old, new) == 0 /* and link for files */
|
||||
|| (stat(new, &st) == 0 && st.st_nlink == 2)) {
|
||||
if (unlink(old) == 0) {
|
||||
ret = 0;
|
||||
} else {
|
||||
err = errno;
|
||||
unlink(new);
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
err = errno;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Could not rename folder %s to %s: destination exists"),
|
||||
old, new);
|
||||
} else if (rename(old, new) == 0 || errno==ENOENT) {
|
||||
ret = 0;
|
||||
} else if (stat(old, &st) == -1 && errno==ENOENT && stat(new, &st) == 0) {
|
||||
/* for nfs, check if the rename worked anyway ... */
|
||||
ret = 0;
|
||||
_("Could not rename folder %s to %s: %s"),
|
||||
old, new, strerror(err));
|
||||
}
|
||||
|
||||
g_free(old);
|
||||
@ -167,16 +266,16 @@ rename_folder(CamelStore *store, const char *old, const char *new, CamelExceptio
|
||||
char *path = CAMEL_SERVICE (store)->url->path;
|
||||
|
||||
/* try to rollback failures, has obvious races */
|
||||
if (xrename(old, new, path, ".ibex", ex)) {
|
||||
if (xrename(old, new, path, ".ibex", TRUE, ex)) {
|
||||
return;
|
||||
}
|
||||
if (xrename(old, new, path, ".ev-summary", ex)) {
|
||||
xrename(new, old, path, ".ibex", ex);
|
||||
if (xrename(old, new, path, ".ev-summary", TRUE, ex)) {
|
||||
xrename(new, old, path, ".ibex", TRUE, ex);
|
||||
return;
|
||||
}
|
||||
if (xrename(old, new, path, "", ex)) {
|
||||
xrename(new, old, path, ".ev-summary", ex);
|
||||
xrename(new, old, path, ".ibex", ex);
|
||||
if (xrename(old, new, path, "", FALSE, ex)) {
|
||||
xrename(new, old, path, ".ev-summary", TRUE, ex);
|
||||
xrename(new, old, path, ".ibex", TRUE, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -168,7 +168,7 @@ camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev,
|
||||
return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->decode_x_evolution(cls, xev, info);
|
||||
}
|
||||
|
||||
#define DOSTATS
|
||||
/*#define DOSTATS*/
|
||||
#ifdef DOSTATS
|
||||
struct _stat_info {
|
||||
int mitotal;
|
||||
|
||||
@ -40,9 +40,9 @@
|
||||
#include "camel-mime-message.h"
|
||||
#include "camel-exception.h"
|
||||
|
||||
#define d(x) (printf("%s(%d): ", __FILE__, __LINE__),(x))
|
||||
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
|
||||
|
||||
static CamelFolderClass *parent_class = NULL;
|
||||
static CamelLocalFolderClass *parent_class = NULL;
|
||||
|
||||
/* Returns the class for a CamelMaildirFolder */
|
||||
#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
|
||||
@ -61,7 +61,7 @@ static void camel_maildir_folder_class_init(CamelObjectClass * camel_maildir_fol
|
||||
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_maildir_folder_class);
|
||||
CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_maildir_folder_class;
|
||||
|
||||
parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_folder_get_type()));
|
||||
parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type()));
|
||||
|
||||
/* virtual method definition */
|
||||
|
||||
|
||||
@ -27,6 +27,8 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
#include "camel-maildir-store.h"
|
||||
#include "camel-maildir-folder.h"
|
||||
#include "camel-exception.h"
|
||||
@ -47,7 +49,7 @@ static void camel_maildir_store_class_init(CamelObjectClass * camel_maildir_stor
|
||||
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_maildir_store_class);
|
||||
/*CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_maildir_store_class);*/
|
||||
|
||||
parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_folder_get_type());
|
||||
parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type());
|
||||
|
||||
/* virtual method overload, use defaults for most */
|
||||
camel_store_class->get_folder = get_folder;
|
||||
@ -85,6 +87,10 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin
|
||||
struct stat st;
|
||||
CamelFolder *folder = NULL;
|
||||
|
||||
(void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex);
|
||||
if (camel_exception_is_set(ex))
|
||||
return NULL;
|
||||
|
||||
name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
|
||||
tmp = g_strdup_printf("%s/tmp", name);
|
||||
cur = g_strdup_printf("%s/cur", name);
|
||||
@ -99,8 +105,6 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
|
||||
_("Folder `%s' does not exist."), folder_name);
|
||||
} else {
|
||||
printf("creating ...\n");
|
||||
|
||||
if (mkdir(name, 0700) != 0
|
||||
|| mkdir(tmp, 0700) != 0
|
||||
|| mkdir(cur, 0700) != 0
|
||||
@ -113,7 +117,6 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin
|
||||
rmdir(new);
|
||||
rmdir(name);
|
||||
} else {
|
||||
printf("created ok?\n");
|
||||
folder = camel_maildir_folder_new(store, folder_name, flags, ex);
|
||||
}
|
||||
}
|
||||
@ -138,23 +141,62 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin
|
||||
static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex)
|
||||
{
|
||||
char *name, *tmp, *cur, *new;
|
||||
struct stat st;
|
||||
|
||||
name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
|
||||
|
||||
tmp = g_strdup_printf("%s/tmp", name);
|
||||
cur = g_strdup_printf("%s/cur", name);
|
||||
new = g_strdup_printf("%s/new", name);
|
||||
|
||||
/* remove subdirs first - will fail if not empty */
|
||||
if ((rmdir(tmp) == -1 && errno != ENOENT)
|
||||
|| (rmdir(new) == -1 && errno != ENOENT)
|
||||
|| (rmdir(cur) == -1 && errno != ENOENT)
|
||||
|| (rmdir(name) == -1 && errno != ENOENT)) {
|
||||
if (stat(name, &st) == -1 || !S_ISDIR(st.st_mode)
|
||||
|| stat(tmp, &st) == -1 || !S_ISDIR(st.st_mode)
|
||||
|| stat(cur, &st) == -1 || !S_ISDIR(st.st_mode)
|
||||
|| stat(new, &st) == -1 || !S_ISDIR(st.st_mode)) {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Could not delete folder `%s': %s"),
|
||||
folder_name, strerror(errno));
|
||||
folder_name, errno?strerror(errno):_("not a maildir directory"));
|
||||
} else {
|
||||
/* and remove metadata */
|
||||
((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex);
|
||||
int err = 0;
|
||||
|
||||
/* remove subdirs first - will fail if not empty */
|
||||
if (rmdir(cur) == -1 || rmdir(new) == -1) {
|
||||
err = errno;
|
||||
} else {
|
||||
DIR *dir;
|
||||
struct dirent *d;
|
||||
|
||||
/* for tmp (only), its contents is irrelevant */
|
||||
dir = opendir(tmp);
|
||||
if (dir) {
|
||||
while ( (d=readdir(dir)) ) {
|
||||
char *name = d->d_name, *file;
|
||||
|
||||
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
||||
continue;
|
||||
file = g_strdup_printf("%s/%s", tmp, name);
|
||||
unlink(file);
|
||||
g_free(file);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
if (rmdir(tmp) == -1 || rmdir(name) == -1)
|
||||
err = errno;
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
/* easier just to mkdir all (and let them fail), than remember what we got to */
|
||||
mkdir(name, 0700);
|
||||
mkdir(cur, 0700);
|
||||
mkdir(new, 0700);
|
||||
mkdir(tmp, 0700);
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Could not delete folder `%s': %s"),
|
||||
folder_name, strerror(err));
|
||||
} else {
|
||||
/* and remove metadata */
|
||||
((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(name);
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define d(x) (printf("%s(%d): ", __FILE__, __LINE__),(x))
|
||||
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
|
||||
|
||||
#define CAMEL_MAILDIR_SUMMARY_VERSION (0x2000)
|
||||
|
||||
@ -103,6 +103,9 @@ camel_maildir_summary_init (CamelMaildirSummary *o)
|
||||
/* set unique file version */
|
||||
s->version += CAMEL_MAILDIR_SUMMARY_VERSION;
|
||||
|
||||
s->message_info_size = sizeof(CamelMaildirMessageInfo);
|
||||
s->content_info_size = sizeof(CamelMaildirMessageContentInfo);
|
||||
|
||||
if (gethostname(hostname, 256) == 0) {
|
||||
o->priv->hostname = g_strdup(hostname);
|
||||
} else {
|
||||
|
||||
@ -47,7 +47,7 @@ camel_mbox_store_class_init (CamelMboxStoreClass *camel_mbox_store_class)
|
||||
{
|
||||
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_mbox_store_class);
|
||||
|
||||
parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_folder_get_type());
|
||||
parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type());
|
||||
|
||||
/* virtual method overload */
|
||||
camel_store_class->get_folder = get_folder;
|
||||
@ -87,6 +87,10 @@ get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelExcep
|
||||
char *name;
|
||||
struct stat st;
|
||||
|
||||
(void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex);
|
||||
if (camel_exception_is_set(ex))
|
||||
return NULL;
|
||||
|
||||
name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
|
||||
|
||||
if (stat(name, &st) == -1) {
|
||||
@ -137,12 +141,6 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
|
||||
|
||||
name = g_strdup_printf ("%s%s", CAMEL_SERVICE (store)->url->path, folder_name);
|
||||
if (stat (name, &st) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
/* file doesn't exist - it's kinda like deleting it ;-) */
|
||||
g_free (name);
|
||||
return;
|
||||
}
|
||||
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Could not delete folder `%s':\n%s"),
|
||||
folder_name, g_strerror (errno));
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
|
||||
|
||||
static CamelFolderClass *parent_class = NULL;
|
||||
static CamelLocalFolderClass *parent_class = NULL;
|
||||
|
||||
/* Returns the class for a CamelMhFolder */
|
||||
#define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
|
||||
@ -61,7 +61,7 @@ static void camel_mh_folder_class_init(CamelObjectClass * camel_mh_folder_class)
|
||||
CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_mh_folder_class);
|
||||
CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_mh_folder_class;
|
||||
|
||||
parent_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_folder_get_type()));
|
||||
parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type()));
|
||||
|
||||
/* virtual method definition */
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ static void camel_mh_store_class_init(CamelObjectClass * camel_mh_store_class)
|
||||
CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_mh_store_class);
|
||||
/*CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_mh_store_class);*/
|
||||
|
||||
parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_folder_get_type());
|
||||
parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type());
|
||||
|
||||
/* virtual method overload, use defaults for most */
|
||||
camel_store_class->get_folder = get_folder;
|
||||
@ -84,6 +84,10 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin
|
||||
char *name;
|
||||
struct stat st;
|
||||
|
||||
(void) ((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex);
|
||||
if (camel_exception_is_set(ex))
|
||||
return NULL;
|
||||
|
||||
name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
|
||||
|
||||
if (stat(name, &st) == -1) {
|
||||
@ -100,8 +104,6 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin
|
||||
g_free (name);
|
||||
return NULL;
|
||||
}
|
||||
printf("creating ...\n");
|
||||
|
||||
if (mkdir(name, 0700) != 0) {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Could not create folder `%s':\n%s"),
|
||||
@ -109,8 +111,6 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guin
|
||||
g_free (name);
|
||||
return NULL;
|
||||
}
|
||||
printf("created ok?\n");
|
||||
|
||||
} else if (!S_ISDIR(st.st_mode)) {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
|
||||
_("`%s' is not a directory."), name);
|
||||
@ -128,7 +128,7 @@ static void delete_folder(CamelStore * store, const char *folder_name, CamelExce
|
||||
|
||||
/* remove folder directory - will fail if not empty */
|
||||
name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
|
||||
if (rmdir(name) == -1 && errno != ENOENT) {
|
||||
if (rmdir(name) == -1) {
|
||||
camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Could not delete folder `%s': %s"),
|
||||
folder_name, strerror(errno));
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
SUBDIRS = lib \
|
||||
message
|
||||
message folder
|
||||
|
||||
|
||||
@ -2,6 +2,10 @@
|
||||
This directory is to contain regression tests that should be run
|
||||
before committing anything to camel.
|
||||
|
||||
In each subdirectory of tests there is a README containing a
|
||||
one-line description of each test file. This README must be kept
|
||||
uptodate.
|
||||
|
||||
To write a new test: copy an existing one and replace the contents.
|
||||
|
||||
See camel-test.h for a number of functions and macros which setup and
|
||||
|
||||
23
camel/tests/folder/Makefile.am
Normal file
23
camel/tests/folder/Makefile.am
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/intl -I$(top_srcdir) -I$(top_srcdir)/camel \
|
||||
-I$(includedir) \
|
||||
-I$(top_srcdir)/camel/tests/lib \
|
||||
-DG_LOG_DOMAIN=\"evolution-tests\"
|
||||
|
||||
LDADD = \
|
||||
$(top_builddir)/camel/libcamel.la \
|
||||
$(top_builddir)/e-util/libeutil.la \
|
||||
$(top_builddir)/libibex/libibex.la \
|
||||
$(GNOME_LIBDIR) \
|
||||
$(top_builddir)/camel/tests/lib/libcameltest.a \
|
||||
$(GNOMEUI_LIBS) $(INTLLIBS) $(EXTRA_GNOME_LIBS)
|
||||
|
||||
check_PROGRAMS = \
|
||||
test1 \
|
||||
test2
|
||||
# test3
|
||||
|
||||
#TESTS = test1
|
||||
|
||||
|
||||
|
||||
4
camel/tests/folder/README
Normal file
4
camel/tests/folder/README
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
test1 camel store folder operations (local only)
|
||||
test2 basic folder operations
|
||||
test3 folder searching and indexing
|
||||
149
camel/tests/folder/test1.c
Normal file
149
camel/tests/folder/test1.c
Normal file
@ -0,0 +1,149 @@
|
||||
/* store testing */
|
||||
|
||||
#include "camel-test.h"
|
||||
|
||||
#include <camel/camel-exception.h>
|
||||
#include <camel/camel-service.h>
|
||||
#include <camel/camel-session.h>
|
||||
#include <camel/camel-store.h>
|
||||
|
||||
/* god, who designed this horrid interface */
|
||||
static char *auth_callback(CamelAuthCallbackMode mode,
|
||||
char *data, gboolean secret,
|
||||
CamelService *service, char *item,
|
||||
CamelException *ex)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
static char *local_providers[] = {
|
||||
"mbox",
|
||||
"mh",
|
||||
"maildir"
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CamelSession *session;
|
||||
CamelStore *store;
|
||||
CamelException *ex;
|
||||
CamelFolder *folder, *root;
|
||||
int i;
|
||||
char *path;
|
||||
|
||||
ex = camel_exception_new();
|
||||
|
||||
camel_test_init(argc, argv);
|
||||
|
||||
session = camel_session_new("/tmp/camel-test", auth_callback, NULL, NULL);
|
||||
|
||||
/* todo: cross-check everything with folder_info checks as well */
|
||||
/* todo: subscriptions? */
|
||||
/* todo: work out how to do imap/pop/nntp tests */
|
||||
for (i=0;i<ARRAY_LEN(local_providers);i++) {
|
||||
char *what = g_strdup_printf("testing local store: %s", local_providers[i]);
|
||||
|
||||
camel_test_start(what);
|
||||
g_free(what);
|
||||
|
||||
push("getting store");
|
||||
path = g_strdup_printf("%s:///tmp/camel-test/%s", local_providers[i], local_providers[i]);
|
||||
store = camel_session_get_store(session, path, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "getting store: %s", camel_exception_get_description(ex));
|
||||
check(store != NULL);
|
||||
pull();
|
||||
|
||||
/* local providers == no root folder */
|
||||
push("getting root folder");
|
||||
root = camel_store_get_root_folder(store, ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
check(root == NULL);
|
||||
camel_exception_clear(ex);
|
||||
pull();
|
||||
|
||||
/* same for default folder */
|
||||
push("getting default folder");
|
||||
root = camel_store_get_root_folder(store, ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
check(root == NULL);
|
||||
camel_exception_clear(ex);
|
||||
pull();
|
||||
|
||||
push("getting a non-existant folder, no create");
|
||||
folder = camel_store_get_folder(store, "unknown", 0, ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
check(folder == NULL);
|
||||
camel_exception_clear(ex);
|
||||
pull();
|
||||
|
||||
push("getting a non-existant folder, with create");
|
||||
folder = camel_store_get_folder(store, "testbox", CAMEL_STORE_FOLDER_CREATE, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
check(folder != NULL);
|
||||
camel_object_unref((CamelObject *)folder);
|
||||
pull();
|
||||
|
||||
push("getting an existing folder");
|
||||
folder = camel_store_get_folder(store, "testbox", 0, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
check(folder != NULL);
|
||||
camel_object_unref((CamelObject *)folder);
|
||||
pull();
|
||||
|
||||
push("renaming a non-existant folder");
|
||||
camel_store_rename_folder(store, "unknown1", "unknown2", ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
camel_exception_clear(ex);
|
||||
pull();
|
||||
|
||||
push("renaming an existing folder");
|
||||
camel_store_rename_folder(store, "testbox", "testbox2", ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
pull();
|
||||
|
||||
push("opening the old name of a renamed folder");
|
||||
folder = camel_store_get_folder(store, "testbox", 0, ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
check(folder == NULL);
|
||||
camel_exception_clear(ex);
|
||||
pull();
|
||||
|
||||
push("opening the new name of a renamed folder");
|
||||
folder = camel_store_get_folder(store, "testbox2", 0, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
check(folder != NULL);
|
||||
camel_object_unref((CamelObject *)folder);
|
||||
pull();
|
||||
|
||||
push("deleting a non-existant folder");
|
||||
camel_store_delete_folder(store, "unknown", ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
camel_exception_clear(ex);
|
||||
pull();
|
||||
|
||||
push("deleting an existing folder");
|
||||
camel_store_delete_folder(store, "testbox2", ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
pull();
|
||||
|
||||
push("opening a folder that has been deleted");
|
||||
folder = camel_store_get_folder(store, "testbox2", 0, ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
check(folder == NULL);
|
||||
camel_exception_clear(ex);
|
||||
pull();
|
||||
|
||||
camel_object_unref((CamelObject *)store);
|
||||
|
||||
g_free(path);
|
||||
|
||||
camel_test_end();
|
||||
}
|
||||
|
||||
camel_object_unref((CamelObject *)session);
|
||||
camel_exception_free(ex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
241
camel/tests/folder/test2.c
Normal file
241
camel/tests/folder/test2.c
Normal file
@ -0,0 +1,241 @@
|
||||
/* folder testing */
|
||||
|
||||
#include "camel-test.h"
|
||||
#include "messages.h"
|
||||
#include "folders.h"
|
||||
|
||||
#include <camel/camel-exception.h>
|
||||
#include <camel/camel-service.h>
|
||||
#include <camel/camel-session.h>
|
||||
#include <camel/camel-store.h>
|
||||
|
||||
#include <camel/camel-folder.h>
|
||||
#include <camel/camel-folder-summary.h>
|
||||
#include <camel/camel-mime-message.h>
|
||||
|
||||
/* god, who designed this horrid interface */
|
||||
static char *auth_callback(CamelAuthCallbackMode mode,
|
||||
char *data, gboolean secret,
|
||||
CamelService *service, char *item,
|
||||
CamelException *ex)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
static char *stores[] = {
|
||||
"mbox:///tmp/camel-test/mbox",
|
||||
"mh:///tmp/camel-test/mh",
|
||||
"maildir:///tmp/camel-test/maildir"
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CamelSession *session;
|
||||
CamelStore *store;
|
||||
CamelException *ex;
|
||||
CamelFolder *folder;
|
||||
CamelMimeMessage *msg;
|
||||
int i, j;
|
||||
int indexed;
|
||||
GPtrArray *uids;
|
||||
const CamelMessageInfo *info;
|
||||
|
||||
ex = camel_exception_new();
|
||||
|
||||
camel_test_init(argc, argv);
|
||||
|
||||
session = camel_session_new("/tmp/camel-test", auth_callback, NULL, NULL);
|
||||
|
||||
/* todo: cross-check everything with folder_info checks as well */
|
||||
/* todo: work out how to do imap/pop/nntp tests */
|
||||
|
||||
/* we iterate over all stores we want to test, with indexing or indexing turned on or off */
|
||||
for (i=0;i<ARRAY_LEN(stores);i++) {
|
||||
char *name = stores[i];
|
||||
for (indexed = 0;indexed<2;indexed++) {
|
||||
char *what = g_strdup_printf("folder ops: %s (%sindexed)", name, indexed?"":"non-");
|
||||
int flags;
|
||||
|
||||
camel_test_start(what);
|
||||
test_free(what);
|
||||
|
||||
push("getting store");
|
||||
store = camel_session_get_store(session, stores[i], ex);
|
||||
check_msg(!camel_exception_is_set(ex), "getting store: %s", camel_exception_get_description(ex));
|
||||
check(store != NULL);
|
||||
pull();
|
||||
|
||||
push("creating %sindexed folder", indexed?"":"non-");
|
||||
if (indexed)
|
||||
flags = CAMEL_STORE_FOLDER_CREATE|CAMEL_STORE_FOLDER_BODY_INDEX;
|
||||
else
|
||||
flags = CAMEL_STORE_FOLDER_CREATE;
|
||||
folder = camel_store_get_folder(store, "testbox", flags, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
check(folder != NULL);
|
||||
|
||||
/* verify empty/can't get nonexistant stuff */
|
||||
test_folder_counts(folder, 0, 0);
|
||||
test_folder_not_message(folder, "0");
|
||||
test_folder_not_message(folder, "");
|
||||
|
||||
for (j=0;j<10;j++) {
|
||||
char *content, *subject;
|
||||
|
||||
push("creating test message");
|
||||
msg = test_message_create_simple();
|
||||
content = g_strdup_printf("Test message %d contents\n\n", j);
|
||||
test_message_set_content_simple((CamelMimePart *)msg, 0, "text/plain",
|
||||
content, strlen(content));
|
||||
test_free(content);
|
||||
subject = g_strdup_printf("Test message %d", j);
|
||||
camel_mime_message_set_subject(msg, subject);
|
||||
pull();
|
||||
|
||||
push("appending simple message %d", j);
|
||||
camel_folder_append_message(folder, msg, NULL, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
test_folder_counts(folder, j+1, j+1);
|
||||
|
||||
push("checking it is in the right uid slot & exists");
|
||||
uids = camel_folder_get_uids(folder);
|
||||
check(uids != NULL);
|
||||
check(uids->len == j+1);
|
||||
test_folder_message(folder, uids->pdata[j]);
|
||||
pull();
|
||||
|
||||
push("checking it is the right message (subject): %s", subject);
|
||||
info = camel_folder_get_message_info(folder, uids->pdata[j]);
|
||||
check_msg(strcmp(info->subject, subject)==0, "info->subject %s", info->subject);
|
||||
camel_folder_free_uids(folder, uids);
|
||||
pull();
|
||||
|
||||
test_free(subject);
|
||||
|
||||
check_unref(msg, 1);
|
||||
pull();
|
||||
}
|
||||
|
||||
check_unref(folder, 1);
|
||||
pull();
|
||||
|
||||
push("deleting test folder, with messages in it");
|
||||
camel_store_delete_folder(store, "testbox", ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
camel_exception_clear(ex);
|
||||
pull();
|
||||
|
||||
push("re-opening folder");
|
||||
folder = camel_store_get_folder(store, "testbox", flags, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
check(folder != NULL);
|
||||
|
||||
/* verify counts */
|
||||
test_folder_counts(folder, 10, 10);
|
||||
|
||||
/* re-check uid's, after a reload */
|
||||
uids = camel_folder_get_uids(folder);
|
||||
check(uids != NULL);
|
||||
check(uids->len == 10);
|
||||
for (j=0;j<10;j++) {
|
||||
char *subject = g_strdup_printf("Test message %d", j);
|
||||
|
||||
push("verify reload of %s", subject);
|
||||
test_folder_message(folder, uids->pdata[j]);
|
||||
|
||||
info = camel_folder_get_message_info(folder, uids->pdata[j]);
|
||||
check_msg(strcmp(info->subject, subject)==0, "info->subject %s", info->subject);
|
||||
test_free(subject);
|
||||
pull();
|
||||
}
|
||||
|
||||
push("deleting first message & expunging");
|
||||
camel_folder_delete_message(folder, uids->pdata[0]);
|
||||
test_folder_counts(folder, 10, 10);
|
||||
camel_folder_expunge(folder, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
test_folder_not_message(folder, uids->pdata[0]);
|
||||
test_folder_counts(folder, 9, 9);
|
||||
|
||||
camel_folder_free_uids(folder, uids);
|
||||
|
||||
uids = camel_folder_get_uids(folder);
|
||||
check(uids != NULL);
|
||||
check(uids->len == 9);
|
||||
for (j=0;j<9;j++) {
|
||||
char *subject = g_strdup_printf("Test message %d", j+1);
|
||||
|
||||
push("verify after expunge of %s", subject);
|
||||
test_folder_message(folder, uids->pdata[j]);
|
||||
|
||||
info = camel_folder_get_message_info(folder, uids->pdata[j]);
|
||||
check_msg(strcmp(info->subject, subject)==0, "info->subject %s", info->subject);
|
||||
test_free(subject);
|
||||
pull();
|
||||
}
|
||||
pull();
|
||||
|
||||
push("deleting last message & expunging");
|
||||
camel_folder_delete_message(folder, uids->pdata[8]);
|
||||
/* sync? */
|
||||
test_folder_counts(folder, 9, 9);
|
||||
camel_folder_expunge(folder, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
test_folder_not_message(folder, uids->pdata[8]);
|
||||
test_folder_counts(folder, 8, 8);
|
||||
|
||||
camel_folder_free_uids(folder, uids);
|
||||
|
||||
uids = camel_folder_get_uids(folder);
|
||||
check(uids != NULL);
|
||||
check(uids->len == 8);
|
||||
for (j=0;j<8;j++) {
|
||||
char *subject = g_strdup_printf("Test message %d", j+1);
|
||||
|
||||
push("verify after expunge of %s", subject);
|
||||
test_folder_message(folder, uids->pdata[j]);
|
||||
|
||||
info = camel_folder_get_message_info(folder, uids->pdata[j]);
|
||||
check_msg(strcmp(info->subject, subject)==0, "info->subject %s", info->subject);
|
||||
test_free(subject);
|
||||
pull();
|
||||
}
|
||||
pull();
|
||||
|
||||
push("deleting all messages & expunging");
|
||||
for (j=0;j<8;j++) {
|
||||
camel_folder_delete_message(folder, uids->pdata[j]);
|
||||
}
|
||||
/* sync? */
|
||||
test_folder_counts(folder, 8, 8);
|
||||
camel_folder_expunge(folder, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
for (j=0;j<8;j++) {
|
||||
test_folder_not_message(folder, uids->pdata[j]);
|
||||
}
|
||||
test_folder_counts(folder, 0, 0);
|
||||
|
||||
camel_folder_free_uids(folder, uids);
|
||||
pull();
|
||||
|
||||
camel_object_unref((CamelObject *)folder);
|
||||
pull(); /* re-opening folder */
|
||||
|
||||
push("deleting test folder, with no messages in it");
|
||||
camel_store_delete_folder(store, "testbox", ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
pull();
|
||||
|
||||
camel_object_unref((CamelObject *)store);
|
||||
camel_test_end();
|
||||
}
|
||||
}
|
||||
|
||||
camel_object_unref((CamelObject *)session);
|
||||
camel_exception_free(ex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
290
camel/tests/folder/test3.c
Normal file
290
camel/tests/folder/test3.c
Normal file
@ -0,0 +1,290 @@
|
||||
/* folder/index testing */
|
||||
|
||||
#include "camel-test.h"
|
||||
#include "messages.h"
|
||||
#include "folders.h"
|
||||
|
||||
#include <camel/camel-exception.h>
|
||||
#include <camel/camel-service.h>
|
||||
#include <camel/camel-session.h>
|
||||
#include <camel/camel-store.h>
|
||||
|
||||
#include <camel/camel-folder.h>
|
||||
#include <camel/camel-folder-summary.h>
|
||||
#include <camel/camel-mime-message.h>
|
||||
|
||||
/* god, who designed this horrid interface */
|
||||
static char *auth_callback(CamelAuthCallbackMode mode,
|
||||
char *data, gboolean secret,
|
||||
CamelService *service, char *item,
|
||||
CamelException *ex)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_folder_search_sub(CamelFolder *folder, const char *expr, int expected)
|
||||
{
|
||||
CamelException *ex = camel_exception_new();
|
||||
GPtrArray *uids;
|
||||
GHashTable *hash;
|
||||
int i;
|
||||
|
||||
uids = camel_folder_search_by_expression(folder, expr, ex);
|
||||
check(uids != NULL);
|
||||
check(uids->len == expected);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
|
||||
/* check the uid's are actually unique, too */
|
||||
hash = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
for (i=0;uids->len;i++) {
|
||||
check(g_hash_table_lookup(hash, uids->pdata[i]) == NULL);
|
||||
g_hash_table_insert(hash, uids->pdata[i], uids->pdata[i]);
|
||||
}
|
||||
g_hash_table_destroy(hash);
|
||||
|
||||
camel_folder_search_free(folder, uids);
|
||||
|
||||
camel_exception_free(ex);
|
||||
}
|
||||
|
||||
static void
|
||||
test_folder_search(CamelFolder *folder, const char *expr, int expected)
|
||||
{
|
||||
char *matchall;
|
||||
|
||||
push("Testing search: %s", expr);
|
||||
test_folder_search_sub(folder, expr, expected);
|
||||
pull();
|
||||
|
||||
matchall = g_strdup_printf("(match-all %s)", expr);
|
||||
push("Testing search: %s", matchall);
|
||||
test_folder_search_sub(folder, matchall, expected);
|
||||
test_free(matchall);
|
||||
pull();
|
||||
}
|
||||
|
||||
#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
static char *stores[] = {
|
||||
"mbox:///tmp/camel-test/mbox",
|
||||
"mh:///tmp/camel-test/mh",
|
||||
"maildir:///tmp/camel-test/maildir"
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CamelSession *session;
|
||||
CamelStore *store;
|
||||
CamelException *ex;
|
||||
CamelFolder *folder;
|
||||
CamelMimeMessage *msg;
|
||||
int i, j;
|
||||
int indexed;
|
||||
GPtrArray *uids;
|
||||
|
||||
ex = camel_exception_new();
|
||||
|
||||
camel_test_init(argc, argv);
|
||||
|
||||
session = camel_session_new("/tmp/camel-test", auth_callback, NULL, NULL);
|
||||
|
||||
/* todo: cross-check everything with folder_info checks as well */
|
||||
/* todo: work out how to do imap/pop/nntp tests */
|
||||
|
||||
/* we iterate over all stores we want to test, with indexing or indexing turned on or off */
|
||||
for (i=0;i<ARRAY_LEN(stores);i++) {
|
||||
char *name = stores[i];
|
||||
for (indexed = 0;indexed<2;indexed++) {
|
||||
char *what = g_strdup_printf("folder search: %s (%sindexed)", name, indexed?"":"non-");
|
||||
int flags;
|
||||
|
||||
camel_test_start(what);
|
||||
test_free(what);
|
||||
|
||||
push("getting store");
|
||||
store = camel_session_get_store(session, stores[i], ex);
|
||||
check_msg(!camel_exception_is_set(ex), "getting store: %s", camel_exception_get_description(ex));
|
||||
check(store != NULL);
|
||||
pull();
|
||||
|
||||
push("creating %sindexed folder", indexed?"":"non-");
|
||||
if (indexed)
|
||||
flags = CAMEL_STORE_FOLDER_CREATE|CAMEL_STORE_FOLDER_BODY_INDEX;
|
||||
else
|
||||
flags = CAMEL_STORE_FOLDER_CREATE;
|
||||
folder = camel_store_get_folder(store, "testbox", flags, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
check(folder != NULL);
|
||||
|
||||
/* we need an empty folder for this to work */
|
||||
test_folder_counts(folder, 0, 0);
|
||||
pull();
|
||||
|
||||
/* append a bunch of messages with specific content */
|
||||
push("appending 100 test messages");
|
||||
for (j=0;j<100;j++) {
|
||||
char *content, *subject;
|
||||
|
||||
push("creating test message");
|
||||
msg = test_message_create_simple();
|
||||
content = g_strdup_printf("data%d content\n", j);
|
||||
test_message_set_content_simple((CamelMimePart *)msg, 0, "text/plain",
|
||||
content, strlen(content));
|
||||
test_free(content);
|
||||
subject = g_strdup_printf("Test%d message%d subject", j, 100-j);
|
||||
camel_mime_message_set_subject(msg, subject);
|
||||
|
||||
camel_mime_message_set_date(msg, j*60*24, 0);
|
||||
|
||||
pull();
|
||||
|
||||
push("appending simple message %d", j);
|
||||
camel_folder_append_message(folder, msg, NULL, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
pull();
|
||||
|
||||
test_free(subject);
|
||||
|
||||
check_unref(msg, 1);
|
||||
}
|
||||
pull();
|
||||
|
||||
push("Setting up some flags &c");
|
||||
uids = camel_folder_get_uids(folder);
|
||||
check(uids->len == 100);
|
||||
for (j=0;j<100;j++) {
|
||||
char *uid = uids->pdata[j];
|
||||
|
||||
if ((j/13)*13 == j) {
|
||||
camel_folder_set_message_user_flag(folder, uid, "every13", TRUE);
|
||||
}
|
||||
if ((j/17)*17 == j) {
|
||||
camel_folder_set_message_user_flag(folder, uid, "every17", TRUE);
|
||||
}
|
||||
if ((j/7)*7 == j) {
|
||||
char *tag = g_strdup_printf("7tag%d", j/7);
|
||||
camel_folder_set_message_user_tag(folder, uid, "every7", tag);
|
||||
test_free(tag);
|
||||
}
|
||||
if ((j/11)*11 == j) {
|
||||
camel_folder_set_message_user_tag(folder, uid, "every11", "11tag");
|
||||
}
|
||||
}
|
||||
camel_folder_free_uids(folder, uids);
|
||||
pull();
|
||||
|
||||
/* should try invalid search strings too */
|
||||
|
||||
/* try some searches */
|
||||
push("performing searches");
|
||||
test_folder_search(folder, "(header-contains \"subject\" \"subject\")", 100);
|
||||
test_folder_search(folder, "(header-contains \"subject\" \"Subject\")", 100);
|
||||
|
||||
test_folder_search(folder, "(body-contains \"content\")", 100);
|
||||
test_folder_search(folder, "(body-contains \"Content\")", 100);
|
||||
|
||||
test_folder_search(folder, "(user-flag \"every7\")", 0);
|
||||
test_folder_search(folder, "(user-flag \"every13\")", 100/13);
|
||||
test_folder_search(folder, "(= \"7tag1\" (user-tag \"every7\"))", 1);
|
||||
test_folder_search(folder, "(= \"11tag\" (user-tag \"every11\"))", 100/11);
|
||||
|
||||
test_folder_search(folder, "(user-flag \"every13\" \"every17\")", 100/13 + 100/17);
|
||||
test_folder_search(folder, "(or (user-flag \"every13\") (user-flag \"every17\"))", 100/13 + 100/17);
|
||||
test_folder_search(folder, "(and (user-flag \"every13\") (user-flag \"every17\"))", 0);
|
||||
|
||||
test_folder_search(folder, "(and (header-contains \"subject\" \"Test1\")"
|
||||
"(header-contains \"subject\" \"Test2\"))", 0);
|
||||
test_folder_search(folder, "(and (header-contains \"subject\" \"Test1\")"
|
||||
"(header-contains \"subject\" \"subject\"))", 1);
|
||||
test_folder_search(folder, "(and (header-contains \"subject\" \"Test1\")"
|
||||
"(header-contains \"subject\" \"message99\"))", 1);
|
||||
|
||||
test_folder_search(folder, "(or (header-contains \"subject\" \"Test1\")"
|
||||
"(header-contains \"subject\" \"Test2\"))", 2);
|
||||
test_folder_search(folder, "(or (header-contains \"subject\" \"Test1\")"
|
||||
"(header-contains \"subject\" \"subject\"))", 100);
|
||||
test_folder_search(folder, "(or (header-contains \"subject\" \"Test1\")"
|
||||
"(header-contains \"subject\" \"message99\"))", 1);
|
||||
|
||||
/* 7200 is 24*60*50 == half the 'sent date' of the messages */
|
||||
test_folder_search(folder, "(> 7200 (get-sent-date))", 49);
|
||||
test_folder_search(folder, "(< 7200 (get-sent-date))", 49);
|
||||
test_folder_search(folder, "(= 7200 (get-sent-date))", 1);
|
||||
test_folder_search(folder, "(= 7201 (get-sent-date))", 0);
|
||||
|
||||
test_folder_search(folder, "(and (user-flag \"every17\") (< 7200 (get-sent-date)))", 49/17);
|
||||
test_folder_search(folder, "(and (user-flag \"every17\") (> 7200 (get-sent-date)))", 49/17-1);
|
||||
test_folder_search(folder, "(and (user-flag \"every13\") (< 7200 (get-sent-date)))", 49/13);
|
||||
test_folder_search(folder, "(and (user-flag \"every13\") (> 7200 (get-sent-date)))", 49/13-1);
|
||||
|
||||
test_folder_search(folder, "(or (user-flag \"every17\") (< 7200 (get-sent-date)))", 49);
|
||||
test_folder_search(folder, "(or (user-flag \"every17\") (> 7200 (get-sent-date)))", 49);
|
||||
test_folder_search(folder, "(or (user-flag \"every13\") (< 7200 (get-sent-date)))", 49);
|
||||
test_folder_search(folder, "(or (user-flag \"every13\") (> 7200 (get-sent-date)))", 49);
|
||||
|
||||
push("deleting every 2nd message & expunging");
|
||||
uids = camel_folder_get_uids(folder);
|
||||
check(uids->len == 100);
|
||||
for (j=0;j<uids->len;j++) {
|
||||
camel_folder_delete_message(folder, uids->pdata[j]);
|
||||
}
|
||||
|
||||
push("searches after deletions, before sync");
|
||||
test_folder_search(folder, "(header-contains \"subject\" \"subject\")", 100);
|
||||
test_folder_search(folder, "(body-contains \"content\")", 100);
|
||||
pull();
|
||||
|
||||
camel_folder_sync(folder, FALSE, ex);
|
||||
|
||||
push("searches after sync, before expunge");
|
||||
test_folder_search(folder, "(header-contains \"subject\" \"subject\")", 100);
|
||||
test_folder_search(folder, "(body-contains \"content\")", 100);
|
||||
pull();
|
||||
|
||||
camel_folder_expunge(folder, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
camel_folder_free_uids(folder, uids);
|
||||
pull();
|
||||
|
||||
/* more searches */
|
||||
push("searches after deletions");
|
||||
test_folder_search(folder, "(header-contains \"subject\" \"subject\")", 50);
|
||||
test_folder_search(folder, "(body-contains \"content\")", 50);
|
||||
pull();
|
||||
|
||||
push("deleting remaining messages & expunging");
|
||||
uids = camel_folder_get_uids(folder);
|
||||
check(uids->len == 100);
|
||||
for (j=0;j<uids->len;j++) {
|
||||
camel_folder_delete_message(folder, uids->pdata[j]);
|
||||
}
|
||||
camel_folder_expunge(folder, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
camel_folder_free_uids(folder, uids);
|
||||
pull();
|
||||
|
||||
push("searches wtih no messages");
|
||||
test_folder_search(folder, "(header-contains \"subject\" \"subject\")", 0);
|
||||
test_folder_search(folder, "(body-contains \"content\")", 0);
|
||||
pull();
|
||||
|
||||
check_unref(folder, 1);
|
||||
pull();
|
||||
|
||||
push("deleting test folder, with no messages in it");
|
||||
camel_store_delete_folder(store, "testbox", ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
pull();
|
||||
|
||||
camel_object_unref((CamelObject *)store);
|
||||
camel_test_end();
|
||||
}
|
||||
}
|
||||
|
||||
camel_object_unref((CamelObject *)session);
|
||||
camel_exception_free(ex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4,7 +4,9 @@ check_LIBRARIES = libcameltest.a
|
||||
libcameltest_a_SOURCES = \
|
||||
camel-test.c camel-test.h \
|
||||
messages.c messages.h \
|
||||
addresses.c addresses.h
|
||||
addresses.c addresses.h \
|
||||
folders.c folders.h
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
183
camel/tests/lib/folders.c
Normal file
183
camel/tests/lib/folders.c
Normal file
@ -0,0 +1,183 @@
|
||||
|
||||
#include "camel-test.h"
|
||||
#include "folders.h"
|
||||
|
||||
#include "camel/camel-exception.h"
|
||||
|
||||
/* check the total/unread is what we think it should be */
|
||||
void
|
||||
test_folder_counts(CamelFolder *folder, int total, int unread)
|
||||
{
|
||||
GPtrArray *s;
|
||||
int i, myunread;
|
||||
const CamelMessageInfo *info;
|
||||
|
||||
push("test folder counts %d total %d unread", total, unread);
|
||||
|
||||
/* first, use the standard functions */
|
||||
check(camel_folder_get_message_count(folder) == total);
|
||||
check(camel_folder_get_unread_message_count(folder) == total);
|
||||
|
||||
/* next, use the summary */
|
||||
s = camel_folder_get_summary(folder);
|
||||
check(s != NULL);
|
||||
check(s->len == total);
|
||||
myunread = s->len;
|
||||
for (i=0;i<s->len;i++) {
|
||||
info = s->pdata[i];
|
||||
if (info->flags & CAMEL_MESSAGE_SEEN)
|
||||
myunread--;
|
||||
}
|
||||
check(unread == myunread);
|
||||
camel_folder_free_summary(folder, s);
|
||||
|
||||
/* last, use the uid list */
|
||||
s = camel_folder_get_uids(folder);
|
||||
check(s != NULL);
|
||||
check(s->len == total);
|
||||
myunread = s->len;
|
||||
for (i=0;i<s->len;i++) {
|
||||
info = camel_folder_get_message_info(folder, s->pdata[i]);
|
||||
if (info->flags & CAMEL_MESSAGE_SEEN)
|
||||
myunread--;
|
||||
}
|
||||
check(unread == myunread);
|
||||
camel_folder_free_uids(folder, s);
|
||||
|
||||
pull();
|
||||
}
|
||||
|
||||
static int
|
||||
safe_strcmp(const char *a, const char *b)
|
||||
{
|
||||
if (a == NULL && b == NULL)
|
||||
return 0;
|
||||
if (a == NULL)
|
||||
return 1;
|
||||
if (b == NULL)
|
||||
return -1;
|
||||
return strcmp(a, b);
|
||||
}
|
||||
|
||||
void
|
||||
test_message_info(CamelMimeMessage *msg, const CamelMessageInfo *info)
|
||||
{
|
||||
check_msg(safe_strcmp(info->subject, camel_mime_message_get_subject(msg)) == 0,
|
||||
"info->subject = '%s', get_subject() = '%s'", info->subject, camel_mime_message_get_subject(msg));
|
||||
|
||||
/* FIXME: testing from/cc/to, etc is more tricky */
|
||||
|
||||
check(info->date_sent == camel_mime_message_get_date(msg, NULL));
|
||||
|
||||
/* date received isn't set for messages that haven't been sent anywhere ... */
|
||||
/*check(info->date_received == camel_mime_message_get_date_received(msg, NULL));*/
|
||||
|
||||
/* so is messageid/references, etc */
|
||||
}
|
||||
|
||||
/* check a message is present */
|
||||
void
|
||||
test_folder_message(CamelFolder *folder, const char *uid)
|
||||
{
|
||||
CamelMimeMessage *msg;
|
||||
const CamelMessageInfo *info;
|
||||
GPtrArray *s;
|
||||
int i;
|
||||
CamelException *ex = camel_exception_new();
|
||||
int found;
|
||||
|
||||
push("uid %s is in folder", uid);
|
||||
|
||||
/* first try getting info */
|
||||
info = camel_folder_get_message_info(folder, uid);
|
||||
check(info != NULL);
|
||||
check(strcmp(info->uid, uid) == 0);
|
||||
|
||||
/* then, getting message */
|
||||
msg = camel_folder_get_message(folder, uid, ex);
|
||||
check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
|
||||
check(msg != NULL);
|
||||
|
||||
/* cross check with info */
|
||||
test_message_info(msg, info);
|
||||
|
||||
camel_object_unref((CamelObject *)msg);
|
||||
|
||||
/* see if it is in the summary (only once) */
|
||||
s = camel_folder_get_summary(folder);
|
||||
check(s != NULL);
|
||||
found = 0;
|
||||
for (i=0;i<s->len;i++) {
|
||||
info = s->pdata[i];
|
||||
if (strcmp(info->uid, uid) == 0)
|
||||
found++;
|
||||
}
|
||||
check(found == 1);
|
||||
camel_folder_free_summary(folder, s);
|
||||
|
||||
/* check it is in the uid list */
|
||||
s = camel_folder_get_uids(folder);
|
||||
check(s != NULL);
|
||||
found = 0;
|
||||
for (i=0;i<s->len;i++) {
|
||||
if (strcmp(s->pdata[i], uid) == 0)
|
||||
found++;
|
||||
}
|
||||
check(found == 1);
|
||||
camel_folder_free_uids(folder, s);
|
||||
|
||||
camel_exception_free(ex);
|
||||
|
||||
pull();
|
||||
}
|
||||
|
||||
/* check message not present */
|
||||
void
|
||||
test_folder_not_message(CamelFolder *folder, const char *uid)
|
||||
{
|
||||
CamelMimeMessage *msg;
|
||||
const CamelMessageInfo *info;
|
||||
GPtrArray *s;
|
||||
int i;
|
||||
CamelException *ex = camel_exception_new();
|
||||
int found;
|
||||
|
||||
push("uid %s is not in folder", uid);
|
||||
|
||||
/* first try getting info */
|
||||
info = camel_folder_get_message_info(folder, uid);
|
||||
check(info == NULL);
|
||||
|
||||
/* then, getting message */
|
||||
msg = camel_folder_get_message(folder, uid, ex);
|
||||
check(camel_exception_is_set(ex));
|
||||
check(msg == NULL);
|
||||
camel_exception_clear(ex);
|
||||
|
||||
/* see if it is not in the summary (only once) */
|
||||
s = camel_folder_get_summary(folder);
|
||||
check(s != NULL);
|
||||
found = 0;
|
||||
for (i=0;i<s->len;i++) {
|
||||
info = s->pdata[i];
|
||||
if (strcmp(info->uid, uid) == 0)
|
||||
found++;
|
||||
}
|
||||
check(found == 0);
|
||||
camel_folder_free_summary(folder, s);
|
||||
|
||||
/* check it is not in the uid list */
|
||||
s = camel_folder_get_uids(folder);
|
||||
check(s != NULL);
|
||||
found = 0;
|
||||
for (i=0;i<s->len;i++) {
|
||||
if (strcmp(s->pdata[i], uid) == 0)
|
||||
found++;
|
||||
}
|
||||
check(found == 0);
|
||||
camel_folder_free_uids(folder, s);
|
||||
|
||||
camel_exception_free(ex);
|
||||
|
||||
pull();
|
||||
}
|
||||
13
camel/tests/lib/folders.h
Normal file
13
camel/tests/lib/folders.h
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
#include <camel/camel-folder.h>
|
||||
#include <camel/camel-folder-summary.h>
|
||||
#include <camel/camel-mime-message.h>
|
||||
|
||||
/* check the total/unread is what we think it should be, everywhere it can be determined */
|
||||
void test_folder_counts(CamelFolder *folder, int total, int unread);
|
||||
/* cross-check info/msg */
|
||||
void test_message_info(CamelMimeMessage *msg, const CamelMessageInfo *info);
|
||||
/* check a message is present everywhere it should be */
|
||||
void test_folder_message(CamelFolder *folder, const char *uid);
|
||||
/* check message not present everywhere it shouldn't be */
|
||||
void test_folder_not_message(CamelFolder *folder, const char *uid);
|
||||
3
camel/tests/message/README
Normal file
3
camel/tests/message/README
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
test1 creating, saving, loading simple messages
|
||||
test2 camelinternetaddress tests, internationalised addresses, etc.
|
||||
Reference in New Issue
Block a user