Fix issues found by Coverity Scan
[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                 if (foreach_configured_source_async_next (&ad, source))
261                         return ad;
262
263                 return NULL;
264         }
265
266         async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
267         if (!async_data->current_source) {
268                 gpointer ad = async_data;
269
270                 if (foreach_configured_source_async_next (&ad, source))
271                         return ad;
272
273                 return NULL;
274         }
275
276         *source = async_data->current_source->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         g_return_val_if_fail (async_data->source_list != NULL, FALSE);
293         g_return_val_if_fail (async_data->current_group != NULL, FALSE);
294
295         if (async_data->current_source)
296                 async_data->current_source = async_data->current_source->next;
297         if (async_data->current_source) {
298                 *source = async_data->current_source->data;
299                 return TRUE;
300         }
301
302         do {
303                 async_data->current_group = async_data->current_group->next;
304                 if (async_data->current_group)
305                         async_data->current_source = e_source_group_peek_sources (async_data->current_group->data);
306         } while (async_data->current_group && !async_data->current_source);
307
308         if (async_data->current_source) {
309                 *source = async_data->current_source->data;
310                 return TRUE;
311         }
312
313         g_object_unref (async_data->source_list);
314         g_free (async_data);
315
316         *foreach_async_data = NULL;
317
318         return FALSE;
319 }
320
321 EBookClient *
322 new_temp_client (gchar **uri)
323 {
324         EBookClient *book_client;
325         ESource *source;
326         gchar *abs_uri, *filename;
327         gint handle;
328         GError *error = NULL;
329
330         filename = g_build_filename (g_get_tmp_dir (), "e-book-client-test-XXXXXX/", NULL);
331         handle = g_mkstemp (filename);
332
333         if (handle != -1)
334                 close (handle);
335
336         g_return_val_if_fail (g_mkdir_with_parents (filename, 0700) == 0, NULL);
337
338         abs_uri = g_strconcat ("local://", filename, NULL);
339         g_free (filename);
340
341         source = e_source_new_with_absolute_uri ("Test book", abs_uri);
342         if (uri)
343                 *uri = abs_uri;
344         else
345                 g_free (abs_uri);
346
347         g_return_val_if_fail (source != NULL, NULL);
348
349         book_client = e_book_client_new (source, &error);
350         g_object_unref (source);
351
352         if (error)
353                 report_error ("new temp client", &error);
354
355         return book_client;
356 }
357
358 gchar *
359 new_vcard_from_test_case (const gchar *case_name)
360 {
361         gchar *filename;
362         gchar *case_filename;
363         GFile * file;
364         GError *error = NULL;
365         gchar *vcard;
366
367         case_filename = g_strdup_printf ("%s.vcf", case_name);
368         filename = g_build_filename (SRCDIR, "..", "data", "vcards", case_filename, NULL);
369         file = g_file_new_for_path (filename);
370         if (!g_file_load_contents (file, NULL, &vcard, NULL, NULL, &error)) {
371                 g_warning ("failed to read test contact file '%s': %s",
372                                 filename, error->message);
373                 exit (1);
374         }
375
376         g_free (case_filename);
377         g_free (filename);
378         g_object_unref (file);
379
380         return vcard;
381 }
382
383 static gboolean
384 contacts_are_equal_shallow (EContact *a,
385                             EContact *b)
386 {
387         const gchar *uid_a, *uid_b;
388
389         /* Avoid warnings if one or more are NULL, to make this function
390          * "NULL-friendly" */
391         if (!a && !b)
392                 return TRUE;
393
394         if (!E_IS_CONTACT (a) || !E_IS_CONTACT (b))
395                 return FALSE;
396
397         uid_a = e_contact_get_const (a, E_CONTACT_UID);
398         uid_b = e_contact_get_const (b, E_CONTACT_UID);
399
400         return g_strcmp0 (uid_a, uid_b) == 0;
401 }
402
403 gboolean
404 add_contact_from_test_case_verify (EBookClient *book_client,
405                                    const gchar *case_name,
406                                    EContact **contact)
407 {
408         gchar *vcard;
409         EContact *contact_orig;
410         EContact *contact_final;
411         gchar *uid;
412         GError *error = NULL;
413
414         vcard = new_vcard_from_test_case (case_name);
415         contact_orig = e_contact_new_from_vcard (vcard);
416         g_free (vcard);
417         if (!e_book_client_add_contact_sync (book_client, contact_orig, &uid, NULL, &error)) {
418                 report_error ("add contact sync", &error);
419                 g_object_unref (contact_orig);
420                 return FALSE;
421         }
422
423         e_contact_set (contact_orig, E_CONTACT_UID, uid);
424
425         if (!e_book_client_get_contact_sync (book_client, uid, &contact_final, NULL, &error)) {
426                 report_error ("get contact sync", &error);
427                 g_object_unref (contact_orig);
428                 g_free (uid);
429                 return FALSE;
430         }
431
432         /* verify the contact was added "successfully" (not thorough) */
433         g_assert (contacts_are_equal_shallow (contact_orig, contact_final));
434
435         if (contact)
436                 *contact = contact_final;
437         else
438                 g_object_unref (contact_final);
439         g_object_unref (contact_orig);
440         g_free (uid);
441
442         return TRUE;
443 }
444
445 gboolean
446 add_contact_verify (EBookClient *book_client,
447                     EContact *contact)
448 {
449         EContact *contact_final;
450         gchar *uid;
451         GError *error = NULL;
452
453         if (!e_book_client_add_contact_sync (book_client, contact, &uid, NULL, &error)) {
454                 report_error ("add contact sync", &error);
455                 return FALSE;
456         }
457
458         e_contact_set (contact, E_CONTACT_UID, uid);
459
460         if (!e_book_client_get_contact_sync (book_client, uid, &contact_final, NULL, &error)) {
461                 report_error ("get contact sync", &error);
462                 g_free (uid);
463                 return FALSE;
464         }
465
466         /* verify the contact was added "successfully" (not thorough) */
467         g_assert (contacts_are_equal_shallow (contact, contact_final));
468
469         g_object_unref (contact_final);
470         g_free (uid);
471
472         return TRUE;
473 }