[evolution-data-server/wip/offline-cache] Miscellaneous changes around ECalMetaBackend and ECalCache



commit 4b730d2cb2869fb48cdf40d7d212daff77daf1d1
Author: Milan Crha <mcrha redhat com>
Date:   Tue Mar 14 17:30:05 2017 +0100

    Miscellaneous changes around ECalMetaBackend and ECalCache

 src/calendar/libedata-cal/e-cal-backend.c      |    1 +
 src/calendar/libedata-cal/e-cal-backend.h      |    2 +-
 src/calendar/libedata-cal/e-cal-cache.c        |   88 +++++++++--
 src/calendar/libedata-cal/e-cal-cache.h        |    7 +-
 src/calendar/libedata-cal/e-cal-meta-backend.c |  129 +++++++++++++++-
 src/calendar/libedata-cal/e-cal-meta-backend.h |   10 ++
 tests/libedata-cal/test-cal-meta-backend.c     |  200 +++++++++++++++++++++++-
 7 files changed, 412 insertions(+), 25 deletions(-)
---
diff --git a/src/calendar/libedata-cal/e-cal-backend.c b/src/calendar/libedata-cal/e-cal-backend.c
index 4a81c7e..f4e3651 100644
--- a/src/calendar/libedata-cal/e-cal-backend.c
+++ b/src/calendar/libedata-cal/e-cal-backend.c
@@ -953,6 +953,7 @@ e_cal_backend_class_init (ECalBackendClass *class)
        backend_class = E_BACKEND_CLASS (class);
        backend_class->prepare_shutdown = cal_backend_prepare_shutdown;
 
+       class->use_serial_dispatch_queue = TRUE;
        class->get_backend_property = cal_backend_get_backend_property;
        class->shutdown = cal_backend_shutdown;
 
diff --git a/src/calendar/libedata-cal/e-cal-backend.h b/src/calendar/libedata-cal/e-cal-backend.h
index 51d3c71..84e5532 100644
--- a/src/calendar/libedata-cal/e-cal-backend.h
+++ b/src/calendar/libedata-cal/e-cal-backend.h
@@ -116,7 +116,7 @@ struct _ECalBackend {
 /**
  * ECalBackendClass:
  * @use_serial_dispatch_queue: Whether a serial dispatch queue should
- *                             be used for this backend or not.
+ *                             be used for this backend or not. The default is %TRUE.
  * @get_backend_property: Fetch a property value by name from the backend
  * @open: Open the backend
  * @refresh: Refresh the backend
diff --git a/src/calendar/libedata-cal/e-cal-cache.c b/src/calendar/libedata-cal/e-cal-cache.c
index 1c7e45f..bf845ee 100644
--- a/src/calendar/libedata-cal/e-cal-cache.c
+++ b/src/calendar/libedata-cal/e-cal-cache.c
@@ -1801,27 +1801,27 @@ e_cal_cache_new (const gchar *filename,
 /**
  * e_cal_cache_dup_component_revision:
  * @cal_cache: an #ECalCache
- * @component: an #ECalComponent
+ * @icalcomp: an icalcomponent
  *
- * Returns the @component revision, used to detect changes.
+ * Returns the @icalcomp revision, used to detect changes.
  * The returned string should be freed with g_free(), when
  * no longer needed.
  *
  * Returns: (transfer full): A newly allocated string containing
- *    revision of the @component.
+ *    revision of the @icalcomp.
  *
  * Since: 3.26
  **/
 gchar *
 e_cal_cache_dup_component_revision (ECalCache *cal_cache,
-                                   ECalComponent *component)
+                                   icalcomponent *icalcomp)
 {
        gchar *revision = NULL;
 
        g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), NULL);
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (component), NULL);
+       g_return_val_if_fail (icalcomp != NULL, NULL);
 
-       g_signal_emit (cal_cache, signals[DUP_COMPONENT_REVISION], 0, component, &revision);
+       g_signal_emit (cal_cache, signals[DUP_COMPONENT_REVISION], 0, icalcomp, &revision);
 
        return revision;
 }
