Check if notmuch-deliver really waits for the database to become
available again.

This is done via a test program that locks the notmuch database, and then
spawns the program to be tested. The test can be run with make check.
---
 contrib/notmuch-deliver/.gitignore          |    2 +
 contrib/notmuch-deliver/Makefile.am         |    2 +-
 contrib/notmuch-deliver/configure.ac        |    1 +
 contrib/notmuch-deliver/test/Makefile.am    |   26 ++++
 contrib/notmuch-deliver/test/nm-test.sh     |    9 ++
 contrib/notmuch-deliver/test/nm-testconfig  |   12 ++
 contrib/notmuch-deliver/test/notmuch-lock.c |  167 +++++++++++++++++++++++++++
 contrib/notmuch-deliver/test/testmail       |    7 +
 8 files changed, 225 insertions(+), 1 deletions(-)
 create mode 100644 contrib/notmuch-deliver/test/Makefile.am
 create mode 100755 contrib/notmuch-deliver/test/nm-test.sh
 create mode 100644 contrib/notmuch-deliver/test/nm-testconfig
 create mode 100644 contrib/notmuch-deliver/test/notmuch-lock.c
 create mode 100644 contrib/notmuch-deliver/test/testmail

diff --git a/contrib/notmuch-deliver/.gitignore 
b/contrib/notmuch-deliver/.gitignore
index 6971ef2..91da18b 100644
--- a/contrib/notmuch-deliver/.gitignore
+++ b/contrib/notmuch-deliver/.gitignore
@@ -40,3 +40,5 @@ m4/lt*.m4

 maildrop/numlib/config.h
 src/notmuch-deliver
+test/notmuch-lock
+test/nm-test-mail
diff --git a/contrib/notmuch-deliver/Makefile.am 
b/contrib/notmuch-deliver/Makefile.am
index 365558a..4392771 100644
--- a/contrib/notmuch-deliver/Makefile.am
+++ b/contrib/notmuch-deliver/Makefile.am
@@ -3,6 +3,6 @@ MAINTAINERCLEANFILES= Makefile.in configure aclocal.m4 \
                      config.h config.h.in INSTALL
 ACLOCAL_AMFLAGS= -I m4
 AUTOMAKE_OPTIONS= dist-bzip2 no-dist-gzip std-options foreign
-SUBDIRS= maildrop/numlib src .
+SUBDIRS= maildrop/numlib src test .

 doc_DATA= README.mkd
diff --git a/contrib/notmuch-deliver/configure.ac 
b/contrib/notmuch-deliver/configure.ac
index 4deb658..693923f 100644
--- a/contrib/notmuch-deliver/configure.ac
+++ b/contrib/notmuch-deliver/configure.ac
@@ -152,5 +152,6 @@ AC_OUTPUT(
                  Makefile
                  maildrop/numlib/Makefile
                  src/Makefile
+                 test/Makefile
                  )
 dnl }}}
