Re: [evolution-patches] 65178, maildir issues




An update to the camel part, removes some debug and fixes test case changes.

On Mon, 2005-01-17 at 14:14 +0800, Not Zed wrote:

It changes a few things with maildir stores:
- fixes the bug
- doesn't put folders under "inbox" in the display anymore, they all go in the top level
- fixes a long-existing vfolder bug with folder uri comparisons, needed for the next bit
- puts code in to handle old uri's with folders under inbox transparently, so that old vfolders and filters still work without needing an upgrade
- adds a new test case for maildir stores (should probably loop it and test all local stores similarly).

Since this is quite big, i'm not sure if this should go into 2.0.x, this patch is against head but it should also apply to 2.0.x.


? camel/camel-mime-tables.c
? camel/tests/folder/test10
? camel/tests/folder/test11
? camel/tests/message/test4
? camel/tests/mime-filter/test-tohtml
? camel/tests/misc/test2
? camel/tests/misc/url-scan
Index: camel/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/ChangeLog,v
retrieving revision 1.2371
diff -u -p -r1.2371 ChangeLog
--- camel/ChangeLog	13 Jan 2005 21:22:48 -0000	1.2371
+++ camel/ChangeLog	17 Jan 2005 07:41:27 -0000
@@ -1,3 +1,33 @@
+2005-01-17  Not Zed  <NotZed Ximian com>
+
+	* tests/lib/folders.c (test_folder_basic): dont enforce local
+	store == no inbox; maildir implements one now.
+
+2005-01-14  Not Zed  <NotZed Ximian com>
+
+	** Better fix for #65178.
+	
+	* tests/folder/test11.c: new maildir test.
+
+	* camel-store.c (camel_store_folder_uri_equal): dont pass NULL
+	values to compare_folder_name.
+
+	* providers/local/camel-maildir-store.c (get_folder_info):
+	reimplemented, now everything isn't a subfolder of INBOX ('.')
+	anymore.
+	(get_inbox): call main entry point so we don't create multiple
+	inboxes each call.
+	(scan_dirs): re-implemented using non-recursive implementation.
+	(scan_fi, scan_free, scan_equal, scan_hash): helpers for above.
+	(md_canon_name): helper to canonicalise old-format names to new
+	ones.
+	(maildir_hash_folder_name, maildir_compare_folder_name): implement
+	custom folder hash functions so canonicalisation works.
+	(get_folder): canoncalise name before using it.  special case '.'
+	aka 'inbox', so that it is implicitly created if accessed.
+	(delete_folder): don't let the caller delete ".".
+	(camel_folder_info_new): removed.
+
 2005-01-12  Jeffrey Stedfast  <fejj novell com>
 
 	* providers/imap4/camel-imap4-provider.c: Use the same key
Index: camel/camel-store.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-store.c,v
retrieving revision 1.155
diff -u -p -r1.155 camel-store.c
--- camel/camel-store.c	4 Nov 2004 05:34:05 -0000	1.155
+++ camel/camel-store.c	17 Jan 2005 07:41:28 -0000
@@ -1196,7 +1196,7 @@ camel_store_folder_uri_equal (CamelStore
 			name1 = url1->path[0] == '/' ? url1->path + 1 : url1->path;
 		}
 		
-		equal = CS_CLASS (store)->compare_folder_name (name0, name1);
+		equal = name0 && name1 && CS_CLASS (store)->compare_folder_name (name0, name1);
 	}
 	
 	camel_url_free (url0);
Index: camel/providers/local/camel-maildir-store.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/local/camel-maildir-store.c,v
retrieving revision 1.41
diff -u -p -r1.41 camel-maildir-store.c
--- camel/providers/local/camel-maildir-store.c	13 Jan 2005 04:00:11 -0000	1.41
+++ camel/providers/local/camel-maildir-store.c	17 Jan 2005 07:41:28 -0000
@@ -55,6 +55,9 @@ static void maildir_rename_folder(CamelS
 
 static CamelFolderInfo * get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex);
 
+static gboolean maildir_compare_folder_name(const void *a, const void *b);
+static guint maildir_hash_folder_name(const void *a);
+
 static void camel_maildir_store_class_init(CamelObjectClass * camel_maildir_store_class)
 {
 	CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_maildir_store_class);
@@ -63,6 +66,8 @@ static void camel_maildir_store_class_in
 	parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type());
 
 	/* virtual method overload, use defaults for most */
