[evolution-ews/wip/tests: 10/11] Bug 708121 - Add low level tests in EWS (for EwsConnection)



commit e81a9948e5926d777b8f577007f09efeaed1e477
Author: Fabiano Fidêncio <fidencio redhat com>
Date:   Mon Sep 30 14:02:36 2013 +0200

    Bug 708121 - Add low level tests in EWS (for EwsConnection)
    
    Use uhttpmock as test framework for EEwsConnection API
    For now the implemented tests are covering only create/mve/delete folder.

 Makefile.am                   |    1 +
 configure.ac                  |   28 ++
 gtester.mk                    |   60 +++
 src/Makefile.am               |   24 +-
 src/server/e-ews-connection.c |   43 ++-
 src/server/e-ews-connection.h |    6 +
 src/server/e-ews-debug.c      |   24 ++
 src/server/e-ews-debug.h      |    4 +
 src/server/e-ews-folder.c     |    3 -
 src/tests/Makefile.am         |   36 ++
 src/tests/camel.c             |  851 +++++++++++++++++++++++++++++++++++++++++
 src/tests/common.c            |  370 ++++++++++++++++++
 src/tests/common.h            |   52 +++
 13 files changed, 1484 insertions(+), 18 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 1eec1a9..2a26737 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,6 +52,7 @@ MAINTAINERCLEANFILES = \
 #     once libmspack >= 0.4 becomes more widespread.
 DISTCHECK_CONFIGURE_FLAGS = \
        --with-internal-lzx \
+       --enable-tests \
        $(NULL)
 
 -include $(top_srcdir)/git.mk
diff --git a/configure.ac b/configure.ac
index b4482b3..fe110b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -284,6 +284,32 @@ LIBS=$save_libs
 AC_MSG_RESULT([$ac_cv_have_smi])
 
 dnl ****************************
+dnl Check for uhttpmock
+dnl ****************************
+AC_ARG_ENABLE([tests],
+       [AS_HELP_STRING([--enable-tests],
+       [Enable low level tests for EwsConnection @<:@default=no@:>@])],
+       [enable_tests="$enableval"], [enable_tests=no])
+
+if test "x$enable_tests" = "xyes" ; then
+       PKG_CHECK_MODULES(UHTTPMOCK, [libuhttpmock-0.0], have_uhttpmock=yes,
+                         have_uhttpmock=no)
+       AC_SUBST(UHTTPMOCK_CFLAGS)
+       AC_SUBST(UHTTPMOCK_LIBS)
+
+       if test "x$have_uhttpmock" = "xyes" ; then
+               AC_DEFINE(ENABLE_TESTS, 1, [Define to add support for low level tests])
+       else
+               AC_ERROR([
+
+               libuhttpmock >= 0.0 not found.
+
+               ])
+       fi
+fi
+AM_CONDITIONAL([ENABLE_TESTS], [test "x$have_uhttpmock" = "xyes"])
+
+dnl ****************************
 dnl Expose version information
 dnl ****************************
 API_VERSION=1.2
@@ -352,6 +378,7 @@ src/calendar/Makefile
 src/camel/Makefile
 src/collection/Makefile
 src/configuration/Makefile
+src/tests/Makefile
 po/Makefile.in
 ])
 AC_OUTPUT
@@ -360,5 +387,6 @@ AC_MSG_NOTICE([
        Kerberos 5      : $msg_krb5
        Strict building : $enable_strict
        Use libmspack   : $have_mspack
+       Enable tests    : $enable_tests
 ])
 
diff --git a/gtester.mk b/gtester.mk
new file mode 100644
index 0000000..1306193
--- /dev/null
+++ b/gtester.mk
@@ -0,0 +1,60 @@
+# GLIB - Library of useful C routines
+# From http://git.gnome.org/browse/glib/tree/Makefile.decl
+
+GTESTER = gtester
+GTESTER_REPORT = gtester-report
+
+# initialize variables for unconditional += appending
+EXTRA_DIST =
+TEST_PROGS =
+
+### testing rules
+
+# test: run all tests in cwd and subdirs
+test:  ${TEST_PROGS}
+       @test -z "${TEST_PROGS}" || ${GTESTER} --verbose ${TEST_PROGS}
+       @ for subdir in $(SUBDIRS) . ; do \
+           test "$$subdir" = "." -o "$$subdir" = "po" || \
+           ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
+         done
+
+# test-report: run tests in subdirs and generate report
+# perf-report: run tests in subdirs with -m perf and generate report
+# full-report: like test-report: with -m perf and -m slow
+test-report perf-report full-report:   ${TEST_PROGS}
+       @test -z "${TEST_PROGS}" || { \
+         case $@ in \
+         test-report) test_options="-k";; \
+         perf-report) test_options="-k -m=perf";; \
+         full-report) test_options="-k -m=perf -m=slow";; \
+         esac ; \
+         if test -z "$$GTESTER_LOGDIR" ; then  \
+           ${GTESTER} --verbose $$test_options -o test-report.xml ${TEST_PROGS} ; \
+         elif test -n "${TEST_PROGS}" ; then \
+           ${GTESTER} --verbose $$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \
+         fi ; \
+       }
+       @ ignore_logdir=true ; \
+         if test -z "$$GTESTER_LOGDIR" ; then \
+           GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \
+           ignore_logdir=false ; \
+         fi ; \
+         for subdir in $(SUBDIRS) . ; do \
+           test "$$subdir" = "." -o "$$subdir" = "po" || \
+           ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
+         done ; \
+         $$ignore_logdir || { \
+           echo '<?xml version="1.0"?>' > $  xml ; \
+           echo '<report-collection>'  >> $  xml ; \
+           for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \
+             sed '1,1s/^<?xml\b[^>?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $  xml ; \
+           done ; \
+           echo >> $  xml ; \
+           echo '</report-collection>' >> $  xml ; \
+           rm -rf "$$GTESTER_LOGDIR"/ ; \
+           ${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $  xml >$  
html ; \
+         }
+.PHONY: test test-report perf-report full-report
+# run make test as part of make check
+check-local: test
+
diff --git a/src/Makefile.am b/src/Makefile.am
index 7a1e4e3..8fcc15e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,24 @@
-SUBDIRS = server utils camel calendar addressbook collection configuration
-DIST_SUBDIRS = server utils camel calendar addressbook collection configuration
+if ENABLE_TESTS
+TESTS_DIR = tests
+endif
+
+SUBDIRS = \
+       server \
+       utils \
+       camel \
+       calendar \
+       addressbook \
+       collection \
+       configuration \
+       $(TESTS_DIR)
+
+DIST_SUBDIRS = \
+       server \
+       utils \
+       camel \
+       calendar \
+       addressbook \
+       collection \
+       configuration
 
 -include $(top_srcdir)/git.mk
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index b1cd4a9..b868b29 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -563,18 +563,7 @@ ews_discover_server_version (EEwsConnection *cnc,
 
        version = e_soap_parameter_get_property (param, "Version");
 
-       if (g_strcmp0 (version, "Exchange2007") == 0)
-               cnc->priv->version = E_EWS_EXCHANGE_2007;
-       else if (g_strcmp0 (version, "Exchange2007_SP1") == 0)
-               cnc->priv->version = E_EWS_EXCHANGE_2007_SP1;
-       else if (g_strcmp0 (version, "Exchange2010") == 0)
-               cnc->priv->version = E_EWS_EXCHANGE_2010;
-       else if (g_strcmp0 (version, "Exchange2010_SP1") == 0)
-               cnc->priv->version = E_EWS_EXCHANGE_2010_SP1;
-       else if (g_strcmp0 (version, "Exchange2010_SP2") == 0)
-               cnc->priv->version = E_EWS_EXCHANGE_2010_SP2;
-       else
-               cnc->priv->version = E_EWS_EXCHANGE_FUTURE;
+       e_ews_connection_set_server_version_from_string (cnc, version);
 
        g_free (version);
 }
