[evolution-data-server] I#136 - Meta backends: Fails to remove locally created object in online mode



commit 4c674a581a2876b0b16b38760771a23353e5a721
Author: Milan Crha <mcrha redhat com>
Date:   Wed Aug 21 15:56:42 2019 +0200

    I#136 - Meta backends: Fails to remove locally created object in online mode
    
    Closes https://gitlab.gnome.org/GNOME/evolution-data-server/issues/136

 .../libedata-book/e-book-meta-backend.c            |   3 +-
 src/calendar/libedata-cal/e-cal-cache.c            |  44 +++++++++
 src/calendar/libedata-cal/e-cal-cache.h            |   5 +
 src/calendar/libedata-cal/e-cal-meta-backend.c     |   3 +-
 tests/libedata-book/test-book-meta-backend.c       |  87 +++++++++++++++++
 tests/libedata-cal/test-cal-meta-backend.c         | 105 +++++++++++++++++++++
 6 files changed, 245 insertions(+), 2 deletions(-)
---
diff --git a/src/addressbook/libedata-book/e-book-meta-backend.c 
b/src/addressbook/libedata-book/e-book-meta-backend.c
index e3677dae1..3307d6a5f 100644
--- a/src/addressbook/libedata-book/e-book-meta-backend.c
+++ b/src/addressbook/libedata-book/e-book-meta-backend.c
@@ -1624,7 +1624,8 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
        if (!e_book_cache_get_contact_extra (book_cache, uid, &extra, cancellable, NULL))
                extra = NULL;
 
-       if (*offline_flag == E_CACHE_IS_ONLINE) {
+       if (*offline_flag == E_CACHE_IS_ONLINE &&
+            e_cache_get_offline_state (E_CACHE (book_cache), uid, cancellable, NULL) != 
E_OFFLINE_STATE_LOCALLY_CREATED) {
                gchar *vcard_string = NULL;
 
                g_warn_if_fail (e_book_cache_get_vcard (book_cache, uid, FALSE, &vcard_string, cancellable, 
NULL));
diff --git a/src/calendar/libedata-cal/e-cal-cache.c b/src/calendar/libedata-cal/e-cal-cache.c
index 85e040e51..d853294f3 100644
--- a/src/calendar/libedata-cal/e-cal-cache.c
+++ b/src/calendar/libedata-cal/e-cal-cache.c
@@ -3582,6 +3582,50 @@ e_cal_cache_get_offline_changes  (ECalCache *cal_cache,
        return changes;
 }
 
+/**
+ * e_cal_cache_get_offline_state:
+ * @cal_cache: an #ECalCache
+ * @uid: a UID of the component
+ * @rid: (nullable): an optional Recurrence-ID
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * This is a wrapper of e_cache_get_offline_state(), ensuring that
+ * a correct #ECache UID will be used.
+ *
+ * Returns: Current offline state #EOfflineState for the given component.
+ *    It returns %E_OFFLINE_STATE_UNKNOWN when the component could not be
+ *    found or other error happened.
+ *
+ * Since: 3.34
+ **/
+EOfflineState
+e_cal_cache_get_offline_state (ECalCache *cal_cache,
+                              const gchar *uid,
+                              const gchar *rid,
+                              GCancellable *cancellable,
+                              GError **error)
+{
+       EOfflineState res;
+
+       g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), E_OFFLINE_STATE_UNKNOWN);
+       g_return_val_if_fail (uid != NULL, E_OFFLINE_STATE_UNKNOWN);
+
+       if (rid && *rid) {
+               gchar *id;
+
+               id = ecc_encode_id_sql (uid, rid);
+
+               res = e_cache_get_offline_state (E_CACHE (cal_cache), id, cancellable, error);
+
+               g_free (id);
+       } else {
+               res = e_cache_get_offline_state (E_CACHE (cal_cache), uid, cancellable, error);
+       }
+
+       return res;
+}
+
 /**
  * e_cal_cache_delete_attachments:
  * @cal_cache: an #ECalCache
diff --git a/src/calendar/libedata-cal/e-cal-cache.h b/src/calendar/libedata-cal/e-cal-cache.h
index 4e3ca2668..f9fc3641a 100644
--- a/src/calendar/libedata-cal/e-cal-cache.h
+++ b/src/calendar/libedata-cal/e-cal-cache.h
@@ -319,6 +319,11 @@ gboolean   e_cal_cache_search_with_callback
                                                 gpointer user_data,
                                                 GCancellable *cancellable,
                                                 GError **error);
+EOfflineState  e_cal_cache_get_offline_state   (ECalCache *cal_cache,
+                                                const gchar *uid,
+                                                const gchar *rid,
+                                                GCancellable *cancellable,
+                                                GError **error);
 GSList *       e_cal_cache_get_offline_changes (ECalCache *cal_cache,
                                                 GCancellable *cancellable,
                                                 GError **error);
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.c b/src/calendar/libedata-cal/e-cal-meta-backend.c
index 0e48f7825..68c57ecaa 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.c
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.c
@@ -2257,7 +2257,8 @@ ecmb_remove_object_sync (ECalMetaBackend *meta_backend,
                        extra = NULL;
 
                if (mod == E_CAL_OBJ_MOD_ALL) {
-                       if (*offline_flag == E_CACHE_IS_ONLINE) {
+                       if (*offline_flag == E_CACHE_IS_ONLINE &&
+                           e_cal_cache_get_offline_state (cal_cache, uid, NULL, cancellable, NULL) != 
E_OFFLINE_STATE_LOCALLY_CREATED) {
                                gchar *ical_string = NULL;
 
                                /* Use the master object, if exists */