+	camel_store_class->hash_folder_name = maildir_hash_folder_name;
+	camel_store_class->compare_folder_name = maildir_compare_folder_name;
 	camel_store_class->get_folder = get_folder;
 	camel_store_class->get_inbox = get_inbox;
 	camel_store_class->delete_folder = delete_folder;
@@ -89,31 +94,66 @@ CamelType camel_maildir_store_get_type(v
 	return camel_maildir_store_type;
 }
 
+/* This fixes up some historical cruft of names starting with "./" */
+static const char *
+md_canon_name(const char *a)
+{
+	if (a != NULL) {
+		if (a[0] == '/')
+			a++;
+		if (a[0] == '.' && a[1] == '/')
+			a+=2;
+	}
+	return a;
+}
+
+static guint maildir_hash_folder_name(const void *a)
+{
+	return g_str_hash(md_canon_name(a));
+}
+
+static gboolean maildir_compare_folder_name(const void *a, const void *b)
+{
+	return g_str_equal(md_canon_name(a), md_canon_name(b));
+}
+
 static CamelFolder *
-get_folder(CamelStore * store, const char *infolder_name, guint32 flags, CamelException * ex)
+get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex)
 {
-	char *name, *tmp, *cur, *new, *folder_namea = NULL;
-	const char *folder_name;
+	char *name, *tmp, *cur, *new;
 	struct stat st;
 	CamelFolder *folder = NULL;
 
-	/* HACK: if we try to create a folder "/xxx", convert it to implicit "./xxx" as getfolderinfo will */
-	if (infolder_name[0] == '/')
-		folder_name = folder_namea = g_strdup_printf(".%s", infolder_name);
-	else
-		folder_name = infolder_name;
+	folder_name = md_canon_name(folder_name);
 
-	if (!((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex)) {
-		g_free(folder_namea);
+	if (!((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex))
 		return NULL;
-	}
 
 	name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name);
 	tmp = g_strdup_printf("%s/tmp", name);
 	cur = g_strdup_printf("%s/cur", name);
 	new = g_strdup_printf("%s/new", name);
 
-	if (stat(name, &st) == -1) {
+	if (!strcmp(folder_name, ".")) {
+		/* special case "." (aka inbox), may need to be created */
+		if (stat(tmp, &st) != 0 || !S_ISDIR(st.st_mode)
+		    || stat(cur, &st) != 0 || !S_ISDIR(st.st_mode)
+		    || stat(new, &st) != 0 || !S_ISDIR(st.st_mode)) {
+			if (mkdir(tmp, 0700) != 0
+			    || mkdir(cur, 0700) != 0
+			    || mkdir(new, 0700) != 0) {
+				camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+						     _("Cannot create folder `%s': %s"),
+						     folder_name, g_strerror(errno));
+				rmdir(tmp);
+				rmdir(cur);
+				rmdir(new);
+				goto fail;
+			}
+		}
+		folder = camel_maildir_folder_new(store, folder_name, flags, ex);
+	} else if (stat(name, &st) == -1) {
+		/* folder doesn't exist, see if we should create it */
 		if (errno != ENOENT) {
 			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
 					      _("Cannot get folder `%s': %s"),
@@ -142,6 +182,7 @@ get_folder(CamelStore * store, const cha
 		   || stat(tmp, &st) != 0 || !S_ISDIR(st.st_mode)
 		   || stat(cur, &st) != 0 || !S_ISDIR(st.st_mode)
 		   || stat(new, &st) != 0 || !S_ISDIR(st.st_mode)) {
+		/* folder exists, but not maildir */
 		camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
 				     _("Cannot get folder `%s': not a maildir directory."), name);
 	} else if (flags & CAMEL_STORE_FOLDER_EXCL) {
@@ -151,12 +192,11 @@ get_folder(CamelStore * store, const cha
 	} else {
 		folder = camel_maildir_folder_new(store, folder_name, flags, ex);
 	}
-
+fail:
 	g_free(name);
 	g_free(tmp);
 	g_free(cur);
 	g_free(new);
-	g_free(folder_namea);
 
 	return folder;
 }
@@ -164,7 +204,7 @@ get_folder(CamelStore * store, const cha
 static CamelFolder *
 get_inbox (CamelStore *store, CamelException *ex)
 {
-	return get_folder (store, ".", 0, ex);
+	return camel_store_get_folder(store, ".", CAMEL_STORE_FOLDER_CREATE, ex);
 }
 
 static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex)
@@ -172,6 +212,12 @@ static void delete_folder(CamelStore * s
 	char *name, *tmp, *cur, *new;
 	struct stat st;
 
+	if (strcmp(folder_name, ".") == 0) {
+		camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
+				     _("Cannot delete folder: %s: Invalid operation"), _("Inbox"));
+		return;
+	}
+
 	name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name);
 
 	tmp = g_strdup_printf("%s/tmp", name);
@@ -247,26 +293,6 @@ maildir_rename_folder(CamelStore *store,
 	((CamelStoreClass *)parent_class)->rename_folder(store, old, new, ex);
 }
 
-static CamelFolderInfo *camel_folder_info_new(CamelURL *url, const char *full, const char *name)
-{
-	CamelFolderInfo *fi;
-
-	fi = g_malloc0(sizeof(*fi));
-	fi->uri = camel_url_to_string(url, 0);
-	fi->full_name = g_strdup(full);
-	if (!strcmp(full, ".")) {
-		fi->flags |= CAMEL_FOLDER_SYSTEM;
-		fi->name = g_strdup(_("Inbox"));
-	} else
-		fi->name = g_strdup(name);
-	fi->unread = -1;
-	fi->total = -1;
-
-	d(printf("Adding maildir info: '%s' '%s' '%s'\n", fi->name, fi->full_name, fi->uri));
-
-	return fi;
-}
-
 static void
 fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags)
 {
@@ -304,69 +330,112 @@ fill_fi(CamelStore *store, CamelFolderIn
 	}
 }
 
-/* used to find out where we've visited already */
-struct _inode {
+struct _scan_node {
+	struct _scan_node *next;
+	struct _scan_node *prev;
+
+	CamelFolderInfo *fi;
+
 	dev_t dnode;
 	ino_t inode;
 };
 
-/* returns number of records found at or below this level */
-static int scan_dir(CamelStore *store, GHashTable *visited, CamelURL *url, const char *path, guint32 flags, CamelFolderInfo *parent, CamelFolderInfo **fip, CamelException *ex)
+static guint scan_hash(const void *d)
 {
-	DIR *dir;
-	struct dirent *d;
-	char *name, *tmp, *cur, *new;
-	const char *base, *root = ((CamelService *)store)->url->path;
-	CamelFolderInfo *fi = NULL;
-	struct stat st;
+	const struct _scan_node *v = d;
 
-	/* look for folders matching the right structure, recursively */
-	name = g_strdup_printf("%s/%s", root, path);
+	return v->inode ^ v->dnode;
+}
 
-	d(printf("checking dir '%s' part '%s' for maildir content\n", root, path));
+static gboolean scan_equal(const void *a, const void *b)
+{
+	const struct _scan_node *v1 = a, *v2 = b;
+	
+	return v1->inode == v2->inode && v1->dnode == v2->dnode;
+}
 
-	tmp = g_strdup_printf("%s/tmp", name);
-	cur = g_strdup_printf("%s/cur", name);
-	new = g_strdup_printf("%s/new", name);
+static void scan_free(void *k, void *v, void *d)
+{
+	g_free(k);
+}
 
-	base = strrchr(path, '/');
-	if (base)
-		base++;
-	else
-		base = path;
+static CamelFolderInfo *scan_fi(CamelStore *store, guint32 flags, CamelURL *url, const char *full, const char *name)
+{
+	CamelFolderInfo *fi;
+	char *tmp, *cur, *new;
+	struct stat st;
 
-	camel_url_set_fragment(url, path);
+	fi = g_malloc0(sizeof(*fi));
+	fi->full_name = g_strdup(full);
+	fi->name = g_strdup(name);
+	camel_url_set_fragment(url, fi->full_name);
+	fi->uri = camel_url_to_string(url, 0);
+	fi->unread = -1;
+	fi->total = -1;
+	/* we only calculate nochildren properly if we're recursive */
+	if (((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) != 0))
+		fi->flags = CAMEL_FOLDER_NOCHILDREN;
 
-	fi = camel_folder_info_new(url, path, base);
-	fill_fi(store, fi, flags);
+	d(printf("Adding maildir info: '%s' '%s' '%s'\n", fi->name, fi->full_name, fi->uri));
+
+	tmp = g_build_filename(url->path, fi->full_name, "tmp", NULL);
+	cur = g_build_filename(url->path, fi->full_name, "cur", NULL);
+	new = g_build_filename(url->path, fi->full_name, "new", NULL);
 
 	if (!(stat(tmp, &st) == 0 && S_ISDIR(st.st_mode)
 	      && stat(cur, &st) == 0 && S_ISDIR(st.st_mode)
 	      && stat(new, &st) == 0 && S_ISDIR(st.st_mode)))
 		fi->flags |= CAMEL_FOLDER_NOSELECT;
 
-	d(printf("found! uri = %s\n", fi->uri));
-	d(printf("  full_name = %s\n  name = '%s'\n", fi->full_name, fi->name));
-	
-	fi->parent = parent;
-	fi->next = *fip;
-	*fip = fi;
-
-	g_free(tmp);
-	g_free(cur);
 	g_free(new);
+	g_free(cur);
+	g_free(tmp);
+
+	fill_fi(store, fi, flags);
 
-	/* always look further if asked */
-	if (((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) || parent == NULL)) {
-		int children = 0;
+	return fi;
+}
+
+static int
+scan_dirs(CamelStore *store, guint32 flags, CamelFolderInfo *topfi, CamelURL *url, CamelException *ex)
+{
+	EDList queue = E_DLIST_INITIALISER(queue);
+	struct _scan_node *sn;
+	const char *root = ((CamelService *)store)->url->path;
+	char *tmp;
+	GHashTable *visited;
+	struct stat st;
+	int res = -1;
+
+	visited = g_hash_table_new(scan_hash, scan_equal);
+
+	sn = g_malloc0(sizeof(*sn));
+	sn->fi = topfi;
+	e_dlist_addtail(&queue, (EDListNode *)sn);
+	g_hash_table_insert(visited, sn, sn);
+
+	while (!e_dlist_empty(&queue)) {
+		char *name;
+		DIR *dir;
+		struct dirent *d;
+		CamelFolderInfo *last;
+
+		sn = (struct _scan_node *)e_dlist_remhead(&queue);
+
+		last = (CamelFolderInfo *)&sn->fi->child;
+
+		if (!strcmp(sn->fi->full_name, "."))
+			name = g_strdup(root);
+		else
+			name = g_build_filename(root, sn->fi->full_name, NULL);
 
 		dir = opendir(name);
 		if (dir == NULL) {
-			camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-					      _("Could not scan folder `%s': %s"),
-					      root, g_strerror (errno));
 			g_free(name);
-			return -1;
+			camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+					     _("Could not scan folder `%s': %s"),
+					     root, g_strerror(errno));
+			goto fail;
 		}
 
 		while ( (d = readdir(dir)) ) {
@@ -377,95 +446,100 @@ static int scan_dir(CamelStore *store, G
 			    || strcmp(d->d_name, "..") == 0)
 				continue;
 
-			tmp = g_strdup_printf("%s/%s", name, d->d_name);
+			tmp = g_build_filename(name, d->d_name, NULL);
 			if (stat(tmp, &st) == 0 && S_ISDIR(st.st_mode)) {
-				struct _inode in = { st.st_dev, st.st_ino };
+				struct _scan_node in;
+
+				in.dnode = st.st_dev;
+				in.inode = st.st_ino;
 
 				/* see if we've visited already */
 				if (g_hash_table_lookup(visited, &in) == NULL) {
-					struct _inode *inew = g_malloc(sizeof(*inew));
+					struct _scan_node *snew = g_malloc(sizeof(*snew));
+					char *full;
+
+					snew->dnode = in.dnode;
+					snew->inode = in.inode;
+
+					if (!strcmp(sn->fi->full_name, "."))
+						full = g_strdup(d->d_name);
+					else
+						full = g_strdup_printf("%s/%s", sn->fi->full_name, d->d_name);
+					snew->fi = scan_fi(store, flags, url, full, d->d_name);
+					g_free(full);
+
+					last->next =  snew->fi;
+					last = snew->fi;
+					snew->fi->parent = sn->fi;
+
+					sn->fi->flags &= ~CAMEL_FOLDER_NOCHILDREN;
+					sn->fi->flags |= CAMEL_FOLDER_CHILDREN;
 
-					children++;
+					g_hash_table_insert(visited, snew, snew);
 
-					*inew = in;
-					g_hash_table_insert(visited, inew, inew);
-					new = g_strdup_printf("%s/%s", path, d->d_name);
-					if (scan_dir(store, visited, url, new, flags, fi, &fi->child, ex) == -1) {
-						g_free(tmp);
-						g_free(new);
-						closedir(dir);
-						return -1;
-					}
-					g_free(new);
+					if (((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) != 0))
+						e_dlist_addtail(&queue, (EDListNode *)snew);
 				}
 			}
 			g_free(tmp);
 		}
 		closedir(dir);
-
-		if (children)
-			fi->flags |= CAMEL_FOLDER_CHILDREN;
-		else
-			fi->flags |= CAMEL_FOLDER_NOCHILDREN;
 	}
 
-	g_free(name);
-
-	return 0;
-}
-
-static guint inode_hash(const void *d)
-{
-	const struct _inode *v = d;
-
-	return v->inode ^ v->dnode;
-}
+	res = 0;
+fail:
+	g_hash_table_foreach(visited, scan_free, NULL);
+	g_hash_table_destroy(visited);
 
-static gboolean inode_equal(const void *a, const void *b)
-{
-	const struct _inode *v1 = a, *v2 = b;
-	
-	return v1->inode == v2->inode && v1->dnode == v2->dnode;
-}
-
-static void inode_free(void *k, void *v, void *d)
-{
-	g_free(k);
+	return res;
 }
 
 static CamelFolderInfo *
-get_folder_info (CamelStore *store, const char *topin, guint32 flags, CamelException *ex)
+get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex)
 {
 	CamelFolderInfo *fi = NULL;
 	CamelLocalStore *local_store = (CamelLocalStore *)store;
-	GHashTable *visited;
 	CamelURL *url;
-	const char *top;
-	char *topa = NULL;
-
-	visited = g_hash_table_new(inode_hash, inode_equal);
 
 	url = camel_url_new("maildir:", NULL);
 	camel_url_set_path(url, ((CamelService *)local_store)->url->path);
 
-	/* HACK: if we try to get folderinfo from "/xxx", convert it to implicit "./xxx" as getfolderinfo will later */
-	if (topin == NULL || topin[0] == 0)
-		top = ".";
-	else if (topin[0] == '/')
-		top = topa = g_strdup_printf(".%s", topin);
-	else
-		top = topin;
+	if (top == NULL || top[0] == 0) {
+		CamelFolderInfo *scan;
 
-	if (scan_dir(store, visited, url, top, flags, NULL, &fi, ex) == -1 && fi != NULL) {
-		camel_store_free_folder_info_full(store, fi);
-		fi = NULL;
-	}
+		/* create a dummy "." parent inbox, use to scan, then put back at the top level */
+		fi = scan_fi(store, flags, url, ".", _("Inbox"));
+		if (scan_dirs(store, flags, fi, url, ex) == -1)
+			goto fail;
+		fi->next = fi->child;
+		scan = fi->child;
+		fi->child = NULL;
+		while (scan) {
+			scan->parent = NULL;
+			scan = scan->next;
+		}
+		fi->flags &= ~CAMEL_FOLDER_CHILDREN;
+		fi->flags |= CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_NOCHILDREN|CAMEL_FOLDER_NOINFERIORS;
+	} else if (!strcmp(top, ".")) {
+		fi = scan_fi(store, flags, url, ".", _("Inbox"));
+		fi->flags |= CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_NOCHILDREN|CAMEL_FOLDER_NOINFERIORS;
+	} else {
+		const char *name = strrchr(top, '/');
 
-	g_free(topa);
+		fi = scan_fi(store, flags, url, top, name?name+1:top);
+		if (scan_dirs(store, flags, fi, url, ex) == -1)
+			goto fail;
+	}
 
 	camel_url_free(url);
-	g_hash_table_foreach(visited, inode_free, NULL);
-	g_hash_table_destroy(visited);
 
 	return fi;
+
+fail:
+	if (fi)
+		camel_store_free_folder_info_full(store, fi);
+
+	camel_url_free(url);
+
+	return NULL;
 }
