I#27 - [IMAPx] Ignore DavMail's CR/LF in BODYSTRUCTURE response
[evolution-data-server.git] / tests / libedata-cal / test-cal-cache-intervals.c
blob449bc0c1385e05facb7cba323a60aa0c8d2da975
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * This program is free software: you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
10 * for more details.
12 * You should have received a copy of the GNU Lesser General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include <stdlib.h>
18 #include <locale.h>
19 #include <libecal/libecal.h>
21 #include "test-cal-cache-utils.h"
23 #define NUM_INTERVALS_CLOSED 100
24 #define NUM_INTERVALS_OPEN 100
25 #define NUM_SEARCHES 500
26 #define DELETE_PROBABILITY 0.3
27 #define _TIME_MIN ((time_t) 0) /* Min valid time_t */
28 #define _TIME_MAX ((time_t) INT_MAX) /* Max valid time_t */
30 typedef struct _IntervalData {
31 gint start;
32 gint end;
33 ECalComponent * comp;
34 } IntervalData;
36 static void
37 interval_data_free (gpointer ptr)
39 IntervalData *id = ptr;
41 if (id) {
42 g_object_unref (id->comp);
43 g_free (id);
47 static gint
48 compare_intervals (time_t x_start,
49 time_t x_end,
50 time_t y_start,
51 time_t y_end)
53 /* assumption: x_start <= x_end */
54 /* assumption: y_start <= y_end */
56 /* x is left of y */
57 if (x_end < y_start)
58 return -1;
60 /* x is right of y */
61 if (y_end < x_start)
62 return 1;
64 /* x and y overlap */
65 return 0;
68 static GHashTable *
69 search_in_intervals (ETimezoneCache *zone_cache,
70 GSList *intervals,
71 time_t start,
72 time_t end)
74 ECalBackendSExp *sexp;
75 struct icaltimetype itt_start, itt_end;
76 gchar *expr;
77 GSList *link;
78 GHashTable *res;
80 itt_start = icaltime_from_timet_with_zone (start, FALSE, NULL);
81 itt_end = icaltime_from_timet_with_zone (end, FALSE, NULL);
83 expr = g_strdup_printf ("(occur-in-time-range? (make-time \"%04d%02d%02dT%02d%02d%02dZ\") (make-time \"%04d%02d%02dT%02d%02d%02dZ\"))",
84 itt_start.year, itt_start.month, itt_start.day, itt_start.hour, itt_start.minute, itt_start.second,
85 itt_end.year, itt_end.month, itt_end.day, itt_end.hour, itt_end.minute, itt_end.second);
87 sexp = e_cal_backend_sexp_new (expr);
89 g_free (expr);
91 g_assert_nonnull (sexp);
93 res = g_hash_table_new_full ((GHashFunc) e_cal_component_id_hash, (GEqualFunc) e_cal_component_id_equal,
94 (GDestroyNotify) e_cal_component_free_id, g_object_unref);
96 for (link = intervals; link; link = g_slist_next (link)) {
97 IntervalData *data = link->data;
99 if (compare_intervals (start, end, data->start, data->end) == 0 &&
100 e_cal_backend_sexp_match_comp (sexp, data->comp, zone_cache)) {
101 ECalComponentId *id = NULL;
103 id = e_cal_component_get_id (data->comp);
104 g_assert_nonnull (id);
106 g_hash_table_insert (res, id, g_object_ref (data->comp));
110 g_object_unref (sexp);
112 return res;
115 static void
116 check_search_results (GSList *ecalcomps,
117 GHashTable *from_intervals)
119 GSList *link;
121 g_assert_cmpint (g_slist_length (ecalcomps), ==, g_hash_table_size (from_intervals));
123 for (link = ecalcomps; link; link = g_slist_next (link)) {
124 ECalComponent *comp = link->data;
125 ECalComponentId *id = NULL;
127 id = e_cal_component_get_id (comp);
128 g_assert_nonnull (id);
130 g_assert (g_hash_table_contains (from_intervals, id));
132 e_cal_component_free_id (id);
136 static ECalComponent *
137 create_test_component (time_t start,
138 time_t end)
140 ECalComponent *comp;
141 ECalComponentText summary;
142 struct icaltimetype current, ittstart, ittend;
144 comp = e_cal_component_new ();
146 e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
148 ittstart = icaltime_from_timet_with_zone (start, 0, NULL);
149 ittend = icaltime_from_timet_with_zone (end, 0, NULL);
151 icalcomponent_set_dtstart (e_cal_component_get_icalcomponent (comp), ittstart);
152 if (end != _TIME_MAX)
153 icalcomponent_set_dtend (e_cal_component_get_icalcomponent (comp), ittend);
155 summary.value = g_strdup_printf ("%s - %s", icaltime_as_ical_string (ittstart), icaltime_as_ical_string (ittend));
156 summary.altrep = NULL;
158 e_cal_component_set_summary (comp, &summary);
160 g_free ((gchar *) summary.value);
162 current = icaltime_from_timet_with_zone (time (NULL), 0, NULL);
163 e_cal_component_set_created (comp, &current);
164 e_cal_component_set_last_modified (comp, &current);
166 e_cal_component_rescan (comp);
168 return comp;
171 static void
172 test_intervals (TCUFixture *fixture,
173 gconstpointer user_data)
176 * outline:
177 * 1. create new tree and empty list of intervals
178 * 2. insert some intervals into tree and list
179 * 3. do various searches, compare results of both structures
180 * 4. delete some intervals
181 * 5. do various searches, compare results of both structures
182 * 6. free memory
184 GRand *myrand;
185 IntervalData *interval;
186 ECalComponent *comp;
187 ETimezoneCache *zone_cache;
188 GSList *l1, *intervals = NULL;
189 GHashTable *from_intervals;
190 gint num_deleted = 0;
191 gint ii, start, end;
192 gboolean success;
193 GError *error = NULL;
195 zone_cache = E_TIMEZONE_CACHE (fixture->cal_cache);
197 myrand = g_rand_new ();
199 for (ii = 0; ii < NUM_INTERVALS_CLOSED; ii++) {
200 start = g_rand_int_range (myrand, 0, 1000);
201 end = g_rand_int_range (myrand, start, 2000);
202 comp = create_test_component (start, end);
203 g_assert (comp != NULL);
205 interval = g_new (IntervalData, 1);
206 interval->start = start;
207 interval->end = end;
208 interval->comp = comp;
210 intervals = g_slist_prepend (intervals, interval);
212 success = e_cal_cache_put_component (fixture->cal_cache, comp, NULL, E_CACHE_IS_ONLINE, NULL, &error);
213 g_assert_no_error (error);
214 g_assert (success);
217 end = _TIME_MAX;
219 /* insert open ended intervals */
220 for (ii = 0; ii < NUM_INTERVALS_OPEN; ii++) {
221 start = g_rand_int_range (myrand, 0, 1000);
222 comp = create_test_component (start, end);
223 g_assert (comp != NULL);
225 interval = g_new (IntervalData, 1);
226 interval->start = start;
227 interval->end = end;
228 interval->comp = comp;
230 intervals = g_slist_prepend (intervals, interval);
232 success = e_cal_cache_put_component (fixture->cal_cache, comp, NULL, E_CACHE_IS_ONLINE, NULL, &error);
233 g_assert_no_error (error);
234 g_assert (success);
237 for (ii = 0; ii < NUM_SEARCHES; ii++) {
238 start = g_rand_int_range (myrand, 0, 1000);
239 end = g_rand_int_range (myrand, 2000, _TIME_MAX);
241 l1 = NULL;
243 success = e_cal_cache_get_components_in_range (fixture->cal_cache, start, end, &l1, NULL, &error);
244 g_assert_no_error (error);
245 g_assert (success);
247 from_intervals = search_in_intervals (zone_cache, intervals, start, end);
249 check_search_results (l1, from_intervals);
251 g_slist_free_full (l1, g_object_unref);
252 g_hash_table_destroy (from_intervals);
255 /* open-ended intervals */
256 for (ii = 0; ii < 20; ii++) {
257 start = g_rand_int_range (myrand, 0, 1000);
258 end = _TIME_MAX;
260 l1 = NULL;
262 success = e_cal_cache_get_components_in_range (fixture->cal_cache, start, end, &l1, NULL, &error);
263 g_assert_no_error (error);
264 g_assert (success);
266 from_intervals = search_in_intervals (zone_cache, intervals, start, end);
268 check_search_results (l1, from_intervals);
270 g_slist_free_full (l1, g_object_unref);
271 g_hash_table_destroy (from_intervals);
274 l1 = intervals;
276 while (l1) {
277 /* perhaps we will delete l1 */
278 GSList *next = l1->next;
280 if (g_rand_double (myrand) < DELETE_PROBABILITY) {
281 ECalComponent *comp;
282 ECalComponentId *id;
284 interval = l1->data;
285 comp = interval->comp;
287 id = e_cal_component_get_id (comp);
288 g_assert (id != NULL);
290 success = e_cal_cache_remove_component (fixture->cal_cache, id->uid, id->rid, E_CACHE_IS_ONLINE, NULL, &error);
291 g_assert_no_error (error);
292 g_assert (success);
294 e_cal_component_free_id (id);
296 interval_data_free (interval);
297 intervals = g_slist_delete_link (intervals, l1);
299 num_deleted++;
302 l1 = next;
305 for (ii = 0; ii < NUM_SEARCHES; ii++) {
306 start = g_rand_int_range (myrand, 0, 1000);
307 end = g_rand_int_range (myrand, start + 1, 2000);
309 l1 = NULL;
311 success = e_cal_cache_get_components_in_range (fixture->cal_cache, start, end, &l1, NULL, &error);
312 g_assert_no_error (error);
313 g_assert (success);
315 from_intervals = search_in_intervals (zone_cache, intervals, start, end);
317 check_search_results (l1, from_intervals);
319 g_slist_free_full (l1, g_object_unref);
320 g_hash_table_destroy (from_intervals);
323 g_slist_free_full (intervals, interval_data_free);
324 g_rand_free (myrand);
327 gint
328 main (gint argc,
329 gchar **argv)
331 #if !GLIB_CHECK_VERSION (2, 35, 1)
332 g_type_init ();
333 #endif
334 g_test_init (&argc, &argv, NULL);
336 /* Ensure that the client and server get the same locale */
337 g_assert (g_setenv ("LC_ALL", "en_US.UTF-8", TRUE));
338 setlocale (LC_ALL, "");
340 g_test_add ("/ECalCache/Intervals", TCUFixture, NULL,
341 tcu_fixture_setup, test_intervals, tcu_fixture_teardown);
343 return g_test_run ();