@@ -1970,7 +1970,7 @@ e_cal_cache_put_components (ECalCache *cal_cache,
                }
                e_cal_component_free_id (id);
 
-               rev = e_cal_cache_dup_component_revision (cal_cache, component);
+               rev = e_cal_cache_dup_component_revision (cal_cache, e_cal_component_get_icalcomponent 
(component));
 
                success = e_cache_put (cache, uid, rev, icalstring, other_columns, offline_flag, cancellable, 
error);
 
@@ -3027,7 +3027,7 @@ e_cal_cache_load_zones_cb (ECache *cache,
        GHashTable *loaded_zones = user_data;
 
        g_return_val_if_fail (loaded_zones != NULL, FALSE);
-       g_return_val_if_fail (ncols != 2, FALSE);
+       g_return_val_if_fail (ncols == 2, FALSE);
 
        /* Do not overwrite already loaded timezones, they can be used anywhere around */
        if (!g_hash_table_lookup (loaded_zones, column_values[0])) {
@@ -3054,6 +3054,10 @@ e_cal_cache_load_zones_cb (ECache *cache,
  * when no longer needed; the icaltimezone-s are owned
  * by the @cal_cache.
  *
+ * Note: The list can contain timezones previously stored
+ * in the cache, but removed from it since they were loaded,
+ * because these are freed only when also the @cal_cache is freed.
+ *
  * Returns: Whether succeeded.
  *
  * Since: 3.26
@@ -3078,6 +3082,13 @@ e_cal_cache_list_timezones (ECalCache *cal_cache,
                e_cal_cache_get_uint64_cb, &n_stored, cancellable, error);
 
        if (success && n_stored != g_hash_table_size (cal_cache->priv->loaded_timezones)) {
+               if (n_stored == 0) {
+                       g_rec_mutex_unlock (&cal_cache->priv->timezones_lock);
+                       *out_timezones = NULL;
+
+                       return TRUE;
+               }
+
                stmt = e_cache_sqlite_stmt_printf ("SELECT tzid, zone FROM " ECC_TABLE_TIMEZONES);
                success = e_cache_sqlite_select (E_CACHE (cal_cache), stmt,
                        e_cal_cache_load_zones_cb, cal_cache->priv->loaded_timezones, cancellable, error);
@@ -3102,6 +3113,56 @@ e_cal_cache_list_timezones (ECalCache *cal_cache,
 }
 
 /**
+ * e_cal_cache_remove_timezones:
+ * @cal_cache: an #ECalCache
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Removes all stored timezones from the @cal_cache.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_cal_cache_remove_timezones (ECalCache *cal_cache,
+                             GCancellable *cancellable,
+                             GError **error)
+{
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
+
+       e_cache_lock (E_CACHE (cal_cache), E_CACHE_LOCK_WRITE);
+
+       g_rec_mutex_lock (&cal_cache->priv->timezones_lock);
+
+       success = e_cache_sqlite_exec (E_CACHE (cal_cache), "DELETE FROM " ECC_TABLE_TIMEZONES, cancellable, 
error);
+
+       g_rec_mutex_unlock (&cal_cache->priv->timezones_lock);
+
+       e_cache_unlock (E_CACHE (cal_cache), success ? E_CACHE_UNLOCK_COMMIT : E_CACHE_UNLOCK_ROLLBACK);
+
+       return success;
+}
+
+void _e_cal_cache_remove_loaded_timezones (ECalCache *cal_cache);
+
+/* Private function, not meant to be part of the public API */
+void
+_e_cal_cache_remove_loaded_timezones (ECalCache *cal_cache)
+{
+       g_return_if_fail (E_IS_CAL_CACHE (cal_cache));
+
+       g_rec_mutex_lock (&cal_cache->priv->timezones_lock);
+
+       g_hash_table_remove_all (cal_cache->priv->loaded_timezones);
+       g_hash_table_remove_all (cal_cache->priv->modified_timezones);
+
+       g_rec_mutex_unlock (&cal_cache->priv->timezones_lock);
+}
+
+/**
  * e_cal_cache_resolve_timezone_cb:
  * @tzid: a timezone ID
  * @cal_cache: an #ECalCache
@@ -3172,16 +3233,13 @@ ecc_empty_aux_tables (ECache *cache,
    <DTSTAMP> "-" <LAST-MODIFIED> "-" <SEQUENCE> */
 static gchar *
 ecc_dup_component_revision (ECalCache *cal_cache,
-                           ECalComponent *component)
+                           icalcomponent *icalcomp)
 {
-       icalcomponent *icalcomp;
        struct icaltimetype itt;
        icalproperty *prop;
        GString *revision;
 
-       g_return_val_if_fail (E_IS_CAL_COMPONENT (component), NULL);
-
-       icalcomp = e_cal_component_get_icalcomponent (component);
+       g_return_val_if_fail (icalcomp != NULL, NULL);
 
        revision = g_string_sized_new (48);
 
@@ -3427,7 +3485,7 @@ e_cal_cache_class_init (ECalCacheClass *klass)
 
        /**
         * @ECalCache:dup-component-revision:
-        * A signal being called to get revision of an #ECalComponent.
+        * A signal being called to get revision of an icalcomponent.
         * The default implementation uses a concatenation of
         * DTSTAMP '-' LASTMODIFIED '-' SEQUENCE.
         **/
@@ -3440,7 +3498,7 @@ e_cal_cache_class_init (ECalCacheClass *klass)
                NULL,
                g_cclosure_marshal_generic,
                G_TYPE_STRING, 1,
-               E_TYPE_CAL_COMPONENT);
+               G_TYPE_POINTER);
 }
 
 static void
diff --git a/src/calendar/libedata-cal/e-cal-cache.h b/src/calendar/libedata-cal/e-cal-cache.h
index 9dd1476..305fbb3 100644
--- a/src/calendar/libedata-cal/e-cal-cache.h
+++ b/src/calendar/libedata-cal/e-cal-cache.h
@@ -178,7 +178,7 @@ struct _ECalCacheClass {
        /* Signals */
        gchar *         (* dup_component_revision)
                                                (ECalCache *cal_cache,
-                                                ECalComponent *component);
+                                                icalcomponent *icalcomp);
 
        /* Padding for future expansion */
        gpointer reserved[10];
@@ -191,7 +191,7 @@ ECalCache * e_cal_cache_new                 (const gchar *filename,
                                                 GError **error);
 gchar *                e_cal_cache_dup_component_revision
                                                (ECalCache *cal_cache,
-                                                ECalComponent *component);
+                                                icalcomponent *icalcomp);
 gboolean       e_cal_cache_contains            (ECalCache *cal_cache,
                                                 const gchar *uid,
                                                 const gchar *rid,
@@ -315,6 +315,9 @@ gboolean    e_cal_cache_list_timezones      (ECalCache *cal_cache,
                                                 GList **out_timezones,
                                                 GCancellable *cancellable,
                                                 GError **error);
+gboolean       e_cal_cache_remove_timezones    (ECalCache *cal_cache,
+                                                GCancellable *cancellable,
+                                                GError **error);
 icaltimezone * e_cal_cache_resolve_timezone_cb (const gchar *tzid,
                                                 gpointer cal_cache,
                                                 GCancellable *cancellable,
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.c b/src/calendar/libedata-cal/e-cal-meta-backend.c
index ac8af44..a35dc1e 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.c
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.c
@@ -1069,9 +1069,21 @@ ecmb_open_sync (ECalBackendSync *sync_backend,
                gboolean only_if_exists,
                GError **error)
 {
+       ESource *source;
+
        g_return_if_fail (E_IS_CAL_META_BACKEND (sync_backend));
 
-       /* Not much to do here, just confirm and schedule refresh */
+       if (e_cal_backend_is_opened (E_CAL_BACKEND (sync_backend)))
+               return;
+
+       source = e_backend_get_source (E_BACKEND (sync_backend));
+       if (e_source_has_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND)) {
+               ESourceWebdav *webdav_extension;
+
+               webdav_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
+               e_source_webdav_unset_temporary_ssl_trust (webdav_extension);
+       }
+
        ecmb_schedule_refresh (E_CAL_META_BACKEND (sync_backend));
 }
 
@@ -2515,6 +2527,8 @@ ecmb_get_backend_property (ECalBackend *cal_backend,
                g_object_unref (comp);
 
                return prop_value;
+       } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+               return g_strdup (e_cal_meta_backend_get_capabilities (E_CAL_META_BACKEND (cal_backend)));
        }
 
        /* Chain up to parent's method. */
