/* Evolution calendar client - test program * * Copyright (C) 2000 Ximian, Inc. * Copyright (C) 2000 Ximian, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include /* start_testing_scaffold */ #define mu_assert(message, test) do { if (!(test)) return message; else { tests_passed++; return NULL;}} while (0) #define mu_run_test(test) do { char *message = test; tests_run++; \ if (message) { cl_printf (client, "***Error***\n%s\n", message); break;} } while (0) static int tests_run = 0; static int tests_passed = 0; /* end_testing_scaffold */ static ECal *client1; static ECal *client2; static GMainLoop *loop; /* Prints a message with a client identifier */ static void cl_printf (ECal *client, const char *format, ...) { va_list args; va_start (args, format); if ( client != client1) return; printf ("Client %s: ", "Test"); vprintf (format, args); va_end (args); } static void objects_added_cb (GObject *object, GList *objects, gpointer data) { GList *l; for (l = objects; l; l = l->next) cl_printf (data, "Object added %s\n", icalcomponent_get_uid (l->data)); } static void objects_modified_cb (GObject *object, GList *objects, gpointer data) { GList *l; for (l = objects; l; l = l->next) cl_printf (data, "Object modified %s\n", icalcomponent_get_uid (l->data)); } static void objects_removed_cb (GObject *object, GList *objects, gpointer data) { GList *l; for (l = objects; l; l = l->next) cl_printf (data, "Object removed %s\n", icalcomponent_get_uid (l->data)); } static void view_done_cb (GObject *object, ECalendarStatus status, gpointer data) { cl_printf (data, "View done\n"); } static gboolean list_uids (ECal *client) { GList *objects = NULL; GList *l; if (!e_cal_get_object_list (client, "(contains? \"any\" \"test\")", &objects, NULL)) return FALSE; cl_printf (client, "UIDS: "); cl_printf (client, "\nGot %d objects\n", g_list_length (objects)); if (!objects) printf ("none\n"); else { for (l = objects; l; l = l->next) { const char *uid; uid = icalcomponent_get_uid (l->data); printf ("`%s' ", uid); } printf ("\n"); for (l = objects; l; l = l->next) { printf ("------------------------------\n"); printf ("%s", icalcomponent_as_ical_string (l->data)); printf ("------------------------------\n"); } } e_cal_free_object_list (objects); return FALSE; } /* Callback used when a client is destroyed */ static void client_destroy_cb (gpointer data, GObject *object) { if (E_CAL (object) == client1) client1 = NULL; else if (E_CAL (object) == client2) client2 = NULL; else g_assert_not_reached (); if (!client1 && !client2) g_main_loop_quit (loop); } static char * test_object_creation (ECal *client, char **uid) { ECalComponent *comp, *comp_retrieved; icalcomponent *icalcomp, *icalcomp_retrieved; struct icaltimetype tt; ECalComponentText text; ECalComponentDateTime dt; ECalComponentTransparency transp; gboolean compare; GError *error = NULL; comp = e_cal_component_new (); /* set fields */ e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT); text.value = "Creation of new test event"; text.altrep = NULL; e_cal_component_set_summary (comp, &text); tt = icaltime_from_string ("20040109T090000Z"); dt.value = &tt; dt.tzid ="UTC"; e_cal_component_set_dtstart (comp, &dt); tt = icaltime_from_string ("20040109T103000"); dt.value = &tt; dt.tzid ="UTC"; e_cal_component_set_dtend (comp, &dt); e_cal_component_set_transparency (comp, E_CAL_COMPONENT_TRANSP_OPAQUE); e_cal_component_commit_sequence (comp); icalcomp = e_cal_component_get_icalcomponent (comp); if (!e_cal_create_object (client, icalcomp, uid, &error)) { cl_printf (client, "Object creation: %s\n", error->message); g_free (comp); g_free (icalcomp); return "Test Object Creation failed"; } e_cal_component_commit_sequence (comp); if (!e_cal_get_object (client, *uid, NULL, &icalcomp_retrieved, &error)) { cl_printf (client, "Object retrieval: %s\n", error->message); g_free (uid); g_free (comp); g_free (icalcomp); return "Test Object Creation failed"; } comp_retrieved = e_cal_component_new (); if (!e_cal_component_set_icalcomponent (comp_retrieved, icalcomp_retrieved)) { cl_printf (client, "Could not set icalcomponent\n"); g_free (uid); g_free (comp); g_free (icalcomp); g_free (icalcomp_retrieved); return "Test Object Creation failed"; } /* Dumping icalcomp into a string is not useful as the retrieved object * has some generated information like timestamps. We compare * member values we set during creation*/ compare = e_cal_component_event_dates_match (comp, comp_retrieved); if (compare) { e_cal_component_get_transparency (comp_retrieved, &transp); compare = (transp == E_CAL_COMPONENT_TRANSP_OPAQUE); } g_free (comp_retrieved); g_free (comp); g_free (icalcomp); g_free (icalcomp_retrieved); mu_assert ("Test Object creation : Created object does not match retrieved data\n", compare); return NULL; } static char * test_object_modification (ECal *client, char *uid) { const char *summary = "This summary was modified"; icalcomponent *icalcomp, *icalcomp_modified; gboolean compare; GError *error = NULL; if (!e_cal_get_object (client, uid, NULL, &icalcomp, &error)) { cl_printf (client, "Test Modify object : Could not get the object: %s\n", error->message); g_free (uid); return error->message; } // modify one property of the icalcomp and save it. Now retrieve it and // check the field. icalcomponent_set_summary (icalcomp, summary); if (!e_cal_modify_object (client, icalcomp, CALOBJ_MOD_THIS, &error)) { cl_printf (client, "Test Modify object : Could not modify the object: %s\n", error->message); g_free (uid); g_free (icalcomp); return error->message; } if (!e_cal_get_object (client, uid, NULL, &icalcomp_modified, &error)) { cl_printf (client, "Test Modify object : Could not get the modified object: %s\n", error->message); g_free (uid); g_free (icalcomp); return "Test Object Creation failed"; } compare = !strcmp ( icalcomponent_get_summary (icalcomp_modified), summary); g_free (uid); g_free (icalcomp); g_free (icalcomp_modified); mu_assert ("Test Modify object : Modification failed\n", compare); return NULL; } #if 0 static char * test_object_removal (ECal *client) { char *uid; ECalComponent *comp; icalcomponent *icalcomp; gboolean compare = 1; GError *error = NULL; comp = e_cal_component_new (); e_cal_component_commit_sequence (comp); icalcomp = e_cal_component_get_icalcomponent (comp); if (!e_cal_create_object (client, icalcomp, &uid, &error)) { cl_printf (client, "Test object removal - Object creation: %s\n", error->message); g_object_unref (comp); g_object_unref(icalcomp); return "Test Object Removal failed\n"; } if (!e_cal_remove_object (client, uid, &error)) { cl_printf (client, "Test object removal - Could not remove the object\n"); g_free (uid); g_object_unref (comp); g_object_unref (icalcomp); return "Test Object Removal failed\n"; } compare = e_cal_get_object (client, uid, NULL, &icalcomp, &error); g_free (uid); g_object_unref (comp); g_object_unref (icalcomp); mu_assert ("Test object removal - Failed\n", compare); return NULL; } #endif static char * test_get_alarms_in_range (ECal *client) { GSList *alarms; icaltimezone *utc; time_t start = time (NULL), end; gboolean compare; utc = icaltimezone_get_utc_timezone (); start = time_from_isodate ("20040212T000000Z"); end = time_add_day_with_zone (start, 2, utc); alarms = e_cal_get_alarms_in_range (client, start, end); compare = (g_slist_length (alarms) == 3); e_cal_free_alarms (alarms); mu_assert ("Test getting alarms in range\n", compare); return NULL; } static char * test_set_uri (ECal *client, const gchar *uri) { /* The uri is set as part of create_client call. This method merely * verifies it was done correctly. */ char *cal_uri; gboolean compare = 0; cal_uri = g_strconcat ("file://", uri, NULL); compare = !strcmp (e_cal_get_uri (client), cal_uri); g_free (cal_uri); mu_assert ("Test set_uri : uri was not set correctly\n", compare); return NULL; } static char * test_cal_loaded (ECal *client) { /* Test one loaded calendar and another that is not loaded. */ mu_assert ("Test get_cal_load_state : Failed \n", (E_CAL_LOAD_LOADED == e_cal_get_load_state (client)) && (E_CAL_LOAD_NOT_LOADED == e_cal_get_load_state (NULL))); return NULL; } static char * test_get_source (ECal *client, const gchar *expected) { ESource *source; char *uri; char *cal_uri; gboolean compare = 0; source = e_cal_get_source (client); uri = e_source_get_uri (source); cal_uri = g_strconcat ("file://", expected, NULL); compare = !strcmp (expected, uri); g_free (cal_uri); mu_assert ("Test get_source : Failed\n", compare); return NULL; } static char * test_query (ECal *client, const char *query, int expected) { /* This uses pre-loaded data. Hence its results are valid only * when called before any write operation is performed. */ int i = 0; GList *objects = NULL; if (!e_cal_get_object_list (client, query, &objects, NULL)) return "Could not get the list of objects"; i = g_list_length (objects); e_cal_free_object_list (objects); mu_assert ("Test get_object_list : Expected number of objects not found", i == expected); return NULL; } #if 0 static char * test_e_cal_new (ECal **cal, const char *uri) { GError *error = NULL; char *cal_uri, *cal_file; gboolean created = 0; cal_uri = g_strconcat ("file://", uri, NULL); *cal = e_cal_new_from_uri (cal_uri, E_CAL_SOURCE_TYPE_EVENT); if (!*cal) { g_message (G_STRLOC ": could not create the client"); g_free (cal_uri); return "Test Creation of new calendar : Failed"; } g_object_weak_ref (G_OBJECT (*cal), client_destroy_cb, NULL); cl_printf (*cal, "Calendar loading `%s'...\n", uri); if (!e_cal_open (*cal, FALSE, &error)) { cl_printf (*cal, "Load/create %s\n", error->message); g_free (cal_uri); return "Test creation of new calendar : Failed"; } cal_file = g_strconcat (uri, "/calendar.ics", NULL); created = g_file_test (cal_file, G_FILE_TEST_EXISTS); g_free (cal_uri); g_free (cal_file); mu_assert ("Test creation of new calendar : Failed", created); return NULL; } static char * test_e_cal_remove (ECal *ecal, const char *uri) { char *cal_uri; GError *error = NULL; gboolean removed = 0; cal_uri = g_strconcat (uri, "/calendar.ics", NULL); if (!e_cal_remove (ecal, &error)) { cl_printf (ecal, "Test Calendar removal : Could not remove the Calendar : %s\n", error->message); } removed = !g_file_test (uri, G_FILE_TEST_EXISTS); g_free (cal_uri); mu_assert ("Test Remove calendar : Failed ", removed); return NULL; } #endif static char * test_new_system_calendar(void) { ECal *cal; char *uri; gboolean created; cal = e_cal_new_system_calendar (); uri = g_build_filename (g_get_home_dir (), ".evolution", "calendar", "local", "system", "calendar.ics", NULL); created = g_file_test (uri, G_FILE_TEST_EXISTS); g_free (uri); mu_assert ("Test creation of default system calendar : Failed", created); return NULL; } static char * test_new_system_tasks(void) { ECal *cal; char *uri; gboolean created; cal = e_cal_new_system_tasks (); uri = g_build_filename (g_get_home_dir (), ".evolution", "tasks", "local", "system", "tasks.ics", NULL); created = g_file_test (uri, G_FILE_TEST_EXISTS); g_free (uri); mu_assert ("Test creation of default system tasks : Failed", created); return NULL; } static char * test_new_system_memos(void) { ECal *cal; char *uri; gboolean created; cal = e_cal_new_system_memos (); uri = g_build_filename (g_get_home_dir (), ".evolution", "memos", "local", "system", "journal.ics", NULL); created = g_file_test (uri, G_FILE_TEST_EXISTS); g_free (uri); mu_assert ("Test creation of default system memos : Failed", created); return NULL; } static char * test_get_free_busy (ECal *client) { // TODO uses NULL for users and currently specific to file backend. GList *l, *freebusy = NULL; GError *error = NULL; icaltimezone *utc; time_t start = time (NULL), end; utc = icaltimezone_get_utc_timezone (); start = time_from_isodate ("20040212T000000Z"); end = time_add_day_with_zone (start, 2, utc); if (!e_cal_get_free_busy (client, NULL, start, end, &freebusy, &error)) { cl_printf (client, "Test free/busy : Could not retrieve free busy information : %s\n", error->message); return error->message; } if (freebusy) { cl_printf (client, "Printing free busy information\n"); for (l = freebusy; l; l = l->next) { char *comp_string; ECalComponent *comp = E_CAL_COMPONENT (l->data); comp_string = e_cal_component_get_as_string (comp); cl_printf (client, "%s\n\n", comp_string); g_object_unref (comp); g_free (comp_string); } } else { cl_printf (client, "free_busy was returned but NULL"); } return NULL; } static char * test_get_default_object (ECal *client) { icalcomponent *icalcomp; GError *error = NULL; char *ical_string; if (e_cal_get_default_object (client, &icalcomp, &error)) { ical_string = icalcomponent_as_ical_string (icalcomp); cl_printf (client, "Obtained default object: %s\n", ical_string); g_free (ical_string); tests_passed++; return NULL; } else cl_printf (client, "Test Get default object : Could not get the default object: %s\n", error->message); return error->message; } /* XXX The string pasted below is *really* ugly. Alternatively, it could be * read from a file at run-time. Not sure if it is an elegant solution when * multiple clients try to load the same file during stress testing. * how can this be done better ? */ #define EXPECTED \ "BEGIN:VEVENT\ UID:20040213T055519Z-15802-500-1-3@testcal\ DTSTAMP:20040213T055519Z\ DTSTART;TZID=/softwarestudio.org/Olson_20011030_5/Asia/Calcutta:\ 20040213T130000\ DTEND;TZID=/softwarestudio.org/Olson_20011030_5/Asia/Calcutta:\ 20040213T133000\ TRANSP:OPAQUE\ SEQUENCE:3\ SUMMARY:Test - Travel plans to Kansas\ LOCATION:Yellow Brick road\ CLASS:PUBLIC\ ORGANIZER;CN=dorothy:MAILTO:dorothy@oz\ DESCRIPTION: Discuss way to home\ ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;\ RSVP=TRUE;CN=dorothy;LANGUAGE=en:MAILTO:dorothy@oz\ ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;\ RSVP=TRUE;CN=tinman;LANGUAGE=en:MAILTO:tinman@oz\ ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;\ RSVP=TRUE;CN=toto;LANGUAGE=en:MAILTO:toto@oz\ ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=OPT-PARTICIPANT;PARTSTAT=NEEDS-ACTION;\ RSVP=TRUE;CN=scarecrow;LANGUAGE=en:MAILTO:scarecrow@oz\ LAST-MODIFIED:20040213T055647Z\ END:VEVENT" static char * test_get_object (ECal *client) { const char *uid = "20040213T055519Z-15802-500-1-3@testcal"; char *actual; icalcomponent *icalcomp; gboolean compare; GError *error = NULL; if (!e_cal_get_object (client, uid, NULL, &icalcomp, &error)) { cl_printf (client, "Test Get object : Could not get the object: %s\n", error->message); return error->message; } actual = icalcomponent_as_ical_string (icalcomp); compare = !strcmp (actual, EXPECTED); g_free (actual); mu_assert ("Test : get_object does not match the expected output", compare); return NULL; } static char * test_timezones (ECal *client) { icaltimezone *zone; GError *error = NULL; if (!e_cal_get_timezone (client, "UTC", &zone, &error)) { cl_printf (client, "Could not get the timezone\n"); } printf ("\n\nTime Zones : \n%s *** %s", icaltimezone_get_display_name (zone), icaltimezone_get_tzid (zone)); printf ("\n\nTime Zones : \n%s", icaltimezone_get_location (zone)); return NULL; } static char * all_tests(ECal *client, const gchar *uri) { char *uid; mu_run_test (test_new_system_calendar ()); mu_run_test (test_new_system_tasks ()); mu_run_test (test_new_system_memos ()); mu_run_test (test_set_uri (client, uri)); mu_run_test (test_get_source (client, uri)); mu_run_test (test_cal_loaded (client)); /* test_query acts on pre-loaded data. Hence it must executed before * any writes are made */ mu_run_test (test_query (client, "(contains? \"any\" \"test\")", 2)); mu_run_test (test_query (client, "(contains? \"summary\" \"Kansas\")", 1)); mu_run_test (test_query (client, "(contains? \"any\" \"gibberish\")", 0)); mu_run_test (test_get_default_object (client)); mu_run_test (test_get_object (client)); mu_run_test (test_get_free_busy (client)); mu_run_test (test_object_creation (client, &uid)); mu_run_test (test_object_modification (client, uid)); // mu_run_test (test_object_removal (client)); mu_run_test (test_get_alarms_in_range (client)); // tmp = g_strconcat (uri, "_tmp", NULL); // mu_run_test (test_e_cal_new (&ecal, tmp)); // mu_run_test (test_e_cal_remove (ecal, tmp)); // g_free (tmp); test_timezones (client); return NULL; } /* Creates a calendar client and tries to load the specified URI into it */ static void create_client (ECal **client, const gchar *uri, ECalSourceType type, gboolean only_if_exists) { char *results; ECalView *query; char *cal_uri; GError *error = NULL; cal_uri = g_strconcat ("file://", uri, NULL); *client = e_cal_new_from_uri (cal_uri, type); if (!*client) { g_message (G_STRLOC ": could not create the client"); exit (1); } g_object_weak_ref (G_OBJECT (*client), client_destroy_cb, NULL); cl_printf (*client, "Calendar loading `%s'...\n", uri); if (!e_cal_open (*client, only_if_exists, &error)) { cl_printf (*client, "Load/create %s\n", error->message); exit (1); } g_clear_error (&error); if (!e_cal_get_query (*client, "(contains? \"any\" \"Event\")", &query, NULL)) { cl_printf (*client, G_STRLOC ": Unable to obtain query"); exit (1); } g_signal_connect (G_OBJECT (query), "objects_added", G_CALLBACK (objects_added_cb), client); g_signal_connect (G_OBJECT (query), "objects_modified", G_CALLBACK (objects_modified_cb), client); g_signal_connect (G_OBJECT (query), "objects_removed", G_CALLBACK (objects_removed_cb), client); g_signal_connect (G_OBJECT (query), "view_done", G_CALLBACK (view_done_cb), client); e_cal_view_start (query); results = all_tests (*client, uri); cl_printf (*client, "\n\n\n*************Tests run: %d****************\n\n", tests_run); cl_printf (*client, "*************Tests passed: %d*************\n\n\n", tests_passed); if (results != 0) cl_printf (*client, "***Failures********%s\n", results); cl_printf (*client, "dump of the test calendar data"); list_uids (*client); g_free (cal_uri); } int main (int argc, char **argv) { char *uri; bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR); textdomain (GETTEXT_PACKAGE); g_type_init (); loop = g_main_loop_new (NULL, TRUE); /* arg1- file name; arg2- client suffix */ uri = g_strconcat (argv[1], argv[2], NULL); create_client (&client1, uri, E_CAL_SOURCE_TYPE_EVENT, FALSE); g_free (uri); g_main_loop_run (loop); return 0; }