/* test-utils.c * * Copyright © 2018 Georges Basile Stavracas Neto * * 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 . */ #include #include #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? | Référence système\n" \ "Pour les organisateurs : Options de réunion\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 Lima" }, { "\"Lima, Ana\" ", "ana@example.com", "Lima, Ana" }, { "", "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 ", }; 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 (); }