@@ -3362,6 +3376,119 @@ e_cal_meta_backend_store_inline_attachments_sync (ECalMetaBackend *meta_backend,
 }
 
 /**
+ * e_cal_meta_backend_gather_timezones_sync:
+ * @meta_backend: an #ECalMetaBackend
+ * @vcalendar: a VCALENDAR icalcomponent
+ * @remove_existing: whether to remove any existing first
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Extracts all VTIMEZONE components from the @vcalendar and adds them
+ * to the cache, thus they are available when needed. The function does
+ * nothing when the @vcalendar doesn't hold a VCALENDAR component.
+ *
+ * Set the @remove_existing argument to %TRUE to remove all cached timezones
+ * first and then add the existing in the @vcalendar, or set it to %FALSE
+ * to preserver existing timezones and merge them with those in @vcalendar.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_cal_meta_backend_gather_timezones_sync (ECalMetaBackend *meta_backend,
+                                         icalcomponent *vcalendar,
+                                         gboolean remove_existing,
+                                         GCancellable *cancellable,
+                                         GError **error)
+{
+       ECalCache *cal_cache;
+       gboolean success = TRUE;
+
+       g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
+       g_return_val_if_fail (vcalendar != NULL, FALSE);
+
+       if (icalcomponent_isa (vcalendar) != ICAL_VCALENDAR_COMPONENT)
+               return TRUE;
+
+       cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
+       if (!cal_cache)
+               return FALSE;
+
+       e_cache_lock (E_CACHE (cal_cache), E_CACHE_LOCK_WRITE);
+
+       if (remove_existing)
+               success = e_cal_cache_remove_timezones (cal_cache, cancellable, error);
+
+       if (success)
+               ecmb_gather_timezones (meta_backend, E_TIMEZONE_CACHE (cal_cache), vcalendar);
+
+       e_cache_unlock (E_CACHE (cal_cache), success ? E_CACHE_UNLOCK_COMMIT : E_CACHE_UNLOCK_ROLLBACK);
+
+       g_object_unref (cal_cache);
+
+       return TRUE;
+}
+
+/**
+ * e_cal_meta_backend_empty_cache_sync:
+ * @meta_backend: an #ECalMetaBackend
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Empties the local cache by removing all known components from it
+ * and notifies about such removal any opened views. It removes also
+ * all known time zones.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_cal_meta_backend_empty_cache_sync (ECalMetaBackend *meta_backend,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+       ECalBackend *cal_backend;
+       ECalCache *cal_cache;
+       GSList *ids = NULL, *link;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
+
+       cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
+       if (!cal_cache)
+               return FALSE;
+
+       e_cache_lock (E_CACHE (cal_cache), E_CACHE_LOCK_WRITE);
+
+       cal_backend = E_CAL_BACKEND (meta_backend);
+
+       success = e_cal_cache_search_ids (cal_cache, NULL, &ids, cancellable, error);
+       if (success)
+               success = e_cache_remove_all (E_CACHE (cal_cache), cancellable, error);
+
+       e_cache_unlock (E_CACHE (cal_cache), success ? E_CACHE_UNLOCK_COMMIT : E_CACHE_UNLOCK_ROLLBACK);
+
+       g_object_unref (cal_cache);
+
+       if (success) {
+               for (link = ids; link; link = g_slist_next (link)) {
+                       ECalComponentId *id = link->data;
+
+                       if (!id)
+                               continue;
+
+                       e_cal_backend_notify_component_removed (cal_backend, id, NULL, NULL);
+               }
+       }
+
+       g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
+
+       return success;
+}
+
+/**
  * e_cal_meta_backend_connect_sync:
  * @meta_backend: an #ECalMetaBackend
  * @credentials: (nullable): an #ENamedParameters with previously used credentials, or %NULL
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.h b/src/calendar/libedata-cal/e-cal-meta-backend.h
index e516a00..7079a91 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.h
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.h
@@ -171,6 +171,16 @@ gboolean   e_cal_meta_backend_store_inline_attachments_sync
                                                 icalcomponent *component,
                                                 GCancellable *cancellable,
                                                 GError **error);
+gboolean       e_cal_meta_backend_gather_timezones_sync
+                                               (ECalMetaBackend *meta_backend,
+                                                icalcomponent *vcalendar,
+                                                gboolean remove_existing,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_cal_meta_backend_empty_cache_sync
+                                               (ECalMetaBackend *meta_backend,
+                                                GCancellable *cancellable,
+                                                GError **error);
 gboolean       e_cal_meta_backend_connect_sync (ECalMetaBackend *meta_backend,
                                                 const ENamedParameters *credentials,
                                                 ESourceAuthenticationResult *out_auth_result,
diff --git a/tests/libedata-cal/test-cal-meta-backend.c b/tests/libedata-cal/test-cal-meta-backend.c
index 02eb5d8..b870d49 100644
--- a/tests/libedata-cal/test-cal-meta-backend.c
+++ b/tests/libedata-cal/test-cal-meta-backend.c
@@ -24,6 +24,8 @@
 
 #include "test-cal-cache-utils.h"
 
+void _e_cal_cache_remove_loaded_timezones (ECalCache *cal_cache); /* e-cal-cache.c, private function */
+
 #define EXPECTED_TZID          "/freeassociation.sourceforge.net/America/New_York"
 #define EXPECTED_LOCATION      "America/New_York"
 #define REMOTE_URL             "https://www.gnome.org/wp-content/themes/gnome-grass/images/gnome-logo.svg";
