/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2017 Red Hat, Inc. (www.redhat.com)
*
* This library is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* This library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see .
*/
#include "evolution-data-server-config.h"
#include
#include
#include
#include "libebook-contacts/libebook-contacts.h"
#include "e-test-server-utils.h"
#include "test-book-cache-utils.h"
#define REMOTE_URL "https://www.gnome.org/wp-content/themes/gnome-grass/images/gnome-logo.svg"
#define MODIFIED_FN_STR "Modified FN"
typedef struct _EBookMetaBackendTest {
EBookMetaBackend parent;
GHashTable *contacts;
gint sync_tag_index;
gboolean can_connect;
gboolean is_connected;
gint connect_count;
gint list_count;
gint save_count;
gint load_count;
gint remove_count;
} EBookMetaBackendTest;
typedef struct _EBookMetaBackendTestClass {
EBookMetaBackendClass parent_class;
} EBookMetaBackendTestClass;
#define E_TYPE_BOOK_META_BACKEND_TEST (e_book_meta_backend_test_get_type ())
#define E_BOOK_META_BACKEND_TEST(obj) \
(G_TYPE_CHECK_INSTANCE_CAST \
((obj), E_TYPE_BOOK_META_BACKEND_TEST, EBookMetaBackendTest))
#define E_IS_BOOK_META_BACKEND_TEST(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE \
((obj), E_TYPE_BOOK_META_BACKEND_TEST))
GType e_book_meta_backend_test_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE (EBookMetaBackendTest, e_book_meta_backend_test, E_TYPE_BOOK_META_BACKEND)
static void
ebmb_test_add_test_case (EBookMetaBackendTest *test_backend,
const gchar *case_name)
{
EContact *contact;
g_assert_nonnull (test_backend);
g_assert_nonnull (case_name);
contact = tcu_new_contact_from_test_case (case_name);
g_assert_nonnull (contact);
g_hash_table_insert (test_backend->contacts, e_contact_get (contact, E_CONTACT_UID), contact);
}
static void
ebmb_test_remove_component (EBookMetaBackendTest *test_backend,
const gchar *uid)
{
g_assert_nonnull (test_backend);
g_assert_nonnull (uid);
g_hash_table_remove (test_backend->contacts, uid);
}
static GHashTable * /* gchar * ~> NULL */
ebmb_test_gather_uids (va_list args)
{
GHashTable *expects;
const gchar *uid;
expects = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
uid = va_arg (args, const gchar *);
while (uid) {
g_hash_table_insert (expects, g_strdup (uid), NULL);
uid = va_arg (args, const gchar *);
}
return expects;
}
static void
ebmb_test_hash_contains (GHashTable *contacts, /* gchar *uid ~> EContact * */
gboolean negate,
gboolean exact,
...) /* uid-s, ended with NULL */
{
va_list args;
GHashTable *expects;
GHashTableIter iter;
gpointer uid;
guint ntotal;
g_return_if_fail (contacts != NULL);
va_start (args, exact);
expects = ebmb_test_gather_uids (args);
va_end (args);
ntotal = g_hash_table_size (expects);
g_hash_table_iter_init (&iter, contacts);
while (g_hash_table_iter_next (&iter, &uid, NULL)) {
if (exact) {
if (negate)
g_assert_true (!g_hash_table_remove (expects, uid));
else
g_assert_true (g_hash_table_remove (expects, uid));
} else {
g_hash_table_remove (expects, uid);
}
}
if (negate)
g_assert_cmpint (g_hash_table_size (expects), ==, ntotal);
else
g_assert_cmpint (g_hash_table_size (expects), ==, 0);
g_hash_table_destroy (expects);
}
static void
ebmb_test_cache_contains (EBookCache *book_cache,
gboolean negate,
gboolean exact,
...) /* uid-s, ended with NULL */
{
va_list args;
GHashTable *expects;
GHashTableIter iter;
ECache *cache;
gpointer key;
gint found = 0;
g_return_if_fail (E_IS_BOOK_CACHE (book_cache));
va_start (args, exact);
expects = ebmb_test_gather_uids (args);
va_end (args);
cache = E_CACHE (book_cache);
g_hash_table_iter_init (&iter, expects);
while (g_hash_table_iter_next (&iter, &key, NULL)) {
const gchar *uid = key;
g_assert_nonnull (uid);
if (e_cache_contains (cache, uid, E_CACHE_EXCLUDE_DELETED))
found++;
}
if (negate)
g_assert_cmpint (0, ==, found);
else
g_assert_cmpint (g_hash_table_size (expects), ==, found);
g_hash_table_destroy (expects);
if (exact && !negate)
g_assert_cmpint (e_cache_get_count (cache, E_CACHE_EXCLUDE_DELETED, NULL, NULL), ==, found);
}
static void
ebmb_test_cache_and_server_equal (EBookCache *book_cache,
GHashTable *contacts,
ECacheDeletedFlag deleted_flag)
{
ECache *cache;
GHashTableIter iter;
gpointer uid;
g_return_if_fail (E_IS_BOOK_CACHE (book_cache));
g_return_if_fail (contacts != NULL);
cache = E_CACHE (book_cache);
g_assert_cmpint (e_cache_get_count (cache, deleted_flag, NULL, NULL), ==,
g_hash_table_size (contacts));
g_hash_table_iter_init (&iter, contacts);
while (g_hash_table_iter_next (&iter, &uid, NULL)) {
g_assert_true (e_cache_contains (cache, uid, deleted_flag));
}
}
static gchar *
e_book_meta_backend_test_get_backend_property (EBookBackend *book_backend,
const gchar *prop_name)
{
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (book_backend), NULL);
g_return_val_if_fail (prop_name != NULL, NULL);
if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
return g_strjoin (",",
e_book_meta_backend_get_capabilities (E_BOOK_META_BACKEND (book_backend)),
"local",
"contact-lists",
NULL);
}
/* Chain up to parent's method. */
return E_BOOK_BACKEND_CLASS (e_book_meta_backend_test_parent_class)->impl_get_backend_property (book_backend, prop_name);
}
static gboolean
e_book_meta_backend_test_get_destination_address (EBackend *backend,
gchar **host,
guint16 *port)
{
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (backend), FALSE);
if (e_backend_get_online (backend))
return FALSE;
/* Provide something unreachable, to not have the meta backend switch the backend to online */
*host = g_strdup ("server.no.where");
*port = 65535;
return TRUE;
}
static gboolean
e_book_meta_backend_test_connect_sync (EBookMetaBackend *meta_backend,
const ENamedParameters *credentials,
ESourceAuthenticationResult *out_auth_result,
gchar **out_certificate_pem,
GTlsCertificateFlags *out_certificate_errors,
GCancellable *cancellable,
GError **error)
{
EBookMetaBackendTest *test_backend;
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (meta_backend), FALSE);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
if (test_backend->is_connected)
return TRUE;
test_backend->connect_count++;
if (test_backend->can_connect) {
test_backend->is_connected = TRUE;
return TRUE;
}
g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_REPOSITORY_OFFLINE,
e_client_error_to_string (E_CLIENT_ERROR_REPOSITORY_OFFLINE));
return FALSE;
}
static gboolean
e_book_meta_backend_test_disconnect_sync (EBookMetaBackend *meta_backend,
GCancellable *cancellable,
GError **error)
{
EBookMetaBackendTest *test_backend;
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (meta_backend), FALSE);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
test_backend->is_connected = FALSE;
return TRUE;
}
static gboolean
e_book_meta_backend_test_get_changes_sync (EBookMetaBackend *meta_backend,
const gchar *last_sync_tag,
gboolean is_repeat,
gchar **out_new_sync_tag,
gboolean *out_repeat,
GSList **out_created_objects,
GSList **out_modified_objects,
GSList **out_removed_objects,
GCancellable *cancellable,
GError **error)
{
EBookMetaBackendTest *test_backend;
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (meta_backend), FALSE);
g_return_val_if_fail (out_new_sync_tag != NULL, FALSE);
g_return_val_if_fail (out_repeat != NULL, FALSE);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
if (!test_backend->sync_tag_index) {
g_assert_null (last_sync_tag);
} else {
g_assert_nonnull (last_sync_tag);
g_assert_cmpint (atoi (last_sync_tag), ==, test_backend->sync_tag_index);
}
test_backend->sync_tag_index++;
*out_new_sync_tag = g_strdup_printf ("%d", test_backend->sync_tag_index);
if (test_backend->sync_tag_index == 2)
*out_repeat = TRUE;
else if (test_backend->sync_tag_index == 3)
return TRUE;
/* Nothing to do here at the moment, left the work to the parent class,
which calls list_existing_sync() internally. */
return E_BOOK_META_BACKEND_CLASS (e_book_meta_backend_test_parent_class)->get_changes_sync (meta_backend,
last_sync_tag, is_repeat, out_new_sync_tag, out_repeat, out_created_objects,
out_modified_objects, out_removed_objects, cancellable, error);
}
static gboolean
e_book_meta_backend_test_list_existing_sync (EBookMetaBackend *meta_backend,
gchar **out_new_sync_tag,
GSList **out_existing_objects,
GCancellable *cancellable,
GError **error)
{
EBookMetaBackendTest *test_backend;
GHashTableIter iter;
gpointer key, value;
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (meta_backend), FALSE);
g_return_val_if_fail (out_new_sync_tag, FALSE);
g_return_val_if_fail (out_existing_objects, FALSE);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
test_backend->list_count++;
g_assert_true (test_backend->is_connected);
*out_existing_objects = NULL;
g_hash_table_iter_init (&iter, test_backend->contacts);
while (g_hash_table_iter_next (&iter, &key, &value)) {
const gchar *uid;
gchar *revision;
EBookMetaBackendInfo *nfo;
uid = key;
revision = e_contact_get (value, E_CONTACT_REV);
nfo = e_book_meta_backend_info_new (uid, revision, NULL, NULL);
*out_existing_objects = g_slist_prepend (*out_existing_objects, nfo);
g_free (revision);
}
return TRUE;
}
static gboolean
e_book_meta_backend_test_save_contact_sync (EBookMetaBackend *meta_backend,
gboolean overwrite_existing,
EConflictResolution conflict_resolution,
EContact *contact,
const gchar *extra,
guint32 opflags,
gchar **out_new_uid,
gchar **out_new_extra,
GCancellable *cancellable,
GError **error)
{
EBookMetaBackendTest *test_backend;
const gchar *uid;
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (meta_backend), FALSE);
g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
g_return_val_if_fail (out_new_uid != NULL, FALSE);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
test_backend->save_count++;
g_assert_true (test_backend->is_connected);
uid = e_contact_get_const (contact, E_CONTACT_UID);
g_assert_nonnull (uid);
if (g_hash_table_contains (test_backend->contacts, uid)) {
if (!overwrite_existing) {
g_propagate_error (error, e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS, NULL));
return FALSE;
}
g_hash_table_remove (test_backend->contacts, uid);
}
/* Intentionally do not add a referenced 'contact', thus any later changes
on it are not "propagated" into the test_backend's content. */
g_hash_table_insert (test_backend->contacts, g_strdup (uid), e_contact_duplicate (contact));
*out_new_uid = g_strdup (uid);
return TRUE;
}
static gboolean
e_book_meta_backend_test_load_contact_sync (EBookMetaBackend *meta_backend,
const gchar *uid,
const gchar *extra,
EContact **out_contact,
gchar **out_extra,
GCancellable *cancellable,
GError **error)
{
EBookMetaBackendTest *test_backend;
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (meta_backend), FALSE);
g_return_val_if_fail (uid != NULL, FALSE);
g_return_val_if_fail (out_contact != NULL, FALSE);
g_return_val_if_fail (out_extra != NULL, FALSE);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
test_backend->load_count++;
g_assert_true (test_backend->is_connected);
*out_contact = g_hash_table_lookup (test_backend->contacts, uid);
if (*out_contact) {
*out_contact = e_contact_duplicate (*out_contact);
*out_extra = g_strconcat ("extra for ", uid, NULL);
return TRUE;
} else {
g_propagate_error (error, e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, NULL));
}
return FALSE;
}
static gboolean
e_book_meta_backend_test_remove_contact_sync (EBookMetaBackend *meta_backend,
EConflictResolution conflict_resolution,
const gchar *uid,
const gchar *extra,
const gchar *object,
guint32 opflags,
GCancellable *cancellable,
GError **error)
{
EBookMetaBackendTest *test_backend;
gboolean success = FALSE;
g_return_val_if_fail (E_IS_BOOK_META_BACKEND_TEST (meta_backend), FALSE);
g_return_val_if_fail (uid != NULL, FALSE);
g_return_val_if_fail (extra != NULL, FALSE);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
test_backend->remove_count++;
g_assert_true (test_backend->is_connected);
success = g_hash_table_remove (test_backend->contacts, uid);
if (success) {
gchar *expected_extra;
expected_extra = g_strconcat ("extra for ", uid, NULL);
g_assert_cmpstr (expected_extra, ==, extra);
g_free (expected_extra);
} else {
g_propagate_error (error, e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, NULL));
}
return success;
}
static void
e_book_meta_backend_test_reset_counters (EBookMetaBackendTest *test_backend)
{
g_return_if_fail (E_IS_BOOK_META_BACKEND_TEST (test_backend));
test_backend->connect_count = 0;
test_backend->list_count = 0;
test_backend->save_count = 0;
test_backend->load_count = 0;
test_backend->remove_count = 0;
}
static EBookCache *glob_use_cache = NULL;
static void
e_book_meta_backend_test_constructed (GObject *object)
{
EBookMetaBackendTest *test_backend = E_BOOK_META_BACKEND_TEST (object);
g_assert_nonnull (glob_use_cache);
/* Set it before EBookMetaBackend::constucted() creates its own cache */
e_book_meta_backend_set_cache (E_BOOK_META_BACKEND (test_backend), glob_use_cache);
/* Chain up to parent's method. */
G_OBJECT_CLASS (e_book_meta_backend_test_parent_class)->constructed (object);
}
static void
e_book_meta_backend_test_finalize (GObject *object)
{
EBookMetaBackendTest *test_backend = E_BOOK_META_BACKEND_TEST (object);
g_assert_nonnull (test_backend->contacts);
g_hash_table_destroy (test_backend->contacts);
/* Chain up to parent's method. */
G_OBJECT_CLASS (e_book_meta_backend_test_parent_class)->finalize (object);
}
static void
e_book_meta_backend_test_class_init (EBookMetaBackendTestClass *klass)
{
EBookMetaBackendClass *book_meta_backend_class;
EBookBackendClass *book_backend_class;
EBackendClass *backend_class;
GObjectClass *object_class;
book_meta_backend_class = E_BOOK_META_BACKEND_CLASS (klass);
book_meta_backend_class->connect_sync = e_book_meta_backend_test_connect_sync;
book_meta_backend_class->disconnect_sync = e_book_meta_backend_test_disconnect_sync;
book_meta_backend_class->get_changes_sync = e_book_meta_backend_test_get_changes_sync;
book_meta_backend_class->list_existing_sync = e_book_meta_backend_test_list_existing_sync;
book_meta_backend_class->save_contact_sync = e_book_meta_backend_test_save_contact_sync;
book_meta_backend_class->load_contact_sync = e_book_meta_backend_test_load_contact_sync;
book_meta_backend_class->remove_contact_sync = e_book_meta_backend_test_remove_contact_sync;
book_backend_class = E_BOOK_BACKEND_CLASS (klass);
book_backend_class->impl_get_backend_property = e_book_meta_backend_test_get_backend_property;
backend_class = E_BACKEND_CLASS (klass);
backend_class->get_destination_address = e_book_meta_backend_test_get_destination_address;
object_class = G_OBJECT_CLASS (klass);
object_class->constructed = e_book_meta_backend_test_constructed;
object_class->finalize = e_book_meta_backend_test_finalize;
}
static void
e_book_meta_backend_test_init (EBookMetaBackendTest *test_backend)
{
test_backend->sync_tag_index = 0;
test_backend->is_connected = FALSE;
test_backend->can_connect = TRUE;
test_backend->contacts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
ebmb_test_add_test_case (test_backend, "custom-1");
ebmb_test_add_test_case (test_backend, "custom-2");
ebmb_test_add_test_case (test_backend, "custom-3");
ebmb_test_add_test_case (test_backend, "custom-5");
ebmb_test_add_test_case (test_backend, "custom-6");
e_book_meta_backend_test_reset_counters (test_backend);
e_backend_set_online (E_BACKEND (test_backend), TRUE);
e_book_backend_set_writable (E_BOOK_BACKEND (test_backend), TRUE);
}
static ESourceRegistry *glob_registry = NULL;
static EBookMetaBackend *
e_book_meta_backend_test_new (EBookCache *cache)
{
EBookMetaBackend *meta_backend;
GHashTableIter iter;
ESource *scratch;
gpointer contact;
gboolean success;
GError *error = NULL;
g_assert_true (E_IS_BOOK_CACHE (cache));
g_assert_nonnull (glob_registry);
g_assert_null (glob_use_cache);
glob_use_cache = cache;
scratch = e_source_new_with_uid ("test-source", NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (scratch);
meta_backend = g_object_new (E_TYPE_BOOK_META_BACKEND_TEST,
"source", scratch,
"registry", glob_registry,
NULL);
g_assert_nonnull (meta_backend);
g_assert_true (glob_use_cache == cache);
glob_use_cache = NULL;
g_object_unref (scratch);
g_hash_table_iter_init (&iter, E_BOOK_META_BACKEND_TEST (meta_backend)->contacts);
while (g_hash_table_iter_next (&iter, NULL, &contact)) {
gchar *extra;
extra = g_strconcat ("extra for ", e_contact_get_const (contact, E_CONTACT_UID), NULL);
success = e_book_cache_put_contact (cache, contact, extra, 0, E_CACHE_IS_ONLINE, NULL, &error);
g_free (extra);
g_assert_no_error (error);
g_assert_true (success);
}
return meta_backend;
}
static void
e_book_meta_backend_test_change_online (EBookMetaBackend *meta_backend,
gboolean is_online)
{
EFlag *flag;
gulong handler_id;
if (!is_online) {
e_backend_set_online (E_BACKEND (meta_backend), FALSE);
return;
}
if (e_backend_get_online (E_BACKEND (meta_backend)))
return;
flag = e_flag_new ();
handler_id = g_signal_connect_swapped (meta_backend, "refresh-completed",
G_CALLBACK (e_flag_set), flag);
/* Going online triggers refresh, thus wait for it */
e_backend_set_online (E_BACKEND (meta_backend), TRUE);
e_flag_wait (flag);
e_flag_free (flag);
g_signal_handler_disconnect (meta_backend, handler_id);
}
static void
e_book_meta_backend_test_call_refresh (EBookMetaBackend *meta_backend)
{
EBookBackendSyncClass *backend_sync_class;
EFlag *flag;
gulong handler_id;
gboolean success;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->refresh_sync != NULL);
if (!e_backend_get_online (E_BACKEND (meta_backend)))
return;
flag = e_flag_new ();
handler_id = g_signal_connect_swapped (meta_backend, "refresh-completed",
G_CALLBACK (e_flag_set), flag);
success = backend_sync_class->refresh_sync (E_BOOK_BACKEND_SYNC (meta_backend), NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
e_flag_wait (flag);
e_flag_free (flag);
g_signal_handler_disconnect (meta_backend, handler_id);
}
static void
test_one_photo (EBookMetaBackend *meta_backend,
const gchar *test_case,
EContactField field)
{
EContact *contact;
EContactPhoto *photo;
guchar *orig_content;
gchar *new_content = NULL;
gsize orig_len = 0, new_len = 0;
gchar *filename;
gchar *mime_type;
gboolean success;
GError *error = NULL;
g_assert_true (E_IS_BOOK_META_BACKEND (meta_backend));
g_assert_nonnull (test_case);
g_assert_true (field == E_CONTACT_PHOTO || field == E_CONTACT_LOGO);
contact = tcu_new_contact_from_test_case (test_case);
g_assert_nonnull (contact);
photo = e_contact_get (contact, field);
g_assert_nonnull (photo);
g_assert_cmpint (photo->type, ==, E_CONTACT_PHOTO_TYPE_INLINED);
orig_content = (guchar *) e_contact_photo_get_inlined (photo, &orig_len);
g_assert_nonnull (orig_content);
g_assert_cmpint (orig_len, >, 0);
mime_type = g_strdup (e_contact_photo_get_mime_type (photo));
g_assert_nonnull (mime_type);
orig_content = g_memdup (orig_content, (guint) orig_len);
e_contact_photo_free (photo);
success = e_book_meta_backend_store_inline_photos_sync (meta_backend, contact, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
photo = e_contact_get (contact, field);
g_assert_nonnull (photo);
g_assert_cmpint (photo->type, ==, E_CONTACT_PHOTO_TYPE_URI);
g_assert_nonnull (e_contact_photo_get_uri (photo));
filename = g_filename_from_uri (e_contact_photo_get_uri (photo), NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (filename);
success = g_file_get_contents (filename, &new_content, &new_len, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_nonnull (new_content);
g_assert_cmpmem (orig_content, orig_len, new_content, new_len);
g_free (new_content);
g_free (filename);
e_contact_photo_free (photo);
success = e_book_meta_backend_inline_local_photos_sync (meta_backend, contact, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
photo = e_contact_get (contact, field);
g_assert_nonnull (photo);
g_assert_cmpint (photo->type, ==, E_CONTACT_PHOTO_TYPE_INLINED);
new_content = (gchar *) e_contact_photo_get_inlined (photo, &new_len);
g_assert_nonnull (new_content);
g_assert_cmpmem (orig_content, orig_len, new_content, new_len);
g_assert_cmpstr (mime_type, ==, e_contact_photo_get_mime_type (photo));
e_contact_photo_free (photo);
g_free (orig_content);
g_free (mime_type);
/* Also try with remote URI, which should be left as is */
photo = e_contact_photo_new ();
g_assert_nonnull (photo);
photo->type = E_CONTACT_PHOTO_TYPE_URI;
e_contact_photo_set_uri (photo, REMOTE_URL);
e_contact_set (contact, field, photo);
e_contact_photo_free (photo);
photo = e_contact_get (contact, field);
g_assert_nonnull (photo);
g_assert_cmpint (photo->type, ==, E_CONTACT_PHOTO_TYPE_URI);
g_assert_cmpstr (e_contact_photo_get_uri (photo), ==, REMOTE_URL);
e_contact_photo_free (photo);
success = e_book_meta_backend_store_inline_photos_sync (meta_backend, contact, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
photo = e_contact_get (contact, field);
g_assert_nonnull (photo);
g_assert_cmpint (photo->type, ==, E_CONTACT_PHOTO_TYPE_URI);
g_assert_cmpstr (e_contact_photo_get_uri (photo), ==, REMOTE_URL);
e_contact_photo_free (photo);
success = e_book_meta_backend_inline_local_photos_sync (meta_backend, contact, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
photo = e_contact_get (contact, field);
g_assert_nonnull (photo);
g_assert_cmpint (photo->type, ==, E_CONTACT_PHOTO_TYPE_URI);
g_assert_cmpstr (e_contact_photo_get_uri (photo), ==, REMOTE_URL);
e_contact_photo_free (photo);
g_object_unref (contact);
}
static void
test_photos (TCUFixture *fixture,
gconstpointer user_data)
{
EBookMetaBackend *meta_backend;
meta_backend = e_book_meta_backend_test_new (fixture->book_cache);
g_assert_nonnull (meta_backend);
test_one_photo (meta_backend, "photo-1", E_CONTACT_PHOTO);
test_one_photo (meta_backend, "logo-1", E_CONTACT_LOGO);
g_object_unref (meta_backend);
}
static void
test_empty_cache (TCUFixture *fixture,
gconstpointer user_data)
{
EBookMetaBackend *meta_backend;
EBookMetaBackendTest *test_backend;
GSList *uids;
gboolean success;
GError *error = NULL;
meta_backend = e_book_meta_backend_test_new (fixture->book_cache);
g_assert_nonnull (meta_backend);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
g_assert_nonnull (test_backend);
uids = NULL;
success = e_book_cache_search_uids (fixture->book_cache, NULL, &uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (uids), >, 0);
g_slist_free_full (uids, g_free);
g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), >, 0);
g_assert_no_error (error);
/* Empty the cache */
success = e_book_meta_backend_empty_cache_sync (meta_backend, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
/* Verify the cache is truly empty */
uids = NULL;
success = e_book_cache_search_uids (fixture->book_cache, NULL, &uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (uids), ==, 0);
g_slist_free_full (uids, g_free);
g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 0);
g_assert_no_error (error);
g_object_unref (meta_backend);
}
static void
test_create_contacts (EBookMetaBackend *meta_backend)
{
EBookMetaBackendTest *test_backend;
EBookBackendSyncClass *backend_sync_class;
EBookCache *book_cache;
GSList *offline_changes;
gchar *vcards[2] = { NULL, NULL }, *tmp;
GSList *new_contacts = NULL;
gboolean success;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->create_contacts_sync != NULL);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
book_cache = e_book_meta_backend_ref_cache (meta_backend);
g_assert_nonnull (book_cache);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
/* Try to add existing contact, it should fail */
vcards[0] = tcu_new_vcard_from_test_case ("custom-1");
success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS);
g_assert_true (!success);
g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
g_clear_error (&error);
g_free (vcards[0]);
e_book_meta_backend_test_reset_counters (test_backend);
/* Try to add new contact */
vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
g_assert_cmpstr (e_contact_get_const (new_contacts->data, E_CONTACT_UID), ==, "custom-7");
g_assert_cmpint (test_backend->connect_count, ==, 1);
g_assert_cmpint (test_backend->list_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 1);
g_assert_cmpint (test_backend->save_count, ==, 1);
g_slist_free_full (new_contacts, g_object_unref);
new_contacts = NULL;
g_free (vcards[0]);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
/* Going offline */
e_book_meta_backend_test_change_online (meta_backend, FALSE);
e_book_meta_backend_test_reset_counters (test_backend);
/* Try to add existing contact, it should fail */
vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS);
g_assert_true (!success);
g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
g_clear_error (&error);
g_free (vcards[0]);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
/* Try to add new contact */
vcards[0] = tcu_new_vcard_from_test_case ("custom-8");
success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
g_assert_cmpstr (e_contact_get_const (new_contacts->data, E_CONTACT_UID), ==, "custom-8");
g_assert_cmpint (test_backend->connect_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_slist_free_full (new_contacts, g_object_unref);
new_contacts = NULL;
g_free (vcards[0]);
ebmb_test_hash_contains (test_backend->contacts, TRUE, FALSE,
"custom-8", NULL, NULL);
ebmb_test_cache_contains (book_cache, FALSE, FALSE,
"custom-8", NULL, NULL);
/* Going online */
e_book_meta_backend_test_change_online (meta_backend, TRUE);
g_assert_cmpint (test_backend->connect_count, ==, 1);
g_assert_cmpint (test_backend->load_count, ==, 1);
g_assert_cmpint (test_backend->save_count, ==, 1);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
offline_changes = e_cache_get_offline_changes (E_CACHE (book_cache), NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (0, ==, g_slist_length (offline_changes));
/* Add contact without UID */
vcards[0] = tcu_new_vcard_from_test_case ("custom-9");
g_assert_nonnull (vcards[0]);
tmp = strstr (vcards[0], "UID:custom-9\r\n");
g_assert_nonnull (tmp);
memcpy (tmp, "X-TEST:*007*", 12);
success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
g_assert_cmpstr (e_contact_get_const (new_contacts->data, E_CONTACT_UID), !=, "custom-9");
g_assert_cmpint (test_backend->connect_count, ==, 1);
g_assert_cmpint (test_backend->list_count, ==, 1);
g_assert_cmpint (test_backend->load_count, ==, 2);
g_assert_cmpint (test_backend->save_count, ==, 2);
tmp = e_vcard_to_string (E_VCARD (new_contacts->data), EVC_FORMAT_VCARD_30);
g_assert_nonnull (tmp);
g_assert_nonnull (strstr (tmp, "X-TEST:*007*\r\n"));
g_assert_nonnull (strstr (tmp, e_contact_get_const (new_contacts->data, E_CONTACT_UID)));
g_free (tmp);
g_slist_free_full (new_contacts, g_object_unref);
new_contacts = NULL;
g_free (vcards[0]);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
g_object_unref (book_cache);
}
static gchar *
ebmb_test_modify_case (const gchar *case_name)
{
gchar *vcard, *tmp;
const gchar *rev;
EContact *contact;
g_assert_nonnull (case_name);
contact = tcu_new_contact_from_test_case (case_name);
g_assert_nonnull (contact);
e_contact_set (contact, E_CONTACT_FULL_NAME, MODIFIED_FN_STR);
rev = e_contact_get_const (contact, E_CONTACT_REV);
if (!rev)
tmp = g_strdup ("0");
else
tmp = g_strdup_printf ("%d", atoi (rev) + 1);
e_contact_set (contact, E_CONTACT_REV, tmp);
g_free (tmp);
vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
g_object_unref (contact);
return vcard;
}
static void
test_modify_contacts (EBookMetaBackend *meta_backend)
{
EBookMetaBackendTest *test_backend;
EBookBackendSyncClass *backend_sync_class;
EBookCache *book_cache;
EContact *contact;
GSList *offline_changes;
gchar *vcards[2] = { NULL, NULL }, *tmp;
GSList *new_contacts = NULL;
gint old_rev, new_rev;
gboolean success;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->modify_contacts_sync != NULL);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
book_cache = e_book_meta_backend_ref_cache (meta_backend);
g_assert_nonnull (book_cache);
/* Modify non-existing contact */
vcards[0] = tcu_new_vcard_from_test_case ("custom-1");
g_assert_nonnull (vcards[0]);
tmp = strstr (vcards[0], "UID:custom-1");
g_assert_nonnull (tmp);
memcpy (tmp + 4, "unknown", 7);
success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
g_assert_true (!success);
g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
g_clear_error (&error);
g_free (vcards[0]);
/* Modify existing contact */
vcards[0] = ebmb_test_modify_case ("custom-1");
success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
g_assert_cmpint (test_backend->load_count, ==, 1);
g_assert_cmpint (test_backend->save_count, ==, 1);
contact = tcu_new_contact_from_test_case ("custom-1");
g_assert_nonnull (contact);
g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_REV));
g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_FULL_NAME));
old_rev = atoi (e_contact_get_const (contact, E_CONTACT_REV));
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_FULL_NAME), !=, MODIFIED_FN_STR);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-1");
g_object_unref (contact);
contact = new_contacts->data;
g_assert_nonnull (contact);
g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_REV));
g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_FULL_NAME));
new_rev = atoi (e_contact_get_const (contact, E_CONTACT_REV));
g_assert_cmpint (old_rev + 1, ==, new_rev);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_FULL_NAME), ==, MODIFIED_FN_STR);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-1");
g_slist_free_full (new_contacts, g_object_unref);
new_contacts = NULL;
g_free (vcards[0]);
/* Going offline */
e_book_meta_backend_test_change_online (meta_backend, FALSE);
e_book_meta_backend_test_reset_counters (test_backend);
/* Modify custom-2 */
vcards[0] = ebmb_test_modify_case ("custom-2");
success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
contact = tcu_new_contact_from_test_case ("custom-2");
g_assert_nonnull (contact);
g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_REV));
g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_FULL_NAME));
old_rev = atoi (e_contact_get_const (contact, E_CONTACT_REV));
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_FULL_NAME), !=, MODIFIED_FN_STR);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-2");
g_object_unref (contact);
contact = new_contacts->data;
g_assert_nonnull (contact);
g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_REV));
g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_FULL_NAME));
new_rev = atoi (e_contact_get_const (contact, E_CONTACT_REV));
g_assert_cmpint (old_rev + 1, ==, new_rev);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_FULL_NAME), ==, MODIFIED_FN_STR);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-2");
g_slist_free_full (new_contacts, g_object_unref);
new_contacts = NULL;
g_free (vcards[0]);
/* Going online */
e_book_meta_backend_test_change_online (meta_backend, TRUE);
g_assert_cmpint (test_backend->load_count, ==, 1);
g_assert_cmpint (test_backend->save_count, ==, 1);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
offline_changes = e_cache_get_offline_changes (E_CACHE (book_cache), NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (0, ==, g_slist_length (offline_changes));
g_object_unref (book_cache);
}
static void
test_remove_contacts (EBookMetaBackend *meta_backend)
{
EBookMetaBackendTest *test_backend;
EBookBackendSyncClass *backend_sync_class;
EBookCache *book_cache;
EOfflineState state;
const gchar *uids[2] = { NULL, NULL };
GSList *offline_changes;
GSList *removed_uids = NULL;
gboolean success;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->remove_contacts_sync != NULL);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
book_cache = e_book_meta_backend_ref_cache (meta_backend);
g_assert_nonnull (book_cache);
/* Remove non-existing contact */
uids[0] = "unknown-contact";
success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
g_assert_true (!success);
g_assert_null (removed_uids);
g_clear_error (&error);
/* Remove existing contact */
uids[0] = "custom-1";
success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->remove_count, ==, 1);
g_assert_cmpint (g_slist_length (removed_uids), ==, 1);
g_assert_cmpstr (removed_uids->data, ==, uids[0]);
g_slist_free_full (removed_uids, g_free);
removed_uids = NULL;
ebmb_test_hash_contains (test_backend->contacts, TRUE, FALSE,
"custom-1", NULL,
NULL);
/* Going offline */
e_book_meta_backend_test_change_online (meta_backend, FALSE);
e_book_meta_backend_test_reset_counters (test_backend);
/* Remove existing contact */
uids[0] = "custom-3";
success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->remove_count, ==, 0);
g_assert_cmpint (g_slist_length (removed_uids), ==, 1);
g_assert_cmpstr (removed_uids->data, ==, uids[0]);
g_slist_free_full (removed_uids, g_free);
removed_uids = NULL;
ebmb_test_hash_contains (test_backend->contacts, FALSE, FALSE,
"custom-3", NULL,
NULL);
ebmb_test_cache_contains (book_cache, TRUE, FALSE,
"custom-3", NULL,
NULL);
/* Going online */
e_book_meta_backend_test_change_online (meta_backend, TRUE);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->remove_count, ==, 1);
ebmb_test_hash_contains (test_backend->contacts, TRUE, FALSE,
"custom-3", NULL,
NULL);
ebmb_test_cache_contains (book_cache, TRUE, FALSE,
"custom-3", NULL,
NULL);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
offline_changes = e_cache_get_offline_changes (E_CACHE (book_cache), NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (0, ==, g_slist_length (offline_changes));
/* Set a contact as being created in offline */
uids[0] = "custom-2";
success = e_cache_set_offline_state (E_CACHE (book_cache), uids[0], E_OFFLINE_STATE_LOCALLY_CREATED, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
state = e_cache_get_offline_state (E_CACHE (book_cache), uids[0], NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (state, ==, E_OFFLINE_STATE_LOCALLY_CREATED);
success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->remove_count, ==, 1);
g_assert_cmpint (g_slist_length (removed_uids), ==, 1);
g_assert_cmpstr (removed_uids->data, ==, uids[0]);
g_slist_free_full (removed_uids, g_free);
removed_uids = NULL;
ebmb_test_hash_contains (test_backend->contacts, FALSE, FALSE,
uids[0], NULL,
NULL);
ebmb_test_cache_contains (book_cache, TRUE, FALSE,
uids[0], NULL,
NULL);
/* Set a contact as being modified in offline */
uids[0] = "custom-5";
success = e_cache_set_offline_state (E_CACHE (book_cache), uids[0], E_OFFLINE_STATE_LOCALLY_MODIFIED, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
state = e_cache_get_offline_state (E_CACHE (book_cache), uids[0], NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (state, ==, E_OFFLINE_STATE_LOCALLY_MODIFIED);
success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->remove_count, ==, 2);
g_assert_cmpint (g_slist_length (removed_uids), ==, 1);
g_assert_cmpstr (removed_uids->data, ==, uids[0]);
g_slist_free_full (removed_uids, g_free);
removed_uids = NULL;
ebmb_test_hash_contains (test_backend->contacts, TRUE, FALSE,
uids[0], NULL,
NULL);
ebmb_test_cache_contains (book_cache, TRUE, FALSE,
uids[0], NULL,
NULL);
/* Set a contact as being deleted in offline */
uids[0] = "custom-6";
success = e_cache_set_offline_state (E_CACHE (book_cache), uids[0], E_OFFLINE_STATE_LOCALLY_DELETED, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
state = e_cache_get_offline_state (E_CACHE (book_cache), uids[0], NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (state, ==, E_OFFLINE_STATE_LOCALLY_DELETED);
success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
g_assert_true (!success);
g_assert_null (removed_uids);
g_clear_error (&error);
g_assert_cmpint (test_backend->load_count, ==, 0);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->remove_count, ==, 2);
ebmb_test_hash_contains (test_backend->contacts, FALSE, FALSE,
uids[0], NULL,
NULL);
ebmb_test_cache_contains (book_cache, TRUE, FALSE,
uids[0], NULL,
NULL);
g_object_unref (book_cache);
}
static void
test_get_contact (EBookMetaBackend *meta_backend)
{
EBookMetaBackendTest *test_backend;
EBookBackendSyncClass *backend_sync_class;
EBookCache *book_cache;
EContact *contact;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->get_contact_sync != NULL);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
book_cache = e_book_meta_backend_ref_cache (meta_backend);
g_assert_nonnull (book_cache);
e_book_cache_remove_contact (book_cache, "custom-5", 0, E_CACHE_IS_ONLINE, NULL, &error);
g_assert_no_error (error);
e_book_cache_remove_contact (book_cache, "custom-6", 0, E_CACHE_IS_ONLINE, NULL, &error);
g_assert_no_error (error);
/* Non-existing */
contact = backend_sync_class->get_contact_sync (E_BOOK_BACKEND_SYNC (meta_backend), "unknown-contact", NULL, &error);
g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
g_assert_null (contact);
g_clear_error (&error);
/* Existing */
contact = backend_sync_class->get_contact_sync (E_BOOK_BACKEND_SYNC (meta_backend), "custom-1", NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (contact);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-1");
g_object_unref (contact);
/* Going offline */
e_book_meta_backend_test_change_online (meta_backend, FALSE);
g_assert_true (!e_cache_contains (E_CACHE (book_cache), "custom-5", E_CACHE_EXCLUDE_DELETED));
e_book_meta_backend_test_reset_counters (test_backend);
contact = backend_sync_class->get_contact_sync (E_BOOK_BACKEND_SYNC (meta_backend), "custom-5", NULL, &error);
g_assert_error (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND);
g_assert_null (contact);
g_clear_error (&error);
g_assert_cmpint (test_backend->connect_count, ==, 0);
g_assert_cmpint (test_backend->list_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 0);
/* Going online */
e_book_meta_backend_test_change_online (meta_backend, TRUE);
g_assert_true (e_cache_contains (E_CACHE (book_cache), "custom-5", E_CACHE_EXCLUDE_DELETED));
/* Remove it from the cache, thus it's loaded from the "server" on demand */
e_book_cache_remove_contact (book_cache, "custom-5", 0, E_CACHE_IS_ONLINE, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (test_backend->connect_count, ==, 1);
e_book_meta_backend_test_reset_counters (test_backend);
g_assert_cmpint (test_backend->connect_count, ==, 0);
contact = backend_sync_class->get_contact_sync (E_BOOK_BACKEND_SYNC (meta_backend), "custom-5", NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (contact);
g_assert_cmpint (test_backend->connect_count, ==, 0);
g_assert_cmpint (test_backend->list_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 1);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-5");
g_object_unref (contact);
g_assert_true (e_cache_contains (E_CACHE (book_cache), "custom-5", E_CACHE_EXCLUDE_DELETED));
g_object_unref (book_cache);
}
static void
test_get_contact_list (EBookMetaBackend *meta_backend)
{
EBookBackendSyncClass *backend_sync_class;
GSList *contacts = NULL;
EContact *contact;
gboolean success;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->get_contact_list_sync != NULL);
success = backend_sync_class->get_contact_list_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"(is \"uid\" \"unknown-contact\")", &contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (contacts), ==, 0);
success = backend_sync_class->get_contact_list_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"(is \"uid\" \"custom-3\")", &contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (contacts), ==, 1);
contact = contacts->data;
g_assert_nonnull (contact);
g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_UID), ==, "custom-3");
g_slist_free_full (contacts, g_object_unref);
}
static void
test_get_contact_list_uids (EBookMetaBackend *meta_backend)
{
EBookBackendSyncClass *backend_sync_class;
GSList *uids = NULL;
gboolean success;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->get_contact_list_uids_sync != NULL);
success = backend_sync_class->get_contact_list_uids_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"(is \"uid\" \"unknown-contact\")", &uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (uids), ==, 0);
success = backend_sync_class->get_contact_list_uids_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"(is \"uid\" \"custom-3\")", &uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (uids), ==, 1);
g_assert_nonnull (uids->data);
g_assert_cmpstr (uids->data, ==, "custom-3");
g_slist_free_full (uids, g_free);
}
static void
test_refresh (EBookMetaBackend *meta_backend)
{
EBookMetaBackendTest *test_backend;
EBookCache *book_cache;
ECache *cache;
guint count;
EContact *contact;
gchar *sync_tag;
GError *error = NULL;
g_assert_nonnull (meta_backend);
test_backend = E_BOOK_META_BACKEND_TEST (meta_backend);
book_cache = e_book_meta_backend_ref_cache (meta_backend);
g_assert_nonnull (book_cache);
cache = E_CACHE (book_cache);
/* Empty local cache */
e_cache_remove_all (cache, NULL, &error);
g_assert_no_error (error);
count = e_cache_get_count (cache, E_CACHE_INCLUDE_DELETED, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (count, ==, 0);
e_book_meta_backend_test_reset_counters (test_backend);
ebmb_test_remove_component (test_backend, "custom-5");
ebmb_test_remove_component (test_backend, "custom-6");
/* Sync with server content */
e_book_meta_backend_test_call_refresh (meta_backend);
g_assert_cmpint (test_backend->list_count, ==, 1);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 3);
g_assert_cmpint (test_backend->remove_count, ==, 0);
count = e_cache_get_count (cache, E_CACHE_INCLUDE_DELETED, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (count, ==, 3);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
sync_tag = e_book_meta_backend_dup_sync_tag (meta_backend);
g_assert_nonnull (sync_tag);
g_assert_cmpstr (sync_tag, ==, "1");
g_free (sync_tag);
/* Add new contact */
ebmb_test_add_test_case (test_backend, "custom-5");
/* Sync with server content */
e_book_meta_backend_test_call_refresh (meta_backend);
g_assert_cmpint (test_backend->list_count, ==, 2);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 4);
g_assert_cmpint (test_backend->remove_count, ==, 0);
count = e_cache_get_count (cache, E_CACHE_INCLUDE_DELETED, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (count, ==, 4);
ebmb_test_hash_contains (test_backend->contacts, FALSE, TRUE,
"custom-1",
"custom-2",
"custom-3",
"custom-5",
NULL);
ebmb_test_cache_contains (book_cache, FALSE, TRUE,
"custom-1",
"custom-2",
"custom-3",
"custom-5",
NULL);
/* Sync with server content */
e_book_meta_backend_test_call_refresh (meta_backend);
g_assert_cmpint (test_backend->list_count, ==, 3);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 4);
g_assert_cmpint (test_backend->remove_count, ==, 0);
count = e_cache_get_count (cache, E_CACHE_INCLUDE_DELETED, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (count, ==, 4);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
/* Add some more contacts */
ebmb_test_add_test_case (test_backend, "custom-6");
ebmb_test_add_test_case (test_backend, "custom-7");
/* Sync with server content */
e_book_meta_backend_test_call_refresh (meta_backend);
g_assert_cmpint (test_backend->list_count, ==, 4);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 6);
g_assert_cmpint (test_backend->remove_count, ==, 0);
count = e_cache_get_count (cache, E_CACHE_INCLUDE_DELETED, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (count, ==, 6);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
/* Remove two contacts */
ebmb_test_remove_component (test_backend, "custom-2");
ebmb_test_remove_component (test_backend, "custom-5");
/* Sync with server content */
e_book_meta_backend_test_call_refresh (meta_backend);
g_assert_cmpint (test_backend->list_count, ==, 5);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 6);
g_assert_cmpint (test_backend->remove_count, ==, 0);
count = e_cache_get_count (cache, E_CACHE_INCLUDE_DELETED, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (count, ==, 4);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
/* Mix add/remove/modify */
ebmb_test_add_test_case (test_backend, "custom-8");
ebmb_test_remove_component (test_backend, "custom-3");
ebmb_test_remove_component (test_backend, "custom-6");
contact = g_hash_table_lookup (test_backend->contacts, "custom-1");
g_assert_nonnull (contact);
e_contact_set (contact, E_CONTACT_REV, "changed");
contact = g_hash_table_lookup (test_backend->contacts, "custom-7");
g_assert_nonnull (contact);
e_contact_set (contact, E_CONTACT_REV, "changed");
/* Sync with server content */
e_book_meta_backend_test_call_refresh (meta_backend);
g_assert_cmpint (test_backend->list_count, ==, 6);
g_assert_cmpint (test_backend->save_count, ==, 0);
g_assert_cmpint (test_backend->load_count, ==, 9);
g_assert_cmpint (test_backend->remove_count, ==, 0);
count = e_cache_get_count (cache, E_CACHE_INCLUDE_DELETED, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (count, ==, 3);
ebmb_test_cache_and_server_equal (book_cache, test_backend->contacts, E_CACHE_INCLUDE_DELETED);
sync_tag = e_book_meta_backend_dup_sync_tag (meta_backend);
g_assert_nonnull (sync_tag);
g_assert_cmpstr (sync_tag, ==, "7");
g_free (sync_tag);
g_object_unref (book_cache);
}
static void
test_cursor (EBookMetaBackend *meta_backend)
{
EBookBackendClass *backend_class;
EBookBackendSyncClass *backend_sync_class;
EDataBookCursor *cursor;
EContactField sort_fields[] = { E_CONTACT_FULL_NAME };
EBookCursorSortType sort_types[] = { E_BOOK_CURSOR_SORT_ASCENDING };
GSList *contacts = NULL;
GSList *removed_uids = NULL;
gchar *vcards[2] = { NULL, NULL };
const gchar *uids[2] = { NULL, NULL };
gint traversed;
gboolean success;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_class = E_BOOK_BACKEND_GET_CLASS (meta_backend);
g_return_if_fail (backend_class != NULL);
g_return_if_fail (backend_class->impl_create_cursor != NULL);
g_return_if_fail (backend_class->impl_delete_cursor != NULL);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->create_contacts_sync != NULL);
g_return_if_fail (backend_sync_class->modify_contacts_sync != NULL);
g_return_if_fail (backend_sync_class->remove_contacts_sync != NULL);
/* Create the cursor */
cursor = backend_class->impl_create_cursor (E_BOOK_BACKEND (meta_backend),
sort_fields, sort_types, 1, &error);
g_assert_no_error (error);
g_assert_nonnull (cursor);
g_assert_cmpint (e_data_book_cursor_get_total (cursor), ==, 5);
g_assert_cmpint (e_data_book_cursor_get_position (cursor), ==, 0);
traversed = e_data_book_cursor_step (cursor, NULL, E_BOOK_CURSOR_STEP_MOVE, E_BOOK_CURSOR_ORIGIN_CURRENT, 3, NULL, NULL, &error);
g_assert_no_error (error);
g_assert_cmpint (traversed, ==, 3);
g_assert_cmpint (e_data_book_cursor_get_total (cursor), ==, 5);
g_assert_cmpint (e_data_book_cursor_get_position (cursor), ==, 3);
/* Create */
vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (contacts), ==, 1);
g_slist_free_full (contacts, g_object_unref);
contacts = NULL;
g_free (vcards[0]);
g_assert_cmpint (e_data_book_cursor_get_total (cursor), ==, 6);
g_assert_cmpint (e_data_book_cursor_get_position (cursor), ==, 3);
/* Modify */
vcards[0] = ebmb_test_modify_case ("custom-2");
success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &contacts, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (contacts), ==, 1);
g_slist_free_full (contacts, g_object_unref);
contacts = NULL;
g_free (vcards[0]);
g_assert_cmpint (e_data_book_cursor_get_total (cursor), ==, 6);
g_assert_cmpint (e_data_book_cursor_get_position (cursor), ==, 3);
/* Remove */
uids[0] = "custom-3";
success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
(const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
g_assert_cmpint (g_slist_length (removed_uids), ==, 1);
g_assert_cmpstr (removed_uids->data, ==, uids[0]);
g_slist_free_full (removed_uids, g_free);
removed_uids = NULL;
g_assert_cmpint (e_data_book_cursor_get_total (cursor), ==, 5);
g_assert_cmpint (e_data_book_cursor_get_position (cursor), ==, 2);
/* Free the cursor */
success = backend_class->impl_delete_cursor (E_BOOK_BACKEND (meta_backend), cursor, &error);
g_assert_no_error (error);
g_assert_true (success);
}
static void
test_contains_email (EBookMetaBackend *meta_backend)
{
EBookBackendSyncClass *backend_sync_class;
gboolean success;
GError *error = NULL;
g_assert_nonnull (meta_backend);
backend_sync_class = E_BOOK_BACKEND_SYNC_GET_CLASS (meta_backend);
g_return_if_fail (backend_sync_class != NULL);
g_return_if_fail (backend_sync_class->contains_email_sync != NULL);
success = backend_sync_class->contains_email_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"bobby@brown.com", NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
success = backend_sync_class->contains_email_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"\"Bobby\" ", NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
success = backend_sync_class->contains_email_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"\"Unknown\" ", NULL, &error);
g_assert_no_error (error);
g_assert_true (!success);
success = backend_sync_class->contains_email_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"\"Unknown\" , \"Bobby\" ", NULL, &error);
g_assert_no_error (error);
g_assert_true (success);
success = backend_sync_class->contains_email_sync (E_BOOK_BACKEND_SYNC (meta_backend),
"", NULL, &error);
g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_CONSTRAINT);
g_assert_true (!success);
g_clear_error (&error);
}
typedef void (* TestWithMainLoopFunc) (EBookMetaBackend *meta_backend);
typedef struct _MainLoopThreadData {
TestWithMainLoopFunc func;
EBookMetaBackend *meta_backend;
GMainLoop *main_loop;
} MainLoopThreadData;
static gpointer
test_with_main_loop_thread (gpointer user_data)
{
MainLoopThreadData *mlt = user_data;
g_assert_nonnull (mlt);
g_assert_nonnull (mlt->func);
g_assert_nonnull (mlt->meta_backend);
mlt->func (mlt->meta_backend);
g_main_loop_quit (mlt->main_loop);
return NULL;
}
static gboolean
quit_test_with_mainloop_cb (gpointer user_data)
{
GMainLoop *main_loop = user_data;
g_assert_nonnull (main_loop);
g_main_loop_quit (main_loop);
return FALSE;
}
static gboolean
test_with_mainloop_run_thread_idle (gpointer user_data)
{
GThread *thread;
g_assert_nonnull (user_data);
thread = g_thread_new (NULL, test_with_main_loop_thread, user_data);
g_thread_unref (thread);
return FALSE;
}
static void
test_with_main_loop (EBookCache *book_cache,
TestWithMainLoopFunc func)
{
MainLoopThreadData mlt;
EBookMetaBackend *meta_backend;
guint timeout_id;
g_assert_nonnull (book_cache);
g_assert_nonnull (func);
meta_backend = e_book_meta_backend_test_new (book_cache);
g_assert_nonnull (meta_backend);
mlt.func = func;
mlt.meta_backend = meta_backend;
mlt.main_loop = g_main_loop_new (NULL, FALSE);
g_idle_add (test_with_mainloop_run_thread_idle, &mlt);
timeout_id = g_timeout_add_seconds (10, quit_test_with_mainloop_cb, mlt.main_loop);
g_main_loop_run (mlt.main_loop);
g_source_remove (timeout_id);
g_main_loop_unref (mlt.main_loop);
g_clear_object (&mlt.meta_backend);
}
#define main_loop_wrapper(_func) \
static void \
_func ## _tcu (TCUFixture *fixture, \
gconstpointer user_data) \
{ \
test_with_main_loop (fixture->book_cache, _func); \
}
main_loop_wrapper (test_create_contacts)
main_loop_wrapper (test_modify_contacts)
main_loop_wrapper (test_remove_contacts)
main_loop_wrapper (test_get_contact)
main_loop_wrapper (test_get_contact_list)
main_loop_wrapper (test_get_contact_list_uids)
main_loop_wrapper (test_refresh)
main_loop_wrapper (test_cursor)
main_loop_wrapper (test_contains_email)
#undef main_loop_wrapper
gint
main (gint argc,
gchar **argv)
{
ETestServerClosure tsclosure = {
E_TEST_SERVER_NONE,
NULL, /* Source customization function */
0, /* Calendar Type */
TRUE, /* Keep the working sandbox after the test, don't remove it */
NULL, /* Destroy Notify function */
};
ETestServerFixture tsfixture = { 0 };
TCUClosure closure = { 0 };
gint res;
#if !GLIB_CHECK_VERSION (2, 35, 1)
g_type_init ();
#endif
g_test_init (&argc, &argv, NULL);
g_test_bug_base ("https://gitlab.gnome.org/GNOME/evolution-data-server/");
tcu_read_args (argc, argv);
/* Ensure that the client and server get the same locale */
g_assert_true (g_setenv ("LC_ALL", "en_US.UTF-8", TRUE));
setlocale (LC_ALL, "");
e_test_server_utils_prepare_run (argc, argv, 0);
e_test_server_utils_setup (&tsfixture, &tsclosure);
glob_registry = tsfixture.registry;
g_assert_nonnull (glob_registry);
g_test_add ("/EBookMetaBackend/Photos", TCUFixture, &closure,
tcu_fixture_setup, test_photos, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/EmptyCache", TCUFixture, &closure,
tcu_fixture_setup, test_empty_cache, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/CreateContacts", TCUFixture, &closure,
tcu_fixture_setup, test_create_contacts_tcu, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/ModifyContacts", TCUFixture, &closure,
tcu_fixture_setup, test_modify_contacts_tcu, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/RemoveContacts", TCUFixture, &closure,
tcu_fixture_setup, test_remove_contacts_tcu, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/GetContact", TCUFixture, &closure,
tcu_fixture_setup, test_get_contact_tcu, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/GetContactList", TCUFixture, &closure,
tcu_fixture_setup, test_get_contact_list_tcu, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/GetContactListUids", TCUFixture, &closure,
tcu_fixture_setup, test_get_contact_list_uids_tcu, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/Refresh", TCUFixture, &closure,
tcu_fixture_setup, test_refresh_tcu, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/Cursor", TCUFixture, &closure,
tcu_fixture_setup, test_cursor_tcu, tcu_fixture_teardown);
g_test_add ("/EBookMetaBackend/ContainsEmail", TCUFixture, &closure,
tcu_fixture_setup, test_contains_email_tcu, tcu_fixture_teardown);
res = g_test_run ();
e_test_server_utils_teardown (&tsfixture, &tsclosure);
e_test_server_utils_finish_run ();
return res;
}