diff --git a/tests/libedata-book/test-book-meta-backend.c b/tests/libedata-book/test-book-meta-backend.c
index b288bf75e..7419e2cd6 100644
--- a/tests/libedata-book/test-book-meta-backend.c
+++ b/tests/libedata-book/test-book-meta-backend.c
@@ -1143,6 +1143,7 @@ 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;
@@ -1235,6 +1236,92 @@ test_remove_contacts (EBookMetaBackend *meta_backend)
        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 (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 (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 (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 (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 (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 (!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);
 }
 
diff --git a/tests/libedata-cal/test-cal-meta-backend.c b/tests/libedata-cal/test-cal-meta-backend.c
index 327898188..a2637a37c 100644
--- a/tests/libedata-cal/test-cal-meta-backend.c
+++ b/tests/libedata-cal/test-cal-meta-backend.c
@@ -2257,7 +2257,10 @@ test_remove_objects (ECalMetaBackend *meta_backend)
        ECalMetaBackendTest *test_backend;
        ECalBackendSyncClass *backend_class;
        ECalCache *cal_cache;
+       EOfflineState state;
        GSList *ids, *old_components = NULL, *new_components = NULL, *offline_changes;
+       const gchar *uid;
+       gboolean success;
        GError *error = NULL;
 
        g_assert_nonnull (meta_backend);
@@ -2428,6 +2431,108 @@ test_remove_objects (ECalMetaBackend *meta_backend)
        g_assert_no_error (error);
        g_assert_cmpint (0, ==, g_slist_length (offline_changes));
 
+       /* Set an event as being created in offline */
+       uid = "event-7";
+       ids = g_slist_prepend (NULL, e_cal_component_id_new (uid, NULL));
+
+       success = e_cache_set_offline_state (E_CACHE (cal_cache), uid, E_OFFLINE_STATE_LOCALLY_CREATED, NULL, 
&error);
+       g_assert_no_error (error);
+       g_assert (success);
+       state = e_cal_cache_get_offline_state (cal_cache, uid, NULL, NULL, &error);
+       g_assert_no_error (error);
+       g_assert_cmpint (state, ==, E_OFFLINE_STATE_LOCALLY_CREATED);
+
+       backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
+       g_assert_no_error (error);
+       g_assert_cmpint (g_slist_length (old_components), ==, 1);
+       g_assert_cmpint (g_slist_length (new_components), ==, 1);
+       g_assert_null (new_components->data);
+       g_assert_cmpint (test_backend->load_count, ==, 0);
+       g_assert_cmpint (test_backend->save_count, ==, 0);
+       g_assert_cmpint (test_backend->remove_count, ==, 1);
+
+       ecmb_test_vcalendar_contains (test_backend->vcalendar, FALSE, FALSE,
+               uid, NULL,
+               NULL);
+       ecmb_test_cache_contains (cal_cache, TRUE, FALSE,
+               uid, NULL,
+               NULL);
+
+       g_slist_free_full (old_components, g_object_unref);
+       g_slist_free (new_components);
+       g_slist_free_full (ids, e_cal_component_id_free);
+       old_components = NULL;
+       new_components = NULL;
+
+       /* Set an event as being modified in offline */
+       uid = "event-8";
+       ids = g_slist_prepend (NULL, e_cal_component_id_new (uid, NULL));
+
+       success = e_cache_set_offline_state (E_CACHE (cal_cache), uid, E_OFFLINE_STATE_LOCALLY_MODIFIED, 
NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       state = e_cal_cache_get_offline_state (cal_cache, uid, NULL, NULL, &error);
+       g_assert_no_error (error);
+       g_assert_cmpint (state, ==, E_OFFLINE_STATE_LOCALLY_MODIFIED);
+
+       backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
+       g_assert_no_error (error);
+       g_assert_cmpint (g_slist_length (old_components), ==, 1);
+       g_assert_cmpint (g_slist_length (new_components), ==, 1);
+       g_assert_null (new_components->data);
+       g_assert_cmpint (test_backend->load_count, ==, 0);
+       g_assert_cmpint (test_backend->save_count, ==, 0);
+       g_assert_cmpint (test_backend->remove_count, ==, 2);
+
+       ecmb_test_vcalendar_contains (test_backend->vcalendar, TRUE, FALSE,
+               uid, NULL,
+               NULL);
+       ecmb_test_cache_contains (cal_cache, TRUE, FALSE,
+               uid, NULL,
+               NULL);
+
+       g_slist_free_full (old_components, g_object_unref);
+       g_slist_free (new_components);
+       g_slist_free_full (ids, e_cal_component_id_free);
+       old_components = NULL;
+       new_components = NULL;
+
+       /* Set an event as being deleted in offline */
+       uid = "event-9";
+       ids = g_slist_prepend (NULL, e_cal_component_id_new (uid, NULL));
+
+       success = e_cache_set_offline_state (E_CACHE (cal_cache), uid, E_OFFLINE_STATE_LOCALLY_DELETED, NULL, 
&error);
+       g_assert_no_error (error);
+       g_assert (success);
+       state = e_cal_cache_get_offline_state (cal_cache, uid, NULL, NULL, &error);
+       g_assert_no_error (error);
+       g_assert_cmpint (state, ==, E_OFFLINE_STATE_LOCALLY_DELETED);
+
+       backend_class->remove_objects_sync (E_CAL_BACKEND_SYNC (meta_backend),
+               NULL, NULL, ids, E_CAL_OBJ_MOD_ALL, 0, &old_components, &new_components, &error);
+       g_assert_no_error (error);
+       g_assert_cmpint (g_slist_length (old_components), ==, 1);
+       g_assert_cmpint (g_slist_length (new_components), ==, 1);
+       g_assert_null (new_components->data);
+       g_assert_cmpint (test_backend->load_count, ==, 0);
+       g_assert_cmpint (test_backend->save_count, ==, 0);
+       g_assert_cmpint (test_backend->remove_count, ==, 3);
+
+       ecmb_test_vcalendar_contains (test_backend->vcalendar, TRUE, FALSE,
+               uid, NULL,
+               NULL);
+       ecmb_test_cache_contains (cal_cache, TRUE, FALSE,
+               uid, NULL,
+               NULL);
+
+       g_slist_free_full (old_components, g_object_unref);
+       g_slist_free (new_components);
+       g_slist_free_full (ids, e_cal_component_id_free);
+       old_components = NULL;
+       new_components = NULL;
+
        g_object_unref (cal_cache);
 }
 


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