@@ -384,7 +386,6 @@ e_cal_meta_backend_test_list_existing_sync (ECalMetaBackend *meta_backend,
             icalcomp = icalcomponent_get_next_component (test_backend->vcalendar, ICAL_VEVENT_COMPONENT)) {
                const gchar *uid;
                gchar *revision;
-               ECalComponent *comp;
                ECalMetaBackendInfo *nfo;
 
                /* Detached instances are stored together with the master object */
@@ -392,10 +393,7 @@ e_cal_meta_backend_test_list_existing_sync (ECalMetaBackend *meta_backend,
                        continue;
 
                uid = icalcomponent_get_uid (icalcomp);
-
-               comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone (icalcomp));
-               revision = e_cal_cache_dup_component_revision (cal_cache, comp);
-               g_object_unref (comp);
+               revision = e_cal_cache_dup_component_revision (cal_cache, icalcomp);
 
                nfo = e_cal_meta_backend_info_new (uid, NULL, revision);
                *out_existing_objects = g_slist_prepend (*out_existing_objects, nfo);
@@ -1139,6 +1137,77 @@ test_attachments (TCUFixture *fixture,
 }
 
 static void
+test_empty_cache (TCUFixture *fixture,
+                 gconstpointer user_data)
+{
+       #define TZID "/meta/backend/test/timezone"
+       #define TZLOC "test/timezone"
+
+       const gchar *in_tzobj =
+               "BEGIN:VTIMEZONE\r\n"
+               "TZID:" TZID "\r\n"
+               "X-LIC-LOCATION:" TZLOC "\r\n"
+               "BEGIN:STANDARD\r\n"
+               "TZNAME:Test-ST\r\n"
+               "DTSTART:19701106T020000\r\n"
+               "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11\r\n"
+               "TZOFFSETFROM:-0400\r\n"
+               "TZOFFSETTO:-0500\r\n"
+               "END:STANDARD\r\n"
+               "BEGIN:DAYLIGHT\r\n"
+               "TZNAME:Test-DT\r\n"
+               "DTSTART:19700313T020000\r\n"
+               "RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3\r\n"
+               "TZOFFSETFROM:-0500\r\n"
+               "TZOFFSETTO:-0400\r\n"
+               "END:DAYLIGHT\r\n"
+               "END:VTIMEZONE\r\n";
+       ECalMetaBackend *meta_backend;
+       GList *zones;
+       gboolean success;
+       GError *error = NULL;
+
+       meta_backend = e_cal_meta_backend_test_new (fixture->cal_cache);
+       g_assert_nonnull (meta_backend);
+
+       /* Add timezone to the cache */
+       E_CAL_BACKEND_SYNC_GET_CLASS (meta_backend)->add_timezone_sync (E_CAL_BACKEND_SYNC (meta_backend),
+               NULL, NULL, in_tzobj, &error);
+       g_assert_no_error (error);
+
+       zones = NULL;
+       success = e_cal_cache_list_timezones (fixture->cal_cache, &zones, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_cmpint (g_list_length (zones), ==, 1);
+       g_list_free (zones);
+
+       g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_INCLUDE_DELETED, NULL, 
&error), >, 0);
+       g_assert_no_error (error);
+
+       /* Empty the cache */
+       success = e_cal_meta_backend_empty_cache_sync (meta_backend, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       /* Verify the cache is truly empty */
+       zones = NULL;
+       success = e_cal_cache_list_timezones (fixture->cal_cache, &zones, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_cmpint (g_list_length (zones), ==, 0);
+       g_list_free (zones);
+
+       g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->cal_cache), E_CACHE_INCLUDE_DELETED, NULL, 
&error), ==, 0);
+       g_assert_no_error (error);
+
+       g_object_unref (meta_backend);
+
+       #undef TZID
+       #undef TZLOC
+}
+
+static void
 test_send_objects (ECalMetaBackend *meta_backend)
 {
        GSList *users = NULL;
@@ -1235,7 +1304,11 @@ test_timezones (ECalMetaBackend *meta_backend)
                "TZOFFSETTO:-0400\r\n"
                "END:DAYLIGHT\r\n"
                "END:VTIMEZONE\r\n";
+       ECalCache *cal_cache;
+       icalcomponent *vcalendar;
        gchar *tzobj = NULL;
+       GList *zones;
+       gboolean success;
        GError *error = NULL;
 
        g_assert_nonnull (meta_backend);
@@ -1273,7 +1346,7 @@ test_timezones (ECalMetaBackend *meta_backend)
        g_assert_null (tzobj);
        g_clear_error (&error);
 
-       /* Try also internal timezone */
+       /* Try also internal timezone, which will be renamed and added to the cache too */
        E_CAL_BACKEND_SYNC_GET_CLASS (meta_backend)->get_timezone_sync (E_CAL_BACKEND_SYNC (meta_backend),
                NULL, NULL, "America/New_York", &tzobj, &error);
        g_assert_no_error (error);
@@ -1282,6 +1355,119 @@ test_timezones (ECalMetaBackend *meta_backend)
        g_free (tzobj);
        tzobj = NULL;
 
+       cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
+       g_assert_nonnull (cal_cache);
+
+       vcalendar = icalcomponent_new_from_string (
+               "BEGIN:VCALENDAR\r\n"
+               "BEGIN:VTIMEZONE\r\n"
+               "TZID:tzid1\r\n"
+               "X-LIC-LOCATION:tzid/1\r\n"
+               "BEGIN:STANDARD\r\n"
+               "TZNAME:Test-ST\r\n"
+               "DTSTART:19701106T020000\r\n"
+               "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11\r\n"
+               "TZOFFSETFROM:-0400\r\n"
+               "TZOFFSETTO:-0500\r\n"
+               "END:STANDARD\r\n"
+               "BEGIN:DAYLIGHT\r\n"
+               "TZNAME:Test-DT\r\n"
+               "DTSTART:19700313T020000\r\n"
+               "RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3\r\n"
+               "TZOFFSETFROM:-0500\r\n"
+               "TZOFFSETTO:-0400\r\n"
+               "END:DAYLIGHT\r\n"
+               "END:VTIMEZONE\r\n"
+               "BEGIN:VTIMEZONE\r\n"
+               "TZID:tzid2\r\n"
+               "X-LIC-LOCATION:tzid/2\r\n"
+               "BEGIN:STANDARD\r\n"
+               "TZNAME:Test-ST\r\n"
+               "DTSTART:19701106T020000\r\n"
+               "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11\r\n"
+               "TZOFFSETFROM:-0400\r\n"
+               "TZOFFSETTO:-0500\r\n"
+               "END:STANDARD\r\n"
+               "BEGIN:DAYLIGHT\r\n"
+               "TZNAME:Test-DT\r\n"
+               "DTSTART:19700313T020000\r\n"
+               "RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3\r\n"
+               "TZOFFSETFROM:-0500\r\n"
+               "TZOFFSETTO:-0400\r\n"
+               "END:DAYLIGHT\r\n"
+               "END:VTIMEZONE\r\n"
+               "BEGIN:VEVENT\r\n"
+               "UID:test-event\r\n"
+               "DTSTAMP:20170130T000000Z\r\n"
+               "CREATED:20170216T155507Z\r\n"
+               "LAST-MODIFIED:20170216T155543Z\r\n"
+               "SEQUENCE:1\r\n"
+               "DTSTART:20170209T013000Z\r\n"
+               "DTEND:20170209T030000Z\r\n"
+               "SUMMARY:Test Event\r\n"
+               "END:VEVENT\r\n"
+               "END:VCALENDAR\r\n");
+       g_assert_nonnull (vcalendar);
+
+       zones = NULL;
+       success = e_cal_cache_list_timezones (cal_cache, &zones, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_cmpint (g_list_length (zones), ==, 2);
+       g_list_free (zones);
+
+       /* Merge with existing */
+       success = e_cal_meta_backend_gather_timezones_sync (meta_backend, vcalendar, FALSE, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       zones = NULL;
+       success = e_cal_cache_list_timezones (cal_cache, &zones, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_cmpint (g_list_length (zones), ==, 4);
+       g_list_free (zones);
+
+       success = e_cal_cache_remove_timezones (cal_cache, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       _e_cal_cache_remove_loaded_timezones (cal_cache);
+
+       zones = NULL;
+       success = e_cal_cache_list_timezones (cal_cache, &zones, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_cmpint (g_list_length (zones), ==, 0);
+
+       E_CAL_BACKEND_SYNC_GET_CLASS (meta_backend)->add_timezone_sync (E_CAL_BACKEND_SYNC (meta_backend),
+               NULL, NULL, in_tzobj, &error);
+       g_assert_no_error (error);
+
+       zones = NULL;
+       success = e_cal_cache_list_timezones (cal_cache, &zones, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_cmpint (g_list_length (zones), ==, 1);
+       g_list_free (zones);
+
+       /* Remove existing and add the new */
+       success = e_cal_meta_backend_gather_timezones_sync (meta_backend, vcalendar, TRUE, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+
+       _e_cal_cache_remove_loaded_timezones (cal_cache);
+
+       zones = NULL;
+       success = e_cal_cache_list_timezones (cal_cache, &zones, NULL, &error);
+       g_assert_no_error (error);
+       g_assert (success);
+       g_assert_cmpint (g_list_length (zones), ==, 2);
+       g_list_free (zones);
+
+       icalcomponent_free (vcalendar);
+       g_object_unref (cal_cache);
+
        #undef TZLOC
        #undef TZID
 }
@@ -2465,6 +2651,8 @@ main (gint argc,
                tcu_fixture_setup, test_merge_instances, tcu_fixture_teardown);
        g_test_add ("/ECalMetaBackend/Attachments", TCUFixture, &closure_events,
                tcu_fixture_setup, test_attachments, tcu_fixture_teardown);
+       g_test_add ("/ECalMetaBackend/EmptyCache", TCUFixture, &closure_events,
+               tcu_fixture_setup, test_empty_cache, tcu_fixture_teardown);
        g_test_add ("/ECalMetaBackend/SendObjects", TCUFixture, &closure_events,
                tcu_fixture_setup, test_send_objects_tcu, tcu_fixture_teardown);
        g_test_add ("/ECalMetaBackend/GetAttachmentUris", TCUFixture, &closure_events,


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