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