[evolution-data-server/wip/mcrha/libical-glib] Add ECalComponent unit tests



commit 72896e91f0ab5959bbab8d98fbb7719be187f0ed
Author: Milan Crha <mcrha redhat com>
Date:   Fri Feb 1 14:12:26 2019 +0100

    Add ECalComponent unit tests

 tests/libecal/CMakeLists.txt       |    1 +
 tests/libecal/test-cal-component.c | 3399 ++++++++++++++++++++++++++++++++++++
 2 files changed, 3400 insertions(+)
---
diff --git a/tests/libecal/CMakeLists.txt b/tests/libecal/CMakeLists.txt
index b580028e0..8d69e5924 100644
--- a/tests/libecal/CMakeLists.txt
+++ b/tests/libecal/CMakeLists.txt
@@ -32,6 +32,7 @@ set(TESTS
        test-cal-client-revision-view
        test-cal-client-get-revision
        test-cal-client-get-free-busy
+       test-cal-component
 )
 
 foreach(_test ${TESTS})
diff --git a/tests/libecal/test-cal-component.c b/tests/libecal/test-cal-component.c
new file mode 100644
index 000000000..eeb5385a3
--- /dev/null
+++ b/tests/libecal/test-cal-component.c
@@ -0,0 +1,3399 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
+ *
+ * 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 "evolution-data-server-config.h"
+
+#include <glib.h>
+#include <libecal/libecal.h>
+
+static void
+verify_ical_attach_equal (ICalAttach *expected,
+                         ICalAttach *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+       g_assert_cmpint (i_cal_attach_get_is_url (expected) ? 1 : 0, ==, i_cal_attach_get_is_url (received) ? 
1 : 0);
+
+       if (i_cal_attach_get_is_url (expected)) {
+               g_assert_cmpstr (i_cal_attach_get_url (expected), ==, i_cal_attach_get_url (received));
+       } else {
+               const gchar *data_expected, *data_received;
+
+               data_expected = i_cal_attach_get_data (expected);
+               data_received = i_cal_attach_get_data (received);
+
+               g_assert_nonnull (data_expected);
+               g_assert_nonnull (data_received);
+               g_assert_cmpmem (data_expected, strlen (data_expected), data_received, strlen 
(data_received));
+       }
+}
+
+static void
+verify_ical_attach_list_equal (GSList *expected, /* ICalAttach * */
+                              GSList *received) /* ICalAttach * */
+{
+       GSList *link1, *link2;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+       g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+       for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 = 
g_slist_next (link2)) {
+               verify_ical_attach_equal (link1->data, link2->data);
+       }
+
+       g_assert (link1 == link2);
+}
+
+static void
+verify_ical_durationtype_equal (ICalDurationType *expected,
+                               ICalDurationType *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (i_cal_duration_type_as_int (expected), ==, i_cal_duration_type_as_int (received));
+}
+
+static void
+verify_ical_timetype_equal (ICalTimetype *expected,
+                           ICalTimetype *received)
+{
+       ICalTimezone *zone_expected, *zone_received;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (i_cal_timetype_get_year (expected), ==, i_cal_timetype_get_year (received));
+       g_assert_cmpint (i_cal_timetype_get_month (expected), ==, i_cal_timetype_get_month (received));
+       g_assert_cmpint (i_cal_timetype_get_day (expected), ==, i_cal_timetype_get_day (received));
+       g_assert_cmpint (i_cal_timetype_get_hour (expected), ==, i_cal_timetype_get_hour (received));
+       g_assert_cmpint (i_cal_timetype_get_minute (expected), ==, i_cal_timetype_get_minute (received));
+       g_assert_cmpint (i_cal_timetype_get_second (expected), ==, i_cal_timetype_get_second (received));
+       g_assert_cmpint (i_cal_timetype_get_is_date (expected) ? 1 : 0, ==, i_cal_timetype_get_is_date 
(received) ? 1 : 0);
+       g_assert_cmpint (i_cal_timetype_get_is_daylight (expected) ? 1 : 0, ==, 
i_cal_timetype_get_is_daylight (received) ? 1 : 0);
+
+       zone_expected = i_cal_timetype_get_zone (expected);
+       zone_received = i_cal_timetype_get_zone (received);
+
+       if (!zone_expected) {
+               g_assert_null (zone_received);
+       } else if (zone_received) {
+               g_assert_cmpstr (i_cal_timezone_get_location (zone_expected), ==, i_cal_timezone_get_location 
(zone_received));
+       }
+}
+
+static void
+verify_struct_attendee_equal (const ECalComponentAttendee *expected,
+                             const ECalComponentAttendee *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_attendee_get_value (expected), ==, 
e_cal_component_attendee_get_value (received));
+       g_assert_cmpstr (e_cal_component_attendee_get_member (expected), ==, 
e_cal_component_attendee_get_member (received));
+       g_assert_cmpint (e_cal_component_attendee_get_cutype (expected), ==, 
e_cal_component_attendee_get_cutype (received));
+       g_assert_cmpint (e_cal_component_attendee_get_role (expected), ==, e_cal_component_attendee_get_role 
(received));
+       g_assert_cmpint (e_cal_component_attendee_get_partstat (expected), ==, 
e_cal_component_attendee_get_partstat (received));
+       g_assert_cmpint (e_cal_component_attendee_get_rsvp (expected) ? 1 : 0, ==, 
e_cal_component_attendee_get_rsvp (received) ? 1 : 0);
+       g_assert_cmpstr (e_cal_component_attendee_get_delegatedfrom (expected), ==, 
e_cal_component_attendee_get_delegatedfrom (received));
+       g_assert_cmpstr (e_cal_component_attendee_get_delegatedto (expected), ==, 
e_cal_component_attendee_get_delegatedto (received));
+       g_assert_cmpstr (e_cal_component_attendee_get_sentby (expected), ==, 
e_cal_component_attendee_get_sentby (received));
+       g_assert_cmpstr (e_cal_component_attendee_get_cn (expected), ==, e_cal_component_attendee_get_cn 
(received));
+       g_assert_cmpstr (e_cal_component_attendee_get_language (expected), ==, 
e_cal_component_attendee_get_language (received));
+}
+
+static void
+verify_struct_attendee_list_equal (GSList *expected, /* ECalComponentAttendee * */
+                                  GSList *received) /* ECalComponentAttendee * */
+{
+       GSList *link1, *link2;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+       g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+       for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 = 
g_slist_next (link2)) {
+               verify_struct_attendee_equal (link1->data, link2->data);
+       }
+
+       g_assert (link1 == link2);
+}
+
+static void
+verify_struct_datetime_equal (const ECalComponentDateTime *expected,
+                             const ECalComponentDateTime *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       verify_ical_timetype_equal (e_cal_component_datetime_get_value (expected),
+                                   e_cal_component_datetime_get_value (received));
+
+       g_assert_cmpstr (e_cal_component_datetime_get_tzid (expected), ==, e_cal_component_datetime_get_tzid 
(received));
+}
+
+static void
+verify_struct_id_equal (const ECalComponentId *expected,
+                       const ECalComponentId *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_id_get_uid (expected), ==, e_cal_component_id_get_uid (received));
+       g_assert_cmpstr (e_cal_component_id_get_rid (expected), ==, e_cal_component_id_get_rid (received));
+       g_assert_cmpint (e_cal_component_id_hash (expected), ==, e_cal_component_id_hash (received));
+       g_assert (e_cal_component_id_equal (expected, received));
+}
+
+static void
+verify_struct_organizer_equal (const ECalComponentOrganizer *expected,
+                              const ECalComponentOrganizer *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_organizer_get_value (expected), ==, 
e_cal_component_organizer_get_value (received));
+       g_assert_cmpstr (e_cal_component_organizer_get_sentby (expected), ==, 
e_cal_component_organizer_get_sentby (received));
+       g_assert_cmpstr (e_cal_component_organizer_get_cn (expected), ==, e_cal_component_organizer_get_cn 
(received));
+       g_assert_cmpstr (e_cal_component_organizer_get_language (expected), ==, 
e_cal_component_organizer_get_language (received));
+}
+
+static void
+verify_struct_period_equal (const ECalComponentPeriod *expected,
+                           const ECalComponentPeriod *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_period_get_kind (expected), ==, e_cal_component_period_get_kind 
(received));
+
+       verify_ical_timetype_equal (e_cal_component_period_get_start (expected),
+                                   e_cal_component_period_get_start (received));
+
+       switch (e_cal_component_period_get_kind (expected)) {
+       case E_CAL_COMPONENT_PERIOD_DATETIME:
+               verify_ical_timetype_equal (e_cal_component_period_get_end (expected),
+                                           e_cal_component_period_get_end (received));
+               break;
+       case E_CAL_COMPONENT_PERIOD_DURATION:
+               verify_ical_durationtype_equal (e_cal_component_period_get_duration (expected),
+                                               e_cal_component_period_get_duration (received));
+               break;
+       }
+}
+
+static void
+verify_struct_range_equal (const ECalComponentRange *expected,
+                          const ECalComponentRange *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_range_get_kind (expected), ==, e_cal_component_range_get_kind 
(received));
+
+       verify_struct_datetime_equal (e_cal_component_range_get_datetime (expected),
+                                     e_cal_component_range_get_datetime (received));
+}
+
+static void
+verify_struct_text_equal (const ECalComponentText *expected,
+                         const ECalComponentText *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_text_get_value (expected), ==, e_cal_component_text_get_value 
(received));
+       g_assert_cmpstr (e_cal_component_text_get_altrep (expected), ==, e_cal_component_text_get_altrep 
(received));
+}
+
+static void
+verify_struct_alarm_repeat_equal (const ECalComponentAlarmRepeat *expected,
+                                 const ECalComponentAlarmRepeat *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_repetitions (expected), ==, 
e_cal_component_alarm_repeat_get_repetitions (received));
+       verify_ical_durationtype_equal (e_cal_component_alarm_repeat_get_interval (expected),
+                                       e_cal_component_alarm_repeat_get_interval (received));
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (expected), ==, 
e_cal_component_alarm_repeat_get_interval_seconds (received));
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (expected), ==,
+                        i_cal_duration_type_as_int (e_cal_component_alarm_repeat_get_interval (expected)));
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (received), ==,
+                        i_cal_duration_type_as_int (e_cal_component_alarm_repeat_get_interval (received)));
+       g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (expected), ==,
+                        i_cal_duration_type_as_int (e_cal_component_alarm_repeat_get_interval (received)));
+}
+
+static void
+verify_struct_alarm_trigger_equal (const ECalComponentAlarmTrigger *expected,
+                                  const ECalComponentAlarmTrigger *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpint (e_cal_component_alarm_trigger_get_kind (expected), ==, 
e_cal_component_alarm_trigger_get_kind (received));
+
+       switch (e_cal_component_alarm_trigger_get_kind (expected)) {
+       case E_CAL_COMPONENT_ALARM_TRIGGER_NONE:
+               break;
+       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START:
+       case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END:
+               verify_ical_durationtype_equal (e_cal_component_alarm_trigger_get_duration (expected),
+                                               e_cal_component_alarm_trigger_get_duration (received));
+               break;
+       case E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE:
+               verify_ical_timetype_equal (e_cal_component_alarm_trigger_get_absolute_time (expected),
+                                           e_cal_component_alarm_trigger_get_absolute_time (received));
+               break;
+       }
+}
+
+static void
+verify_struct_alarm_equal (const ECalComponentAlarm *expected,
+                          const ECalComponentAlarm *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_alarm_get_uid (expected), ==, e_cal_component_alarm_get_uid 
(received));
+       g_assert_cmpint (e_cal_component_alarm_get_action (expected), ==, e_cal_component_alarm_get_action 
(received));
+
+       verify_struct_text_equal (e_cal_component_alarm_get_description (expected),
+                                 e_cal_component_alarm_get_description (received));
+
+       verify_struct_alarm_repeat_equal (e_cal_component_alarm_get_repeat (expected),
+                                         e_cal_component_alarm_get_repeat (received));
+
+       verify_struct_alarm_trigger_equal (e_cal_component_alarm_get_trigger (expected),
+                                          e_cal_component_alarm_get_trigger (received));
+
+       g_assert_cmpint (e_cal_component_alarm_has_attendees (expected) ? 1 : 0, ==, 
e_cal_component_alarm_has_attendees (received) ? 1 : 0);
+
+       verify_struct_attendee_list_equal (e_cal_component_alarm_get_attendees (expected),
+                                          e_cal_component_alarm_get_attendees (received));
+
+       g_assert_cmpint (e_cal_component_alarm_has_attachments (expected) ? 1 : 0, ==, 
e_cal_component_alarm_has_attachments (received) ? 1 : 0);
+
+       verify_ical_attach_list_equal (e_cal_component_alarm_get_attachments (expected),
+                                      e_cal_component_alarm_get_attachments (received));
+}
+
+static void
+verify_struct_alarm_instance_equal (const ECalComponentAlarmInstance *expected,
+                                   const ECalComponentAlarmInstance *received)
+{
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       g_assert_cmpstr (e_cal_component_alarm_instance_get_uid (expected), ==, 
e_cal_component_alarm_instance_get_uid (received));
+       g_assert_cmpint (e_cal_component_alarm_instance_get_time (expected), ==, 
e_cal_component_alarm_instance_get_time (received));
+       g_assert_cmpint (e_cal_component_alarm_instance_get_occur_start (expected), ==, 
e_cal_component_alarm_instance_get_occur_start (received));
+       g_assert_cmpint (e_cal_component_alarm_instance_get_occur_end (expected), ==, 
e_cal_component_alarm_instance_get_occur_end (received));
+}
+
+static void
+verify_struct_alarms_equal (const ECalComponentAlarms *expected,
+                           const ECalComponentAlarms *received)
+{
+       GSList *inst_expected, *inst_received, *link1, *link2;
+       const gchar *uid_expected, *uid_received;
+       gchar *rid_expected, *rid_received;
+
+       if (!expected) {
+               g_assert_null (received);
+               return;
+       }
+
+       g_assert_nonnull (received);
+
+       uid_expected = e_cal_component_get_uid (e_cal_component_alarms_get_component (expected));
+       uid_received = e_cal_component_get_uid (e_cal_component_alarms_get_component (received));
+       g_assert_cmpstr (uid_expected, ==, uid_received);
+
+       rid_expected = e_cal_component_get_recurid_as_string (e_cal_component_alarms_get_component 
(expected));
+       rid_received = e_cal_component_get_recurid_as_string (e_cal_component_alarms_get_component 
(received));
+       g_assert_cmpstr (rid_expected, ==, rid_received);
+       g_free (rid_expected);
+       g_free (rid_received);
+
+       inst_expected = e_cal_component_alarms_get_instances (expected);
+       inst_received = e_cal_component_alarms_get_instances (received);
+
+       g_assert_cmpint (g_slist_length (inst_expected), ==, g_slist_length (inst_received));
+
+       for (link1 = inst_expected, link2 = inst_received; link1 && link2; link1 = g_slist_next (link1), 
link2 = g_slist_next (link2)) {
+               verify_struct_alarm_instance_equal (link1->data, link2->data);
+       }
+
+       g_assert (link1 == link2);
+}
+
+static void
+test_component_struct_alarm (void)
+{
+       struct _values {
+               const gchar *uid;
+               ECalComponentAlarmAction action;
+               const gchar *description;
+               gboolean with_repeat;
+               gboolean with_trigger;
+               gboolean with_attendees;
+               gboolean with_attachments;
+       } values[] = {
+               { "1", E_CAL_COMPONENT_ALARM_AUDIO, NULL, FALSE, FALSE, FALSE, FALSE },
+               { "2", E_CAL_COMPONENT_ALARM_DISPLAY, "display text", FALSE, FALSE, FALSE, FALSE },
+               { "3", E_CAL_COMPONENT_ALARM_EMAIL, NULL, TRUE, FALSE, FALSE, FALSE },
+               { "4", E_CAL_COMPONENT_ALARM_PROCEDURE, "procedure", FALSE, TRUE, FALSE, FALSE },
+               { "5", E_CAL_COMPONENT_ALARM_AUDIO, NULL, FALSE, FALSE, TRUE, FALSE },
+               { "6", E_CAL_COMPONENT_ALARM_DISPLAY, "display text", FALSE, FALSE, FALSE, TRUE },
+               { "7", E_CAL_COMPONENT_ALARM_EMAIL, NULL, TRUE, FALSE, TRUE, FALSE },
+               { "8", E_CAL_COMPONENT_ALARM_PROCEDURE, "procedure", TRUE, TRUE, TRUE, TRUE }
+       };
+       gint ii, nth_description = 0, nth_repeat = 0, nth_trigger = 0, nth_attendees = 0, nth_attachments = 0;
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentAlarm *expected, *received;
+               ICalComponent *icalcomp;
+
+               expected = e_cal_component_alarm_new ();
+               e_cal_component_alarm_set_uid (expected, values[ii].uid);
+               e_cal_component_alarm_set_action (expected, values[ii].action);
+
+               if (values[ii].description) {
+                       nth_description++;
+
+                       if ((nth_description & 1) != 0) {
+                               ECalComponentText *txt;
+
+                               txt = e_cal_component_text_new (values[ii].description, "alt-representation");
+                               e_cal_component_alarm_set_description (expected, txt);
+                               e_cal_component_text_free (txt);
+                       } else {
+                               e_cal_component_alarm_take_description (expected, e_cal_component_text_new 
(values[ii].description, NULL));
+                       }
+               }
+
+               if (values[ii].with_repeat) {
+                       nth_repeat++;
+
+                       if ((nth_repeat & 1) != 0) {
+                               ECalComponentAlarmRepeat *rpt;
+
+                               rpt = e_cal_component_alarm_repeat_new_seconds (3, 6);
+                               e_cal_component_alarm_set_repeat (expected, rpt);
+                               e_cal_component_alarm_repeat_free (rpt);
+                       } else {
+                               e_cal_component_alarm_take_repeat (expected, 
e_cal_component_alarm_repeat_new_seconds (9, 12));
+                       }
+               }
+
+               if (values[ii].with_trigger) {
+                       nth_trigger++;
+
+                       if ((nth_trigger & 1) != 0) {
+                               ECalComponentAlarmTrigger *trg;
+                               ICalTimetype *tt;
+
+                               tt = i_cal_time_from_string ("20201030T102030");
+                               g_assert_nonnull (tt);
+
+                               trg = e_cal_component_alarm_trigger_new_absolute (tt);
+                               e_cal_component_alarm_set_trigger (expected, trg);
+                               e_cal_component_alarm_trigger_free (trg);
+                               g_object_unref (tt);
+                       } else {
+                               ICalTimetype *tt;
+
+                               tt = i_cal_time_from_string ("21211129T122233");
+                               g_assert_nonnull (tt);
+
+                               e_cal_component_alarm_take_trigger (expected, 
e_cal_component_alarm_trigger_new_absolute (tt));
+
+                               g_object_unref (tt);
+                       }
+               }
+
+               if (values[ii].with_attendees) {
+                       GSList *attendees = NULL;
+                       gint jj;
+
+                       nth_attendees++;
+
+                       for (jj = 0; jj < nth_attendees; jj++) {
+                               ECalComponentAttendee *att;
+                               gchar *value;
+
+                               value = g_strdup_printf ("MAILTO:attendee-%d", jj);
+
+                               att = e_cal_component_attendee_new ();
+                               e_cal_component_attendee_set_value (att, value);
+                               g_free (value);
+
+                               attendees = g_slist_prepend (attendees, att);
+                       }
+
+                       if ((nth_attendees & 1) != 0) {
+                               e_cal_component_alarm_set_attendees (expected, attendees);
+                               g_slist_free_full (attendees, e_cal_component_attendee_free);
+                       } else {
+                               e_cal_component_alarm_take_attendees (expected, attendees);
+                       }
+               }
+
+               if (values[ii].with_attachments) {
+                       GSList *attachments = NULL;
+                       gint jj;
+
+                       nth_attachments++;
+
+                       for (jj = 0; jj < nth_attachments; jj++) {
+                               ICalAttach *attach;
+                               gchar *value;
+
+                               if ((jj & 1) != 0) {
+                                       value = g_strdup_printf ("https://www.no.where/link%d";, jj);
+                                       attach = i_cal_attach_new_from_url (value);
+                               } else {
+                                       value = g_strdup_printf ("Content*%d", jj);
+                                       attach = i_cal_attach_new_from_data (value, NULL, NULL);
+                               }
+
+                               g_free (value);
+
+                               g_assert_nonnull (attach);
+
+                               attachments = g_slist_prepend (attachments, attach);
+                       }
+
+                       if ((nth_attachments & 1) != 0) {
+                               e_cal_component_alarm_set_attachments (expected, attachments);
+                               g_slist_free_full (attachments, g_object_unref);
+                       } else {
+                               e_cal_component_alarm_take_attachments (expected, attachments);
+                       }
+               }
+
+               received = e_cal_component_alarm_copy (expected);
+               verify_struct_alarm_equal (expected, received);
+               e_cal_component_alarm_free (received);
+
+               icalcomp = e_cal_component_alarm_get_as_component (expected);
+               g_assert_nonnull (icalcomp);
+               received = e_cal_component_alarm_new_from_component (icalcomp);
+               verify_struct_alarm_equal (expected, received);
+               e_cal_component_alarm_free (received);
+               g_object_unref (icalcomp);
+
+               icalcomp = i_cal_component_new_valarm ();
+               g_assert_nonnull (icalcomp);
+               e_cal_component_alarm_fill_component (expected, icalcomp);
+               received = e_cal_component_alarm_new ();
+               e_cal_component_alarm_set_from_component (received, icalcomp);
+               g_object_unref (icalcomp);
+               verify_struct_alarm_equal (expected, received);
+               e_cal_component_alarm_free (received);
+
+               e_cal_component_alarm_free (expected);
+       }
+
+       g_assert_cmpint (nth_description, >, 1);
+       g_assert_cmpint (nth_repeat, >, 1);
+       g_assert_cmpint (nth_trigger, >, 1);
+       g_assert_cmpint (nth_attendees, >, 1);
+       g_assert_cmpint (nth_attachments, >, 1);
+}
+
+static void
+test_component_struct_alarms (void)
+{
+       ECalComponent *comp;
+       ECalComponentAlarms *expected, *received;
+       ECalComponentAlarmInstance *instance;
+       GSList *instances = NULL;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       e_cal_component_set_uid (comp, "123");
+
+       expected = e_cal_component_alarms_new (comp);
+       g_assert_nonnull (e_cal_component_alarms_get_component (expected));
+       g_assert_cmpstr ("123", ==, e_cal_component_get_uid (e_cal_component_alarms_get_component 
(expected)));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       instance = e_cal_component_alarm_instance_new ("1", (time_t) 1, (time_t) 2, (time_t) 3);
+       e_cal_component_alarms_add_instance (expected, instance);
+
+       g_assert_cmpint (1, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+       verify_struct_alarm_instance_equal (instance, e_cal_component_alarms_get_instances (expected)->data);
+       e_cal_component_alarm_instance_free (instance);
+
+       g_object_unref (comp);
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       instance = e_cal_component_alarm_instance_new ("2", (time_t) 2, (time_t) 3, (time_t) 4);
+       e_cal_component_alarms_take_instance (expected, instance);
+       g_assert_cmpint (2, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       g_assert (!e_cal_component_alarms_remove_instance (expected, GINT_TO_POINTER (123)));
+       g_assert (e_cal_component_alarms_remove_instance (expected, instance));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       e_cal_component_alarms_set_instances (expected, NULL);
+       g_assert_cmpint (0, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       instances = NULL;
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("3", (time_t) 3, (time_t) 
4, (time_t) 5));
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("4", (time_t) 4, (time_t) 
5, (time_t) 6));
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("5", (time_t) 5, (time_t) 
6, (time_t) 7));
+
+       e_cal_component_alarms_set_instances (expected, instances);
+       g_assert_cmpint (3, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+       g_slist_free_full (instances, e_cal_component_alarm_instance_free);
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       instances = NULL;
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("6", (time_t) 6, (time_t) 
7, (time_t) 8));
+       instances = g_slist_prepend (instances, e_cal_component_alarm_instance_new ("7", (time_t) 7, (time_t) 
8, (time_t) 9));
+
+       e_cal_component_alarms_take_instances (expected, instances);
+       g_assert_cmpint (2, ==, g_slist_length (e_cal_component_alarms_get_instances (expected)));
+
+       received = e_cal_component_alarms_copy (expected);
+       verify_struct_alarms_equal (expected, received);
+       e_cal_component_alarms_free (received);
+
+       e_cal_component_alarms_free (expected);
+}
+
+static void
+test_component_struct_alarm_instance (void)
+{
+       struct _values {
+               const gchar *uid;
+               gint instance_time;
+               gint occur_start;
+               gint occur_end;
+       } values[] = {
+               { "1", 1, 2, 3 },
+               { "2", 2, 3, 4 },
+               { "3", 3, 4, 6 },
+               { "4", 4, 5, 6 },
+               { "5", 5, 6, 7 }
+       };
+       gint ii;
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentAlarmInstance *expected, *received;
+
+               if ((ii & 1) != 0) {
+                       expected = e_cal_component_alarm_instance_new (values[ii].uid,
+                                                                      (time_t) values[ii].instance_time,
+                                                                      (time_t) values[ii].occur_start,
+                                                                      (time_t) values[ii].occur_end);
+               } else {
+                       expected = e_cal_component_alarm_instance_new ("X", (time_t) 100, (time_t) 200, 
(time_t) 300);
+                       e_cal_component_alarm_instance_set_uid (expected, values[ii].uid);
+                       e_cal_component_alarm_instance_set_time (expected, (time_t) values[ii].instance_time);
+                       e_cal_component_alarm_instance_set_occur_start (expected, (time_t) 
values[ii].occur_start);
+                       e_cal_component_alarm_instance_set_occur_end (expected, (time_t) 
values[ii].occur_end);
+               }
+
+               g_assert_nonnull (expected);
+
+               g_assert_cmpstr (e_cal_component_alarm_instance_get_uid (expected), ==, values[ii].uid);
+               g_assert_cmpint (e_cal_component_alarm_instance_get_time (expected), ==, (time_t) 
values[ii].instance_time);
+               g_assert_cmpint (e_cal_component_alarm_instance_get_occur_start (expected), ==, (time_t) 
values[ii].occur_start);
+               g_assert_cmpint (e_cal_component_alarm_instance_get_occur_end (expected), ==, (time_t) 
values[ii].occur_end);
+
+               received = e_cal_component_alarm_instance_copy (expected);
+               verify_struct_alarm_instance_equal (expected, received);
+               e_cal_component_alarm_instance_free (received);
+
+               e_cal_component_alarm_instance_free (expected);
+       }
+
+       g_assert_cmpint (ii, >, 1);
+}
+
+static void
+test_component_struct_alarm_repeat (void)
+{
+       struct _values {
+               gint repetitions;
+               gint interval;
+       } values[] = {
+               { 10, 20 },
+               { 30, 40 },
+               { 50, 60 },
+               { 70, 80 },
+               { 90, 55 }
+       };
+       gint ii;
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentAlarmRepeat *expected, *received;
+               ICalDurationType *dur;
+
+               if ((ii % 4) == 0) {
+                       dur = i_cal_duration_type_from_int (values[ii].interval);
+                       expected = e_cal_component_alarm_repeat_new (values[ii].repetitions, dur);
+                       g_object_unref (dur);
+               } else if ((ii % 4) == 1) {
+                       expected = e_cal_component_alarm_repeat_new_seconds (values[ii].repetitions, 
values[ii].interval);
+               } else if ((ii % 4) == 2) {
+                       expected = e_cal_component_alarm_repeat_new_seconds (1000, 2000);
+                       e_cal_component_alarm_repeat_set_repetitions (expected, values[ii].repetitions);
+                       e_cal_component_alarm_repeat_set_interval_seconds (expected, values[ii].interval);
+               } else {
+                       dur = i_cal_duration_type_from_int (values[ii].interval);
+
+                       expected = e_cal_component_alarm_repeat_new_seconds (1000, 2000);
+                       e_cal_component_alarm_repeat_set_repetitions (expected, values[ii].repetitions);
+                       e_cal_component_alarm_repeat_set_interval (expected, dur);
+
+                       g_object_unref (dur);
+               }
+
+               g_assert_nonnull (expected);
+
+               dur = i_cal_duration_type_from_int (values[ii].interval);
+               g_assert_nonnull (dur);
+               g_assert_cmpint (e_cal_component_alarm_repeat_get_repetitions (expected), ==, 
values[ii].repetitions);
+               g_assert_cmpint (e_cal_component_alarm_repeat_get_interval_seconds (expected), ==, 
values[ii].interval);
+               verify_ical_durationtype_equal (dur, e_cal_component_alarm_repeat_get_interval (expected));
+               g_object_unref (dur);
+
+               received = e_cal_component_alarm_repeat_copy (expected);
+               verify_struct_alarm_repeat_equal (expected, received);
+               e_cal_component_alarm_repeat_free (received);
+
+               e_cal_component_alarm_repeat_free (expected);
+       }
+
+       g_assert_cmpint (ii, >, 4);
+}
+
+static void
+test_component_struct_alarm_trigger (void)
+{
+       struct _values {
+               ECalComponentAlarmTriggerKind kind;
+               gint duration;
+               const gchar *abs_time;
+       } values[] = {
+               { E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START, -100, NULL },
+               { E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE, 0, "21090807T001122Z" },
+               { E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END, 200, NULL },
+               { E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE, 0, "21090807T213243Z" }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 3; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentAlarmTrigger *expected = NULL, *received;
+                       ICalDurationType *dur;
+                       ICalTimetype *tt;
+                       ICalProperty *prop;
+
+                       if (set_kind == 0) {
+                               /* nothing, create it as it should be */
+                       } else if (set_kind == 1) {
+                               dur = i_cal_duration_type_from_int (33);
+                               expected = e_cal_component_alarm_trigger_new_relative 
(E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END, dur);
+                               g_object_unref (dur);
+
+                               g_assert_nonnull (expected);
+                       } else if (set_kind == 2) {
+                               tt = i_cal_time_today ();
+                               expected = e_cal_component_alarm_trigger_new_absolute (tt);
+                               g_object_unref (tt);
+
+                               g_assert_nonnull (expected);
+                       } else {
+                               g_assert_not_reached ();
+                       }
+
+                       if (expected) {
+                               if (values[ii].kind == e_cal_component_alarm_trigger_get_kind (expected)) {
+                                       if (values[ii].kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                                               tt = i_cal_time_from_string (values[ii].abs_time);
+                                               e_cal_component_alarm_trigger_set_absolute_time (expected, 
tt);
+                                               g_object_unref (tt);
+                                       } else {
+                                               dur = i_cal_duration_type_from_int (values[ii].duration);
+                                               e_cal_component_alarm_trigger_set_kind (expected, 
values[ii].kind);
+                                               e_cal_component_alarm_trigger_set_duration (expected, dur);
+                                               g_object_unref (dur);
+                                       }
+                               } else if (values[ii].kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                                       tt = i_cal_time_from_string (values[ii].abs_time);
+                                       e_cal_component_alarm_trigger_set_absolute (expected, tt);
+                                       g_object_unref (tt);
+                               } else {
+                                       dur = i_cal_duration_type_from_int (values[ii].duration);
+                                       e_cal_component_alarm_trigger_set_relative (expected, 
values[ii].kind, dur);
+                                       g_object_unref (dur);
+                               }
+                       } else {
+                               if (values[ii].kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                                       tt = i_cal_time_from_string (values[ii].abs_time);
+                                       expected = e_cal_component_alarm_trigger_new_absolute (tt);
+                                       g_assert_nonnull (expected);
+                                       g_assert_nonnull (e_cal_component_alarm_trigger_get_absolute_time 
(expected));
+                                       verify_ical_timetype_equal (tt, 
e_cal_component_alarm_trigger_get_absolute_time (expected));
+                                       g_object_unref (tt);
+                               } else {
+                                       dur = i_cal_duration_type_from_int (values[ii].duration);
+                                       expected = e_cal_component_alarm_trigger_new_relative 
(values[ii].kind, dur);
+                                       g_assert_nonnull (expected);
+                                       g_object_unref (dur);
+                               }
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       g_assert_cmpint (values[ii].kind, ==, e_cal_component_alarm_trigger_get_kind 
(expected));
+                       if (values[ii].kind == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
+                               tt = i_cal_time_from_string (values[ii].abs_time);
+                               g_assert_nonnull (tt);
+                               verify_ical_timetype_equal (tt, 
e_cal_component_alarm_trigger_get_absolute_time (expected));
+                               g_object_unref (tt);
+                       } else {
+                               dur = i_cal_duration_type_from_int (values[ii].duration);
+                               g_assert_nonnull (dur);
+                               verify_ical_durationtype_equal (dur, 
e_cal_component_alarm_trigger_get_duration (expected));
+                               g_object_unref (dur);
+                       }
+
+                       received = e_cal_component_alarm_trigger_copy (expected);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+
+                       prop = e_cal_component_alarm_trigger_get_as_property (expected);
+                       g_assert_nonnull (prop);
+
+                       received = e_cal_component_alarm_trigger_new_from_property (prop);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+
+                       dur = i_cal_duration_type_from_int (33);
+                       received = e_cal_component_alarm_trigger_new_relative 
(E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END, dur);
+                       g_object_unref (dur);
+                       e_cal_component_alarm_trigger_set_from_property (received, prop);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+
+                       tt = i_cal_time_today ();
+                       received = e_cal_component_alarm_trigger_new_absolute (tt);
+                       g_object_unref (tt);
+                       e_cal_component_alarm_trigger_set_from_property (received, prop);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+
+                       g_object_unref (prop);
+
+                       prop = i_cal_property_new (I_CAL_TRIGGER_PROPERTY);
+                       e_cal_component_alarm_trigger_fill_property (expected, prop);
+                       received = e_cal_component_alarm_trigger_new_from_property (prop);
+                       verify_struct_alarm_trigger_equal (expected, received);
+                       e_cal_component_alarm_trigger_free (received);
+                       g_object_unref (prop);
+
+                       e_cal_component_alarm_trigger_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_attendee (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *member;
+               ICalParameterCutype cutype;
+               ICalParameterRole role;
+               ICalParameterPartstat partstat;
+               gboolean rsvp;
+               const gchar *delegatedfrom;
+               const gchar *delegatedto;
+               const gchar *sentby;
+               const gchar *cn;
+               const gchar *language;
+       } values[] = {
+               { "MAILTO:att1",
+                  "member",
+                  I_CAL_CUTYPE_INDIVIDUAL,
+                  I_CAL_ROLE_CHAIR,
+                  I_CAL_PARTSTAT_NEEDSACTION,
+                  FALSE,
+                  "MAILTO:delgfrom",
+                  "MAILTO:delgto",
+                  "MAILTO:sentby",
+                  "First attendee",
+                  "en_US" },
+               { "MAILTO:room",
+                  NULL,
+                  I_CAL_CUTYPE_ROOM,
+                  I_CAL_ROLE_REQPARTICIPANT,
+                  I_CAL_PARTSTAT_ACCEPTED,
+                  FALSE,
+                  NULL,
+                  NULL,
+                  NULL,
+                  "Meeting room",
+                  NULL },
+               { "MAILTO:att2",
+                  NULL,
+                  I_CAL_CUTYPE_INDIVIDUAL,
+                  I_CAL_ROLE_REQPARTICIPANT,
+                  I_CAL_PARTSTAT_TENTATIVE,
+                  TRUE,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  "en_US" }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentAttendee *expected = NULL, *received;
+                       ICalProperty *prop;
+
+                       if (set_kind == 1) {
+                               expected = e_cal_component_attendee_new ();
+                       } else if (set_kind == 2) {
+                               expected = e_cal_component_attendee_new_full ("value", "member",
+                                       I_CAL_CUTYPE_INDIVIDUAL,
+                                       I_CAL_ROLE_CHAIR,
+                                       I_CAL_PARTSTAT_DECLINED,
+                                       TRUE,
+                                       "delegatedfrom", "delegatedto",
+                                       "sentby", "cn", "language");
+                       }
+
+                       if (expected) {
+                               e_cal_component_attendee_set_value (expected, values[ii].value);
+                               e_cal_component_attendee_set_member (expected, values[ii].member);
+                               e_cal_component_attendee_set_cutype (expected, values[ii].cutype);
+                               e_cal_component_attendee_set_role (expected, values[ii].role);
+                               e_cal_component_attendee_set_partstat (expected, values[ii].partstat);
+                               e_cal_component_attendee_set_rsvp (expected, values[ii].rsvp);
+                               e_cal_component_attendee_set_delegatedfrom (expected, 
values[ii].delegatedfrom);
+                               e_cal_component_attendee_set_delegatedto (expected, values[ii].delegatedto);
+                               e_cal_component_attendee_set_sentby (expected, values[ii].sentby);
+                               e_cal_component_attendee_set_cn (expected, values[ii].cn);
+                               e_cal_component_attendee_set_language (expected, values[ii].language);
+                       } else {
+                               expected = e_cal_component_attendee_new_full (values[ii].value,
+                                       values[ii].member,
+                                       values[ii].cutype,
+                                       values[ii].role,
+                                       values[ii].partstat,
+                                       values[ii].rsvp,
+                                       values[ii].delegatedfrom,
+                                       values[ii].delegatedto,
+                                       values[ii].sentby,
+                                       values[ii].cn,
+                                       values[ii].language);
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       g_assert_cmpstr (e_cal_component_attendee_get_value (expected), ==, values[ii].value);
+                       g_assert_cmpstr (e_cal_component_attendee_get_member (expected), ==, 
values[ii].member);
+                       g_assert_cmpint (e_cal_component_attendee_get_cutype (expected), ==, 
values[ii].cutype);
+                       g_assert_cmpint (e_cal_component_attendee_get_role (expected), ==, values[ii].role);
+                       g_assert_cmpint (e_cal_component_attendee_get_partstat (expected), ==, 
values[ii].partstat);
+                       g_assert_cmpint (e_cal_component_attendee_get_rsvp (expected) ? 1 : 0, ==, 
values[ii].rsvp ? 1 : 0);
+                       g_assert_cmpstr (e_cal_component_attendee_get_delegatedfrom (expected), ==, 
values[ii].delegatedfrom);
+                       g_assert_cmpstr (e_cal_component_attendee_get_delegatedto (expected), ==, 
values[ii].delegatedto);
+                       g_assert_cmpstr (e_cal_component_attendee_get_sentby (expected), ==, 
values[ii].sentby);
+                       g_assert_cmpstr (e_cal_component_attendee_get_cn (expected), ==, values[ii].cn);
+                       g_assert_cmpstr (e_cal_component_attendee_get_language (expected), ==, 
values[ii].language);
+
+                       received = e_cal_component_attendee_copy (expected);
+                       verify_struct_attendee_equal (expected, received);
+                       e_cal_component_attendee_free (received);
+
+                       prop = e_cal_component_attendee_get_as_property (expected);
+                       g_assert_nonnull (prop);
+
+                       received = e_cal_component_attendee_new_from_property (prop);
+                       verify_struct_attendee_equal (expected, received);
+                       e_cal_component_attendee_free (received);
+
+                       received = e_cal_component_attendee_new_full ("value", "member",
+                               I_CAL_CUTYPE_INDIVIDUAL,
+                               I_CAL_ROLE_CHAIR,
+                               I_CAL_PARTSTAT_DECLINED,
+                               TRUE,
+                               "delegatedfrom", "delegatedto",
+                               "sentby", "cn", "language");
+                       e_cal_component_attendee_set_from_property (received, prop);
+                       verify_struct_attendee_equal (expected, received);
+                       e_cal_component_attendee_free (received);
+
+                       g_object_unref (prop);
+
+                       prop = i_cal_property_new (I_CAL_ATTENDEE_PROPERTY);
+                       e_cal_component_attendee_fill_property (expected, prop);
+                       received = e_cal_component_attendee_new_from_property (prop);
+                       verify_struct_attendee_equal (expected, received);
+                       e_cal_component_attendee_free (received);
+                       g_object_unref (prop);
+
+                       e_cal_component_attendee_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_datetime (void)
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314", "Europe/Berlin" },
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentDateTime *expected = NULL, *received;
+                       ICalTimetype *tt;
+
+                       if (set_kind == 2) {
+                               tt = i_cal_time_from_string ("19981019");
+                               expected = e_cal_component_datetime_new (tt, NULL);
+                               g_object_unref (tt);
+                       } else if (set_kind == 3) {
+                               tt = i_cal_time_from_string ("19981019");
+                               expected = e_cal_component_datetime_new_take (tt, g_strdup ("Unknown"));
+                       }
+
+                       tt = i_cal_time_from_string (values[ii].time);
+                       g_assert_nonnull (tt);
+
+                       if (expected) {
+                               if (((set_kind + ii) & 1) != 0) {
+                                       e_cal_component_datetime_set (expected, tt, values[ii].tzid);
+                               } else {
+                                       e_cal_component_datetime_set_value (expected, tt);
+                                       e_cal_component_datetime_set_tzid (expected, values[ii].tzid);
+                               }
+                       } else {
+                               if (set_kind == 0) {
+                                       expected = e_cal_component_datetime_new (tt, values[ii].tzid);
+                               } else {
+                                       ICalTimetype *ttcopy;
+
+                                       ttcopy = i_cal_timetype_new_clone (tt);
+                                       g_assert_nonnull (ttcopy);
+
+                                       expected = e_cal_component_datetime_new_take (ttcopy, g_strdup 
(values[ii].tzid));
+                               }
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       verify_ical_timetype_equal (e_cal_component_datetime_get_value (expected), tt);
+                       g_assert_cmpstr (e_cal_component_datetime_get_tzid (expected), ==, values[ii].tzid);
+
+                       g_object_unref (tt);
+
+                       received = e_cal_component_datetime_copy (expected);
+                       verify_struct_datetime_equal (expected, received);
+                       e_cal_component_datetime_free (received);
+
+                       e_cal_component_datetime_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_id (void)
+{
+       struct _values {
+               const gchar *uid;
+               const gchar *rid;
+       } values[] = {
+               { "123", "20181215T111213Z" },
+               { "222", NULL },
+               { "333", NULL },
+               { "44", "20211215T101112" }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentId *expected = NULL, *received;
+
+                       if (set_kind == 2) {
+                               expected = e_cal_component_id_new ("4567", "123");
+                       } else if (set_kind == 3) {
+                               expected = e_cal_component_id_new_take (g_strdup ("5678"), g_strdup 
("Unknown"));
+                       }
+
+                       if (expected) {
+                               e_cal_component_id_set_uid (expected, values[ii].uid);
+                               e_cal_component_id_set_rid (expected, values[ii].rid);
+                       } else {
+                               if (set_kind == 0) {
+                                       expected = e_cal_component_id_new (values[ii].uid, values[ii].rid);
+                               } else {
+                                       expected = e_cal_component_id_new_take (g_strdup (values[ii].uid), 
g_strdup (values[ii].rid));
+                               }
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       g_assert_cmpstr (e_cal_component_id_get_uid (expected), ==, values[ii].uid);
+                       g_assert_cmpstr (e_cal_component_id_get_rid (expected), ==, values[ii].rid);
+
+                       received = e_cal_component_id_copy (expected);
+                       verify_struct_id_equal (expected, received);
+                       g_assert_cmpint (e_cal_component_id_hash (expected), ==, e_cal_component_id_hash 
(received));
+                       g_assert (e_cal_component_id_equal (expected, received));
+                       e_cal_component_id_free (received);
+
+                       e_cal_component_id_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_organizer (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *sentby;
+               const gchar *cn;
+               const gchar *language;
+       } values[] = {
+               { "MAILTO:org1",
+                  "MAILTO:sentby",
+                  "First organizer",
+                  "en_US" },
+               { "MAILTO:room",
+                  NULL,
+                  "Meeting room",
+                  NULL },
+               { "MAILTO:org2",
+                  NULL,
+                  NULL,
+                  "en_US" }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentOrganizer *expected = NULL, *received;
+                       ICalProperty *prop;
+
+                       if (set_kind == 1) {
+                               expected = e_cal_component_organizer_new ();
+                       } else if (set_kind == 2) {
+                               expected = e_cal_component_organizer_new_full ("value", "sentby", "cn", 
"language");
+                       }
+
+                       if (expected) {
+                               e_cal_component_organizer_set_value (expected, values[ii].value);
+                               e_cal_component_organizer_set_sentby (expected, values[ii].sentby);
+                               e_cal_component_organizer_set_cn (expected, values[ii].cn);
+                               e_cal_component_organizer_set_language (expected, values[ii].language);
+                       } else {
+                               expected = e_cal_component_organizer_new_full (values[ii].value,
+                                       values[ii].sentby,
+                                       values[ii].cn,
+                                       values[ii].language);
+                       }
+
+                       g_assert_nonnull (expected);
+
+                       g_assert_cmpstr (e_cal_component_organizer_get_value (expected), ==, 
values[ii].value);
+                       g_assert_cmpstr (e_cal_component_organizer_get_sentby (expected), ==, 
values[ii].sentby);
+                       g_assert_cmpstr (e_cal_component_organizer_get_cn (expected), ==, values[ii].cn);
+                       g_assert_cmpstr (e_cal_component_organizer_get_language (expected), ==, 
values[ii].language);
+
+                       received = e_cal_component_organizer_copy (expected);
+                       verify_struct_organizer_equal (expected, received);
+                       e_cal_component_organizer_free (received);
+
+                       prop = e_cal_component_organizer_get_as_property (expected);
+                       g_assert_nonnull (prop);
+
+                       received = e_cal_component_organizer_new_from_property (prop);
+                       verify_struct_organizer_equal (expected, received);
+                       e_cal_component_organizer_free (received);
+
+                       received = e_cal_component_organizer_new_full ("value", "sentby", "cn", "language");
+                       e_cal_component_organizer_set_from_property (received, prop);
+                       verify_struct_organizer_equal (expected, received);
+                       e_cal_component_organizer_free (received);
+
+                       g_object_unref (prop);
+
+                       prop = i_cal_property_new (I_CAL_ORGANIZER_PROPERTY);
+                       e_cal_component_organizer_fill_property (expected, prop);
+                       received = e_cal_component_organizer_new_from_property (prop);
+                       verify_struct_organizer_equal (expected, received);
+                       e_cal_component_organizer_free (received);
+                       g_object_unref (prop);
+
+                       e_cal_component_organizer_free (expected);
+               }
+       }
+}
+
+static void
+test_component_struct_period (void)
+{
+       struct _values {
+               const gchar *start;
+               const gchar *end;
+               gint duration;
+       } values[] = {
+               { "20181215T111213Z", "20181215T121314Z", -1 },
+               { "20190131T121314Z", NULL, 10 * 24 * 60 * 60 },
+               { "20200708T010305Z", NULL, 2 * 60 * 60 },
+               { "20211215T101112", "20211215T121314", -1 },
+               { "20221110T090807", "20221110T100908", -1 },
+               { "20231009", "20241110", -1 },
+               { "20240908T070605", NULL, -1 },
+               { "20250807", NULL, -1 }
+       };
+       gint ii, set_kind, flipflop1 = 0, flipflop2 = 0;
+
+       for (set_kind = 0; set_kind < 6; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentPeriod *expected = NULL, *received;
+                       ICalTimetype *start, *end = NULL;
+                       ICalDurationType *duration = NULL;
+
+                       start = i_cal_time_from_string (values[ii].start);
+                       g_assert_nonnull (start);
+                       if (values[ii].duration == -1) {
+                               if (values[ii].end) {
+                                       end = i_cal_time_from_string (values[ii].end);
+                                       g_assert_nonnull (end);
+                               }
+                       } else {
+                               duration = i_cal_duration_type_from_int (values[ii].duration);
+                               g_assert_nonnull (duration);
+                       }
+
+                       if ((set_kind % 3) == 1) {
+                               ICalTimetype *ttstart, *ttend;
+
+                               ttstart = i_cal_time_from_string ("19981019");
+                               ttend = i_cal_time_from_string ("19981019");
+
+                               g_assert_nonnull (ttstart);
+
+                               expected = e_cal_component_period_new_datetime (ttstart, ttend);
+
+                               g_clear_object (&ttstart);
+                               g_clear_object (&ttend);
+                       } else if ((set_kind % 3) == 2) {
+                               ICalTimetype *ttstart;
+                               ICalDurationType *ttduration;
+
+                               ttstart = i_cal_time_from_string ("19981019");
+                               ttduration = i_cal_duration_type_from_int (123456);
+                               g_assert_nonnull (ttstart);
+                               g_assert_nonnull (ttduration);
+
+                               expected = e_cal_component_period_new_duration (ttstart, ttduration);
+
+                               g_clear_object (&ttstart);
+                               g_clear_object (&ttduration);
+                       }
+
+                       if (expected) {
+                               if (duration) {
+                                       if (e_cal_component_period_get_kind (expected) == 
E_CAL_COMPONENT_PERIOD_DURATION) {
+                                               flipflop1++;
+                                               if ((flipflop1 & 1) != 0) {
+                                                       e_cal_component_period_set_duration_full (expected, 
start, duration);
+                                               } else {
+                                                       e_cal_component_period_set_start (expected, start);
+                                                       e_cal_component_period_set_duration (expected, 
duration);
+                                               }
+                                       } else {
+                                               e_cal_component_period_set_duration_full (expected, start, 
duration);
+                                       }
+                               } else if (e_cal_component_period_get_kind (expected) == 
E_CAL_COMPONENT_PERIOD_DATETIME) {
+                                       flipflop2++;
+                                       if ((flipflop2 & 1) != 0) {
+                                               e_cal_component_period_set_datetime_full (expected, start, 
end);
+                                       } else {
+                                               e_cal_component_period_set_start (expected, start);
+                                               e_cal_component_period_set_end (expected, end);
+                                       }
+                               } else {
+                                       e_cal_component_period_set_datetime_full (expected, start, end);
+                               }
+                       } else {
+                               if (duration)
+                                       expected = e_cal_component_period_new_duration (start, duration);
+                               else
+                                       expected = e_cal_component_period_new_datetime (start, end);
+                       }
+
+                       g_assert_nonnull (expected);
+                       verify_ical_timetype_equal (start, e_cal_component_period_get_start (expected));
+                       if (duration) {
+                               g_assert_cmpint (e_cal_component_period_get_kind (expected), ==, 
E_CAL_COMPONENT_PERIOD_DURATION);
+                               verify_ical_durationtype_equal (duration, e_cal_component_period_get_duration 
(expected));
+                       } else {
+                               g_assert_cmpint (e_cal_component_period_get_kind (expected), ==, 
E_CAL_COMPONENT_PERIOD_DATETIME);
+                               verify_ical_timetype_equal (end, e_cal_component_period_get_end (expected));
+                       }
+
+                       g_clear_object (&start);
+                       g_clear_object (&end);
+                       g_clear_object (&duration);
+
+                       received = e_cal_component_period_copy (expected);
+                       verify_struct_period_equal (expected, received);
+                       e_cal_component_period_free (received);
+
+                       e_cal_component_period_free (expected);
+               }
+       }
+
+       g_assert_cmpint (flipflop1, >, 2);
+       g_assert_cmpint (flipflop2, >, 2);
+}
+
+static void
+test_component_struct_range (void)
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314", "Europe/Berlin" },
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL }
+       };
+       ECalComponentRangeKind range_kinds[] = {
+               E_CAL_COMPONENT_RANGE_SINGLE,
+               E_CAL_COMPONENT_RANGE_THISPRIOR,
+               E_CAL_COMPONENT_RANGE_THISFUTURE
+       };
+       gint ii, jj, set_kind;
+
+       for (set_kind = 0; set_kind < 4; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       for (jj = 0; jj < G_N_ELEMENTS (range_kinds); jj++) {
+                               ECalComponentRange *expected = NULL, *received;
+                               ECalComponentDateTime *dt;
+
+                               if (set_kind == 2) {
+                                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string 
("19981019"), NULL);
+                                       expected = e_cal_component_range_new (E_CAL_COMPONENT_RANGE_SINGLE, 
dt);
+                                       e_cal_component_datetime_free (dt);
+                               } else if (set_kind == 3) {
+                                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string 
("19981019"), NULL);
+                                       expected = e_cal_component_range_new_take 
(E_CAL_COMPONENT_RANGE_SINGLE, dt);
+                               }
+
+                               dt = e_cal_component_datetime_new_take (i_cal_time_from_string 
(values[ii].time), g_strdup (values[ii].tzid));
+                               g_assert_nonnull (dt);
+
+                               if (expected) {
+                                       e_cal_component_range_set_kind (expected, range_kinds[jj]);
+
+                                       if (((set_kind + ii) & 1) != 0) {
+                                               e_cal_component_range_set_datetime (expected, dt);
+                                       } else {
+                                               ECalComponentDateTime *dtcopy;
+
+                                               dtcopy = e_cal_component_datetime_copy (dt);
+                                               g_assert_nonnull (dtcopy);
+
+                                               e_cal_component_range_take_datetime (expected, dtcopy);
+                                       }
+                               } else {
+                                       if (set_kind == 0) {
+                                               expected = e_cal_component_range_new (range_kinds[jj], dt);
+                                       } else {
+                                               ECalComponentDateTime *dtcopy;
+
+                                               dtcopy = e_cal_component_datetime_copy (dt);
+                                               g_assert_nonnull (dtcopy);
+
+                                               expected = e_cal_component_range_new_take (range_kinds[jj], 
dtcopy);
+                                       }
+                               }
+
+                               g_assert_nonnull (expected);
+
+                               verify_struct_datetime_equal (e_cal_component_range_get_datetime (expected), 
dt);
+                               g_assert_cmpint (e_cal_component_range_get_kind (expected), ==, 
range_kinds[jj]);
+
+                               e_cal_component_datetime_free (dt);
+
+                               received = e_cal_component_range_copy (expected);
+                               verify_struct_range_equal (expected, received);
+                               e_cal_component_range_free (received);
+
+                               e_cal_component_range_free (expected);
+                       }
+               }
+       }
+}
+
+static void
+test_component_struct_text (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *altrep;
+       } values[] = {
+               { "value1", NULL },
+               { "value2", "altrep1" },
+               { "value3", "altrep2" },
+               { "value4", NULL }
+       };
+       gint ii, set_kind;
+
+       for (set_kind = 0; set_kind < 3; set_kind++) {
+               for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+                       ECalComponentText *expected = NULL, *received;
+
+                       if (set_kind == 1) {
+                               expected = e_cal_component_text_new ("non-empty", NULL);
+                       } else if (set_kind == 2) {
+                               expected = e_cal_component_text_new ("non-empty-text", "non-empty-altrep");
+                       }
+
+                       if (expected) {
+                               e_cal_component_text_set_value (expected, values[ii].value);
+                               e_cal_component_text_set_altrep (expected, values[ii].altrep);
+                       } else {
+                               expected = e_cal_component_text_new (values[ii].value, values[ii].altrep);
+                       }
+
+                       g_assert_nonnull (expected);
+                       g_assert_cmpstr (e_cal_component_text_get_value (expected), ==, values[ii].value);
+                       g_assert_cmpstr (e_cal_component_text_get_altrep (expected), ==, values[ii].altrep);
+
+                       received = e_cal_component_text_copy (expected);
+                       verify_struct_text_equal (expected, received);
+                       e_cal_component_text_free (received);
+
+                       e_cal_component_text_free (expected);
+               }
+       }
+}
+
+static void
+verify_changes (ECalComponent *comp,
+               void (* verify_func) (ECalComponent *comp,
+                                     gpointer user_data),
+               gpointer user_data)
+{
+       ECalComponent *clone;
+       ICalComponent *icalcomp;
+       gchar *icalstr;
+
+       e_cal_component_commit_sequence (comp);
+
+       clone = e_cal_component_clone (comp);
+       g_assert_nonnull (clone);
+       verify_func (clone, user_data);
+       g_object_unref (clone);
+
+       icalstr = e_cal_component_get_as_string (comp);
+       g_assert_nonnull (icalstr);
+       clone = e_cal_component_new_from_string (icalstr);
+       g_free (icalstr);
+       g_assert_nonnull (clone);
+       verify_func (clone, user_data);
+       g_object_unref (clone);
+
+       icalcomp = e_cal_component_get_icalcomponent (comp);
+       g_assert_nonnull (icalcomp);
+       clone = e_cal_component_new_from_icalcomponent (i_cal_component_new_clone (icalcomp));
+       g_assert_nonnull (clone);
+       verify_func (clone, user_data);
+       g_object_unref (clone);
+
+       icalcomp = e_cal_component_get_icalcomponent (comp);
+       g_assert_nonnull (icalcomp);
+       icalcomp = i_cal_component_new_clone (icalcomp);
+       g_assert_nonnull (icalcomp);
+       clone = e_cal_component_new ();
+       g_assert_nonnull (clone);
+       g_assert (e_cal_component_set_icalcomponent (clone, icalcomp));
+       verify_func (clone, user_data);
+       g_object_unref (clone);
+
+       verify_func (comp, user_data);
+}
+
+static void
+verify_component_vtype (ECalComponent *comp,
+                       gpointer user_data)
+{
+       g_assert_cmpint (e_cal_component_get_vtype (comp), ==, GPOINTER_TO_INT (user_data));
+}
+
+static void
+test_component_vtype (void)
+{
+       ECalComponentVType values[] = {
+               E_CAL_COMPONENT_EVENT,
+               E_CAL_COMPONENT_TODO,
+               E_CAL_COMPONENT_JOURNAL,
+               E_CAL_COMPONENT_FREEBUSY,
+               E_CAL_COMPONENT_TIMEZONE
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new ();
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_new_vtype (comp, values[ii]);
+               verify_changes (comp, verify_component_vtype, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_uid (ECalComponent *comp,
+                     gpointer user_data)
+{
+       const gchar *uid = user_data;
+       ECalComponentId *id;
+
+       g_assert_cmpstr (e_cal_component_get_uid (comp), ==, uid);
+
+       id = e_cal_component_get_id (comp);
+       g_assert_nonnull (id);
+       g_assert_nonnull (e_cal_component_id_get_uid (id));
+       g_assert_null (e_cal_component_id_get_rid (id));
+
+       g_assert_cmpstr (e_cal_component_id_get_uid (id), ==, uid);
+
+       e_cal_component_id_free (id);
+}
+
+static void
+test_component_uid (void)
+{
+       ECalComponent *comp;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       e_cal_component_set_uid (comp, "123");
+       verify_changes (comp, verify_component_uid, (gpointer) "123");
+
+       e_cal_component_set_uid (comp, "456");
+       verify_changes (comp, verify_component_uid, (gpointer) "456");
+
+       g_object_unref (comp);
+}
+
+static GSList * /* gchar * */
+test_split_categories (const gchar *categories)
+{
+       GSList *list = NULL;
+       gchar **split;
+       gint ii;
+
+       if (!categories)
+               return NULL;
+
+       split = g_strsplit (categories, ",", -1);
+       if (split) {
+               for (ii = 0; split[ii]; ii++) {
+                       list = g_slist_prepend (list, g_strdup (split[ii]));
+               }
+
+               g_strfreev (split);
+       }
+
+       return g_slist_reverse (list);
+}
+
+static void
+verify_component_categories (ECalComponent *comp,
+                            gpointer user_data)
+{
+       const gchar *categories = user_data;
+       gchar *categories_str;
+       GSList *expected, *received, *link1, *link2;
+
+       categories_str = e_cal_component_get_categories (comp);
+       g_assert_cmpstr (categories_str, ==, categories);
+       g_free (categories_str);
+
+       expected = test_split_categories (categories);
+       received = e_cal_component_get_categories_list (comp);
+
+       g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+       for (link1 = expected, link2 = received;
+            link1 && link2;
+            link1 = g_slist_next (link1), link2 = g_slist_next (link2)) {
+               g_assert_cmpstr (link1->data, ==, link2->data);
+       }
+
+       g_assert (link1 == link2);
+
+       g_slist_free_full (expected, g_free);
+       g_slist_free_full (received, g_free);
+}
+
+static void
+test_component_categories (void)
+{
+       const gchar *values[] = {
+               "cat01",
+               "cat02",
+               NULL,
+               "cat03,cat04,cat05",
+               "cat06",
+               "cat07,cat08",
+               NULL
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               GSList *list;
+
+               comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+               g_assert_nonnull (comp);
+
+               e_cal_component_set_categories (comp, values[ii]);
+               verify_changes (comp, verify_component_categories, (gpointer) values[ii]);
+
+               g_object_unref (comp);
+
+               comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+               g_assert_nonnull (comp);
+
+               list = test_split_categories (values[ii]);
+               e_cal_component_set_categories_list (comp, list);
+               g_slist_free_full (list, g_free);
+
+               verify_changes (comp, verify_component_categories, (gpointer) values[ii]);
+
+               g_object_unref (comp);
+       }
+}
+
+static void
+verify_component_classification (ECalComponent *comp,
+                                gpointer user_data)
+{
+       g_assert_cmpint (e_cal_component_get_classification (comp), ==, GPOINTER_TO_INT (user_data));
+}
+
+static void
+test_component_classification (void)
+{
+       ECalComponentClassification values[] = {
+               E_CAL_COMPONENT_CLASS_NONE,
+               E_CAL_COMPONENT_CLASS_PUBLIC,
+               E_CAL_COMPONENT_CLASS_PRIVATE,
+               E_CAL_COMPONENT_CLASS_CONFIDENTIAL
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_classification (comp, values[ii]);
+               verify_changes (comp, verify_component_classification, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+/* Each part is separated by ':', text from its altrep is separated by '|' */
+static GSList * /* ECalComponentText * */
+test_split_texts (const gchar *value)
+{
+       GSList *result = NULL;
+       gchar **textsv;
+       gint ii;
+
+       if (!value)
+               return NULL;
+
+       textsv = g_strsplit (value, ":", -1);
+
+       if (textsv) {
+               for (ii = 0; textsv[ii]; ii++) {
+                       ECalComponentText *comptext;
+                       gchar *altrep;
+
+                       altrep = strchr (textsv[ii], '|');
+                       if (altrep) {
+                               *altrep = '\0';
+                               altrep++;
+                       }
+
+                       comptext = e_cal_component_text_new (textsv[ii], altrep);
+                       g_assert_nonnull (comptext);
+                       result = g_slist_prepend (result, comptext);
+               }
+
+               g_strfreev (textsv);
+       }
+
+       return g_slist_reverse (result);
+}
+
+static void
+verify_component_text_list (GSList * (* get_func) (ECalComponent *comp),
+                           ECalComponent *comp,
+                           gpointer user_data)
+{
+       GSList *expected, *received, *link1, *link2;
+
+       g_assert (get_func != NULL);
+
+       expected = user_data;
+       received = get_func (comp);
+
+       g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+       for (link1 = expected, link2 = received;
+            link1 && link2;
+            link1 = g_slist_next (link1), link2 = g_slist_next (link2)) {
+               ECalComponentText *text1 = link1->data, *text2 = link2->data;
+
+               g_assert_nonnull (text1);
+               g_assert_nonnull (text2);
+
+               verify_struct_text_equal (text1, text2);
+       }
+
+       g_assert (link1 == link2);
+
+       g_slist_free_full (received, e_cal_component_text_free);
+}
+
+static void
+test_component_text_list (void (* set_func) (ECalComponent *comp,
+                                            const GSList *values),
+                         void (* verify_func) (ECalComponent *comp,
+                                               gpointer user_data))
+{
+       const gchar *values[] = {
+               "text",
+               "line1\nline2|altrep",
+               "text|altrep",
+               "text1:text2|altrep2:text3a\ntext3b|altrep3",
+               NULL
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       g_assert (set_func != NULL);
+       g_assert (verify_func != NULL);
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               GSList *expected = test_split_texts (values[ii]);
+
+               set_func (comp, expected);
+               verify_changes (comp, verify_func, expected);
+
+               g_slist_free_full (expected, e_cal_component_text_free);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_icaltime (ICalTimetype * (* get_func) (ECalComponent *comp),
+                          ECalComponent *comp,
+                          gpointer user_data)
+{
+       ICalTimetype *expected, *received;
+
+       g_assert (get_func != NULL);
+
+       expected = user_data;
+       received = get_func (comp);
+
+       verify_ical_timetype_equal (expected, received);
+
+       g_clear_object (&received);
+}
+
+static void
+test_component_icaltime (void (* set_func) (ECalComponent *comp,
+                                           const ICalTimetype *tt),
+                        void (* verify_func) (ECalComponent *comp,
+                                              gpointer user_data),
+                        gboolean can_null_value)
+{
+       const gchar *values[] = {
+               "20181215T111213Z",
+               "20190131T121314Z",
+               NULL,
+               "20200708T010305Z"
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       g_assert (set_func != NULL);
+       g_assert (verify_func != NULL);
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ICalTimetype *tt;
+
+               if (values[ii]) {
+                       tt = i_cal_time_from_string (values[ii]);
+                       g_assert_nonnull (tt);
+               } else if (!can_null_value) {
+                       continue;
+               } else {
+                       tt = NULL;
+               }
+
+               set_func (comp, tt);
+               verify_changes (comp, verify_func, tt);
+
+               g_clear_object (&tt);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_datetime (ECalComponentDateTime * (* get_func) (ECalComponent *comp),
+                          ECalComponent *comp,
+                          gpointer user_data)
+{
+       ECalComponentDateTime *expected, *received;
+
+       g_assert (get_func != NULL);
+
+       expected = user_data;
+       received = get_func (comp);
+
+       verify_struct_datetime_equal (expected, received);
+
+       e_cal_component_datetime_free (received);
+}
+
+static void
+test_component_datetime (void (* set_func) (ECalComponent *comp,
+                                           const ECalComponentDateTime *dt),
+                        void (* verify_func) (ECalComponent *comp,
+                                              gpointer user_data))
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314Z", NULL },
+               { NULL, NULL },
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL }
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       g_assert (set_func != NULL);
+       g_assert (verify_func != NULL);
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentDateTime *dt;
+
+               if (values[ii].time) {
+                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string (values[ii].time), 
g_strdup (values[ii].tzid));
+                       g_assert_nonnull (dt);
+
+                       if (values[ii].tzid) {
+                               ICalTimetype *tt;
+                               ICalTimezone *zone;
+
+                               zone = i_cal_timezone_get_builtin_timezone (values[ii].tzid);
+                               if (zone) {
+                                       tt = e_cal_component_datetime_get_value (dt);
+                                       i_cal_timetype_set_zone (tt, zone);
+                               }
+                       }
+               } else {
+                       dt = NULL;
+               }
+
+               set_func (comp, dt);
+
+               verify_changes (comp, verify_func, dt);
+
+               e_cal_component_datetime_free (dt);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_rules (GSList * (* get_func) (ECalComponent *comp),
+                       GSList * (* get_props_func) (ECalComponent *comp),
+                       gboolean is_exception,
+                       ECalComponent *comp,
+                       gpointer user_data)
+{
+       GSList *expected, *received, *received_props;
+
+       expected = user_data;
+       received = get_func (comp);
+       received_props = get_props_func (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert_null (received_props);
+               if (is_exception) {
+                       g_assert (!e_cal_component_has_exrules (comp));
+                       g_assert (!e_cal_component_has_exceptions (comp));
+               } else {
+                       g_assert (!e_cal_component_has_rrules (comp));
+                       g_assert (!e_cal_component_has_recurrences (comp));
+                       g_assert (e_cal_component_has_simple_recurrence (comp));
+               }
+       } else {
+               GSList *link1, *link2, *link3;
+
+               if (is_exception) {
+                       g_assert (e_cal_component_has_exrules (comp));
+                       g_assert (e_cal_component_has_exceptions (comp));
+                       g_assert (!e_cal_component_has_rrules (comp));
+               } else {
+                       g_assert (!e_cal_component_has_exrules (comp));
+                       g_assert (!e_cal_component_has_exceptions (comp));
+                       g_assert (e_cal_component_has_rrules (comp));
+                       g_assert (e_cal_component_has_recurrences (comp));
+                       if (expected->next)
+                               g_assert (!e_cal_component_has_simple_recurrence (comp));
+                       else
+                               g_assert (e_cal_component_has_simple_recurrence (comp));
+               }
+
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received_props));
+
+               for (link1 = expected, link2 = received, link3 = received_props;
+                    link1 && link2 && link3;
+                    link1 = g_slist_next (link1), link2 = g_slist_next (link2), link3 = g_slist_next 
(link3)) {
+                       ICalRecurrenceType *rt_expected, *rt_received, *rt_received_prop;
+                       ICalProperty *prop_received;
+                       gchar *str_expected, *str_received, *str_received_prop;
+
+                       rt_expected = link1->data;
+                       rt_received = link2->data;
+                       prop_received = link3->data;
+
+                       if (is_exception) {
+                               rt_received_prop = i_cal_property_get_exrule (prop_received);
+                       } else {
+                               rt_received_prop = i_cal_property_get_rrule (prop_received);
+                       }
+
+                       str_expected = i_cal_recurrence_type_as_string_r (rt_expected);
+                       str_received = i_cal_recurrence_type_as_string_r (rt_received);
+                       str_received_prop = i_cal_recurrence_type_as_string_r (rt_received_prop);
+
+                       g_assert_cmpstr (str_expected, ==, str_received);
+                       g_assert_cmpstr (str_expected, ==, str_received_prop);
+
+                       g_free (str_expected);
+                       g_free (str_received);
+                       g_free (str_received_prop);
+                       g_clear_object (&rt_received_prop);
+               }
+
+               g_assert (link1 == link2);
+               g_assert (link2 == link3);
+       }
+
+       g_slist_free_full (received, g_object_unref);
+       g_slist_free_full (received_props, g_object_unref);
+}
+
+static void
+test_component_rules (void (* set_func) (ECalComponent *comp,
+                                        const GSList *recur_list),
+                     void (* verify_func) (ECalComponent *comp,
+                                           gpointer user_data))
+{
+       const gchar *values[] = {
+               "FREQ=DAILY;COUNT=10;INTERVAL=6",
+               NULL, /* terminator */
+               NULL, /* terminator */
+               "FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3",
+               "FREQ=DAILY;BYDAY=1SU",
+               NULL /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *rules = NULL;
+       gint ii;
+
+       g_assert_nonnull (set_func);
+       g_assert_nonnull (verify_func);
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii]) {
+                       ICalRecurrenceType *rt;
+
+                       rt = i_cal_recurrence_type_from_string (values[ii]);
+                       g_assert_nonnull (rt);
+
+                       rules = g_slist_prepend (rules, rt);
+               } else {
+                       rules = g_slist_reverse (rules);
+
+                       set_func (comp, rules);
+                       verify_changes (comp, verify_func, rules);
+
+                       g_slist_free_full (rules, g_object_unref);
+                       rules = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (rules);
+}
+
+static void
+verify_component_comments (ECalComponent *comp,
+                          gpointer user_data)
+{
+       verify_component_text_list (e_cal_component_get_comments, comp, user_data);
+}
+
+static void
+test_component_comments (void)
+{
+       test_component_text_list (e_cal_component_set_comments, verify_component_comments);
+}
+
+static void
+verify_component_completed (ECalComponent *comp,
+                           gpointer user_data)
+{
+       verify_component_icaltime (e_cal_component_get_completed, comp, user_data);
+}
+
+static void
+test_component_completed (void)
+{
+       test_component_icaltime (e_cal_component_set_completed, verify_component_completed, TRUE);
+}
+
+static void
+verify_component_contacts (ECalComponent *comp,
+                          gpointer user_data)
+{
+       verify_component_text_list (e_cal_component_get_contacts, comp, user_data);
+}
+
+static void
+test_component_contacts (void)
+{
+       test_component_text_list (e_cal_component_set_contacts, verify_component_contacts);
+}
+
+static void
+verify_component_created (ECalComponent *comp,
+                         gpointer user_data)
+{
+       verify_component_icaltime (e_cal_component_get_created, comp, user_data);
+}
+
+static void
+test_component_created (void)
+{
+       test_component_icaltime (e_cal_component_set_created, verify_component_created, TRUE);
+}
+
+static void
+verify_component_descriptions (ECalComponent *comp,
+                              gpointer user_data)
+{
+       verify_component_text_list (e_cal_component_get_descriptions, comp, user_data);
+}
+
+static void
+test_component_descriptions (void)
+{
+       test_component_text_list (e_cal_component_set_descriptions, verify_component_descriptions);
+}
+
+static void
+verify_component_dtend (ECalComponent *comp,
+                       gpointer user_data)
+{
+       verify_component_datetime (e_cal_component_get_dtend, comp, user_data);
+}
+
+static void
+test_component_dtend (void)
+{
+       test_component_datetime (e_cal_component_set_dtend, verify_component_dtend);
+}
+
+static void
+verify_component_dtstamp (ECalComponent *comp,
+                         gpointer user_data)
+{
+       verify_component_icaltime (e_cal_component_get_dtstamp, comp, user_data);
+}
+
+static void
+test_component_dtstamp (void)
+{
+       test_component_icaltime (e_cal_component_set_dtstamp, verify_component_dtstamp, FALSE);
+}
+
+static void
+verify_component_dtstart (ECalComponent *comp,
+                         gpointer user_data)
+{
+       verify_component_datetime (e_cal_component_get_dtstart, comp, user_data);
+}
+
+static void
+test_component_dtstart (void)
+{
+       test_component_datetime (e_cal_component_set_dtstart, verify_component_dtstart);
+}
+
+static void
+verify_component_due (ECalComponent *comp,
+                     gpointer user_data)
+{
+       verify_component_datetime (e_cal_component_get_due, comp, user_data);
+}
+
+static void
+test_component_due (void)
+{
+       test_component_datetime (e_cal_component_set_due, verify_component_due);
+}
+
+static void
+verify_component_exdates (ECalComponent *comp,
+                         gpointer user_data)
+{
+       GSList *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_exdates (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_exdates (comp));
+               g_assert (!e_cal_component_has_exceptions (comp));
+       } else {
+               GSList *link1, *link2;
+
+               g_assert (e_cal_component_has_exdates (comp));
+               g_assert (e_cal_component_has_exceptions (comp));
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+               for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 
= g_slist_next (link2)) {
+                       ECalComponentDateTime *dt_expected = link1->data, *dt_received = link2->data;
+
+                       verify_struct_datetime_equal (dt_expected, dt_received);
+               }
+
+               g_assert (link1 == link2);
+       }
+
+       g_slist_free_full (received, e_cal_component_datetime_free);
+}
+
+static void
+test_component_exdates (void)
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314Z", NULL },
+               { NULL, NULL }, /* terminator */
+               { NULL, NULL }, /* terminator */
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL },
+               { NULL, NULL } /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *exdates = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].time) {
+                       ECalComponentDateTime *dt;
+
+                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string (values[ii].time), 
g_strdup (values[ii].tzid));
+                       g_assert_nonnull (dt);
+
+                       if (values[ii].tzid) {
+                               ICalTimetype *tt;
+                               ICalTimezone *zone;
+
+                               zone = i_cal_timezone_get_builtin_timezone (values[ii].tzid);
+                               if (zone) {
+                                       tt = e_cal_component_datetime_get_value (dt);
+                                       i_cal_timetype_set_zone (tt, zone);
+                               }
+                       }
+
+                       exdates = g_slist_prepend (exdates, dt);
+               } else {
+                       exdates = g_slist_reverse (exdates);
+
+                       e_cal_component_set_exdates (comp, exdates);
+                       verify_changes (comp, verify_component_exdates, exdates);
+
+                       g_slist_free_full (exdates, e_cal_component_datetime_free);
+                       exdates = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (exdates);
+}
+
+static void
+verify_component_exrules (ECalComponent *comp,
+                         gpointer user_data)
+{
+       verify_component_rules (e_cal_component_get_exrules, e_cal_component_get_exrule_properties, TRUE, 
comp, user_data);
+}
+
+static void
+test_component_exrules (void)
+{
+       test_component_rules (e_cal_component_set_exrules, verify_component_exrules);
+}
+
+static void
+verify_component_geo (ECalComponent *comp,
+                     gpointer user_data)
+{
+       ICalGeoType *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_geo (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+       } else {
+               g_assert_nonnull (received);
+               g_assert_cmpfloat (i_cal_geo_type_get_lat (expected), ==, i_cal_geo_type_get_lat (received));
+               g_assert_cmpfloat (i_cal_geo_type_get_lon (expected), ==, i_cal_geo_type_get_lon (received));
+       }
+
+       g_clear_object (&received);
+}
+
+static void
+test_component_geo (void)
+{
+       struct _values {
+               gdouble lat;
+               gdouble lon;
+       } values[] = {
+               { 10.0, 20.0 },
+               { -1.0, -1.0 },
+               { 50.0, 30.0 }
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ICalGeoType *geo = NULL;
+
+               if (values[ii].lat > 0.0)
+                       geo = i_cal_geo_type_new (values[ii].lat, values[ii].lon);
+
+               e_cal_component_set_geo (comp, geo);
+               verify_changes (comp, verify_component_geo, geo);
+
+               g_clear_object (&geo);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_lastmodified (ECalComponent *comp,
+                              gpointer user_data)
+{
+       verify_component_icaltime (e_cal_component_get_last_modified, comp, user_data);
+}
+
+static void
+test_component_lastmodified (void)
+{
+       test_component_icaltime (e_cal_component_set_last_modified, verify_component_lastmodified, TRUE);
+}
+
+static void
+verify_component_organizer (ECalComponent *comp,
+                           gpointer user_data)
+{
+       ECalComponentOrganizer *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_organizer (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_organizer (comp));
+       } else {
+               g_assert_nonnull (received);
+               g_assert (e_cal_component_has_organizer (comp));
+               verify_struct_organizer_equal (expected, received);
+       }
+
+       e_cal_component_organizer_free (received);
+}
+
+static void
+test_component_organizer (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *sentby;
+               const gchar *cn;
+               const gchar *language;
+       } values[] = {
+               { "MAILTO:org1", NULL, "First Organizer", NULL },
+               { NULL, NULL, NULL, NULL },
+               { "MAILTO:org2","MAILTO:sentby2", "Second Organizer", "en_US" }
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentOrganizer *org = NULL;
+
+               if (values[ii].value)
+                       org = e_cal_component_organizer_new_full (values[ii].value, values[ii].sentby, 
values[ii].cn, values[ii].language);
+
+               e_cal_component_set_organizer (comp, org);
+               verify_changes (comp, verify_component_organizer, org);
+
+               e_cal_component_organizer_free (org);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_percentcomplete (ECalComponent *comp,
+                                 gpointer user_data)
+{
+       gint expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_percent_complete (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_percentcomplete (void)
+{
+       gint values[] = { 10, -1, 13, 0, 78, 99, -1, 100 };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_percent_complete (comp, values[ii]);
+               verify_changes (comp, verify_component_percentcomplete, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_priority (ECalComponent *comp,
+                          gpointer user_data)
+{
+       gint expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_priority (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_priority (void)
+{
+       gint values[] = { 8, 7, 6, 5, -1, 4, 3, 2, 1, 0, -1, 9 };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_priority (comp, values[ii]);
+               verify_changes (comp, verify_component_priority, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_recurid (ECalComponent *comp,
+                         gpointer user_data)
+{
+       ECalComponentRange *expected, *received;
+       ECalComponentId *id;
+       gchar *rid_str;
+
+       expected = user_data;
+       received = e_cal_component_get_recurid (comp);
+       rid_str = e_cal_component_get_recurid_as_string (comp);
+       id = e_cal_component_get_id (comp);
+
+       g_assert_nonnull (id);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert_null (rid_str);
+               g_assert_null (e_cal_component_id_get_rid (id));
+               g_assert (!e_cal_component_is_instance (comp));
+       } else {
+               g_assert_nonnull (rid_str);
+               g_assert_nonnull (e_cal_component_id_get_rid (id));
+               g_assert (e_cal_component_is_instance (comp));
+               g_assert_cmpstr (e_cal_component_id_get_rid (id), ==, rid_str);
+
+               verify_struct_range_equal (expected, received);
+       }
+
+       e_cal_component_range_free (received);
+       e_cal_component_id_free (id);
+       g_free (rid_str);
+}
+
+static void
+test_component_recurid (void)
+{
+       struct _values {
+               const gchar *time;
+               const gchar *tzid;
+       } values[] = {
+               { "20181215T111213Z", NULL },
+               { "20190131T121314Z", NULL },
+               { NULL, NULL },
+               { "20200708T010305Z", NULL },
+               { "20211215T101112", "America/New_York" },
+               { "20221110T090807", "UTC" },
+               { "20231009", NULL }
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               ECalComponentRange *rid = NULL;
+
+               if (values[ii].time) {
+                       ECalComponentDateTime *dt;
+
+                       dt = e_cal_component_datetime_new_take (i_cal_time_from_string (values[ii].time), 
g_strdup (values[ii].tzid));
+                       g_assert_nonnull (dt);
+
+                       if (values[ii].tzid) {
+                               ICalTimetype *tt;
+                               ICalTimezone *zone;
+
+                               zone = i_cal_timezone_get_builtin_timezone (values[ii].tzid);
+                               if (zone) {
+                                       tt = e_cal_component_datetime_get_value (dt);
+                                       i_cal_timetype_set_zone (tt, zone);
+                               }
+                       }
+
+                       rid = e_cal_component_range_new_take (E_CAL_COMPONENT_RANGE_SINGLE, dt);
+               }
+
+               e_cal_component_set_recurid (comp, rid);
+               verify_changes (comp, verify_component_recurid, rid);
+
+               e_cal_component_range_free (rid);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_rdates (ECalComponent *comp,
+                        gpointer user_data)
+{
+       GSList *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_rdates (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_rdates (comp));
+               g_assert (!e_cal_component_has_recurrences (comp));
+       } else {
+               GSList *link1, *link2;
+
+               g_assert (e_cal_component_has_rdates (comp));
+               g_assert (e_cal_component_has_recurrences (comp));
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+               for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 
= g_slist_next (link2)) {
+                       ECalComponentPeriod *period_expected = link1->data, *period_received = link2->data;
+
+                       verify_struct_period_equal (period_expected, period_received);
+               }
+
+               g_assert (link1 == link2);
+       }
+
+       g_slist_free_full (received, e_cal_component_period_free);
+}
+
+static void
+test_component_rdates (void)
+{
+       struct _values {
+               const gchar *start;
+               const gchar *end;
+               gint duration;
+       } values[] = {
+               { "20181215T111213Z", "20181215T121314Z", -1 },
+               { "20190131T121314Z", NULL, 10 * 24 * 60 * 60 },
+               { NULL, NULL, -1 }, /* terminator */
+               { NULL, NULL, -1 }, /* terminator */
+               { "20200708T010305Z", NULL, 2 * 60 * 60 },
+               { "20211215T101112", "20211215T121314", -1 },
+               { "20221110T090807", "20221110T100908", -1 },
+               { "20231009", "20241110", -1 },
+               { NULL, NULL, -1 }, /* terminator */
+               { "20240908T070605", NULL, -1 },
+               { "20250807", NULL, -1 },
+               { NULL, NULL, -1 } /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *rdates = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].start) {
+                       ICalTimetype *start, *end = NULL;
+                       ICalDurationType *duration = NULL;
+                       ECalComponentPeriod *period;
+
+                       start = i_cal_time_from_string (values[ii].start);
+                       g_assert_nonnull (start);
+                       if (values[ii].duration == -1) {
+                               if (values[ii].end) {
+                                       end = i_cal_time_from_string (values[ii].end);
+                                       g_assert_nonnull (end);
+                               }
+                               period = e_cal_component_period_new_datetime (start, end);
+                       } else {
+                               duration = i_cal_duration_type_from_int (values[ii].duration);
+                               g_assert_nonnull (duration);
+                               period = e_cal_component_period_new_duration (start, duration);
+                       }
+
+                       g_assert_nonnull (period);
+
+                       rdates = g_slist_prepend (rdates, period);
+
+                       g_clear_object (&start);
+                       g_clear_object (&end);
+                       g_clear_object (&duration);
+               } else {
+                       rdates = g_slist_reverse (rdates);
+
+                       e_cal_component_set_rdates (comp, rdates);
+                       verify_changes (comp, verify_component_rdates, rdates);
+
+                       g_slist_free_full (rdates, e_cal_component_period_free);
+                       rdates = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (rdates);
+}
+
+static void
+verify_component_rrules (ECalComponent *comp,
+                        gpointer user_data)
+{
+       verify_component_rules (e_cal_component_get_rrules, e_cal_component_get_rrule_properties, FALSE, 
comp, user_data);
+}
+
+static void
+test_component_rrules (void)
+{
+       test_component_rules (e_cal_component_set_rrules, verify_component_rrules);
+}
+
+static void
+verify_component_sequence (ECalComponent *comp,
+                          gpointer user_data)
+{
+       gint expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_sequence (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_sequence (void)
+{
+       gint values[] = { 8, 7, 6, 5, -1, 4, 3, 2, 1, 0, -1, 9 };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_sequence (comp, values[ii]);
+               e_cal_component_abort_sequence (comp);
+               verify_changes (comp, verify_component_sequence, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_status (ECalComponent *comp,
+                        gpointer user_data)
+{
+       ICalPropertyStatus expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_status (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_status (void)
+{
+       ICalPropertyStatus values[] = {
+               I_CAL_STATUS_TENTATIVE,
+               I_CAL_STATUS_CONFIRMED,
+               I_CAL_STATUS_COMPLETED,
+               I_CAL_STATUS_NEEDSACTION,
+               I_CAL_STATUS_CANCELLED,
+               I_CAL_STATUS_INPROCESS,
+               I_CAL_STATUS_DRAFT,
+               I_CAL_STATUS_FINAL,
+               I_CAL_STATUS_NONE
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_status (comp, values[ii]);
+               verify_changes (comp, verify_component_status, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_summary (ECalComponent *comp,
+                         gpointer user_data)
+{
+       ECalComponentText *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_summary (comp);
+
+       if (expected) {
+               g_assert_nonnull (received);
+               verify_struct_text_equal (expected, received);
+       } else {
+               g_assert_null (received);
+       }
+
+       e_cal_component_text_free (received);
+}
+
+static void
+test_component_summary (void)
+{
+       const gchar *values[] = {
+               "text",
+               "line1\nline2|altrep",
+               "text|altrep",
+               NULL,
+               "text1:text2|altrep2:text3a\ntext3b|altrep3"
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               GSList *expected = test_split_texts (values[ii]), *link;
+
+               if (expected) {
+                       for (link = expected; link; link = g_slist_next (link)) {
+                               ECalComponentText *text = link->data;
+
+                               e_cal_component_set_summary (comp, text);
+                               verify_changes (comp, verify_component_summary, text);
+                       }
+               } else {
+                       e_cal_component_set_summary (comp, NULL);
+                       verify_changes (comp, verify_component_summary, NULL);
+               }
+
+               g_slist_free_full (expected, e_cal_component_text_free);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_transparency (ECalComponent *comp,
+                              gpointer user_data)
+{
+       ECalComponentTransparency expected, received;
+
+       expected = GPOINTER_TO_INT (user_data);
+       received = e_cal_component_get_transparency (comp);
+
+       g_assert_cmpint (expected, ==, received);
+}
+
+static void
+test_component_transparency (void)
+{
+       ECalComponentTransparency values[] = {
+               E_CAL_COMPONENT_TRANSP_TRANSPARENT,
+               E_CAL_COMPONENT_TRANSP_NONE,
+               E_CAL_COMPONENT_TRANSP_OPAQUE
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_transparency (comp, values[ii]);
+               verify_changes (comp, verify_component_transparency, GINT_TO_POINTER (values[ii]));
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_url (ECalComponent *comp,
+                     gpointer user_data)
+{
+       gchar *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_url (comp);
+
+       g_assert_cmpstr (expected, ==, received);
+
+       g_free (received);
+}
+
+static void
+test_component_url (void)
+{
+       const gchar *values[] = {
+               "https://www.gnome.org";,
+               NULL,
+               "https://wiki.gnome.org/Apps/Evolution";
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_url (comp, values[ii]);
+               verify_changes (comp, verify_component_url, (gpointer) values[ii]);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_attendees (ECalComponent *comp,
+                           gpointer user_data)
+{
+       GSList *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_attendees (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_attendees (comp));
+       } else {
+               GSList *link1, *link2;
+
+               g_assert_nonnull (received);
+               g_assert (e_cal_component_has_attendees (comp));
+
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+               for (link1 = expected, link2 = received; link1 && link2; link1 = g_slist_next (link1), link2 
= g_slist_next (link2)) {
+                       ECalComponentAttendee *att_expected = link1->data, *att_received = link2->data;
+
+                       verify_struct_attendee_equal (att_expected, att_received);
+               }
+
+               g_assert (link1 == link2);
+       }
+
+       g_slist_free_full (received, e_cal_component_attendee_free);
+}
+
+static void
+test_component_attendees (void)
+{
+       struct _values {
+               const gchar *value;
+               const gchar *member;
+               ICalParameterCutype cutype;
+               ICalParameterRole role;
+               ICalParameterPartstat partstat;
+               gboolean rsvp;
+               const gchar *delegatedfrom;
+               const gchar *delegatedto;
+               const gchar *sentby;
+               const gchar *cn;
+               const gchar *language;
+       } values[] = {
+               { "MAILTO:att1",
+                  "member",
+                  I_CAL_CUTYPE_INDIVIDUAL,
+                  I_CAL_ROLE_CHAIR,
+                  I_CAL_PARTSTAT_NEEDSACTION,
+                  FALSE,
+                  "MAILTO:delgfrom",
+                  "MAILTO:delgto",
+                  "MAILTO:sentby",
+                  "First attendee",
+                  "en_US" },
+               { NULL, NULL, I_CAL_CUTYPE_NONE, I_CAL_ROLE_NONE, I_CAL_PARTSTAT_NONE, FALSE, NULL, NULL, 
NULL, NULL, NULL }, /* terminator */
+               { NULL, NULL, I_CAL_CUTYPE_NONE, I_CAL_ROLE_NONE, I_CAL_PARTSTAT_NONE, FALSE, NULL, NULL, 
NULL, NULL, NULL }, /* terminator */
+               { "MAILTO:room",
+                  NULL,
+                  I_CAL_CUTYPE_ROOM,
+                  I_CAL_ROLE_REQPARTICIPANT,
+                  I_CAL_PARTSTAT_ACCEPTED,
+                  FALSE,
+                  NULL,
+                  NULL,
+                  NULL,
+                  "Meeting room",
+                  NULL },
+               { "MAILTO:att2",
+                  NULL,
+                  I_CAL_CUTYPE_INDIVIDUAL,
+                  I_CAL_ROLE_REQPARTICIPANT,
+                  I_CAL_PARTSTAT_TENTATIVE,
+                  TRUE,
+                  NULL,
+                  NULL,
+                  NULL,
+                  NULL,
+                  "en_US" },
+               { NULL, NULL, I_CAL_CUTYPE_NONE, I_CAL_ROLE_NONE, I_CAL_PARTSTAT_NONE, FALSE, NULL, NULL, 
NULL, NULL, NULL } /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *attendees = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].value) {
+                       ECalComponentAttendee *att;
+
+                       att = e_cal_component_attendee_new_full (values[ii].value,
+                               values[ii].member,
+                               values[ii].cutype,
+                               values[ii].role,
+                               values[ii].partstat,
+                               values[ii].rsvp,
+                               values[ii].delegatedfrom,
+                               values[ii].delegatedto,
+                               values[ii].sentby,
+                               values[ii].cn,
+                               values[ii].language);
+
+                       attendees = g_slist_prepend (attendees, att);
+               } else {
+                       attendees = g_slist_reverse (attendees);
+
+                       e_cal_component_set_attendees (comp, attendees);
+                       verify_changes (comp, verify_component_attendees, attendees);
+
+                       g_slist_free_full (attendees, e_cal_component_attendee_free);
+                       attendees = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (attendees);
+}
+
+static void
+verify_component_location (ECalComponent *comp,
+                          gpointer user_data)
+{
+       gchar *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_location (comp);
+
+       g_assert_cmpstr (expected, ==, received);
+
+       g_free (received);
+}
+
+static void
+test_component_location (void)
+{
+       const gchar *values[] = {
+               "Headquarter",
+               NULL,
+               "Phone call, +123-456-7890"
+       };
+       ECalComponent *comp;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               e_cal_component_set_location (comp, values[ii]);
+               verify_changes (comp, verify_component_location, (gpointer) values[ii]);
+       }
+
+       g_object_unref (comp);
+}
+
+static void
+verify_component_attachments (ECalComponent *comp,
+                             gpointer user_data)
+{
+       GSList *expected, *received;
+
+       expected = user_data;
+       received = e_cal_component_get_attachments (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert (!e_cal_component_has_attachments (comp));
+       } else {
+               ECalComponent *clone;
+
+               g_assert_nonnull (received);
+               g_assert (e_cal_component_has_attachments (comp));
+
+               verify_ical_attach_list_equal (expected, received);
+
+               /* Also test whether the attachments can be accessed after the component is freed */
+               clone = e_cal_component_clone (comp);
+               g_assert_nonnull (clone);
+
+               g_slist_free_full (received, g_object_unref);
+               received = e_cal_component_get_attachments (clone);
+
+               g_object_unref (clone);
+
+               g_assert_nonnull (received);
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+
+               verify_ical_attach_list_equal (expected, received);
+       }
+
+       g_slist_free_full (received, g_object_unref);
+}
+
+static void
+test_component_attachments (void)
+{
+       struct _values {
+               gboolean is_url;
+               const gchar *content;
+       } values[] = {
+               { TRUE, "https://www.gnome.org/index.html"; },
+               { FALSE, NULL }, /* terminator */
+               { FALSE, NULL }, /* terminator */
+               { FALSE, "0123456789ABCDEF" },
+               { TRUE, "http://www.example.com/files/data.dat"; },
+               { FALSE, NULL } /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *attachments = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].content) {
+                       ICalAttach *attach;
+
+                       if (values[ii].is_url)
+                               attach = i_cal_attach_new_from_url (values[ii].content);
+                       else
+                               attach = i_cal_attach_new_from_data (values[ii].content, NULL, NULL);
+
+                       g_assert_nonnull (attach);
+
+                       attachments = g_slist_prepend (attachments, attach);
+               } else {
+                       attachments = g_slist_reverse (attachments);
+
+                       e_cal_component_set_attachments (comp, attachments);
+                       verify_changes (comp, verify_component_attachments, attachments);
+
+                       g_slist_free_full (attachments, g_object_unref);
+                       attachments = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (attachments);
+}
+
+static void
+verify_component_alarms (ECalComponent *comp,
+                        gpointer user_data)
+{
+       GSList *expected, *received, *received_uids;
+
+       expected = user_data;
+       received = e_cal_component_get_all_alarms (comp);
+       received_uids = e_cal_component_get_alarm_uids (comp);
+
+       if (!expected) {
+               g_assert_null (received);
+               g_assert_null (received_uids);
+               g_assert (!e_cal_component_has_alarms (comp));
+       } else {
+               GSList *link1, *link2, *link3;
+
+               g_assert_nonnull (received);
+               g_assert_nonnull (received_uids);
+               g_assert (e_cal_component_has_alarms (comp));
+
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received));
+               g_assert_cmpint (g_slist_length (expected), ==, g_slist_length (received_uids));
+
+               for (link1 = expected, link2 = received, link3 = received_uids;
+                    link1 && link2 && link3;
+                    link1 = g_slist_next (link1), link2 = g_slist_next (link2), link3 = g_slist_next 
(link3)) {
+                       const ECalComponentAlarm *al_expected = link1->data;
+                       const ECalComponentAlarm *al_received = link2->data;
+                       const gchar *uid_received = link3->data;
+
+                       g_assert_nonnull (al_expected);
+                       g_assert_nonnull (al_received);
+                       g_assert_nonnull (uid_received);
+
+                       g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), ==, uid_received);
+                       g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), ==, 
e_cal_component_alarm_get_uid (al_received));
+
+                       verify_struct_alarm_equal (al_expected, al_received);
+               }
+
+               g_assert (link1 == link2);
+               g_assert (link1 == link3);
+
+               if (expected->next) {
+                       ECalComponentAlarm *al_expected;
+                       ECalComponentAlarm *al_received;
+
+                       al_expected = expected->next->data;
+                       al_received = e_cal_component_get_alarm (comp, e_cal_component_alarm_get_uid 
(al_expected));
+
+                       g_assert_nonnull (al_expected);
+                       g_assert_nonnull (al_received);
+                       g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), ==, 
e_cal_component_alarm_get_uid (al_received));
+
+                       e_cal_component_remove_alarm (comp, e_cal_component_alarm_get_uid (al_expected));
+
+                       e_cal_component_alarm_free (al_received);
+
+                       g_slist_free_full (received, e_cal_component_alarm_free);
+                       g_slist_free_full (received_uids, g_free);
+
+                       g_assert (e_cal_component_has_alarms (comp));
+
+                       received = e_cal_component_get_all_alarms (comp);
+                       received_uids = e_cal_component_get_alarm_uids (comp);
+
+                       g_assert_cmpint (g_slist_length (expected) - 1, ==, g_slist_length (received));
+                       g_assert_cmpint (g_slist_length (expected) - 1, ==, g_slist_length (received_uids));
+
+                       for (link1 = received, link2 = received_uids;
+                            link1 && link2;
+                            link1 = g_slist_next (link1), link2 = g_slist_next (link2)) {
+                               const gchar *uid_received;
+
+                               al_received = link1->data;
+                               uid_received = link2->data;
+
+                               g_assert_nonnull (al_received);
+                               g_assert_nonnull (uid_received);
+                               g_assert_cmpstr (e_cal_component_alarm_get_uid (al_received), ==, 
uid_received);
+                               g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), !=, 
uid_received);
+                               g_assert_cmpstr (e_cal_component_alarm_get_uid (al_expected), !=, 
e_cal_component_alarm_get_uid (al_received));
+                       }
+
+                       g_assert (link1 == link2);
+               } else {
+                       e_cal_component_remove_alarm (comp, e_cal_component_alarm_get_uid (expected->data));
+
+                       g_assert (!e_cal_component_has_alarms (comp));
+                       g_assert_null (e_cal_component_get_all_alarms (comp));
+                       g_assert_null (e_cal_component_get_alarm_uids (comp));
+               }
+       }
+
+       g_slist_free_full (received, e_cal_component_alarm_free);
+       g_slist_free_full (received_uids, g_free);
+}
+
+static void
+test_component_alarms (void)
+{
+       struct _values {
+               const gchar *uid;
+               ECalComponentAlarmAction action;
+               const gchar *description;
+               gint trigger;
+       } values[] = {
+               { "alarm1", E_CAL_COMPONENT_ALARM_DISPLAY, "display reminder", -5 },
+               { NULL, E_CAL_COMPONENT_ALARM_NONE, NULL, 0 }, /* terminator */
+               { NULL, E_CAL_COMPONENT_ALARM_NONE, NULL, 0 }, /* terminator */
+               { "alarm2", E_CAL_COMPONENT_ALARM_AUDIO, "audio reminder", 10 },
+               { "alarm3", E_CAL_COMPONENT_ALARM_EMAIL, "email reminder", 0 },
+               { "alarm4", E_CAL_COMPONENT_ALARM_PROCEDURE, "procedure reminder", -30 },
+               { NULL, E_CAL_COMPONENT_ALARM_NONE, NULL, 0 }, /* terminator */
+       };
+       ECalComponent *comp;
+       GSList *alarms = NULL;
+       gint ii;
+
+       comp = e_cal_component_new_vtype (E_CAL_COMPONENT_EVENT);
+       g_assert_nonnull (comp);
+
+       for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+               if (values[ii].uid) {
+                       ECalComponentAlarm *alarm;
+                       ECalComponentAlarmTriggerKind kind;
+                       ICalDurationType *duration;
+
+                       duration = i_cal_duration_type_from_int (values[ii].trigger * 60);
+                       if (values[ii].trigger < 0)
+                               kind = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
+                       else
+                               kind = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END;
+
+                       alarm = e_cal_component_alarm_new ();
+                       e_cal_component_alarm_set_uid (alarm, values[ii].uid);
+                       e_cal_component_alarm_set_action (alarm, values[ii].action);
+                       e_cal_component_alarm_take_description (alarm, e_cal_component_text_new 
(values[ii].description, NULL));
+                       e_cal_component_alarm_take_trigger (alarm, e_cal_component_alarm_trigger_new_relative 
(kind, duration));
+
+                       e_cal_component_add_alarm (comp, alarm);
+                       alarms = g_slist_prepend (alarms, alarm);
+
+                       g_object_unref (duration);
+               } else {
+                       alarms = g_slist_reverse (alarms);
+
+                       verify_changes (comp, verify_component_alarms, alarms);
+
+                       e_cal_component_remove_all_alarms (comp);
+                       g_slist_free_full (alarms, e_cal_component_alarm_free);
+                       alarms = NULL;
+               }
+       }
+
+       g_object_unref (comp);
+
+       g_assert_null (alarms);
+}
+
+static void
+test_component_striperrors (void)
+{
+       const gchar *vevent =
+               "BEGIN:VEVENT\r\n"
+               "DTSTART:20150102T100000Z\r\n"
+               "DTEND:20150102T100100Z\r\n"
+               "DTSTAMP:20150108T132939Z\r\n"
+               "UID:123\r\n"
+               "CREATED:20150102T181646Z\r\n"
+               "X-LIC-ERROR;X-LIC-ERRORTYPE=VALUE-PARSE-ERROR:No value for DESCRIPTION \r\n"
+               " property. Removing entire property:\r\n"
+               "LAST-MODIFIED:20150102T181722Z\r\n"
+               "X-LIC-ERROR;X-LIC-ERRORTYPE=VALUE-PARSE-ERROR:No value for LOCATION \r\n"
+               " property. Removing entire property:\r\n"
+               "SUMMARY:with errors\r\n"
+               "END:VEVENT\r\n";
+       ECalComponent *comp;
+       ICalComponent *icalcomp;
+
+       comp = e_cal_component_new_from_string (vevent);
+       g_assert_nonnull (comp);
+
+       icalcomp = e_cal_component_get_icalcomponent (comp);
+       g_assert_nonnull (icalcomp);
+
+       g_assert_cmpint (i_cal_component_count_properties (icalcomp, I_CAL_XLICERROR_PROPERTY), ==, 2);
+
+       e_cal_component_strip_errors (comp);
+
+       g_assert_cmpint (i_cal_component_count_properties (icalcomp, I_CAL_XLICERROR_PROPERTY), ==, 0);
+
+       g_object_unref (comp);
+}
+
+gint
+main (gint argc,
+      gchar **argv)
+{
+       g_test_init (&argc, &argv, NULL);
+       g_test_bug_base ("https://bugzilla.gnome.org/";);
+
+       g_test_add_func ("/ECalComponent/struct/Alarm", test_component_struct_alarm);
+       g_test_add_func ("/ECalComponent/struct/Alarms", test_component_struct_alarms);
+       g_test_add_func ("/ECalComponent/struct/AlarmInstance", test_component_struct_alarm_instance);
+       g_test_add_func ("/ECalComponent/struct/AlarmRepeat", test_component_struct_alarm_repeat);
+       g_test_add_func ("/ECalComponent/struct/AlarmTrigger", test_component_struct_alarm_trigger);
+       g_test_add_func ("/ECalComponent/struct/Attendee", test_component_struct_attendee);
+       g_test_add_func ("/ECalComponent/struct/DateTime", test_component_struct_datetime);
+       g_test_add_func ("/ECalComponent/struct/Id", test_component_struct_id);
+       g_test_add_func ("/ECalComponent/struct/Organizer", test_component_struct_organizer);
+       g_test_add_func ("/ECalComponent/struct/Period", test_component_struct_period);
+       g_test_add_func ("/ECalComponent/struct/Range", test_component_struct_range);
+       g_test_add_func ("/ECalComponent/struct/Text", test_component_struct_text);
+       g_test_add_func ("/ECalComponent/vtype", test_component_vtype);
+       g_test_add_func ("/ECalComponent/uid", test_component_uid);
+       g_test_add_func ("/ECalComponent/categories", test_component_categories);
+       g_test_add_func ("/ECalComponent/classification", test_component_classification);
+       g_test_add_func ("/ECalComponent/comments", test_component_comments);
+       g_test_add_func ("/ECalComponent/completed", test_component_completed);
+       g_test_add_func ("/ECalComponent/contacts", test_component_contacts);
+       g_test_add_func ("/ECalComponent/created", test_component_created);
+       g_test_add_func ("/ECalComponent/descriptions", test_component_descriptions);
+       g_test_add_func ("/ECalComponent/dtend", test_component_dtend);
+       g_test_add_func ("/ECalComponent/dtstamp", test_component_dtstamp);
+       g_test_add_func ("/ECalComponent/dtstart", test_component_dtstart);
+       g_test_add_func ("/ECalComponent/due", test_component_due);
+       g_test_add_func ("/ECalComponent/exdates", test_component_exdates);
+       g_test_add_func ("/ECalComponent/exrules", test_component_exrules);
+       g_test_add_func ("/ECalComponent/geo", test_component_geo);
+       g_test_add_func ("/ECalComponent/lastmodified", test_component_lastmodified);
+       g_test_add_func ("/ECalComponent/organizer", test_component_organizer);
+       g_test_add_func ("/ECalComponent/percentcomplete", test_component_percentcomplete);
+       g_test_add_func ("/ECalComponent/priority", test_component_priority);
+       g_test_add_func ("/ECalComponent/recurid", test_component_recurid);
+       g_test_add_func ("/ECalComponent/rdates", test_component_rdates);
+       g_test_add_func ("/ECalComponent/rrules", test_component_rrules);
+       g_test_add_func ("/ECalComponent/sequence", test_component_sequence);
+       g_test_add_func ("/ECalComponent/status", test_component_status);
+       g_test_add_func ("/ECalComponent/summary", test_component_summary);
+       g_test_add_func ("/ECalComponent/transparency", test_component_transparency);
+       g_test_add_func ("/ECalComponent/url", test_component_url);
+       g_test_add_func ("/ECalComponent/attendees", test_component_attendees);
+       g_test_add_func ("/ECalComponent/location", test_component_location);
+       g_test_add_func ("/ECalComponent/attachments", test_component_attachments);
+       g_test_add_func ("/ECalComponent/alarms", test_component_alarms);
+       g_test_add_func ("/ECalComponent/striperrors", test_component_striperrors);
+
+       return g_test_run ();
+}


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