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