[evolution-data-server/wip/mcrha/libical-glib] Add a test for e-cal-recur and fix recurrence generation through ECalClient
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/mcrha/libical-glib] Add a test for e-cal-recur and fix recurrence generation through ECalClient
- Date: Thu, 18 Apr 2019 11:54:43 +0000 (UTC)
commit d80f7907712143e6b2806085fe1a1c7872d898d4
Author: Milan Crha <mcrha redhat com>
Date: Thu Apr 18 13:54:53 2019 +0200
Add a test for e-cal-recur and fix recurrence generation through ECalClient
src/calendar/libecal/e-cal-client.c | 281 +++++--------------------
tests/libecal/CMakeLists.txt | 1 +
tests/libecal/test-cal-recur.c | 407 ++++++++++++++++++++++++++++++++++++
3 files changed, 461 insertions(+), 228 deletions(-)
---
diff --git a/src/calendar/libecal/e-cal-client.c b/src/calendar/libecal/e-cal-client.c
index 38dc2cc43..998fddeda 100644
--- a/src/calendar/libecal/e-cal-client.c
+++ b/src/calendar/libecal/e-cal-client.c
@@ -2159,15 +2159,25 @@ e_cal_client_check_recurrences_no_master (ECalClient *client)
struct comp_instance {
ECalComponent *comp;
- time_t start;
- time_t end;
+ ICalTime *start;
+ ICalTime *end;
};
+static void
+comp_instance_free (gpointer ptr)
+{
+ struct comp_instance *ci = ptr;
+
+ if (ci) {
+ g_clear_object (&ci->comp);
+ g_clear_object (&ci->start);
+ g_clear_object (&ci->end);
+ g_free (ci);
+ }
+}
+
struct instances_info {
GSList **instances;
- ICalTimezone *start_zone;
- ICalTimezone *end_zone;
- ICalTimezone *default_zone;
};
/* Called from cal_recur_generate_instances(); adds an instance to the list */
@@ -2186,49 +2196,23 @@ add_instance_cb (ICalComponent *icomp,
instances_hold = user_data;
list = instances_hold->instances;
- ci = g_new (struct comp_instance, 1);
+ ci = g_new0 (struct comp_instance, 1);
/* add the instance to the list */
ci->comp = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (icomp));
if (!ci->comp) {
- g_free (ci);
+ comp_instance_free (ci);
return FALSE;
}
/* make sure we return an instance */
if (e_cal_component_has_recurrences (ci->comp) &&
!e_cal_component_is_instance (ci->comp)) {
- ECalComponentRange *range;
- ICalTime *itt;
ECalComponentDateTime *dtstart, *dtend;
+ ECalComponentRange *range;
- dtstart = e_cal_component_get_dtstart (ci->comp);
-
- if (instances_hold->start_zone) {
- itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (start),
- dtstart && e_cal_component_datetime_get_value (dtstart) && i_cal_time_is_date
(e_cal_component_datetime_get_value (dtstart)),
- instances_hold->start_zone);
- if (dtstart)
- e_cal_component_datetime_set_tzid (dtstart, i_cal_timezone_get_tzid
(instances_hold->start_zone));
- } else if (dtstart && instances_hold->default_zone &&
- e_cal_component_datetime_get_value (dtstart) &&
- i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart)) &&
- !e_cal_component_datetime_get_tzid (dtstart)) {
- /* Floating date, set in the default zone */
- itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (start), TRUE,
instances_hold->default_zone);
- } else {
- itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (start),
- dtstart && e_cal_component_datetime_get_value (dtstart) && i_cal_time_is_date
(e_cal_component_datetime_get_value (dtstart)),
- NULL);
- if (dtstart)
- e_cal_component_datetime_set_tzid (dtstart, NULL);
- }
-
- if (dtstart)
- e_cal_component_datetime_set_value (dtstart, itt);
- else
- dtstart = e_cal_component_datetime_new (itt, instances_hold->start_zone ?
i_cal_timezone_get_tzid (instances_hold->start_zone) : NULL);
-
+ /* Update DTSTART */
+ dtstart = e_cal_component_datetime_new (start, i_cal_time_get_tzid (start));
e_cal_component_set_dtstart (ci->comp, dtstart);
/* set the RECUR-ID for the instance */
@@ -2238,45 +2222,15 @@ add_instance_cb (ICalComponent *icomp,
e_cal_component_datetime_free (dtstart);
e_cal_component_range_free (range);
- g_clear_object (&itt);
/* Update DTEND */
-
- dtend = e_cal_component_get_dtend (ci->comp);
-
- if (instances_hold->end_zone) {
- itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (end),
- dtend && e_cal_component_datetime_get_value (dtend) && i_cal_time_is_date
(e_cal_component_datetime_get_value (dtend)),
- instances_hold->end_zone);
- if (dtend)
- e_cal_component_datetime_set_tzid (dtend, i_cal_timezone_get_tzid
(instances_hold->end_zone));
- } else if (dtend && instances_hold->default_zone &&
- e_cal_component_datetime_get_value (dtend) &&
- i_cal_time_is_date (e_cal_component_datetime_get_value (dtend)) &&
- !e_cal_component_datetime_get_tzid (dtend)) {
- /* Floating date, set in the default zone */
- itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (end), TRUE,
instances_hold->default_zone);
- } else {
- itt = i_cal_time_from_timet_with_zone (i_cal_time_as_timet (end),
- dtend && e_cal_component_datetime_get_value (dtend) && i_cal_time_is_date
(e_cal_component_datetime_get_value (dtend)),
- NULL);
- if (dtend)
- e_cal_component_datetime_set_tzid (dtend, NULL);
- }
-
- if (dtend)
- e_cal_component_datetime_set_value (dtend, itt);
- else
- dtend = e_cal_component_datetime_new (itt, instances_hold->end_zone ?
i_cal_timezone_get_tzid (instances_hold->end_zone) : NULL);
-
+ dtend = e_cal_component_datetime_new (end, i_cal_time_get_tzid (end));
e_cal_component_set_dtend (ci->comp, dtend);
-
e_cal_component_datetime_free (dtend);
- g_clear_object (&itt);
}
- ci->start = i_cal_time_as_timet (start);
- ci->end = i_cal_time_as_timet (end);
+ ci->start = i_cal_time_new_clone (start);
+ ci->end = i_cal_time_new_clone (end);
*list = g_slist_prepend (*list, ci);
@@ -2289,13 +2243,11 @@ compare_comp_instance (gconstpointer a,
gconstpointer b)
{
const struct comp_instance *cia, *cib;
- time_t diff;
cia = a;
cib = b;
- diff = cia->start - cib->start;
- return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
+ return i_cal_time_compare (cia->start, cib->start);
}
static time_t
@@ -2390,9 +2342,11 @@ process_detached_instances (GSList *instances,
if (e_cal_component_range_get_kind (recur_id) == E_CAL_COMPONENT_RANGE_SINGLE
&& i_rid == d_rid) {
g_object_unref (ci->comp);
+ g_clear_object (&ci->start);
+ g_clear_object (&ci->end);
ci->comp = g_object_ref (cid->comp);
- ci->start = cid->start;
- ci->end = cid->end;
+ ci->start = i_cal_time_new_clone (cid->start);
+ ci->end = i_cal_time_new_clone (cid->end);
processed = TRUE;
} else {
@@ -2426,8 +2380,8 @@ process_detached_instances (GSList *instances,
cid = unprocessed_instances->data;
ci = g_new0 (struct comp_instance, 1);
ci->comp = g_object_ref (cid->comp);
- ci->start = cid->start;
- ci->end = cid->end;
+ ci->start = i_cal_time_new_clone (cid->start);
+ ci->end = i_cal_time_new_clone (cid->end);
instances = g_slist_append (instances, ci);
unprocessed_instances = g_slist_remove (unprocessed_instances, cid);
@@ -2449,6 +2403,7 @@ generate_instances (ECalClient *client,
GSList *l;
ECalClientPrivate *priv;
ICalTimezone *default_zone;
+ ICalTime *starttt, *endtt;
priv = client->priv;
@@ -2459,6 +2414,9 @@ generate_instances (ECalClient *client,
else
default_zone = i_cal_timezone_get_utc_timezone ();
+ starttt = i_cal_time_from_timet_with_zone (start, FALSE, NULL);
+ endtt = i_cal_time_from_timet_with_zone (end, FALSE, NULL);
+
for (l = objects; l && !g_cancellable_is_cancelled (cancellable); l = l->next) {
ECalComponent *comp;
@@ -2466,7 +2424,6 @@ generate_instances (ECalClient *client,
if (e_cal_component_is_instance (comp)) {
struct comp_instance *ci;
ECalComponentDateTime *dtstart, *dtend;
- ICalTimezone *start_zone = NULL, *end_zone = NULL;
/* keep the detached instances apart */
ci = g_new0 (struct comp_instance, 1);
@@ -2475,97 +2432,47 @@ generate_instances (ECalClient *client,
dtstart = e_cal_component_get_dtstart (comp);
dtend = e_cal_component_get_dtend (comp);
- /* For DATE-TIME values with a TZID, we use
- * e_cal_resolve_tzid_cb to resolve the TZID.
- * For DATE values and DATE-TIME values without a
- * TZID (i.e. floating times) we use the default
- * timezone. */
- if (dtstart && e_cal_component_datetime_get_tzid (dtstart) &&
e_cal_component_datetime_get_value (dtstart) &&
- !i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart))) {
- start_zone = e_cal_client_tzlookup_cb (e_cal_component_datetime_get_tzid
(dtstart), client, cancellable, NULL);
- if (!start_zone)
- start_zone = default_zone;
- } else {
- start_zone = default_zone;
- }
-
- if (dtend && e_cal_component_datetime_get_tzid (dtend) &&
e_cal_component_datetime_get_value (dtend) &&
- !i_cal_time_is_date (e_cal_component_datetime_get_value (dtend))) {
- end_zone = e_cal_client_tzlookup_cb (e_cal_component_datetime_get_tzid
(dtend), client, cancellable, NULL);
- if (!end_zone)
- end_zone = default_zone;
- } else {
- end_zone = default_zone;
- }
-
if (!dtstart || !e_cal_component_datetime_get_value (dtstart)) {
g_warn_if_reached ();
e_cal_component_datetime_free (dtstart);
e_cal_component_datetime_free (dtend);
- g_object_unref (G_OBJECT (ci->comp));
- g_free (ci);
+ comp_instance_free (ci);
continue;
}
- ci->start = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value
(dtstart), start_zone);
+ ci->start = i_cal_time_new_clone (e_cal_component_datetime_get_value (dtstart));
if (dtend && e_cal_component_datetime_get_value (dtend))
- ci->end = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value
(dtend), end_zone);
- else if (i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart)))
- ci->end = time_day_end (ci->start);
- else
- ci->end = ci->start;
+ ci->end = i_cal_time_new_clone (e_cal_component_datetime_get_value (dtend));
+ else {
+ ci->end = i_cal_time_new_clone (ci->start);
+
+ if (i_cal_time_is_date (e_cal_component_datetime_get_value (dtstart)))
+ i_cal_time_adjust (ci->end, 1, 0, 0, 0);
+ }
e_cal_component_datetime_free (dtstart);
e_cal_component_datetime_free (dtend);
- if (ci->start <= end && ci->end >= start) {
+ if (i_cal_time_compare (ci->start, endtt) <= 0 && i_cal_time_compare (ci->end,
starttt) >= 0) {
detached_instances = g_slist_prepend (detached_instances, ci);
} else {
/* it doesn't fit to our time range, thus skip it */
- g_object_unref (G_OBJECT (ci->comp));
- g_free (ci);
+ comp_instance_free (ci);
}
} else {
- ECalComponentDateTime *datetime;
- ICalTimezone *start_zone = NULL, *end_zone = NULL;
- ICalTime *starttt, *endtt;
struct instances_info *instances_hold;
- /* Get the start timezone */
- datetime = e_cal_component_get_dtstart (comp);
- if (datetime && e_cal_component_datetime_get_tzid (datetime))
- e_cal_client_get_timezone_sync (client, e_cal_component_datetime_get_tzid
(datetime), &start_zone, cancellable, NULL);
- else
- start_zone = NULL;
- e_cal_component_datetime_free (datetime);
-
- /* Get the end timezone */
- datetime = e_cal_component_get_dtend (comp);
- if (datetime && e_cal_component_datetime_get_tzid (datetime))
- e_cal_client_get_timezone_sync (client, e_cal_component_datetime_get_tzid
(datetime), &end_zone, cancellable, NULL);
- else
- end_zone = NULL;
- e_cal_component_datetime_free (datetime);
-
instances_hold = g_new0 (struct instances_info, 1);
instances_hold->instances = &instances;
- instances_hold->start_zone = start_zone;
- instances_hold->end_zone = end_zone;
- instances_hold->default_zone = default_zone;
-
- starttt = i_cal_time_from_timet_with_zone (start, FALSE, NULL);
- endtt = i_cal_time_from_timet_with_zone (end, FALSE, NULL);
e_cal_recur_generate_instances_sync (
e_cal_component_get_icalcomponent (comp), starttt, endtt, add_instance_cb,
instances_hold,
e_cal_client_tzlookup_cb, client,
default_zone, cancellable, NULL);
- g_clear_object (&starttt);
- g_clear_object (&endtt);
g_free (instances_hold);
}
}
@@ -2582,18 +2489,11 @@ generate_instances (ECalClient *client,
for (l = instances; l && !g_cancellable_is_cancelled (cancellable); l = l->next) {
struct comp_instance *ci;
- ICalTime *starttt, *endtt;
gboolean result;
ci = l->data;
- starttt = i_cal_time_from_timet_with_zone (ci->start, FALSE, default_zone);
- endtt = i_cal_time_from_timet_with_zone (ci->end, FALSE, default_zone);
-
- result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), starttt, endtt, cb_data,
cancellable, NULL);
-
- g_clear_object (&starttt);
- g_clear_object (&endtt);
+ result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), ci->start, ci->end, cb_data,
cancellable, NULL);
if (!result)
break;
@@ -2601,25 +2501,10 @@ generate_instances (ECalClient *client,
/* Clean up */
- for (l = instances; l; l = l->next) {
- struct comp_instance *ci;
-
- ci = l->data;
- g_object_unref (G_OBJECT (ci->comp));
- g_free (ci);
- }
-
- g_slist_free (instances);
-
- for (l = detached_instances; l; l = l->next) {
- struct comp_instance *ci;
-
- ci = l->data;
- g_object_unref (G_OBJECT (ci->comp));
- g_free (ci);
- }
-
- g_slist_free (detached_instances);
+ g_slist_free_full (instances, comp_instance_free);
+ g_slist_free_full (detached_instances, comp_instance_free);
+ g_clear_object (&starttt);
+ g_clear_object (&endtt);
}
static GSList *
@@ -2687,8 +2572,6 @@ struct get_objects_async_data {
gchar *query;
guint tries;
void (* ready_cb) (struct get_objects_async_data *goad, GSList *objects);
- ICalTimezone *start_zone;
- ICalTimezone *end_zone;
ECalComponent *comp;
};
@@ -2973,32 +2856,20 @@ process_instances (ECalClient *client,
ci = instances->data;
if (result) {
- ICalTime *starttt = NULL, *endtt = NULL;
-
instance_rid = e_cal_component_get_recurid_as_string (ci->comp);
if (rid && *rid) {
if (instance_rid && *instance_rid && strcmp (rid, instance_rid) == 0) {
- starttt = i_cal_time_from_timet_with_zone (ci->start, FALSE,
client->priv->default_zone);
- endtt = i_cal_time_from_timet_with_zone (ci->end, FALSE,
client->priv->default_zone);
-
- result = (* cb) (e_cal_component_get_icalcomponent (ci->comp),
starttt, endtt, cb_data, NULL, NULL);
+ result = (* cb) (e_cal_component_get_icalcomponent (ci->comp),
ci->start, ci->end, cb_data, NULL, NULL);
}
} else {
- starttt = i_cal_time_from_timet_with_zone (ci->start, FALSE,
client->priv->default_zone);
- endtt = i_cal_time_from_timet_with_zone (ci->end, FALSE,
client->priv->default_zone);
-
- result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), starttt,
endtt, cb_data, NULL, NULL);
+ result = (* cb) (e_cal_component_get_icalcomponent (ci->comp), ci->start,
ci->end, cb_data, NULL, NULL);
}
-
- g_clear_object (&starttt);
- g_clear_object (&endtt);
}
/* remove instance from list */
instances = g_slist_remove (instances, ci);
- g_object_unref (ci->comp);
- g_free (ci);
+ comp_instance_free (ci);
g_free (instance_rid);
}
@@ -3017,9 +2888,6 @@ generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goa
instances_hold = g_new0 (struct instances_info, 1);
instances_hold->instances = &instances;
- instances_hold->start_zone = goad->start_zone;
- instances_hold->end_zone = goad->end_zone;
- instances_hold->default_zone = e_cal_client_get_default_timezone (goad->client);
/* generate all instances in the given time range */
generate_instances (
@@ -3072,8 +2940,6 @@ e_cal_client_generate_instances_for_object (ECalClient *client,
{
ECalComponent *comp;
const gchar *uid;
- ECalComponentDateTime *datetime;
- ICalTimezone *start_zone = NULL, *end_zone = NULL;
struct get_objects_async_data *goad;
GCancellable *use_cancellable;
@@ -3107,24 +2973,6 @@ e_cal_client_generate_instances_for_object (ECalClient *client,
uid = e_cal_component_get_uid (comp);
- /* Get the start timezone */
- datetime = e_cal_component_get_dtstart (comp);
- if (datetime && e_cal_component_datetime_get_tzid (datetime))
- e_cal_client_get_timezone_sync (
- client, e_cal_component_datetime_get_tzid (datetime), &start_zone, cancellable, NULL);
- else
- start_zone = NULL;
- e_cal_component_datetime_free (datetime);
-
- /* Get the end timezone */
- datetime = e_cal_component_get_dtend (comp);
- if (datetime && e_cal_component_datetime_get_tzid (datetime))
- e_cal_client_get_timezone_sync (
- client, e_cal_component_datetime_get_tzid (datetime), &end_zone, cancellable, NULL);
- else
- end_zone = NULL;
- e_cal_component_datetime_free (datetime);
-
use_cancellable = cancellable;
if (!use_cancellable)
use_cancellable = g_cancellable_new ();
@@ -3137,8 +2985,6 @@ e_cal_client_generate_instances_for_object (ECalClient *client,
goad->cb = cb;
goad->cb_data = cb_data;
goad->destroy_cb_data = destroy_cb_data;
- goad->start_zone = start_zone;
- goad->end_zone = end_zone;
goad->comp = comp;
goad->uid = g_strdup (uid);
@@ -3180,8 +3026,6 @@ e_cal_client_generate_instances_for_object_sync (ECalClient *client,
ECalComponent *comp;
const gchar *uid;
GSList *instances = NULL;
- ECalComponentDateTime *datetime;
- ICalTimezone *start_zone = NULL, *end_zone = NULL;
struct instances_info *instances_hold;
g_return_if_fail (E_IS_CAL_CLIENT (client));
@@ -3212,27 +3056,8 @@ e_cal_client_generate_instances_for_object_sync (ECalClient *client,
uid = e_cal_component_get_uid (comp);
- /* Get the start timezone */
- datetime = e_cal_component_get_dtstart (comp);
- if (datetime && e_cal_component_datetime_get_tzid (datetime))
- e_cal_client_get_timezone_sync (client, e_cal_component_datetime_get_tzid (datetime),
&start_zone, cancellable, NULL);
- else
- start_zone = NULL;
- e_cal_component_datetime_free (datetime);
-
- /* Get the end timezone */
- datetime = e_cal_component_get_dtend (comp);
- if (datetime && e_cal_component_datetime_get_tzid (datetime))
- e_cal_client_get_timezone_sync (client, e_cal_component_datetime_get_tzid (datetime),
&end_zone, cancellable, NULL);
- else
- end_zone = NULL;
- e_cal_component_datetime_free (datetime);
-
instances_hold = g_new0 (struct instances_info, 1);
instances_hold->instances = &instances;
- instances_hold->start_zone = start_zone;
- instances_hold->end_zone = end_zone;
- instances_hold->default_zone = e_cal_client_get_default_timezone (client);
/* generate all instances in the given time range */
generate_instances (
diff --git a/tests/libecal/CMakeLists.txt b/tests/libecal/CMakeLists.txt
index 8d69e5924..5575e53cc 100644
--- a/tests/libecal/CMakeLists.txt
+++ b/tests/libecal/CMakeLists.txt
@@ -33,6 +33,7 @@ set(TESTS
test-cal-client-get-revision
test-cal-client-get-free-busy
test-cal-component
+ test-cal-recur
)
foreach(_test ${TESTS})
diff --git a/tests/libecal/test-cal-recur.c b/tests/libecal/test-cal-recur.c
new file mode 100644
index 000000000..b9d26097d
--- /dev/null
+++ b/tests/libecal/test-cal-recur.c
@@ -0,0 +1,407 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libecal/libecal.h>
+
+#include "e-test-server-utils.h"
+
+static ETestServerClosure test_closure = { E_TEST_SERVER_CALENDAR, NULL, E_CAL_CLIENT_SOURCE_TYPE_EVENTS,
FALSE, NULL, FALSE };
+
+static ICalComponent *
+create_component (const gchar *tz_location)
+{
+ const gchar *comp_str =
+ "BEGIN:VEVENT\r\n"
+ "SUMMARY:recurs\r\n"
+ "UID:recurs-id\r\n"
+ "DTSTART%s:20190107T080000%s\r\n"
+ "DTEND%s:20190107T090000%s\r\n"
+ "DTSTAMP:20190101T050000Z\r\n"
+ "CREATED:20190101T050000Z\r\n"
+ "LAST-MODIFIED:20190101T050000Z\r\n"
+ "RRULE:FREQ=DAILY;COUNT=5\r\n"
+ "END:VEVENT\r\n";
+ gchar *tzref = NULL, tzsuffix[2] = { 0, 0};
+ gchar *str;
+ ICalComponent *icomp;
+ ICalTimezone *zone = NULL;
+ ICalTime *itt;
+
+ if (tz_location) {
+ if (g_ascii_strcasecmp (tz_location, "UTC") == 0) {
+ tzsuffix[0] = 'Z';
+ zone = i_cal_timezone_get_utc_timezone ();
+ } else {
+ const gchar *tzid;
+
+ zone = i_cal_timezone_get_builtin_timezone (tz_location);
+ g_assert_nonnull (zone);
+
+ tzid = i_cal_timezone_get_tzid (zone);
+ g_assert_nonnull (tzid);
+
+ tzref = g_strconcat (";TZID=", tzid, NULL);
+ }
+ }
+
+ str = g_strdup_printf (comp_str, tzref ? tzref : "", tzsuffix, tzref ? tzref : "", tzsuffix);
+ icomp = i_cal_component_new_from_string (str);
+ g_assert_nonnull (icomp);
+
+ g_free (tzref);
+ g_free (str);
+
+ itt = i_cal_component_get_dtstart (icomp);
+ g_assert_nonnull (itt);
+ g_assert (i_cal_time_get_timezone (itt) == zone);
+ g_object_unref (itt);
+
+ itt = i_cal_component_get_dtend (icomp);
+ g_assert_nonnull (itt);
+ g_assert (i_cal_time_get_timezone (itt) == zone);
+ g_object_unref (itt);
+
+ return icomp;
+}
+
+static void
+setup_cal (ECalClient *cal_client,
+ const gchar *tz_location)
+{
+ ICalComponent *icomp;
+ gboolean success;
+ gchar *uid = NULL;
+ GError *error = NULL;
+
+ icomp = create_component (tz_location);
+
+ /* Ignore errors, it'll fail the first time, but will succeed all other times */
+ e_cal_client_remove_object_sync (cal_client, i_cal_component_get_uid (icomp), NULL,
E_CAL_OBJ_MOD_ALL, E_CAL_OPERATION_FLAG_NONE, NULL, NULL);
+
+ success = e_cal_client_create_object_sync (cal_client, icomp, E_CAL_OPERATION_FLAG_NONE, &uid, NULL,
&error);
+ g_assert_no_error (error);
+ g_assert (success);
+ g_assert_nonnull (uid);
+
+ g_object_unref (icomp);
+ g_free (uid);
+}
+
+typedef struct _Instance {
+ ICalTime *start;
+ ICalTime *end;
+ ICalComponent *icomp;
+} Instance;
+
+static Instance *
+instance_new (ICalTime *start,
+ ICalTime *end,
+ ICalComponent *icomp)
+{
+ Instance *ins;
+
+ ins = g_new0 (Instance, 1);
+ ins->start = i_cal_time_new_clone (start);
+ ins->end = i_cal_time_new_clone (end);
+ ins->icomp = i_cal_component_new_clone (icomp);
+
+ return ins;
+}
+
+static void
+instance_free (gpointer ptr)
+{
+ Instance *ins = ptr;
+
+ if (ins) {
+ g_clear_object (&ins->start);
+ g_clear_object (&ins->end);
+ g_clear_object (&ins->icomp);
+ g_free (ins);
+ }
+}
+
+static guint
+instance_hash (gconstpointer ptr)
+{
+ /* Place everything into a single basket */
+ return 0;
+}
+
+static gboolean
+instance_equal (gconstpointer ptr1,
+ gconstpointer ptr2)
+{
+ Instance *ins1 = (Instance *) ptr1;
+ Instance *ins2 = (Instance *) ptr2;
+
+ if (!ins1 || !ins2)
+ return ins1 == ins2;
+
+ return i_cal_time_compare (ins1->start, ins2->start) == 0;
+}
+
+static void
+verify_received_instances (GHashTable *instances,
+ ICalTimezone *comp_zone)
+{
+ const gchar *expected_times[] = {
+ "20190107T080000",
+ "20190108T080000",
+ "20190109T080000",
+ "20190110T080000",
+ "20190111T080000"
+ };
+ gint ii;
+
+ g_assert_nonnull (instances);
+
+ for (ii = 0; ii < G_N_ELEMENTS (expected_times); ii++) {
+ ICalTime *expected_start;
+ Instance ins = { 0, };
+
+ expected_start = i_cal_time_from_string (expected_times[ii]);
+ g_assert_nonnull (expected_start);
+
+ ins.start = expected_start;
+ g_assert (g_hash_table_remove (instances, &ins));
+
+ g_object_unref (expected_start);
+ }
+
+ g_assert_cmpint (g_hash_table_size (instances), ==, 0);
+}
+
+typedef struct _RecurData {
+ GHashTable *instances;
+} RecurData;
+
+static gboolean
+recur_instance_cb (ICalComponent *icomp,
+ ICalTime *instance_start,
+ ICalTime *instance_end,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ RecurData *rd = user_data;
+ Instance *ins;
+ gsize pre;
+
+ g_assert_nonnull (rd);
+
+ ins = instance_new (instance_start, instance_end, icomp);
+
+ pre = g_hash_table_size (rd->instances);
+ g_hash_table_insert (rd->instances, ins, NULL);
+
+ g_assert_cmpint (pre + 1, ==, g_hash_table_size (rd->instances));
+
+ return TRUE;
+}
+
+static void
+test_recur_plain_run (ECalClient *client,
+ const gchar *default_tz,
+ const gchar *comp_tz)
+{
+ ICalTimezone *default_zone, *comp_zone;
+ ICalComponent *icomp;
+ ICalTime *start, *end;
+ RecurData rd;
+ gboolean success;
+ GError *error = NULL;
+
+ default_zone = default_tz ? i_cal_timezone_get_builtin_timezone (default_tz) : NULL;
+ if (default_tz)
+ g_assert_nonnull (default_zone);
+
+ comp_zone = comp_tz ? i_cal_timezone_get_builtin_timezone (comp_tz) : NULL;
+ if (comp_tz)
+ g_assert_nonnull (comp_zone);
+
+ icomp = create_component (comp_tz);
+ start = i_cal_time_from_string ("20190103T080000Z");
+ end = i_cal_time_from_string ("20190115T080000Z");
+
+ rd.instances = g_hash_table_new_full (instance_hash, instance_equal, instance_free, NULL);
+
+ success = e_cal_recur_generate_instances_sync (icomp, start, end,
+ recur_instance_cb, &rd,
+ e_cal_client_tzlookup_cb, client,
+ default_zone, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ g_assert_cmpint (g_hash_table_size (rd.instances), ==, 5);
+
+ verify_received_instances (rd.instances, comp_zone);
+
+ g_hash_table_destroy (rd.instances);
+ g_clear_object (&icomp);
+ g_clear_object (&start);
+ g_clear_object (&end);
+}
+
+static void
+test_recur_client_run (ECalClient *client,
+ const gchar *default_tz,
+ const gchar *comp_tz)
+{
+ ICalTimezone *default_zone, *comp_zone;
+ ICalTime *start, *end;
+ ICalComponent *icomp;
+ RecurData rd;
+
+ default_zone = default_tz ? i_cal_timezone_get_builtin_timezone (default_tz) : NULL;
+ if (default_tz)
+ g_assert_nonnull (default_zone);
+
+ comp_zone = comp_tz ? i_cal_timezone_get_builtin_timezone (comp_tz) : NULL;
+ if (comp_tz)
+ g_assert_nonnull (comp_zone);
+
+ e_cal_client_set_default_timezone (client, default_zone);
+ setup_cal (client, comp_tz);
+
+ start = i_cal_time_from_string ("20190103T080000Z");
+ end = i_cal_time_from_string ("20190115T080000Z");
+
+ rd.instances = g_hash_table_new_full (instance_hash, instance_equal, instance_free, NULL);
+
+ e_cal_client_generate_instances_sync (client,
+ i_cal_time_as_timet (start),
+ i_cal_time_as_timet (end),
+ NULL, /* GCancellable * */
+ recur_instance_cb, &rd);
+
+ g_assert_cmpint (g_hash_table_size (rd.instances), ==, 5);
+
+ verify_received_instances (rd.instances, comp_zone);
+
+ g_hash_table_destroy (rd.instances);
+
+ icomp = create_component (comp_tz);
+ rd.instances = g_hash_table_new_full (instance_hash, instance_equal, instance_free, NULL);
+
+ e_cal_client_generate_instances_for_object_sync (client,
+ icomp,
+ i_cal_time_as_timet (start),
+ i_cal_time_as_timet (end),
+ NULL, /* GCancellable * */
+ recur_instance_cb, &rd);
+
+ g_assert_cmpint (g_hash_table_size (rd.instances), ==, 5);
+
+ verify_received_instances (rd.instances, comp_zone);
+
+ g_hash_table_destroy (rd.instances);
+ g_clear_object (&icomp);
+ g_clear_object (&start);
+ g_clear_object (&end);
+}
+
+static const gchar *timezones[] = {
+ NULL, /* floating time */
+ "Pacific/Midway", /* UTC-11 */
+ "Pacific/Honolulu", /* UTC-10 */
+ "America/Adak", /* UTC-9 */
+ "America/Yakutat", /* UTC-8 */
+ "America/Vancouver", /* UTC-7 */
+ "America/Boise", /* UTC-6 */
+ "America/Cancun", /* UTC-5 */
+ "America/New_York", /* UTC-4 */
+ "Atlantic/Bermuda", /* UTC-3 */
+ "America/Noronha", /* UTC-2 */
+ "Atlantic/Cape_Verde", /* UTC-1 */
+ "Atlantic/Azores", /* UTC */
+ "UTC", /* UTC */
+ "Africa/Casablanca", /* UTC+1 */
+ "Europe/Malta", /* UTC+2 */
+ "Europe/Athens", /* UTC+3 */
+ "Asia/Baku", /* UTC+4 */
+ "Asia/Qyzylorda", /* UTC+5 */
+ "Asia/Urumqi", /* UTC+6 */
+ "Asia/Hovd", /* UTC+7 */
+ "Asia/Irkutsk", /* UTC+8 */
+ "Asia/Seoul", /* UTC+9 */
+ "Asia/Vladivostok", /* UTC+10 */
+ "Asia/Sakhalin", /* UTC+11 */
+ "Asia/Kamchatka", /* UTC+12 */
+ "Pacific/Enderbury", /* UTC+13 */
+ "Pacific/Kiritimati" /* UTC+14 */
+};
+
+static void
+test_recur_plain (ETestServerFixture *fixture,
+ gconstpointer user_data)
+{
+ ECalClient *cal;
+ gint deftz_ii, comptz_ii;
+
+ cal = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
+
+ for (deftz_ii = 0; deftz_ii < G_N_ELEMENTS (timezones); deftz_ii++) {
+ for (comptz_ii = 0; comptz_ii < G_N_ELEMENTS (timezones); comptz_ii++) {
+ test_recur_plain_run (cal, timezones[deftz_ii], timezones[comptz_ii]);
+ }
+ }
+}
+
+static void
+test_recur_client (ETestServerFixture *fixture,
+ gconstpointer user_data)
+{
+ ECalClient *cal;
+ gint deftz_ii, comptz_ii;
+
+ cal = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient);
+
+ for (deftz_ii = 0; deftz_ii < G_N_ELEMENTS (timezones); deftz_ii++) {
+ for (comptz_ii = 0; comptz_ii < G_N_ELEMENTS (timezones); comptz_ii++) {
+ /* Skip the floating time for the client's default timezone */
+ if (timezones[deftz_ii])
+ test_recur_client_run (cal, timezones[deftz_ii], timezones[comptz_ii]);
+ }
+ }
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("http://bugzilla.gnome.org/");
+
+ g_test_add (
+ "/ECalRecur/Plain",
+ ETestServerFixture,
+ &test_closure,
+ e_test_server_utils_setup,
+ test_recur_plain,
+ e_test_server_utils_teardown);
+ g_test_add (
+ "/ECalRecur/Client",
+ ETestServerFixture,
+ &test_closure,
+ e_test_server_utils_setup,
+ test_recur_client,
+ e_test_server_utils_teardown);
+
+ return e_test_server_utils_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]