New EClient/EBookClient/ECalClient API deprecating EBook/ECal
[platform/upstream/evolution-data-server.git] / tests / libebook / client / client-test-utils.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 #include <stdio.h>
4
5 #include "client-test-utils.h"
6
7 void
8 report_error (const gchar *operation, GError **error)
9 {
10         g_return_if_fail (operation != NULL);
11
12         g_printerr ("Failed to %s: %s\n", operation, (error && *error) ? (*error)->message : "Unknown error");
13
14         g_clear_error (error);
15 }
16
17 void
18 print_email (EContact *contact)
19 {
20         const gchar *file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS);
21         const gchar *name_or_org = e_contact_get_const (contact, E_CONTACT_NAME_OR_ORG);
22         GList *emails, *e;
23
24         g_print ("   Contact: %s\n", file_as);
25         g_print ("   Name or org: %s\n", name_or_org);
26         g_print ("   Email addresses:\n");
27         emails = e_contact_get (contact, E_CONTACT_EMAIL);
28         for (e = emails; e; e = e->next) {
29                 g_print ("\t%s\n",  (gchar *)e->data);
30         }
31         g_list_foreach (emails, (GFunc)g_free, NULL);
32         g_list_free (emails);
33
34         g_print ("\n");
35 }
36
37 EBookClient *
38 open_system_book (gboolean only_if_exists)
39 {
40         EBookClient *book_client;
41         GError *error = NULL;
42
43         main_initialize ();
44
45         book_client = e_book_client_new_system (&error);
46         if (error) {
47                 report_error ("create system addressbook", &error);
48                 return NULL;
49         }
50
51         if (!e_client_open_sync (E_CLIENT (book_client), only_if_exists, NULL, &error)) {
52                 g_object_unref (book_client);
53                 report_error ("open client sync", &error);
54                 return NULL;
55         }
56
57         return book_client;
58 }
59
60 void
61 main_initialize (void)
62 {
63         static gboolean initialized = FALSE;
64
65         if (initialized)
66                 return;
67
68         g_type_init ();
69         g_thread_init (NULL);
70
71         initialized = TRUE;
72 }
73
74 struct IdleData {
75         GThreadFunc func;
76         gpointer data;
77         gboolean run_in_thread; /* FALSE to run in idle callback */
78 };
79
80 static gboolean
81 idle_cb (gpointer data)
82 {
83         struct IdleData *idle = data;
84
85         g_return_val_if_fail (idle != NULL, FALSE);
86         g_return_val_if_fail (idle->func != NULL, FALSE);
87
88         if (idle->run_in_thread) {
89                 GError *error = NULL;
90
91                 g_thread_create (idle->func, idle->data, FALSE, &error);
92
93                 if (error) {
94                         report_error ("create thread", &error);
95                         stop_main_loop (1);
96                 }
97         } else {
98                 idle->func (idle->data);
99         }
100
101         g_free (idle);
102
103         return FALSE;
104 }
105
106 static GMainLoop *loop = NULL;
107 static gint main_stop_result = 0;
108
109 static void
110 do_start (GThreadFunc func, gpointer data)
111 {
112         main_initialize ();
113
114         g_return_if_fail (loop == NULL);
115
116         loop = g_main_loop_new (NULL, FALSE);
117
118         if (func)
119                 func (data);
120
121         g_main_loop_run (loop);
122
123         g_main_loop_unref (loop);
124         loop = NULL;
125 }
126
127 /* Starts new main-loop, but just before that calls 'func'.
128    Main-loop is kept running, and this function blocks, 
129    until call of stop_main_loop().
130 */
131 void
132 start_main_loop (GThreadFunc func, gpointer data)
133 {
134         g_return_if_fail (loop == NULL);
135
136         do_start (func, data);
137 }
138
139 /* Starts new main-loop and then invokes func in a new thread.
140    Main-loop is kept running, and this function blocks, 
141    until call of stop_main_loop().
142 */
143 void
144 start_in_thread_with_main_loop (GThreadFunc func, gpointer data)
145 {
146         struct IdleData *idle;
147
148         g_return_if_fail (func != NULL);
149         g_return_if_fail (loop == NULL);
150
151         main_initialize ();
152
153         idle = g_new0 (struct IdleData, 1);
154         idle->func = func;
155         idle->data = data;
156         idle->run_in_thread = TRUE;
157
158         g_idle_add (idle_cb, idle);
159
160         do_start (NULL, NULL);
161 }
162
163 /* Starts new main-loop and then invokes func in an idle callback.
164    Main-loop is kept running, and this function blocks, 
165    until call of stop_main_loop().
166 */
167 void
168 start_in_idle_with_main_loop (GThreadFunc func, gpointer data)
169 {
170         struct IdleData *idle;
171
172         g_return_if_fail (func != NULL);
173         g_return_if_fail (loop == NULL);
174
175         main_initialize ();
176
177         idle = g_new0 (struct IdleData, 1);
178         idle->func = func;
179         idle->data = data;
180         idle->run_in_thread = FALSE;
181
182         g_idle_add (idle_cb, idle);
183
184         do_start (NULL, NULL);
185 }
186
187 /* Stops main-loop previously run by start_main_loop,
188    start_in_thread_with_main_loop or start_in_idle_with_main_loop.
189 */
190 void
191 stop_main_loop (gint stop_result)
192 {
193         g_return_if_fail (loop != NULL);
194
195         main_stop_result = stop_result;
196         g_main_loop_quit (loop);
197 }
198
199 /* returns value used in stop_main_loop() */
200 gint
201 get_main_loop_stop_result (void)
202 {
203         return main_stop_result;
204 }
205
206 void
207 foreach_configured_source (void (*func) (ESource *source))
208 {
209         gpointer foreach_async_data;
210         ESource *source = NULL;
211
212         g_return_if_fail (func != NULL);
213
214         main_initialize ();
215
216         foreach_async_data = foreach_configured_source_async_start (&source);
217         if (!foreach_async_data)
218                 return;
219
220         do {
221                 func (source);
222         } while (foreach_configured_source_async_next (&foreach_async_data, &source));
223 }
224
225 struct ForeachConfiguredData
226 {
227         ESourceList *source_list;
228         GSList *current_group;
229         GSList *current_source;
230 };
231
232 gpointer
233 foreach_configured_source_async_start (ESource **source)
234 {
235         struct ForeachConfiguredData *async_data;
236         ESourceList *source_list = NULL;
237         GError *error = NULL;
238
239         g_return_val_if_fail (source != NULL, NULL);
240
241         main_initialize ();
242
243         if (!e_book_client_get_sources (&source_list, &error)) {
244                 report_error ("get addressbooks", &error);
245                 return NULL;
246         }
247
248         g_return_val_if_fail (source_list != NULL, NULL);
249
250         async_data = g_new0 (struct ForeachConfiguredData, 1);
251         async_data->source_list = source_list;
252         async_data->current_group = e_source_list_peek_groups (source_list);
253         if (!async_data->current_group) {
254                 gpointer ad = async_data;
255
256                 foreach_configured_source_async_next (&ad, source);
257                 return ad;
258         }
259
260         async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
261         if (!async_data->current_source) {
262                 gpointer ad = async_data;
263
264                 if (foreach_configured_source_async_next (&ad, source))
265                         return ad;
266
267                 return NULL;
268         }
269
270         *source = async_data->current_source->data;
271
272         return async_data;
273 }
274
275 gboolean
276 foreach_configured_source_async_next (gpointer *foreach_async_data, ESource **source)
277 {
278         struct ForeachConfiguredData *async_data;
279
280         g_return_val_if_fail (foreach_async_data != NULL, FALSE);
281         g_return_val_if_fail (source != NULL, FALSE);
282
283         async_data = *foreach_async_data;
284         g_return_val_if_fail (async_data != NULL, FALSE);
285         g_return_val_if_fail (async_data->source_list != NULL, FALSE);
286         g_return_val_if_fail (async_data->current_group != NULL, FALSE);
287
288         if (async_data->current_source)
289                 async_data->current_source = async_data->current_source->next;
290         if (async_data->current_source) {
291                 *source = async_data->current_source->data;
292                 return TRUE;
293         }
294
295         do {
296                 async_data->current_group = async_data->current_group->next;
297                 if (async_data->current_group)
298                         async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
299         } while (async_data->current_group && !async_data->current_source);
300
301         if (async_data->current_source) {
302                 *source = async_data->current_source->data;
303                 return TRUE;
304         }
305
306         g_object_unref (async_data->source_list);
307         g_free (async_data);
308
309         *foreach_async_data = NULL;
310
311         return FALSE;
312 }
313
314 EBookClient *
315 new_temp_client (gchar **uri)
316 {
317         EBookClient *book_client;
318         ESource *source;
319         gchar *abs_uri, *filename;
320         gint handle;
321         GError *error = NULL;
322
323         filename = g_build_filename (g_get_tmp_dir (), "e-book-client-test-XXXXXX/", NULL);
324         handle = g_mkstemp (filename);
325
326         if (handle != -1)
327                 close (handle);
328
329         g_return_val_if_fail (g_mkdir_with_parents (filename, 0700) == 0, NULL);
330
331         abs_uri = g_strconcat ("local://", filename, NULL);
332         g_free (filename);
333
334         source = e_source_new_with_absolute_uri ("Test book", abs_uri);
335         if (uri)
336                 *uri = abs_uri;
337         else
338                 g_free (abs_uri);
339
340         g_return_val_if_fail (source != NULL, NULL);
341
342         book_client = e_book_client_new (source, &error);
343         g_object_unref (source);
344
345         if (error)
346                 report_error ("new temp client", &error);
347
348         return book_client;
349 }
350
351 gchar *
352 new_vcard_from_test_case (const gchar *case_name)
353 {
354         gchar *filename;
355         gchar *case_filename;
356         GFile* file;
357         GError *error = NULL;
358         gchar *vcard;
359
360         case_filename = g_strdup_printf ("%s.vcf", case_name);
361         filename = g_build_filename (SRCDIR, "..", "data", "vcards", case_filename, NULL);
362         file = g_file_new_for_path (filename);
363         if (!g_file_load_contents (file, NULL, &vcard, NULL, NULL, &error)) {
364                 g_warning ("failed to read test contact file '%s': %s",
365                                 filename, error->message);
366                 exit (1);
367         }
368
369         g_free (case_filename);
370         g_free (filename);
371         g_object_unref (file);
372
373         return vcard;
374 }
375
376 static gboolean
377 contacts_are_equal_shallow (EContact *a, EContact *b)
378 {
379         const gchar *uid_a, *uid_b;
380
381         /* Avoid warnings if one or more are NULL, to make this function
382          * "NULL-friendly" */
383         if (!a && !b)
384                 return TRUE;
385
386         if (!E_IS_CONTACT (a) || !E_IS_CONTACT (b))
387                 return FALSE;
388
389         uid_a = e_contact_get_const (a, E_CONTACT_UID);
390         uid_b = e_contact_get_const (b, E_CONTACT_UID);
391
392         return g_strcmp0 (uid_a, uid_b) == 0;
393 }
394
395 gboolean
396 add_contact_from_test_case_verify (EBookClient *book_client, const gchar *case_name, EContact **contact)
397 {
398         gchar *vcard;
399         EContact *contact_orig;
400         EContact *contact_final;
401         gchar *uid;
402         GError *error = NULL;
403
404         vcard = new_vcard_from_test_case (case_name);
405         contact_orig = e_contact_new_from_vcard (vcard);
406         g_free (vcard);
407         if (!e_book_client_add_contact_sync (book_client, contact_orig, &uid, NULL, &error)) {
408                 report_error ("add contact sync", &error);
409                 g_object_unref (contact_orig);
410                 return FALSE;
411         }
412
413         e_contact_set (contact_orig, E_CONTACT_UID, uid);
414
415         if (!e_book_client_get_contact_sync (book_client, uid, &contact_final, NULL, &error)) {
416                 report_error ("get contact sync", &error);
417                 g_object_unref (contact_orig);
418                 g_free (uid);
419                 return FALSE;
420         }
421
422         /* verify the contact was added "successfully" (not thorough) */
423         g_assert (contacts_are_equal_shallow (contact_orig, contact_final));
424
425         if (contact)
426                 *contact = contact_final;
427         else
428                 g_object_unref (contact_final);
429         g_object_unref (contact_orig);
430         g_free (uid);
431
432         return TRUE;
433 }