Index: camel/tests/folder/Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/tests/folder/Makefile.am,v
retrieving revision 1.14
diff -u -p -r1.14 Makefile.am
--- camel/tests/folder/Makefile.am	13 Dec 2004 03:08:51 -0000	1.14
+++ camel/tests/folder/Makefile.am	17 Jan 2005 07:41:28 -0000
@@ -20,9 +20,9 @@ check_PROGRAMS =  	\
 	test1	test2	test3	\
 	test4	test5	test6	\
 	test7	test8	test9	\
-	test10
+	test10  test11
 
 TESTS = test1 	test2 	test3 	\
 	test4 	test5 	test6 	\
 	test7	test8	test9	\
-	test10
+	test10  test11
Index: camel/tests/folder/README
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/tests/folder/README,v
retrieving revision 1.5
diff -u -p -r1.5 README
--- camel/tests/folder/README	23 Apr 2003 01:34:03 -0000	1.5
+++ camel/tests/folder/README	17 Jan 2005 07:41:28 -0000
@@ -10,3 +10,5 @@ test7	basic folder operations, NNTP
 test8	multithreaded folder torture test, local
 test9	filtering
 test10  multithreaded folder/store object bag torture test
+
+test11	old format maildir name compatability
Index: camel/tests/folder/test11.c
===================================================================
RCS file: camel/tests/folder/test11.c
diff -N camel/tests/folder/test11.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ camel/tests/folder/test11.c	17 Jan 2005 07:41:28 -0000
@@ -0,0 +1,192 @@
+
+/* threaded folder testing */
+
+#include <string.h>
+#include <pthread.h>
+
+#include "camel-test.h"
+#include "camel-test-provider.h"
+#include "session.h"
+
+#include <camel/camel-exception.h>
+#include <camel/camel-service.h>
+#include <camel/camel-store.h>
+
+#define MAX_LOOP (10000)
+#define MAX_THREADS (5)
+
+#define d(x) 
+
+#define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
+
+static const char *local_drivers[] = { "local" };
+
+static CamelSession *session;
+
+/* FIXME: flags aren't really right yet */
+/* ASCII sorted on full_name */
+static CamelFolderInfo fi_list_1[] = {
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#.", "Inbox", ".", CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#Junk", "Junk", "Junk", CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#Trash", "Trash", "Trash", CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#testbox", "testbox", "testbox", CAMEL_FOLDER_CHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#testbox/foo", "foo", "testbox/foo", CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#testbox2", "testbox2", "testbox2", CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+};
+
+static CamelFolderInfo fi_list_2[] = {
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#.", "Inbox", ".", CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#Junk", "Junk", "Junk", CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#Trash", "Trash", "Trash", CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#testbox", "testbox", "testbox", CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#testbox2", "testbox2", "testbox2", CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+};
+
+static CamelFolderInfo fi_list_3[] = {
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#testbox", "testbox", "testbox", CAMEL_FOLDER_CHILDREN, -1, -1 },
+	{ NULL, NULL, NULL, "maildir:/tmp/camel-test/maildir#testbox/foo", "foo", "testbox/foo", CAMEL_FOLDER_NOCHILDREN, -1, -1 },
+};
+
+static int
+cmp_fi(const void *a, const void *b)
+{
+	const CamelFolderInfo *fa = ((const CamelFolderInfo **)a)[0];
+	const CamelFolderInfo *fb = ((const CamelFolderInfo **)b)[0];
+
+	return strcmp(fa->full_name, fb->full_name);
+}
+
+static void
+add_fi(GPtrArray *folders, CamelFolderInfo *fi)
+{
+	while (fi) {
+		g_ptr_array_add(folders, fi);
+		if (fi->child)
+			add_fi(folders, fi->child);
+		fi = fi->next;
+	}
+}
+
+static void
+check_fi(CamelFolderInfo *fi, CamelFolderInfo *list, int len)
+{
+	GPtrArray *folders = g_ptr_array_new();
+	int i;
+
+	add_fi(folders, fi);
+	check_msg(folders->len == len, "unexpected number of folders returned from folderinfo");
+	qsort(folders->pdata, folders->len, sizeof(folders->pdata[0]), cmp_fi);
+	for (i=0;i<len;i++) {
+		CamelFolderInfo *f = folders->pdata[i];
+
+		camel_test_push("checking folder '%s'", list[i].uri);
+
+		check_msg(!strcmp(f->uri, list[i].uri), "got '%s' expecting '%s'", f->uri, list[i].uri);
+		check(!strcmp(f->full_name, list[i].full_name));
+
+		/* this might be translated, but we can't know */
+		camel_test_nonfatal("Inbox not english");
+		check(!strcmp(f->name, list[i].name));
+		camel_test_fatal();
+
+		camel_test_nonfatal("Flags mismatch");
+		check(f->flags == list[i].flags);
+		camel_test_fatal();
+
+		camel_test_pull();
+	}
+
+	g_ptr_array_free(folders, TRUE);
+}
+
+int main(int argc, char **argv)
+{
+	CamelException *ex;
+	CamelFolder *f1, *f2;
+	CamelStore *store;
+	CamelFolderInfo *fi;
+
+	camel_test_init(argc, argv);
+	camel_test_provider_init(1, local_drivers);
+
+	ex = camel_exception_new();
+
+	/* clear out any camel-test data */
+	system("/bin/rm -rf /tmp/camel-test");
+
+	session = camel_test_session_new("/tmp/camel-test");
+	store = camel_session_get_store(session, "maildir:///tmp/camel-test/maildir", ex);
+	camel_exception_clear(ex);
+
+	camel_test_start("Maildir backward compatability tests");
+
+	camel_test_push("./ prefix path, one level");
+	f1 = camel_store_get_folder(store, "testbox", CAMEL_STORE_FOLDER_CREATE, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	f2 = 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(f1 == f2);
+	check_unref(f2, 2);
+	check_unref(f1, 1);
+	camel_test_pull();
+
+	camel_test_push("./ prefix path, one level, no create");
+	f1 = camel_store_get_folder(store, "testbox2", CAMEL_STORE_FOLDER_CREATE, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	f2 = camel_store_get_folder(store, "./testbox2", 0, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	check(f1 == f2);
+	check_unref(f2, 2);
+	check_unref(f1, 1);
+	camel_test_pull();
+
+	camel_test_push("./ prefix path, two levels");
+	f1 = camel_store_get_folder(store, "testbox/foo", CAMEL_STORE_FOLDER_CREATE, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	f2 = camel_store_get_folder(store, "./testbox/foo", CAMEL_STORE_FOLDER_CREATE, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	check(f1 == f2);
+	check_unref(f2, 2);
+	check_unref(f1, 1);
+	camel_test_pull();
+
+	camel_test_push("'.' == Inbox");
+	f2 = camel_store_get_inbox(store, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	f1 = camel_store_get_folder(store, ".", 0, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	check(f1 == f2);
+	check_unref(f2, 2);
+	check_unref(f1, 1);
+	camel_test_pull();
+
+	camel_test_push("folder info, recursive");
+	fi = camel_store_get_folder_info(store, "", CAMEL_STORE_FOLDER_INFO_RECURSIVE, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	check(fi != NULL);
+	check_fi(fi, fi_list_1, ARRAY_LEN(fi_list_1));
+	camel_test_pull();
+
+	camel_test_push("folder info, flat");
+	fi = camel_store_get_folder_info(store, "", 0, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	check(fi != NULL);
+	check_fi(fi, fi_list_2, ARRAY_LEN(fi_list_2));
+	camel_test_pull();
+
+	camel_test_push("folder info, recursive, non root");
+	fi = camel_store_get_folder_info(store, "testbox", CAMEL_STORE_FOLDER_INFO_RECURSIVE, ex);
+	check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
+	check(fi != NULL);
+	check_fi(fi, fi_list_3, ARRAY_LEN(fi_list_3));
+	camel_test_pull();
+
+	check_unref(store, 1);
+	check_unref(session, 1);
+
+	camel_exception_free(ex);
+
+	camel_test_end();
+
+	return 0;
+}
Index: camel/tests/lib/folders.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/tests/lib/folders.c,v
retrieving revision 1.12
diff -u -p -r1.12 folders.c
--- camel/tests/lib/folders.c	2 Dec 2004 08:03:30 -0000	1.12
+++ camel/tests/lib/folders.c	17 Jan 2005 07:41:28 -0000
@@ -219,9 +219,14 @@ test_folder_basic(CamelSession *session,
 	push("getting inbox folder");
 	folder = camel_store_get_inbox(store, ex);
 	if (local) {
-		check(camel_exception_is_set(ex));
-		check(folder == NULL);
-		camel_exception_clear(ex);
+		/* Well, maildir can have an inbox */
+		if (folder) {
+			check(!camel_exception_is_set(ex));
+			check_unref(folder, 1);
+		} else {
+			check(camel_exception_is_set(ex));
+			camel_exception_clear(ex);
+		}
 	} else {
 		check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex));
 		check(folder != NULL);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]