Files
Georges Basile Stavracas Neto c18218d1f6 core/event-list: Use uids to compare events
We can have multiple GcalEvent* instances for the same underlying
icalcomponent. Compare the uids instead of the raw pointers.

Closes https://gitlab.gnome.org/GNOME/gnome-calendar/-/work_items/1585

Part-of: <https://gitlab.gnome.org/GNOME/gnome-calendar/-/merge_requests/766>
2026-05-20 15:42:15 -04:00

252 lines
8.1 KiB
C

/*
* test-event-list.c
*
* Copyright 2026 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <glib.h>
#include "gcal-event.h"
#include "gcal-event-list.h"
#include "gcal-stub-calendar.h"
#include "gcal-utils.h"
#define EVENT_STRING_FOR_DATE(uid, dtstart,dtend) \
"BEGIN:VEVENT\n" \
"SUMMARY:Stub event\n" \
"UID:example@uid"uid"\n" \
"DTSTAMP:19970114T170000Z\n" \
"DTSTART"dtstart"\n" \
"DTEND"dtend"\n" \
"END:VEVENT\n"
#define EVENT_STRING_FOR_DATE_START(dtstart) \
EVENT_STRING_FOR_DATE(dtstart, ":20260715T035959Z")
#define EVENT_STRING_FOR_DATE_END(dtend) \
EVENT_STRING_FOR_DATE(":19970101T170000Z", dtend)
/*
* Auxiliary methods
*/
static GcalEvent*
create_event_for_string (const gchar *string,
GError **error)
{
g_autoptr (ECalComponent) component = NULL;
g_autoptr (GcalCalendar) calendar = NULL;
component = e_cal_component_new_from_string (string);
calendar = gcal_stub_calendar_new (NULL, error);
return component ? gcal_event_new (calendar, component, error) : NULL;
}
/*********************************************************************************************************************/
static void
event_list_new (void)
{
g_autoptr (GcalEventList) event_list = NULL;
event_list = gcal_event_list_new ();
g_assert_true (GCAL_IS_EVENT_LIST (event_list));
}
/*********************************************************************************************************************/
typedef struct {
guint n_items_changed;
guint position;
guint added;
guint removed;
} AddEventsHelper;
static void
items_changed_cb (GListModel *model,
guint position,
guint removed,
guint added,
gpointer user_data)
{
AddEventsHelper *helper = user_data;
helper->n_items_changed++;
helper->position = position;
helper->removed = removed;
helper->added = added;
}
static void
event_list_add_events (void)
{
g_autoptr (GcalEventList) event_list = NULL;
g_autoptr (GPtrArray) events = NULL;
AddEventsHelper helper = { };
const gchar * const event_strings[] = {
EVENT_STRING_FOR_DATE ("event1", ":20260331T000000Z", ":20260331T030000Z"),
EVENT_STRING_FOR_DATE ("event2", ":20260401T000000Z", ":20260401T030000Z"),
EVENT_STRING_FOR_DATE ("event3", ":20260402T000000Z", ":20260403T030000Z"),
};
event_list = gcal_event_list_new ();
g_assert_true (GCAL_IS_EVENT_LIST (event_list));
events = g_ptr_array_new_null_terminated (G_N_ELEMENTS (event_strings), g_object_unref, TRUE);
for (gsize i = 0; i < G_N_ELEMENTS (event_strings); i++)
{
g_autoptr (GcalEvent) event = NULL;
g_autoptr (GError) error = NULL;
event = create_event_for_string (event_strings[i], &error);
g_assert_no_error (error);
g_ptr_array_add (events, g_steal_pointer (&event));
}
g_signal_connect (event_list, "items-changed", G_CALLBACK (items_changed_cb), &helper);
gcal_event_list_add_events (event_list, (GcalEvent **) events->pdata);
g_assert_cmpuint (helper.n_items_changed, ==, 1);
g_assert_cmpuint (helper.position, ==, 0);
g_assert_cmpuint (helper.removed, ==, 0);
g_assert_cmpuint (helper.added, ==, 3);
g_assert_cmpuint (g_list_model_get_n_items (G_LIST_MODEL (event_list)), ==, 3);
for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (event_list)); i++)
{
g_autoptr (GcalEvent) event = g_list_model_get_item (G_LIST_MODEL (event_list), i);
g_assert_true (event == g_ptr_array_index (events, i));
}
}
/*********************************************************************************************************************/
typedef struct {
guint n_items_changed;
guint position;
guint added;
guint removed;
} RemoveEventsHelper;
static void
event_list_remove_events_items_changed_cb (GListModel *model,
guint position,
guint removed,
guint added,
gpointer user_data)
{
RemoveEventsHelper *helper = user_data;
helper->n_items_changed++;
helper->position = position;
helper->removed = removed;
helper->added = added;
}
static void
event_list_remove_events (void)
{
g_autoptr (GcalEventList) event_list = NULL;
g_autoptr (GPtrArray) events = NULL;
RemoveEventsHelper helper = { };
const gchar * const event_strings[] = {
EVENT_STRING_FOR_DATE ("event1", ":20260331T000000Z", ":20260331T030000Z"),
EVENT_STRING_FOR_DATE ("event2", ":20260401T000000Z", ":20260401T030000Z"),
EVENT_STRING_FOR_DATE ("event3", ":20260402T000000Z", ":20260403T030000Z"),
};
event_list = gcal_event_list_new ();
g_assert_true (GCAL_IS_EVENT_LIST (event_list));
events = g_ptr_array_new_null_terminated (G_N_ELEMENTS (event_strings), g_object_unref, TRUE);
for (gsize i = 0; i < G_N_ELEMENTS (event_strings); i++)
{
g_autoptr (GcalEvent) event = NULL;
g_autoptr (GError) error = NULL;
event = create_event_for_string (event_strings[i], &error);
g_assert_no_error (error);
g_ptr_array_add (events, g_steal_pointer (&event));
}
g_signal_connect (event_list,
"items-changed",
G_CALLBACK (event_list_remove_events_items_changed_cb),
&helper);
gcal_event_list_add_events (event_list, (GcalEvent **) events->pdata);
g_assert_cmpuint (helper.n_items_changed, ==, 1);
g_assert_cmpuint (helper.position, ==, 0);
g_assert_cmpuint (helper.removed, ==, 0);
g_assert_cmpuint (helper.added, ==, 3);
g_assert_cmpuint (g_list_model_get_n_items (G_LIST_MODEL (event_list)), ==, 3);
for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (event_list)); i++)
{
g_autoptr (GcalEvent) event = g_list_model_get_item (G_LIST_MODEL (event_list), i);
g_assert_true (event == g_ptr_array_index (events, i));
}
helper = (RemoveEventsHelper) { };
gcal_event_list_remove_events (event_list, (GcalEvent **) events->pdata);
g_assert_cmpuint (helper.n_items_changed, ==, 1);
g_assert_cmpuint (helper.position, ==, 0);
g_assert_cmpuint (helper.removed, ==, 3);
g_assert_cmpuint (helper.added, ==, 0);
g_assert_cmpuint (g_list_model_get_n_items (G_LIST_MODEL (event_list)), ==, 0);
/* Remove again. These events are not in the list anymore. Nothing should happen */
helper = (RemoveEventsHelper) { };
gcal_event_list_remove_events (event_list, (GcalEvent **) events->pdata);
g_assert_cmpuint (helper.n_items_changed, ==, 0);
g_assert_cmpuint (helper.position, ==, 0);
g_assert_cmpuint (helper.removed, ==, 0);
g_assert_cmpuint (helper.added, ==, 0);
g_assert_cmpuint (g_list_model_get_n_items (G_LIST_MODEL (event_list)), ==, 0);
}
/*********************************************************************************************************************/
gint
main (gint argc,
gchar *argv[])
{
g_setenv ("TZ", "UTC", TRUE);
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/event-list/new", event_list_new);
g_test_add_func ("/event-list/add-events", event_list_add_events);
g_test_add_func ("/event-list/remove-events", event_list_remove_events);
return g_test_run ();
}