Files
federated-calendar/tests/test-utils.c
T

298 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* test-utils.c
*
* Copyright © 2018 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/>.
*/
#include <glib.h>
#include <locale.h>
#include "gcal-utils.h"
#define EVENT_STRING_FOR_DATE(dtstart,dtend) \
"BEGIN:VEVENT\n" \
"SUMMARY:Stub event\n" \
"UID:example@uid\n" \
"DTSTAMP:19970114T170000Z\n" \
"DTSTART"dtstart"\n" \
"DTEND"dtend"\n" \
"END:VEVENT\n"
#define STUB_CALENDAR_VTZ(dtstart,dtend) \
"BEGIN:VCALENDAR\n" \
"VERSION:2.0\n" \
"METHOD:PUBLISH\n" \
"BEGIN:VTIMEZONE\n" \
"TZID:StubTz\n" \
"BEGIN:STANDARD\n" \
"DTSTART:16011028T030000\n" \
"RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\n" \
"TZOFFSETFROM:+0200\n" \
"TZOFFSETTO:+0100\n" \
"END:STANDARD\n" \
"BEGIN:DAYLIGHT\n" \
"DTSTART:16010325T020000\n" \
"RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3\n" \
"TZOFFSETFROM:+0100\n" \
"TZOFFSETTO:+0200\n" \
"END:DAYLIGHT\n" \
"END:VTIMEZONE\n" \
"BEGIN:VEVENT\n" \
"DTSTART;TZID=StubTz"dtstart"\n" \
"DTEND;TZID=StubTz"dtend"\n" \
"LOCATION:somewhere\n" \
"SEQUENCE:0\n" \
"UID:389584207457478\n" \
"DTSTAMP:20240608T184316Z\n" \
"SUMMARY:Test time zone\n" \
"CATEGORIES:\n" \
"END:VEVENT\n" \
"END:VCALENDAR\n"
/*********************************************************************************************************************/
static void
date_time_from_icaltime (void)
{
struct
{
const gchar *string;
const gchar *start;
const gchar *end;
}
events[] = {
{
.string = EVENT_STRING_FOR_DATE (";TZID=America/New_York:20241209T170000",
";TZID=America/New_York:20241209T180000"),
.start = "2024-12-09T17:00:00-05",
.end = "2024-12-09T18:00:00-05",
},
{
.string = EVENT_STRING_FOR_DATE (":20240709T170000Z", ":20240709T180000Z"),
.start = "2024-07-09T17:00:00Z",
.end = "2024-07-09T18:00:00Z",
},
{
// Virtual time zone in standard time
.string = STUB_CALENDAR_VTZ (":20241103T103000", ":20241103T114500"),
.start = "2024-11-03T10:30:00+01",
.end = "2024-11-03T11:45:00+01",
},
{
// Virtual time zone with Daylight Saving Time
.string = STUB_CALENDAR_VTZ (":20240603T103000", ":20240603T114500"),
.start = "2024-06-03T10:30:00+02",
.end = "2024-06-03T11:45:00+02",
},
};
for (gsize i = 0; i < G_N_ELEMENTS (events); i++)
{
g_autoptr (GDateTime) gdt_start = NULL;
g_autoptr (GDateTime) gdt_end = NULL;
g_autoptr (ICalTime) dt_start = NULL;
g_autoptr (ICalTime) dt_end = NULL;
g_autofree gchar *start_str = NULL;
g_autofree gchar *end_str = NULL;
ICalComponent *comp = NULL;
comp = i_cal_component_new_from_string (events[i].string);
g_assert_nonnull (comp);
dt_start = i_cal_component_get_dtstart (comp);
g_assert_nonnull (dt_start);
gdt_start = gcal_date_time_from_icaltime (dt_start);
g_assert_nonnull (gdt_start);
dt_end = i_cal_component_get_dtend (comp);
g_assert_nonnull (dt_end);
gdt_end = gcal_date_time_from_icaltime (dt_end);
g_assert_nonnull (gdt_end);
start_str = g_date_time_format_iso8601 (gdt_start);
end_str = g_date_time_format_iso8601 (gdt_end);
g_assert_cmpstr (start_str, ==, events[i].start);
g_assert_cmpstr (end_str, ==, events[i].end);
g_clear_object (&comp);
}
}
/*********************************************************************************************************************/
#define GOOGLE_SAMPLE_DESCRIPTION \
"-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-\n" \
"Entrar com o Google Meet: https://meet.google.com/abc-defg-hij\n" \
"\n" \
"Saiba mais sobre o Meet em: https://support.google.com/a/users/answer/9282720\n" \
"\n" \
"Não edite esta seção.\n" \
"-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-"
#define GOOGLE_SAMPLE_DESCRIPTION_WITH_COMMENT \
"TROLOLO\n" \
"-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-\n" \
"Entrar com o Google Meet: https://meet.google.com/abc-defg-hij\n" \
"\n" \
"Saiba mais sobre o Meet em: https://support.google.com/a/users/answer/9282720\n" \
"\n" \
"Não edite esta seção.\n" \
"-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-"
#define TEAMS_SAMPLE_DESCRIPTION \
"________________________________________________________________________________\n" \
"Réunion Microsoft Teams\n" \
"Joindre : https://teams.microsoft.com/meet/12345678912345?p=0AbCdEfGjKLm1nOjTj\n" \
"Numéro de réunion : 123 456 789 123 45\n" \
"Code secret : abcdefgh\n" \
"________________________________\n" \
"Besoin d’aide?<https://aka.ms/JoinTeamsMeeting?omkt=fr-CA> | Référence système<https://teams.microsoft.com/l/meetup-join/19%3ameeting_KLMNTABC02UJKL5OC00ZWJhLThhNDgtYmJlYTI2ZTE5YzM0%40abc.v2/0?context=%7b%22Tid%22%3a%3f5f042f-920a-4035-8dc7-477b5dce3c73%22%2c%22Oid%22%3a%aa4dd47c-47a1-4a00-b766-6e5f83e7d367%22%7d>\n" \
"Pour les organisateurs : Options de réunion<https://teams.microsoft.com/meetingOptions/?organizerId=690add55-d0e3-4605-ac28-a3a08193c212&tenantId=43743467-968a-4ded-8250-afd003a4a407&threadId=19_meeting_Yjk5NTI0M2UtNjA5OC00ZWJhLThhNDgtYmJlYTI2ZTE5YzM0&messageId=100&language=fr-CA>\n" \
"________________________________________________________________________________"
static void
extract_meeting_url (void)
{
g_autofree char *description = NULL;
g_autofree char *meeting_url = NULL;
gcal_util_extract_meeting_url (GOOGLE_SAMPLE_DESCRIPTION, &description, &meeting_url);
g_assert_cmpstr (description, ==, "");
g_assert_cmpstr (meeting_url, ==, "https://meet.google.com/abc-defg-hij");
g_clear_pointer (&description, g_free);
g_clear_pointer (&meeting_url, g_free);
gcal_util_extract_meeting_url (GOOGLE_SAMPLE_DESCRIPTION_WITH_COMMENT, &description, &meeting_url);
g_assert_cmpstr (description, ==, "TROLOLO\n");
g_assert_cmpstr (meeting_url, ==, "https://meet.google.com/abc-defg-hij");
g_clear_pointer (&description, g_free);
g_clear_pointer (&meeting_url, g_free);
gcal_util_extract_meeting_url (TEAMS_SAMPLE_DESCRIPTION, &description, &meeting_url);
g_assert_cmpstr (description, ==, "");
g_assert_cmpstr (meeting_url, ==, "https://teams.microsoft.com/meet/12345678912345?p=0AbCdEfGjKLm1nOjTj");
}
/*********************************************************************************************************************/
typedef struct {
const char *locale_name;
int week_start_index;
} LocaleIsoWeekDay;
static void
test_first_weekday (void)
{
LocaleIsoWeekDay test_cases[] = {
{ "C", 7 }, // Baseline standard (Sunday)
{ "en_US.UTF-8", 7 }, // US Standard (Sunday)
{ "de_DE.UTF-8", 1 }, // Euro Standard (Monday)
{ "en_GB.UTF-8", 1 }, // UK Standard (Monday)
{ "fa_IR.UTF-8", 6 } // Iran, Somalia, Afghanistan (Saturday)
};
const char* initial_locale = setlocale (LC_ALL, NULL);
for (size_t i = 0; i < G_N_ELEMENTS (test_cases); ++i)
{
LocaleIsoWeekDay testcase = test_cases[i];
char *current_locale = setlocale (LC_ALL, testcase.locale_name);
if (!current_locale)
{
g_message ("Locale %s not installed. Skipping", testcase.locale_name);
continue;
}
else
{
g_message ("Testing locale %s", testcase.locale_name);
g_assert_cmpint (testcase.week_start_index, ==, gcal_util_get_first_weekday_iso ());
}
}
/* restore locale */
setlocale (LC_ALL, initial_locale);
}
/*********************************************************************************************************************/
static void
parse_email_address (void)
{
struct {
const gchar *text;
const gchar *email;
const gchar *name;
} valid[] = {
{ "ana@example.com", "ana@example.com", NULL },
{ " ana@example.com ", "ana@example.com", NULL },
{ "mailto:ana@example.com", "ana@example.com", NULL },
{ "Ana Lima <ana@example.com>", "ana@example.com", "Ana Lima" },
{ "\"Lima, Ana\" <ana@example.com>", "ana@example.com", "Lima, Ana" },
{ "<ana@example.com>", "ana@example.com", NULL },
{ "ana.lima+work@mail.example.co.uk", "ana.lima+work@mail.example.co.uk", NULL },
};
const gchar *invalid[] = {
NULL,
"",
"ana",
"ana@",
"@example.com",
"ana@example",
"ana@example.",
"ana@.example.com",
"ana@@example.com",
"ana lima@example.com",
"Ana Lima <ana>",
};
for (gsize i = 0; i < G_N_ELEMENTS (valid); i++)
{
g_autofree gchar *email = NULL;
g_autofree gchar *name = NULL;
g_assert_true (gcal_util_parse_email_address (valid[i].text, &email, &name));
g_assert_cmpstr (email, ==, valid[i].email);
g_assert_cmpstr (name, ==, valid[i].name);
}
for (gsize i = 0; i < G_N_ELEMENTS (invalid); i++)
g_assert_false (gcal_util_parse_email_address (invalid[i], NULL, NULL));
}
/*********************************************************************************************************************/
gint
main (gint argc,
gchar *argv[])
{
g_setenv ("TZ", "UTC", TRUE);
g_test_init (&argc, &argv, NULL);
g_test_bug_base ("https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/");
g_test_add_func ("/utils/date-time/date_time_from_icaltime", date_time_from_icaltime);
g_test_add_func ("/utils/misc/extract_meeting_url", extract_meeting_url);
g_test_add_func ("/utils/misc/get_first_weekday", test_first_weekday);
g_test_add_func ("/utils/misc/parse_email_address", parse_email_address);
return g_test_run ();
}