@@ -1760,7 +1749,6 @@ e_ews_connection_init (EEwsConnection *cnc)
 
        cnc->priv->soup_thread = g_thread_new (NULL, e_ews_soup_thread, cnc);
 
-       /* create the SoupSession for this connection */
        cnc->priv->soup_session = soup_session_async_new_with_options (
                SOUP_SESSION_USE_NTLM, TRUE,
                SOUP_SESSION_ASYNC_CONTEXT,
@@ -4049,6 +4037,35 @@ e_ews_connection_get_server_version (EEwsConnection *cnc)
        return cnc->priv->version;
 }
 
+void
+e_ews_connection_set_server_version (EEwsConnection *cnc,
+                                    EEwsServerVersion version)
+{
+       g_return_if_fail (cnc != NULL);
+       g_return_if_fail (cnc->priv != NULL);
+
+       if (cnc->priv->version != version)
+               cnc->priv->version = version;
+}
+
+void
+e_ews_connection_set_server_version_from_string (EEwsConnection *cnc,
+                                                const gchar *version)
+{
+       if (g_strcmp0 (version, "Exchange2007") == 0)
+               cnc->priv->version = E_EWS_EXCHANGE_2007;
+       else if (g_strcmp0 (version, "Exchange2007_SP1") == 0)
+               cnc->priv->version = E_EWS_EXCHANGE_2007_SP1;
+       else if (g_strcmp0 (version, "Exchange2010") == 0)
+               cnc->priv->version = E_EWS_EXCHANGE_2010;
+       else if (g_strcmp0 (version, "Exchange2010_SP1") == 0)
+               cnc->priv->version = E_EWS_EXCHANGE_2010_SP1;
+       else if (g_strcmp0 (version, "Exchange2010_SP2") == 0)
+               cnc->priv->version = E_EWS_EXCHANGE_2010_SP2;
+       else
+               cnc->priv->version = E_EWS_EXCHANGE_FUTURE;
+}
+
 gboolean
 e_ews_connection_satisfies_server_version (EEwsConnection *cnc,
                                          EEwsServerVersion version)
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index 6bc987c..a460f5e 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -336,6 +336,12 @@ gboolean   e_ews_connection_find_folder_items_sync
 EEwsServerVersion
                e_ews_connection_get_server_version
                                                (EEwsConnection *cnc);
+void           e_ews_connection_set_server_version
+                                               (EEwsConnection *cnc,
+                                                EEwsServerVersion version);
+void           e_ews_connection_set_server_version_from_string
+                                               (EEwsConnection *cnc,
+                                                const gchar *version);
 gboolean       e_ews_connection_satisfies_server_version
                                                (EEwsConnection *cnc,
                                                 EEwsServerVersion versio);
diff --git a/src/server/e-ews-debug.c b/src/server/e-ews-debug.c
index 5d6a62e..3c0273a 100644
--- a/src/server/e-ews-debug.c
+++ b/src/server/e-ews-debug.c
@@ -21,6 +21,7 @@
 #endif
 
 #include "e-ews-debug.h"
+#include "e-ews-message.h"
 
 gint
 e_ews_debug_get_log_level (void)
@@ -40,3 +41,26 @@ e_ews_debug_get_log_level (void)
 
        return level;
 }
+
+const gchar *
+e_ews_connection_get_server_version_string (EEwsConnection *cnc)
+{
+       switch (e_ews_connection_get_server_version(cnc)) {
+               case E_EWS_EXCHANGE_2007:
+                       return "2007";
+               case E_EWS_EXCHANGE_2007_SP1:
+                       return "2007_SP1";
+               case E_EWS_EXCHANGE_2010:
+                       return "2010";
+               case E_EWS_EXCHANGE_2010_SP1:
+                       return "2010_SP1";
+               case E_EWS_EXCHANGE_2010_SP2:
+               case E_EWS_EXCHANGE_FUTURE:
+                       return "2010_SP2";
+               case E_EWS_EXCHANGE_UNKNOWN:
+                       return "Unknown";
+               default:
+                       g_assert_not_reached ();
+                       return NULL;
+       }
+}
diff --git a/src/server/e-ews-debug.h b/src/server/e-ews-debug.h
index 95f1f09..b7782a8 100644
--- a/src/server/e-ews-debug.h
+++ b/src/server/e-ews-debug.h
@@ -20,10 +20,14 @@
 #define E_EWS_DEBUG_H
 
 #include <glib.h>