diff --git a/contrib/notmuch-deliver/test/Makefile.am 
b/contrib/notmuch-deliver/test/Makefile.am
new file mode 100644
index 0000000..dfa0b45
--- /dev/null
+++ b/contrib/notmuch-deliver/test/Makefile.am
@@ -0,0 +1,26 @@
+DEFS+= -DGITHEAD=\"$(GITHEAD)\"
+AM_CFLAGS= @NOTMUCH_DELIVER_CFLAGS@ $(glib_CFLAGS)
+
+check_PROGRAMS= notmuch-lock
+
+notmuch_lock_SOURCES= notmuch-lock.c
+notmuch_lock_LDADD= $(glib_LIBS)
+
+TESTS = nm-test.sh
+
+nm-test.sh: notmuch-lock \
+            nm-test-mail/INBOX/cur \
+            nm-test-mail/INBOX/new \
+            nm-test-mail/INBOX/tmp
+
+nm-test-mail/INBOX/cur:
+       mkdir -p $@
+
+nm-test-mail/INBOX/new:
+       mkdir -p $@
+
+nm-test-mail/INBOX/tmp:
+       mkdir -p $@
+
+clean-local:
+       rm -rf nm-test-mail
diff --git a/contrib/notmuch-deliver/test/nm-test.sh 
b/contrib/notmuch-deliver/test/nm-test.sh
new file mode 100755
index 0000000..6113211
--- /dev/null
+++ b/contrib/notmuch-deliver/test/nm-test.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -e
+
+export NOTMUCH_CONFIG=./nm-testconfig
+
+notmuch new
+
+./notmuch-lock -s 1000000 -- ../src/notmuch-deliver -v INBOX < testmail
diff --git a/contrib/notmuch-deliver/test/nm-testconfig 
b/contrib/notmuch-deliver/test/nm-testconfig
new file mode 100644
index 0000000..b94e8d0
--- /dev/null
+++ b/contrib/notmuch-deliver/test/nm-testconfig
@@ -0,0 +1,12 @@
+[database]
+path=./nm-test-mail
+
+[user]
+name=NotMuch Test
+primary_email=notmuc at example.com
+
+[new]
+tags=unread;inbox;
+
+[maildir]
+synchronize_flags=true
diff --git a/contrib/notmuch-deliver/test/notmuch-lock.c 
b/contrib/notmuch-deliver/test/notmuch-lock.c
new file mode 100644
index 0000000..2303843
--- /dev/null
+++ b/contrib/notmuch-deliver/test/notmuch-lock.c
@@ -0,0 +1,167 @@
+/* vim: set cino=t0 fo=croql sw=4 ts=4 sts=0 noet cin fdm=syntax nolist : */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <glib.h>
+
+#include <notmuch.h>
+
+
+#define MIN_UWAIT 1000        // 1 millisecond
+#define MAX_UWAIT 600000000   // 10 minutes
+
+
+
+static gint sleep_option = -1;
+static GOptionEntry entries[] = {
+       { "sleep", 's', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, 
&sleep_option,
+               "Sleep for N microseconds, while holding the lock to the 
database", "N" },
+       {NULL, 0, 0, 0, NULL, NULL, NULL},
+};
+
+
+
+static gboolean
+load_keyfile(const gchar *path, gchar **db_path, gchar ***tags)
+{
+       GKeyFile *fd;
+       GError *error;
+
+       fd = g_key_file_new();
+       error = NULL;
+       if (!g_key_file_load_from_file(fd, path, G_KEY_FILE_NONE,
+                               &error)) {
+               g_printerr("Failed to parse `%s': %s", path,
+                               error->message);
+               g_error_free(error);
+               g_key_file_free(fd);
+               return FALSE;
+       }
+
+       *db_path = g_key_file_get_string(fd, "database",
+                       "path", &error);
+       if (*db_path == NULL) {
+               g_critical("Failed to parse database.path from `%s': %s", path,
+                               error->message);
+               g_error_free(error);
+               g_key_file_free(fd);
+               return FALSE;
+       }
+
+       *tags = g_key_file_get_string_list(fd, "new",
+                       "tags", NULL, NULL);
+
+       g_key_file_free(fd);
+       return TRUE;
+}
+
+
+
+static gchar *
+get_db_path(void)
+{
+       gchar *conf_path, *db_path;
+
+       // Get location of notmuch config
+       if (g_getenv("NOTMUCH_CONFIG"))
+               conf_path = g_strdup(g_getenv("NOTMUCH_CONFIG"));
+       else if (g_getenv("HOME"))
+               conf_path = g_build_filename(g_getenv("HOME"),
+                               ".notmuch-config", NULL);
+       else {
+               g_critical("Neither NOTMUCH_CONFIG nor HOME set");
+               return NULL;
+       }
+
+       // Get location of notmuch database
+       gchar **conf_tags = NULL;
+       g_print("Parsing configuration from `%s'\n", conf_path);
+       if (!load_keyfile(conf_path, &db_path, &conf_tags)) {
+               g_free(conf_path);
+               return NULL;
+       }
+
+       g_free(conf_path);
+       return db_path;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+       gchar *db_path;
+       gint32 sleep_time = 0;
+       notmuch_database_t *db;
+       GError *error = NULL;
+       GOptionContext *context;
+
+       // parse command line options
+       gboolean option_parse_success = FALSE;
+       context = g_option_context_new( "COMMAND [ARGS...]");
+       g_option_context_add_main_entries(context, entries, NULL);
+       g_option_context_set_summary(context,
+                       "Utility to test behaviour of programs while the 
notmuch database is locked");
+       option_parse_success = g_option_context_parse(context, &argc, &argv, 
&error);
+       g_option_context_free(context);
+       if (! option_parse_success) {
+               g_printerr("option parsing failed: %s\n", error->message);
+               return EXIT_FAILURE;
+       }
+
+       // Check new program args
+       if ((argc - 1) <= 0) {
+               g_printerr("no command supplied\n");
+               return EXIT_FAILURE;
+       }
+       char **new_argv = argv + 1;
+       if (g_strcmp0(new_argv[0], "--") == 0)
+               new_argv++;
+
+       // Get notmuch database path
+       db_path = get_db_path();
+       if (db_path == NULL)
+               return EXIT_FAILURE;
+
+       // Open notmuch database
+       g_printerr("Opening notmuch database `%s'\n", db_path);
+       db = notmuch_database_open(db_path, NOTMUCH_DATABASE_MODE_READ_WRITE);
+       g_free(db_path);
+       if (db == NULL)
+               return EXIT_FAILURE;
+
+       gboolean spawn_success = FALSE;
+       GPid child_pid = 0;
+       spawn_success = g_spawn_async(
+                       g_get_current_dir(),
+                       new_argv,
+                       NULL,
+                       G_SPAWN_SEARCH_PATH | G_SPAWN_CHILD_INHERITS_STDIN | 
G_SPAWN_DO_NOT_REAP_CHILD,
+                       NULL,
+                       NULL,
+                       &child_pid,
+                       NULL
+                       );
+       if (!spawn_success) {
+               g_printerr("faild to spawn child\n");
+       }
+
+       // Sleep for some time
+       if (sleep_option >= 0) {
+               sleep_time = sleep_option;
+       } else {
+               sleep_time = g_random_int_range(MIN_UWAIT, MAX_UWAIT);
+       }
+       g_printerr("Sleeping for %f secs\n", ((double)sleep_time)/(1000*1000));
+       usleep(sleep_time);
+
+       // Close database again
+       notmuch_database_close(db);
+
+       int child_status = 0;
+       child_pid = waitpid(child_pid, &child_status, 0);
+
+       return WEXITSTATUS(child_status);
+}
diff --git a/contrib/notmuch-deliver/test/testmail 
b/contrib/notmuch-deliver/test/testmail
new file mode 100644
index 0000000..264518d
--- /dev/null
+++ b/contrib/notmuch-deliver/test/testmail
@@ -0,0 +1,7 @@
+From: test at example.com
+To: test at example.com
+Subject: testmail
+Message-Id: <20111022050326.653C3201BF at example.com>
+Date: Sat, 22 Oct 2011 07:03:26 +0200 (CEST)
+
+testmail
-- 
1.7.7.1

Reply via email to