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