+#include <server/e-ews-connection.h>
 
 G_BEGIN_DECLS
 
 gint           e_ews_debug_get_log_level               (void);
+const gchar *  e_ews_connection_get_server_version_string
+                                                       (EEwsConnection *cnc);
+
 
 G_END_DECLS
 
diff --git a/src/server/e-ews-folder.c b/src/server/e-ews-folder.c
index cb2b005..e0bd058 100644
--- a/src/server/e-ews-folder.c
+++ b/src/server/e-ews-folder.c
@@ -365,9 +365,6 @@ e_ews_folder_id_is_equal (const EwsFolderId *a,
        if (g_strcmp0 (a->id, b->id) != 0)
                return FALSE;
 
-       if (g_strcmp0 (a->change_key, b->change_key) != 0)
-               return FALSE;
-
        return TRUE;
 }
 
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
new file mode 100644
index 0000000..13260c0
--- /dev/null
+++ b/src/tests/Makefile.am
@@ -0,0 +1,36 @@
+include $(top_srcdir)/gtester.mk
+
+AM_CPPFLAGS = \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/src \
+       -I$(top_builddir) \
+       -I$(top_builddir)/src \
+       -DTEST_FILE_DIR="\"$(top_srcdir)/src/tests/\"" \
+       -DG_LOG_DOMAIN=\"libeews\" \
+       -DLOCALEDIR="\"$(datadir)/locale\"" \
+       $(SOUP_CFLAGS) \
+       $(LIBECAL_CFLAGS) \
+       $(LIBICAL_CFLAGS) \
+       $(LIBEDATASERVER_CFLAGS) \
+       $(UHTTPMOCK_CFLAGS) \
+       $(NULL)
+
+
+noinst_PROGRAMS = $(TEST_PROGS)
+
+LIBS = \
+       $(top_builddir)/src/server/libeews-1.2.la \
+       $(top_builddir)/src/utils/libewsutils.la \
+       $(UHTTPMOCK_LIBS)
+       $(NULL)
+
+TEST_SRCS = \
+       common.c \
+       common.h\
+       e-ews-connection.h \
+       $(NULL)
+
+TEST_PROGS                     += camel
+camel_SOURCES                   = camel.c $(TEST_SRCS)
+
+-include $(top_srcdir)/git.mk
diff --git a/src/tests/camel.c b/src/tests/camel.c
new file mode 100644
index 0000000..9a91797
--- /dev/null
+++ b/src/tests/camel.c
@@ -0,0 +1,851 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ *    Fabiano Fidêncio <fidencio redhat com>
+ *    Philip Withnall <philip tecnocode co uk>
+ *    Vadim Rutkovsky <vrutkovs redhat com>
+ */
+
+#include <server/e-ews-connection.h>
+#include <server/e-ews-debug.h>
+#include <server/e-ews-folder.h>
+
+#include "common.h"
+
+static EwsFolderId *distinguished_folder_subfolder_id = NULL;
+static EwsFolderId *non_distinguished_folder_subfolder_id = NULL;
+
+static const gchar *invalid_folder_id =
+"AAMkADQyYzVlYmU0LWNhNTUtNDNkYy04ZGYxLTk5ZTk5ZGY4NmJlMwAuAAAAAAB9G7pDgpwKQKc31aq6C3GTAQAi6qqMgDmPQrslhHoZnZkhAABOpnTeSTE=";
+
+static void
+server_notify_resolver_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
+{
+       UhmServer *local_server;
+       UhmResolver *resolver;
+       EwsTestData *etd;
+       const gchar *hostname;
+
+       local_server = UHM_SERVER (object);
+       etd = user_data;
+       hostname = etd->hostname;
+
+       /* Set up the expected domain names here. This should technically be split up between
+        * the different unit test suites, but that's too much effort. */
+       resolver = uhm_server_get_resolver (local_server);
+
+       if (resolver != NULL) {
+               const gchar *ip_address = uhm_server_get_address (local_server);
+
+               uhm_resolver_add_A (resolver, hostname, ip_address);
+       }
+}
+
+static gboolean
+is_folder_on_server (EEwsConnection *connection,
+                    EwsFolderId *fid,
+                    gboolean should_have)
+{
+       gboolean found = !should_have;
+       GSList *folders_ids = NULL;
+       GSList *folders = NULL, *f;
+       GError *error = NULL;
+
+       folders_ids = g_slist_prepend (folders_ids, fid);
+       e_ews_connection_get_folder_sync (
+               connection, EWS_PRIORITY_MEDIUM, "IdOnly",
+               NULL, folders_ids, &folders,
+               NULL, &error);
+
+       if (error != NULL) {
+               if (g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND))
+                       goto exit;
+
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       for (f = folders; f != NULL; f = f->next) {
+               EEwsFolder *folder = f->data;
+               const EwsFolderId *result_fid;
+
+               if (e_ews_folder_is_error (folder)) {
+                       const GError *folder_error;
+
+                       found = FALSE;
+
+                       folder_error = e_ews_folder_get_error (folder);
+                       if (g_error_matches (folder_error, EWS_CONNECTION_ERROR, 
EWS_CONNECTION_ERROR_ITEMNOTFOUND))
+                               break;
+                       else
+                               continue;
+               }
+
+               result_fid = e_ews_folder_get_id (folder);
+               if (e_ews_folder_id_is_equal (fid, result_fid)) {
+                       found = TRUE;
+                       break;
+               }
+       }
+
+ exit:
+       g_slist_free_full (folders, g_object_unref);
+       g_slist_free (folders_ids);
+       g_clear_error (&error);
+       return found;
+}
+
+static void
+test_create_existing_folder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval;
+       gboolean folder_exists;
+       GError *error = NULL;
+       EwsFolderId *fid;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "create_existing_folder", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_create_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "msgfolderroot", TRUE,
+               "inbox", E_EWS_FOLDER_TYPE_MAILBOX, &fid,
+               NULL, &error);
+
+       if (error != NULL) {
+               folder_exists = g_error_matches (
+                       error,
+                       EWS_CONNECTION_ERROR,
+                       EWS_CONNECTION_ERROR_FOLDEREXISTS);
+
+               if (!folder_exists)
+                       g_printerr ("\n%s\n", error->message);
+       }
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == FALSE && folder_exists == TRUE);
+}
+
+static void
+test_create_folder_with_invalid_distinguished_parent_id (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval;
+       gboolean parent_folder_not_found;
+       GError *error = NULL;
+       EwsFolderId *fid;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "create_folder_with_invalid_distinguished_parent_id", 
&error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_create_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "invalidparentid", TRUE,
+               "folder", E_EWS_FOLDER_TYPE_MAILBOX, &fid,
+               NULL, &error);
+
+       if (error != NULL) {
+               parent_folder_not_found = g_error_matches (
+                       error,
+                       SOUP_HTTP_ERROR,
+                       SOUP_STATUS_IO_ERROR);
+
+               if (!parent_folder_not_found)
+                       g_printerr ("\n%s\n", error->message);
+       }
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == FALSE && parent_folder_not_found == TRUE);
+}
+
+static void
+test_create_folder_with_invalid_non_distinguished_parent_id (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval;
+       gboolean parent_folder_not_found = FALSE;
+       GError *error = NULL;
+       EwsFolderId *fid;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, 
"create_folder_with_invalid_non_distinguished_parent_id", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_create_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               invalid_folder_id, FALSE,
+               "folder", E_EWS_FOLDER_TYPE_MAILBOX, &fid,
+               NULL, &error);
+
+       if (error != NULL) {
+               parent_folder_not_found =
+                       g_error_matches (
+                               error,
+                               EWS_CONNECTION_ERROR,
+                               EWS_CONNECTION_ERROR_NONEXISTENTMAILBOX) ||
+                       g_error_matches (
+                               error,
+                               EWS_CONNECTION_ERROR,
+                               EWS_CONNECTION_ERROR_PARENTFOLDERNOTFOUND);
+
+               if (!parent_folder_not_found)
+                       g_printerr ("\n%s\n", error->message);
+       }
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == FALSE && parent_folder_not_found == TRUE);
+}
+
+static void
+test_create_folder_with_malformed_parent_id (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval;
+       gboolean malformed_parent_id;
+       GError *error = NULL;
+       EwsFolderId *fid;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "create_folder_with_malformed_parent_id", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_create_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "malformedparentid", FALSE,
+               "folder", E_EWS_FOLDER_TYPE_MAILBOX, &fid,
+               NULL, &error);
+
+       if (error != NULL) {
+               malformed_parent_id = g_error_matches (
+                       error,
+                       EWS_CONNECTION_ERROR,
+                       EWS_CONNECTION_ERROR_INVALIDIDMALFORMED);
+
+               if (!malformed_parent_id)
+                       g_printerr ("\n%s\n", error->message);
+       }
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == FALSE && malformed_parent_id == TRUE);
+}
+
+static void
+test_create_distinguished_folder_subfolder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean on_server = FALSE;
+       GError *error = NULL;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "create_distinguished_folder_subfolder", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_create_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "inbox", TRUE,
+               "distinguished-folder-subfolder", E_EWS_FOLDER_TYPE_MAILBOX,
+               &distinguished_folder_subfolder_id, NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       on_server = is_folder_on_server (etd->connection, distinguished_folder_subfolder_id, TRUE);
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == TRUE && on_server == TRUE);
+}
+
+static void
+test_create_non_distinguished_folder_subfolder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean on_server = FALSE;
+       GError *error = NULL;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "create_non_distinguished_folder_subfolder", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_create_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               distinguished_folder_subfolder_id->id, FALSE,
+               "non-distinguished-folder-subfolder", E_EWS_FOLDER_TYPE_MAILBOX,
+               &non_distinguished_folder_subfolder_id,
+               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       on_server = is_folder_on_server (etd->connection, non_distinguished_folder_subfolder_id, TRUE);
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == TRUE && on_server == TRUE);
+}
+
+static void
+test_move_valid_folder_to_invalid_folder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean malformed_parent_id = FALSE;
+       GError *error = NULL;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "move_valid_folder_to_invalid_folder", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_move_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "malformed_parent_id", distinguished_folder_subfolder_id->id,
+               NULL, &error);
+
+       if (error != NULL) {
+               malformed_parent_id = g_error_matches (
+                       error,
+                       EWS_CONNECTION_ERROR,
+                       EWS_CONNECTION_ERROR_INVALIDIDMALFORMED);
+
+               if (!malformed_parent_id)
+                       g_printerr ("\n%s\n", error->message);
+       }
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == FALSE && malformed_parent_id == TRUE);
+}
+
+static void
+test_move_invalid_to_valid_folder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean malformed_parent_id = FALSE;
+       GError *error = NULL;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "move_invalid_folder_to_valid_folder", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_move_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               distinguished_folder_subfolder_id->id, "malformedparentid",
+               NULL, &error);
+
+       if (error != NULL) {
+               malformed_parent_id = g_error_matches (
+                       error,
+                       EWS_CONNECTION_ERROR,
+                       EWS_CONNECTION_ERROR_INVALIDIDMALFORMED);
+
+               if (!malformed_parent_id)
+                       g_printerr ("\n%s\n", error->message);
+       }
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == FALSE && malformed_parent_id == TRUE);
+}
+
+static void
+test_move_folder_to_msgfolderroot (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean moved_to_msgfolderroot = FALSE;
+       GError *error = NULL;
+       GSList *folder_ids = NULL;
+       GSList *folders1;
+       GSList *folders2;
+       EEwsFolder *folder1;
+       EEwsFolder *folder2;
+       EwsFolderId *msgfolderroot;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "move_folder_to_msgfolderroot", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_move_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               NULL, non_distinguished_folder_subfolder_id->id,
+               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       folder_ids = g_slist_prepend (folder_ids, non_distinguished_folder_subfolder_id);
+       e_ews_connection_get_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "AllProperties", NULL, folder_ids, &folders1,
+               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       folder1 = folders1->data;
+
+       msgfolderroot = e_ews_folder_id_new ("msgfolderroot", NULL, TRUE);
+       folder_ids = g_slist_prepend (folder_ids, msgfolderroot);
+       e_ews_connection_get_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "IdOnly", NULL, folder_ids, &folders2,
+               NULL, &error);
+
+       folder2 = folders2->data;
+
+       moved_to_msgfolderroot = e_ews_folder_id_is_equal (
+               e_ews_folder_get_parent_id (folder1),
+               e_ews_folder_get_id (folder2));
+
+ exit:
+       uhm_server_end_trace (local_server);
+
+       g_slist_free_full (folders1, g_object_unref);
+       g_slist_free_full (folders2, g_object_unref);
+       g_slist_free (folder_ids);
+       g_clear_error (&error);
+
+       g_assert (retval == TRUE && moved_to_msgfolderroot == TRUE);
+}
+
+static void
+test_move_folder_to_folder_that_has_subfolder_with_the_same_name (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = TRUE;
+       gboolean move_failed = FALSE;
+       GError *error = NULL;
+       EwsFolderId *fid;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, 
"move_folder_to_folder_that_has_subfolder_with_the_same_name", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       e_ews_connection_create_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               non_distinguished_folder_subfolder_id->id, FALSE,
+               "inbox", E_EWS_FOLDER_TYPE_MAILBOX, &fid,
+               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_move_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               NULL, fid->id,
+               NULL, &error);
+
+       if (error != NULL) {
+               move_failed = g_error_matches (
+                       error,
+                       EWS_CONNECTION_ERROR,
+                       EWS_CONNECTION_ERROR_MOVECOPYFAILED);
+
+               if (!move_failed)
+                       g_printerr ("\n%s\n", error->message);
+       }
+
+ exit:
+       uhm_server_end_trace (local_server);
+       e_ews_folder_id_free (fid);
+
+       g_clear_error (&error);
+
+       g_assert (retval == FALSE && move_failed == TRUE);
+}
+
+static void
+test_move_folder_to_valid_folder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean moved_to_correct_folder = FALSE;
+       GError *error = NULL;
+       GSList *folder_ids = NULL;
+       GSList *folders1;
+       GSList *folders2;
+       EEwsFolder *folder1;
+       EEwsFolder *folder2;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "move_folder_to_valid_folder", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_move_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               distinguished_folder_subfolder_id->id, non_distinguished_folder_subfolder_id->id,
+               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       folder_ids = g_slist_prepend (folder_ids, non_distinguished_folder_subfolder_id);
+       e_ews_connection_get_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "AllProperties", NULL, folder_ids, &folders1,
+               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       folder1 = folders1->data;
+
+       folder_ids = g_slist_prepend (folder_ids, distinguished_folder_subfolder_id);
+       e_ews_connection_get_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "IdOnly", NULL, folder_ids, &folders2,
+               NULL, &error);
+
+       folder2 = folders2->data;
+
+       moved_to_correct_folder = e_ews_folder_id_is_equal (
+               e_ews_folder_get_parent_id (folder1),
+               e_ews_folder_get_id (folder2));
+
+ exit:
+       uhm_server_end_trace (local_server);
+
+       g_slist_free_full (folders1, g_object_unref);
+       g_slist_free_full (folders2, g_object_unref);
+       g_slist_free (folder_ids);
+       g_clear_error (&error);
+
+       g_assert (retval == TRUE && moved_to_correct_folder == TRUE);
+}
+
+static void
+test_hard_delete_distinguished_folder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean distinguished_folder = FALSE;
+       GError *error = NULL;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "hard_delete_root_subfolder", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_delete_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               "inbox", TRUE, "HardDelete",
+               NULL, &error);
+
+       if (error != NULL) {
+               distinguished_folder = g_error_matches (
+                       error,
+                       EWS_CONNECTION_ERROR,
+                       EWS_CONNECTION_ERROR_DELETEDISTINGUISHEDFOLDER);
+
+               if (!distinguished_folder)
+                       g_printerr ("\n%s\n", error->message);
+       }
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+
+       g_assert (retval == FALSE && distinguished_folder == TRUE);
+}
+
+static void
+test_hard_delete_non_distinguished_folder_subfolder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean on_server = TRUE;
+       GError *error = NULL;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "hard_delete_non_distinguished_folder_subfolder", 
&error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_delete_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               non_distinguished_folder_subfolder_id->id, FALSE, "HardDelete",
+               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       on_server = is_folder_on_server (etd->connection, non_distinguished_folder_subfolder_id, FALSE);
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+       e_ews_folder_id_free (non_distinguished_folder_subfolder_id);
+       non_distinguished_folder_subfolder_id = NULL;
+
+       g_assert (retval == TRUE && on_server == FALSE);
+}
+
+static void
+test_hard_delete_distinguished_folder_subfolder (gconstpointer user_data)
+{
+       UhmServer *local_server;
+       gboolean retval = FALSE;
+       gboolean on_server = TRUE;
+       GError *error = NULL;
+       EwsTestData *etd = (gpointer) user_data;
+
+       local_server = ews_test_get_mock_server ();
+
+       ews_test_server_set_trace_directory (local_server, etd->version, "camel/folder");
+       ews_test_server_start_trace (local_server, etd, "hard_delete_distinguished_folder_subfolder", &error);
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       retval = e_ews_connection_delete_folder_sync (
+               etd->connection, EWS_PRIORITY_MEDIUM,
+               distinguished_folder_subfolder_id->id, FALSE, "HardDelete",
+               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("\n%s\n", error->message);
+               goto exit;
+       }
+
+       on_server = is_folder_on_server (etd->connection, distinguished_folder_subfolder_id, FALSE);
+
+ exit:
+       uhm_server_end_trace (local_server);
+       g_clear_error (&error);
+       e_ews_folder_id_free (distinguished_folder_subfolder_id);
+       distinguished_folder_subfolder_id = NULL;
+
+       g_assert (retval == TRUE && on_server == FALSE);
+}
+
+int main (int argc,
+         char **argv)
+{
+       gint retval;
+       GList *etds, *l;
+       UhmServer *server;
+
+       retval = ews_test_init (argc, argv);
+
+       if (retval < 0)
+               goto exit;
+
+       server = ews_test_get_mock_server ();
+       etds = ews_test_get_test_data_list ();
+
+       for (l = etds; l != NULL; l = l->next) {
+               EwsTestData *etd = l->data;
+               gchar *message;
+
+               if (!uhm_server_get_enable_online (server))
+                       g_signal_connect (server, "notify::resolver", (GCallback) server_notify_resolver_cb, 
etd);
+
+               /* Create folder */
+               message = g_strdup_printf ("/%s/camel/folder/create_existing_folder", etd->version);
+               g_test_add_data_func (message, etd, test_create_existing_folder);
+               g_free (message);
+
+               message = g_strdup_printf (
+                       "/%s/camel/folder/create_folder_invalid_distinguished_parent_id", etd->version);
+               g_test_add_data_func (message, etd, test_create_folder_with_invalid_distinguished_parent_id);
+               g_free (message);
+
+               message = g_strdup_printf (
+                       "/%s/camel/folder/create_folder_invalid_non_distinguished_parent_id", etd->version);
+               g_test_add_data_func (message, etd, 
test_create_folder_with_invalid_non_distinguished_parent_id);
+               g_free (message);
+
+               message = g_strdup_printf ("/%s/camel/folder/create_folder_with_malformed_parent_id", 
etd->version);
+               g_test_add_data_func (message, etd, test_create_folder_with_malformed_parent_id);
+               g_free (message);
+
+               message = g_strdup_printf ("/%s/camel/folder/create_distinguished_folder_subfolder", 
etd->version);
+               g_test_add_data_func (message, etd, test_create_distinguished_folder_subfolder);
+               g_free (message);
+
+               message = g_strdup_printf ("/%s/camel/folder/create_non_distinguished_folder_subfolder", 
etd->version);
+               g_test_add_data_func (message, etd, test_create_non_distinguished_folder_subfolder);
+               g_free (message);
+
+               /* Move folder */
+               message = g_strdup_printf ("/%s/camel/folder/move_valid_folder_to_invalid_folder", 
etd->version);
+               g_test_add_data_func (message, etd, test_move_valid_folder_to_invalid_folder);
+               g_free (message);
+
+               message = g_strdup_printf (
+                       "/%s/camel/folder/move_invalid_folder_to_valid_folder", etd->version);
+               g_test_add_data_func (message, etd, test_move_invalid_to_valid_folder);
+               g_free (message);
+
+               message = g_strdup_printf (
+                       "/%s/camel/folder/move_folder_to_msgfolderroot", etd->version);
+               g_test_add_data_func (message, etd, test_move_folder_to_msgfolderroot);
+               g_free (message);
+
+               message = g_strdup_printf (
+                       "/%s/camel/folder/move_folder_to_folder_that_has_subfolder_with_the_same_name", 
etd->version);
+               g_test_add_data_func (message, etd, 
test_move_folder_to_folder_that_has_subfolder_with_the_same_name);
+               g_free (message);
+
+               message = g_strdup_printf (
+                       "/%s/camel/folder/move_folder_to_valid_folder", etd->version);
+               g_test_add_data_func (message, etd, test_move_folder_to_valid_folder);
+               g_free (message);
+
+               /* Delete folder */
+               message = g_strdup_printf ("/%s/camel/folder/hard_delete_distinguished_folder", etd->version);
+               g_test_add_data_func (message, etd, test_hard_delete_distinguished_folder);
+               g_free (message);
+
+               message = g_strdup_printf ("/%s/camel/folder/hard_delete_non_distinguished_folder_subfolder", 
etd->version);
+               g_test_add_data_func (message, etd, test_hard_delete_non_distinguished_folder_subfolder);
+               g_free (message);
+
+               message = g_strdup_printf ("/%s/camel/folder/hard_delete_distinguished_folder_subfolder", 
etd->version);
+               g_test_add_data_func (message, etd, test_hard_delete_distinguished_folder_subfolder);
+               g_free (message);
+
+       }
+
+       retval = g_test_run ();
+
+       if (!uhm_server_get_enable_online (server))
+               for (l = etds; l != NULL; l = l->next)
+                       g_signal_handlers_disconnect_by_func (server, server_notify_resolver_cb, l->data);
+
+ exit:
+       ews_test_cleanup ();
+       return retval;
+}
diff --git a/src/tests/common.c b/src/tests/common.c
new file mode 100644
index 0000000..5ff26ed
--- /dev/null
+++ b/src/tests/common.c
@@ -0,0 +1,370 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ *    Fabiano Fidêncio <fidencio redhat com>
+ *    Philip Withnall <philip tecnocode co uk>
+ *    Vadim Rutkovsky <vrutkovs redhat com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "common.h"
+
+/* declaration of debug handler */
+static void ews_test_debug_handler (const gchar *log_domain,
+                                   GLogLevelFlags log_level,
+                                   const gchar *message,
+                                   gpointer user_data);
+
+/* Directory to output network trace files to, if trace output is enabled. (NULL otherwise.) */
+static const GFile *trace_dir = NULL;
+
+/*
+ * TRUE if tests should be run and a trace file written for each;
+ * FALSE if tests should run offline against existing trace files.
+ */
+static gboolean write_traces = FALSE;
+
+/* Global mock server instance used by all tests */
+static UhmServer *mock_server = NULL;
+
+static GList *etds = NULL;
+
+static gboolean no_interactive = FALSE;
+
+static void
+prepare_fake_data (guint *number,
+                  GList **fake_versions,
+                  GList **fake_hostnames,
+                  GList **fake_server_uris)
+{
+       guint i;
+       const gchar *supported_versions[] = {
+               "2007_SP1",
+               "2010_SP2",
+               NULL
+       };
+
+       for (i = 0; supported_versions[i] != NULL; i++) {
+               *fake_versions = g_list_append (
+                       *fake_versions,
+                       g_strdup_printf ("Exchange%s", supported_versions[i]));
+               *fake_hostnames = g_list_append (
+                       *fake_hostnames,
+                       g_strdup_printf ("exchange%s.server.com", supported_versions[i]));
+               *fake_server_uris = g_list_append (
+                       *fake_server_uris,
+                       g_strdup_printf ("https://exchange%s.server.com:PORT/EWS/Exchange.asmx";, 
supported_versions[i]));
+       }
+
+       *number = i;
+}
+
+static void
+help (gchar *program)
+{
+       /* We have to override --help in order to document --no-interactive and the trace flags. */
+       g_print ("Usage:\n"
+                "  %s [OPTION...]\n\n"
+                "Help Options:\n"
+                "  -?, --help                      Show help options\n"
+                "Test Options:\n"
+                "  -l                              List test cases available in a test executable\n"
+                "  -seed=RANDOMSEED                Provide a random seed to reproduce test\n"
+                "                                  runs using random numbers\n"
+                "  --verbose                       Run tests verbosely\n"
+                "  -q, --quiet                     Run tests quietly\n"
+                "  -p TESTPATH                     Execute all tests matching TESTPATH\n"
+                "  -m {perf|slow|thorough|quick}   Execute tests according modes\n"
+                "  --debug-log                     Debug test logging output\n"
+                "  -i, --no-interactive            Only execute tests which don't require user interaction\n"
+                "  -t, --trace-dir [directory]     Read/Write trace files in the specified directory\n"
+                "  -w, --write-traces              Work online and write trace files to --trace-dir\n"
+                "  -c, --config                    In the format: key=value, where valid keys are:\n"
+                "                                      version, server-uri, username, password\n",
+                program);
+}
+
+gint
+ews_test_init (gint argc,
+              gchar **argv)
+{
+       guint ret = 0;
+       guint number = 0;
+       guint i;
+       GList *versions = NULL;
+       GList *server_uris = NULL;
+       GList *usernames = NULL;
+       GList *passwords = NULL;
+       GList *fake_versions = NULL;
+       GList *fake_hostnames = NULL;
+       GList *fake_server_uris = NULL;
+
+#if !GLIB_CHECK_VERSION (2, 35, 0)
+       g_type_init ();
+#endif
+
+       /* Parse the custom options */
+       for (i = 1; i < argc; i++) {
+               if (g_strcmp0 ("--no-interactive", argv[i]) == 0 || g_strcmp0 ("-i", argv[i]) == 0) {
+                       no_interactive = TRUE;
+                       argv[i] = (char *) "";
+               } else if (g_strcmp0 ("--trace-dir", argv[i]) == 0 || g_strcmp0 ("-t", argv[i]) == 0) {
+                       if (i >= argc - 1) {
+                               g_list_free_full (versions, g_free);
+                               g_list_free_full (server_uris, g_free);
+                               g_list_free_full (usernames, g_free);
+                               g_list_free_full (passwords, g_free);
+
+                               g_error ("Error: Missing directory for --trace-dir option.\n");
+                       }
+
+                       trace_dir = g_file_new_for_path (argv[i + 1]);
+
+                       argv[i] = (char *) "";
+                       argv[i + 1] = (char *) "";
+                       i += 2;
+               } else if (g_strcmp0 ("--config", argv[i]) == 0 || g_strcmp0 ("-c", argv[i]) == 0) {
+                       const gchar *val;
+                       const gchar *value;
+                       gchar *key;
+                       gsize len;
+
+                       if (i >= argc - 1) {
+                               g_list_free_full (versions, g_free);
+                               g_list_free_full (server_uris, g_free);
+                               g_list_free_full (usernames, g_free);
+                               g_list_free_full (passwords, g_free);
+
+                               g_error ("Error: Missing arguments for --config option.\n"
+                                        "       Expected: --config key=value, with valid these valid keys:\n"
+                                        "                 version, server-uri, username, password\n");
+                       }
+
+                       value = argv[i + 1];
+
+                       if (!(val = strchr (value, '='))) {
+                               g_list_free_full (versions, g_free);
+                               g_list_free_full (server_uris, g_free);
+                               g_list_free_full (usernames, g_free);
+                               g_list_free_full (passwords, g_free);
+
+                               g_error ("Error: Missing arguments for --config option.\n"
+                                        "       Expected: --config key=value, with valid these valid keys:\n"
+                                        "                 version, server-uri, username, password\n");
+                       }
+
+                       len = val - value;
+                       val++;
+                       key = g_strndup (value, len);
+
+                       if (g_strcmp0 (key, "number") == 0)
+                               number = g_ascii_strtoll (val, NULL, 0);
+                       else if (g_strcmp0 (key, "version") == 0)
+                               versions = g_list_append (versions, g_strdup (val));
+                       else if (g_strcmp0 (key, "server-uri") == 0)
+                               server_uris = g_list_append (server_uris, g_strdup (val));
+                       else if (g_strcmp0 (key, "username") == 0)
+                               usernames = g_list_append (usernames, g_strdup (val));
+                       else if (g_strcmp0 (key, "password") == 0)
+                               passwords = g_list_append (passwords, g_strdup (val));
+
+                       g_free (key);
+
+                       argv[i] = (char *) "";
+                       argv[i + 1] = (char *) "";
+                       i++;
+               } else if (g_strcmp0 ("--write-traces", argv[i]) == 0 || g_strcmp0 ("-w", argv[i]) == 0) {
+                       write_traces = TRUE;
+                       argv[i] = (char *) "";
+               } else if (g_strcmp0 ("-?", argv[i]) == 0 || g_strcmp0 ("--help", argv[i]) == 0 || g_strcmp0 
("-h" , argv[i]) == 0) {
+                       help (argv[0]);
+
+                       exit (0);
+               }
+       }
+
+       if ((number == 0 && write_traces) ||
+           (number > 0 &&
+            (number != g_list_length (versions) ||
+             number != g_list_length (server_uris) ||
+             number != g_list_length (usernames) ||
+             number != g_list_length (passwords)))) {
+               g_printerr ("Error while parsing options\n");
+               help (argv[0]);
+
+               g_list_free_full (versions, g_free);
+               g_list_free_full (server_uris, g_free);
+               g_list_free_full (usernames, g_free);
+               g_list_free_full (passwords, g_free);
+
+               exit (1);
+       }
+
+       g_test_init (&argc, &argv, NULL);
+       g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=";);
+
+       g_setenv ("EWS_DEBUG", "3", TRUE);
+
+       mock_server = uhm_server_new ();
+       uhm_server_set_default_tls_certificate (mock_server);
+       uhm_server_set_enable_logging (mock_server, write_traces);
+       uhm_server_set_enable_online (mock_server, write_traces);
+
+       /* Set handler of debug information */
+       g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, (GLogFunc) ews_test_debug_handler, mock_server);
+
+       if (number == 0)
+               prepare_fake_data (&number, &fake_versions, &fake_hostnames, &fake_server_uris);
+
+       for (i = 0; i < number; i++) {
+               EwsTestData *etd;
+
+               etd = g_new0 (EwsTestData, 1);
+               if (write_traces) {
+                       CamelEwsSettings *settings = NULL;
+
+                       settings = g_object_new (
+                               CAMEL_TYPE_EWS_SETTINGS,
+                               "user", g_list_nth_data (usernames, i),
+                               NULL);
+
+                       etd->version = g_list_nth_data (versions, i);
+                       etd->connection = e_ews_connection_new (g_list_nth_data (server_uris, i), settings);
+                       e_ews_connection_set_password (etd->connection, g_list_nth_data (passwords, i));
+                       e_ews_connection_set_server_version_from_string (etd->connection, etd->version);
+
+                       g_object_unref (settings);
+               } else {
+                       etd->version = g_list_nth_data (fake_versions, i);
+                       etd->server_uri = g_list_nth_data (fake_server_uris, i);
+                       etd->hostname = g_list_nth_data (fake_hostnames, i);
+               }
+
+               etds = g_list_append (etds, etd);
+       }
+
+       g_list_free (versions);
+       g_list_free (usernames);
+       g_list_free (server_uris);
+       g_list_free (passwords);
+       g_list_free (fake_versions);
+       g_list_free (fake_server_uris);
+       g_list_free (fake_hostnames);
+       return ret;
+}
+
+UhmServer *
+ews_test_get_mock_server (void)
+{
+       return mock_server;
+}
+
+GList * /* EwsTestData */
+ews_test_get_test_data_list (void)
+{
+       return etds;
+}
+
+static void
+ews_test_data_free (EwsTestData *etd)
+{
+       g_free (etd->hostname);
+       g_free (etd->version);
+       g_free (etd->server_uri);
+       g_object_unref (etd->connection);
+       g_free (etd);
+}
+
+void
+ews_test_cleanup (void)
+{
+       g_list_free_full (ews_test_get_test_data_list (), (GDestroyNotify) ews_test_data_free);
+       g_object_unref (ews_test_get_mock_server ());
+}
+
+static void
+ews_test_set_https_port (UhmServer *server,
+                        EwsTestData *etd)
+{
+       CamelEwsSettings *ews_settings;
+       guint16 port;
+       gchar *uri;
+       gchar **tokens;
+
+       port = uhm_server_get_port (server);
+
+       tokens = g_strsplit (etd->server_uri, "PORT", 0);
+       uri = g_strdup_printf ("%s%d%s", tokens[0], port, tokens[1]);
+
+       ews_settings = g_object_new (
+               CAMEL_TYPE_EWS_SETTINGS,
+               "user", "foo",
+               NULL);
+
+       etd->connection = e_ews_connection_new (uri, ews_settings);
+       e_ews_connection_set_password (etd->connection, "bar");
+       e_ews_connection_set_server_version_from_string (etd->connection, etd->version);
+
+       g_free (uri);
+       g_strfreev (tokens);
+       g_object_unref (ews_settings);
+}
+
+void
+ews_test_server_start_trace (UhmServer *server,
+                            EwsTestData *etd,
+                            const gchar *trace_filename,
+                            GError **error)
+{
+       uhm_server_start_trace (server, trace_filename, error);
+       if (!uhm_server_get_enable_online (server))
+               ews_test_set_https_port (server, etd);
+}
+
+void
+ews_test_server_set_trace_directory (UhmServer *server,
+                                    const gchar *version,
+                                    const gchar *tests)
+{
+       gchar *path;
+       GFile *trace_directory;
+
+       path = g_strdup_printf (TEST_FILE_DIR "traces/%s/%s", version, tests);
+       trace_directory = g_file_new_for_path (path);
+       g_free (path);
+       uhm_server_set_trace_directory (server, trace_directory);
+       g_object_unref (trace_directory);
+}
+
+static void
+ews_test_debug_handler (const gchar *log_domain,
+                       GLogLevelFlags log_level,
+                       const gchar *message,
+                       gpointer user_data)
+{
+       UhmServer *server = user_data;
+
+       if (message != NULL &&
+           (*message == '<' || *message == '>' || *message == ' ') &&
+           *(message + 1) == ' ') {
+               uhm_server_received_message_chunk (server, message, strlen (message), NULL);
+       }
+}
diff --git a/src/tests/common.h b/src/tests/common.h
new file mode 100644
index 0000000..086e0dd
--- /dev/null
+++ b/src/tests/common.h
@@ -0,0 +1,52 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ *    Fabiano Fidêncio <fidencio redhat com>
+ */
+
+#include <uhttpmock/uhm.h>
+
+#include "server/camel-ews-settings.h"
+#include "server/e-ews-connection.h"
+
+#ifndef EWS_TEST_COMMON_H
+#define EWS_TEST_COMMON_H
+
+G_BEGIN_DECLS
+
+typedef struct _EwsTestData {
+       EEwsConnection *connection;
+       gchar *hostname;
+       gchar *version;
+       gchar *server_uri;
+} EwsTestData;
+
+gint                   ews_test_init                                   (gint argc,
+                                                                        gchar **argv);
+UhmServer *            ews_test_get_mock_server                        (void);
+GList *                        ews_test_get_test_data_list                     (void);
+void                   ews_test_cleanup                                (void);
+void                   ews_test_server_start_trace                     (UhmServer *server,
+                                                                        EwsTestData *etd,
+                                                                        const gchar *trace_filename,
+                                                                        GError **error);
+void                   ews_test_server_set_trace_directory             (UhmServer *server,
+                                                                        const gchar *version,
+                                                                        const gchar *tests);
+
+G_END_DECLS
+
+#endif /* EWS_TEST_COMMON_H */


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