Further test code cleanups.
[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 #include <stdlib.h>
5
6 #include <libedataserver/libedataserver.h>
7
8 #include "client-test-utils.h"
9
10 void
11 report_error (const gchar *operation,
12               GError **error)
13 {
14         g_return_if_fail (operation != NULL);
15
16         g_printerr ("Failed to %s: %s\n", operation, (error && *error) ? (*error)->message : "Unknown error");
17
18         g_clear_error (error);
19 }
20
21 void
22 print_email (EContact *contact)
23 {
24         const gchar *file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS);
25         const gchar *name_or_org = e_contact_get_const (contact, E_CONTACT_NAME_OR_ORG);
26         GList *emails, *e;
27
28         g_print ("   Contact: %s\n", file_as);
29         g_print ("   Name or org: %s\n", name_or_org);
30         g_print ("   Email addresses:\n");
31         emails = e_contact_get (contact, E_CONTACT_EMAIL);
32         for (e = emails; e; e = e->next) {
33                 g_print ("\t%s\n",  (gchar *) e->data);
34         }
35         g_list_foreach (emails, (GFunc) g_free, NULL);
36         g_list_free (emails);
37
38         g_print ("\n");
39 }
40
41 EBookClient *
42 open_system_book (ESourceRegistry *registry,
43                   gboolean only_if_exists)
44 {
45         ESource *source;
46         EBookClient *book_client;
47         GError *error = NULL;
48
49         main_initialize ();
50
51         source = e_source_registry_ref_builtin_address_book (registry);
52         book_client = e_book_client_new (source, &error);
53         g_object_unref (source);
54
55         if (error) {
56                 report_error ("create system addressbook", &error);
57                 return NULL;
58         }
59
60         if (!e_client_open_sync (E_CLIENT (book_client), only_if_exists, NULL, &error)) {
61                 g_object_unref (book_client);
62                 report_error ("open client sync", &error);
63                 return NULL;
64         }
65
66         return book_client;
67 }
68
69 void
70 main_initialize (void)
71 {
72         static gboolean initialized = FALSE;
73
74         if (initialized)
75                 return;
76
77         g_type_init ();
78         e_gdbus_templates_init_main_thread ();
79
80         initialized = TRUE;
81 }
82
83 struct IdleData {
84         GThreadFunc func;
85         gpointer data;
86         gboolean run_in_thread; /* FALSE to run in idle callback */
87 };
88
89 static gboolean
90 idle_cb (gpointer data)
91 {
92         struct IdleData *idle = data;
93
94         g_return_val_if_fail (idle != NULL, FALSE);
95         g_return_val_if_fail (idle->func != NULL, FALSE);
96
97         if (idle->run_in_thread) {
98                 GError *error = NULL;
99
100                 g_thread_create (idle->func, idle->data, FALSE, &error);
101
102                 if (error) {
103                         report_error ("create thread", &error);
104                         stop_main_loop (1);
105                 }
106         } else {
107                 idle->func (idle->data);
108         }
109
110         g_free (idle);
111
112         return FALSE;
113 }
114
115 static GMainLoop *loop = NULL;
116 static gint main_stop_result = 0;
117
118 static void
119 do_start (GThreadFunc func,
120           gpointer data)
121 {
122         main_initialize ();
123
124         g_return_if_fail (loop == NULL);
125
126         loop = g_main_loop_new (NULL, FALSE);
127
128         if (func)
129                 func (data);
130
131         g_main_loop_run (loop);
132
133         g_main_loop_unref (loop);
134         loop = NULL;
135 }
136
137 /* Starts new main-loop, but just before that calls 'func'.
138  * Main-loop is kept running, and this function blocks,
139  * until call of stop_main_loop (). */
140 void
141 start_main_loop (GThreadFunc func,
142                  gpointer data)
143 {
144         g_return_if_fail (loop == NULL);
145
146         do_start (func, data);
147 }
148
149 /* Starts new main-loop and then invokes func in a new thread.
150  * Main-loop is kept running, and this function blocks,
151  * until call of stop_main_loop (). */
152 void
153 start_in_thread_with_main_loop (GThreadFunc func,
154                                 gpointer data)
155 {
156         struct IdleData *idle;
157
158         g_return_if_fail (func != NULL);
159         g_return_if_fail (loop == NULL);
160
161         main_initialize ();
162
163         idle = g_new0 (struct IdleData, 1);
164         idle->func = func;
165         idle->data = data;
166         idle->run_in_thread = TRUE;
167
168         g_idle_add (idle_cb, idle);
169
170         do_start (NULL, NULL);
171 }
172
173 /* Starts new main-loop and then invokes func in an idle callback.
174  * Main-loop is kept running, and this function blocks,
175  * until call of stop_main_loop (). */
176 void
177 start_in_idle_with_main_loop (GThreadFunc func,
178                               gpointer data)
179 {
180         struct IdleData *idle;
181
182         g_return_if_fail (func != NULL);
183         g_return_if_fail (loop == NULL);
184
185         main_initialize ();
186
187         idle = g_new0 (struct IdleData, 1);
188         idle->func = func;
189         idle->data = data;
190         idle->run_in_thread = FALSE;
191
192         g_idle_add (idle_cb, idle);
193
194         do_start (NULL, NULL);
195 }
196
197 /* Stops main-loop previously run by start_main_loop,
198  * start_in_thread_with_main_loop or start_in_idle_with_main_loop.
199 */
200 void
201 stop_main_loop (gint stop_result)
202 {
203         g_return_if_fail (loop != NULL);
204
205         main_stop_result = stop_result;
206         g_main_loop_quit (loop);
207 }
208
209 /* returns value used in stop_main_loop() */
210 gint
211 get_main_loop_stop_result (void)
212 {
213         return main_stop_result;
214 }
215
216 void
217 foreach_configured_source (ESourceRegistry *registry,
218                            void (*func) (ESource *source))
219 {
220         gpointer foreach_async_data;
221         ESource *source = NULL;
222
223         g_return_if_fail (func != NULL);
224
225         main_initialize ();
226
227         foreach_async_data = foreach_configured_source_async_start (registry, &source);
228         if (!foreach_async_data)
229                 return;
230
231         do {
232                 func (source);
233         } while (foreach_configured_source_async_next (&foreach_async_data, &source));
234 }
235
236 struct ForeachConfiguredData {
237         GList *list;
238 };
239
240 gpointer
241 foreach_configured_source_async_start (ESourceRegistry *registry,
242                                        ESource **source)
243 {
244         struct ForeachConfiguredData *async_data;
245         const gchar *extension_name;
246         GList *list;
247
248         g_return_val_if_fail (source != NULL, NULL);
249
250         main_initialize ();
251
252         extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
253         list = e_source_registry_list_sources (registry, extension_name);
254
255         async_data = g_new0 (struct ForeachConfiguredData, 1);
256         async_data->list = list;
257
258         *source = async_data->list->data;
259
260         return async_data;
261 }
262
263 gboolean
264 foreach_configured_source_async_next (gpointer *foreach_async_data,
265                                       ESource **source)
266 {
267         struct ForeachConfiguredData *async_data;
268
269         g_return_val_if_fail (foreach_async_data != NULL, FALSE);
270         g_return_val_if_fail (source != NULL, FALSE);
271
272         async_data = *foreach_async_data;
273         g_return_val_if_fail (async_data != NULL, FALSE);
274
275         if (async_data->list) {
276                 g_object_unref (async_data->list->data);
277                 async_data->list = async_data->list->next;
278         }
279         if (async_data->list) {
280                 *source = async_data->list->data;
281                 return TRUE;
282         }
283
284         g_free (async_data);
285
286         *foreach_async_data = NULL;
287
288         return FALSE;
289 }
290
291 typedef struct {
292         GMainLoop       *loop;
293         const gchar     *uid;
294         ESourceRegistry *registry;
295         ESource         *scratch;
296         ESource         *source;
297         EBookClient     *book;
298 } CreateBookData;
299
300 static gboolean
301 quit_idle (CreateBookData *data)
302 {
303         g_main_loop_quit (data->loop);
304         return FALSE;
305 }
306
307 static gboolean
308 create_book_idle (CreateBookData *data)
309 {
310         GError *error = NULL;
311
312         data->source = e_source_registry_ref_source (data->registry, data->uid);
313         if (!data->source)
314                 g_error ("Unable to fetch newly created source uid '%s' from the registry", data->uid);
315
316         data->book = e_book_client_new (data->source, &error);
317         if (!data->book)
318                 g_error ("Unable to create the book: %s", error->message);
319
320         g_idle_add ((GSourceFunc) quit_idle, data);
321
322         return FALSE;
323 }
324
325 static gboolean
326 register_source_idle (CreateBookData *data)
327 {
328         GError *error = NULL;
329         ESourceBackend  *backend;
330
331         data->registry = e_source_registry_new_sync (NULL, &error);
332         if (!data->registry)
333                 g_error ("Unable to create the registry: %s", error->message);
334
335         data->scratch = e_source_new_with_uid (data->uid, NULL, &error);
336         if (!data->scratch)
337                 g_error ("Failed to create source with uid '%s': %s", data->uid, error->message);
338
339         backend = e_source_get_extension (data->scratch, E_SOURCE_EXTENSION_ADDRESS_BOOK);
340         e_source_backend_set_backend_name (backend, "local");
341
342         if (!e_source_registry_commit_source_sync (data->registry, data->scratch, NULL, &error))
343                 g_error ("Unable to add new source to the registry for uid %s: %s", data->uid, error->message);
344
345         /* XXX e_source_registry_commit_source_sync isnt really sync... or else
346          * we could call e_source_registry_ref_source() immediately
347          */
348         g_timeout_add (20, (GSourceFunc) create_book_idle, data);
349
350         return FALSE;
351 }
352
353 static EBookClient *
354 ebook_test_utils_book_with_uid (const gchar *uid)
355 {
356         CreateBookData data = { 0, };
357
358         data.uid = uid;
359
360         data.loop = g_main_loop_new (NULL, FALSE);
361         g_idle_add ((GSourceFunc) register_source_idle, &data);
362         g_main_loop_run (data.loop);
363         g_main_loop_unref (data.loop);
364
365         g_object_unref (data.scratch);
366         g_object_unref (data.source);
367         g_object_unref (data.registry);
368
369         return data.book;
370 }
371
372 EBookClient *
373 new_temp_client (gchar **uri)
374 {
375         EBookClient     *book;
376         gchar           *uid;
377         guint64          real_time = g_get_real_time ();
378
379         uid  = g_strdup_printf ("test-book-%" G_GINT64_FORMAT, real_time);
380         book = ebook_test_utils_book_with_uid (uid);
381
382         if (uri)
383                 *uri = g_strdup (uid);
384
385         g_free (uid);
386
387         return book;
388 }
389
390 gchar *
391 new_vcard_from_test_case (const gchar *case_name)
392 {
393         gchar *filename;
394         gchar *case_filename;
395         GFile * file;
396         GError *error = NULL;
397         gchar *vcard;
398
399         case_filename = g_strdup_printf ("%s.vcf", case_name);
400         filename = g_build_filename (SRCDIR, "..", "data", "vcards", case_filename, NULL);
401         file = g_file_new_for_path (filename);
402         if (!g_file_load_contents (file, NULL, &vcard, NULL, NULL, &error)) {
403                 g_warning (
404                         "failed to read test contact file '%s': %s",
405                                 filename, error->message);
406                 exit (1);
407         }
408
409         g_free (case_filename);
410         g_free (filename);
411         g_object_unref (file);
412
413         return vcard;
414 }
415
416 static gboolean
417 contacts_are_equal_shallow (EContact *a,
418                             EContact *b)
419 {
420         const gchar *uid_a, *uid_b;
421
422         /* Avoid warnings if one or more are NULL, to make this function
423          * "NULL-friendly" */
424         if (!a && !b)
425                 return TRUE;
426
427         if (!E_IS_CONTACT (a) || !E_IS_CONTACT (b))
428                 return FALSE;
429
430         uid_a = e_contact_get_const (a, E_CONTACT_UID);
431         uid_b = e_contact_get_const (b, E_CONTACT_UID);
432
433         return g_strcmp0 (uid_a, uid_b) == 0;
434 }
435
436 gboolean
437 add_contact_from_test_case_verify (EBookClient *book_client,
438                                    const gchar *case_name,
439                                    EContact **contact)
440 {
441         gchar *vcard;
442         EContact *contact_orig;
443         EContact *contact_final;
444         gchar *uid;
445         GError *error = NULL;
446
447         vcard = new_vcard_from_test_case (case_name);
448         contact_orig = e_contact_new_from_vcard (vcard);
449         g_free (vcard);
450         if (!e_book_client_add_contact_sync (book_client, contact_orig, &uid, NULL, &error)) {
451                 report_error ("add contact sync", &error);
452                 g_object_unref (contact_orig);
453                 return FALSE;
454         }
455
456         e_contact_set (contact_orig, E_CONTACT_UID, uid);
457
458         if (!e_book_client_get_contact_sync (book_client, uid, &contact_final, NULL, &error)) {
459                 report_error ("get contact sync", &error);
460                 g_object_unref (contact_orig);
461                 g_free (uid);
462                 return FALSE;
463         }
464
465         /* verify the contact was added "successfully" (not thorough) */
466         g_assert (contacts_are_equal_shallow (contact_orig, contact_final));
467
468         if (contact)
469                 *contact = contact_final;
470         else
471                 g_object_unref (contact_final);
472         g_object_unref (contact_orig);
473         g_free (uid);
474
475         return TRUE;
476 }
477
478 gboolean
479 add_contact_verify (EBookClient *book_client,
480                     EContact *contact)
481 {
482         EContact *contact_final;
483         gchar *uid;
484         GError *error = NULL;
485
486         if (!e_book_client_add_contact_sync (book_client, contact, &uid, NULL, &error)) {
487                 report_error ("add contact sync", &error);
488                 return FALSE;
489         }
490
491         e_contact_set (contact, E_CONTACT_UID, uid);
492
493         if (!e_book_client_get_contact_sync (book_client, uid, &contact_final, NULL, &error)) {
494                 report_error ("get contact sync", &error);
495                 g_free (uid);
496                 return FALSE;
497         }
498
499         /* verify the contact was added "successfully" (not thorough) */
500         g_assert (contacts_are_equal_shallow (contact, contact_final));
501
502         g_object_unref (contact_final);
503         g_free (uid);
504
505         return TRUE;
506 }