1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * This library is free software: you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation.
6 *
7 * This library is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
10 * for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public License
13 * along with this library. If not, see <http://www.gnu.org/licenses/>.
14 *
15 */
16
17 #include <stdlib.h>
18 #include <libebook/libebook.h>
19
20 #include "ebook-test-utils.h"
21
22 void
test_print(const gchar * format,...)23 test_print (const gchar *format,
24 ...)
25 {
26 va_list args;
27 const gchar *debug_string;
28 static gboolean debug_set = FALSE;
29 static gboolean debug = FALSE;
30
31 if (!debug_set) {
32 debug_string = g_getenv ("EDS_TEST_DEBUG");
33 if (debug_string) {
34 debug = (g_ascii_strtoll (debug_string, NULL, 10) >= 1);
35 }
36 debug_set = TRUE;
37 }
38
39 if (debug) {
40 va_start (args, format);
41 vprintf (format, args);
42 va_end (args);
43 }
44 }
45
46 gboolean
ebook_test_utils_callback_quit(gpointer user_data)47 ebook_test_utils_callback_quit (gpointer user_data)
48 {
49 EBookTestClosure *closure = user_data;
50 g_main_loop_quit ((GMainLoop *) closure->user_data);
51
52 return FALSE;
53 }
54
55 static const gchar *args_data_dir = NULL;
56
57 void
ebook_test_utils_read_args(gint argc,gchar ** argv)58 ebook_test_utils_read_args (gint argc,
59 gchar **argv)
60 {
61 gint ii;
62
63 for (ii = 0; ii < argc; ii++) {
64 if (g_strcmp0 (argv[ii], "--data-dir") == 0) {
65 if (ii + 1 < argc)
66 args_data_dir = argv[ii + 1];
67 break;
68 }
69 }
70 }
71
72 gchar *
ebook_test_utils_new_vcard_from_test_case(const gchar * case_name)73 ebook_test_utils_new_vcard_from_test_case (const gchar *case_name)
74 {
75 gchar *filename;
76 gchar *case_filename;
77 GFile * file;
78 GError *error = NULL;
79 gchar *vcard;
80
81 case_filename = g_strdup_printf ("%s.vcf", case_name);
82
83 /* In the case of installed tests, they run in ${pkglibexecdir}/installed-tests
84 * and the vcards are installed in ${pkglibexecdir}/installed-tests/vcards
85 */
86 if (g_getenv ("TEST_INSTALLED_SERVICES") != NULL) {
87 filename = g_build_filename (INSTALLED_TEST_DIR, "vcards", case_filename, NULL);
88 } else {
89 if (!args_data_dir) {
90 g_warning ("Data directory not set, pass it with `--data-dir PATH`");
91 exit(1);
92 }
93
94 filename = g_build_filename (args_data_dir, case_filename, NULL);
95 }
96
97 file = g_file_new_for_path (filename);
98 if (!g_file_load_contents (file, NULL, &vcard, NULL, NULL, &error)) {
99 g_warning (
100 "failed to read test contact file '%s': %s",
101 filename, error->message);
102 exit (1);
103 }
104
105 g_free (case_filename);
106 g_free (filename);
107 g_object_unref (file);
108
109 return vcard;
110 }
111
112 gchar *
ebook_test_utils_book_add_contact_from_test_case_verify(EBook * book,const gchar * case_name,EContact ** contact)113 ebook_test_utils_book_add_contact_from_test_case_verify (EBook *book,
114 const gchar *case_name,
115 EContact **contact)
116 {
117 gchar *vcard;
118 EContact *contact_orig;
119 EContact *contact_final;
120 gchar *uid;
121
122 vcard = ebook_test_utils_new_vcard_from_test_case (case_name);
123 contact_orig = e_contact_new_from_vcard (vcard);
124 uid = g_strdup (ebook_test_utils_book_add_contact (book, contact_orig));
125 contact_final = ebook_test_utils_book_get_contact (book, uid);
126
127 /* verify the contact was added "successfully" (not thorough) */
128 g_assert (ebook_test_utils_contacts_are_equal_shallow (contact_orig, contact_final));
129
130 if (contact)
131 *contact = g_object_ref (contact_final);
132
133 return uid;
134 }
135
136 /* This is not a thorough comparison (which is difficult, assuming we give the
137 * back-ends leniency in implementation) and is best suited for simple tests */
138 gboolean
ebook_test_utils_contacts_are_equal_shallow(EContact * a,EContact * b)139 ebook_test_utils_contacts_are_equal_shallow (EContact *a,
140 EContact *b)
141
142 {
143 const gchar *uid_a, *uid_b;
144
145 /* Avoid warnings if one or more are NULL, to make this function
146 * "NULL-friendly" */
147 if (!a && !b)
148 return TRUE;
149 if (!E_IS_CONTACT (a) || !E_IS_CONTACT (b))
150 return FALSE;
151
152 uid_a = e_contact_get_const (a, E_CONTACT_UID);
153 uid_b = e_contact_get_const (b, E_CONTACT_UID);
154
155 return g_strcmp0 (uid_a, uid_b) == 0;
156 }
157
158 const gchar *
ebook_test_utils_book_add_contact(EBook * book,EContact * contact)159 ebook_test_utils_book_add_contact (EBook *book,
160 EContact *contact)
161 {
162 GError *error = NULL;
163
164 if (!e_book_add_contact (book, contact, &error)) {
165 ESource *source;
166 const gchar *name;
167
168 source = e_book_get_source (book);
169 name = e_source_get_display_name (source);
170 g_warning (
171 "failed to add contact to addressbook: `%s': %s",
172 name, error->message);
173 exit (1);
174 }
175
176 return e_contact_get_const (contact, E_CONTACT_UID);
177 }
178
179 static void
add_contact_cb(EBook * book,const GError * error,const gchar * uid,EBookTestClosure * closure)180 add_contact_cb (EBook *book,
181 const GError *error,
182 const gchar *uid,
183 EBookTestClosure *closure)
184 {
185 if (error) {
186 g_warning (
187 "failed to asynchronously add the contact '%s': "
188 "status %d (%s)", uid, error->code, error->message);
189 exit (1);
190 }
191
192 test_print ("successfully asynchronously added the contact "
193 "addressbook\n");
194 if (closure->cb)
195 (*closure->cb) (closure);
196
197 g_free (closure);
198 }
199
200 void
ebook_test_utils_book_async_add_contact(EBook * book,EContact * contact,GSourceFunc callback,gpointer user_data)201 ebook_test_utils_book_async_add_contact (EBook *book,
202 EContact *contact,
203 GSourceFunc callback,
204 gpointer user_data)
205 {
206 EBookTestClosure *closure;
207
208 closure = g_new0 (EBookTestClosure, 1);
209 closure->cb = callback;
210 closure->user_data = user_data;
211 if (!e_book_add_contact_async (book, contact,
212 (EBookIdAsyncCallback) add_contact_cb, closure)) {
213 g_warning ("failed to set up contact add");
214 exit (1);
215 }
216 }
217
218 void
ebook_test_utils_book_commit_contact(EBook * book,EContact * contact)219 ebook_test_utils_book_commit_contact (EBook *book,
220 EContact *contact)
221 {
222 GError *error = NULL;
223
224 if (!e_book_commit_contact (book, contact, &error)) {
225 ESource *source;
226 const gchar *name;
227 const gchar *uid;
228
229 uid = (const gchar *) e_contact_get_const (contact, E_CONTACT_UID);
230
231 source = e_book_get_source (book);
232 name = e_source_get_display_name (source);
233 g_warning (
234 "failed to commit changes to contact '%s' to "
235 "addressbook: `%s': %s", uid, name, error->message);
236 exit (1);
237 }
238 }
239
240 static void
commit_contact_cb(EBook * book,const GError * error,EBookTestClosure * closure)241 commit_contact_cb (EBook *book,
242 const GError *error,
243 EBookTestClosure *closure)
244 {
245 if (error) {
246 g_warning (
247 "failed to asynchronously commit the contact: "
248 "status %d (%s)", error->code, error->message);
249 exit (1);
250 }
251
252 test_print ("successfully asynchronously committed the contact to the "
253 "addressbook\n");
254 if (closure->cb)
255 (*closure->cb) (closure);
256
257 g_free (closure);
258 }
259
260 void
ebook_test_utils_book_async_commit_contact(EBook * book,EContact * contact,GSourceFunc callback,gpointer user_data)261 ebook_test_utils_book_async_commit_contact (EBook *book,
262 EContact *contact,
263 GSourceFunc callback,
264 gpointer user_data)
265 {
266 EBookTestClosure *closure;
267
268 closure = g_new0 (EBookTestClosure, 1);
269 closure->cb = callback;
270 closure->user_data = user_data;
271 if (!e_book_commit_contact_async (book, contact,
272 (EBookAsyncCallback) commit_contact_cb, closure)) {
273 g_warning ("failed to set up contact commit");
274 exit (1);
275 }
276 }
277
278 EContact *
ebook_test_utils_book_get_contact(EBook * book,const gchar * uid)279 ebook_test_utils_book_get_contact (EBook *book,
280 const gchar *uid)
281 {
282 EContact *contact = NULL;
283 GError *error = NULL;
284
285 if (!e_book_get_contact (book, uid, &contact, &error)) {
286 ESource *source;
287 const gchar *name;
288
289 source = e_book_get_source (book);
290 name = e_source_get_display_name (source);
291 g_warning (
292 "failed to get contact '%s' in addressbook: `%s': "
293 "%s", uid, name, error->message);
294 exit (1);
295 }
296
297 return contact;
298 }
299
300 static void
get_contact_cb(EBook * book,const GError * error,EContact * contact,EBookTestClosure * closure)301 get_contact_cb (EBook *book,
302 const GError *error,
303 EContact *contact,
304 EBookTestClosure *closure)
305 {
306 const gchar *uid;
307
308 if (error) {
309 g_warning (
310 "failed to asynchronously get the contact: "
311 "status %d (%s)", error->code, error->message);
312 exit (1);
313 }
314
315 uid = e_contact_get_const (contact, E_CONTACT_UID);
316 test_print (
317 "successfully asynchronously retrieved the contact '%s'\n",
318 uid);
319
320 if (closure->cb)
321 (*closure->cb) (closure);
322
323 g_free (closure);
324 }
325
326 void
ebook_test_utils_book_async_get_contact(EBook * book,const gchar * uid,GSourceFunc callback,gpointer user_data)327 ebook_test_utils_book_async_get_contact (EBook *book,
328 const gchar *uid,
329 GSourceFunc callback,
330 gpointer user_data)
331 {
332 EBookTestClosure *closure;
333
334 closure = g_new0 (EBookTestClosure, 1);
335 closure->cb = callback;
336 closure->user_data = user_data;
337 if (!e_book_get_contact_async (book, uid,
338 (EBookContactAsyncCallback) get_contact_cb,
339 closure)) {
340 g_warning ("failed to set up async getContact");
341 exit (1);
342 }
343 }
344
345 GList *
ebook_test_utils_book_get_required_fields(EBook * book)346 ebook_test_utils_book_get_required_fields (EBook *book)
347 {
348 GList *fields = NULL;
349 GError *error = NULL;
350
351 if (!e_book_get_required_fields (book, &fields, &error)) {
352 ESource *source;
353 const gchar *name;
354
355 source = e_book_get_source (book);
356 name = e_source_get_display_name (source);
357 g_warning (
358 "failed to get required fields for addressbook "
359 "`%s': %s", name, error->message);
360 exit (1);
361 }
362
363 return fields;
364 }
365
366 static void
get_required_fields_cb(EBook * book,const GError * error,EList * fields,EBookTestClosure * closure)367 get_required_fields_cb (EBook *book,
368 const GError *error,
369 EList *fields,
370 EBookTestClosure *closure)
371 {
372 if (error) {
373 g_warning (
374 "failed to asynchronously get the required fields: "
375 "status %d (%s)", error->code, error->message);
376 exit (1);
377 }
378
379 closure->list = fields;
380
381 test_print ("successfully asynchronously retrieved the required fields\n");
382
383 if (closure->cb)
384 (*closure->cb) (closure);
385
386 g_free (closure);
387 }
388
389 void
ebook_test_utils_book_async_get_required_fields(EBook * book,GSourceFunc callback,gpointer user_data)390 ebook_test_utils_book_async_get_required_fields (EBook *book,
391 GSourceFunc callback,
392 gpointer user_data)
393 {
394 EBookTestClosure *closure;
395
396 closure = g_new0 (EBookTestClosure, 1);
397 closure->cb = callback;
398 closure->user_data = user_data;
399 if (!e_book_get_required_fields_async (book,
400 (EBookEListAsyncCallback) get_required_fields_cb,
401 closure)) {
402 g_warning ("failed to set up async getRequiredFields");
403 exit (1);
404 }
405 }
406
407 const gchar *
ebook_test_utils_book_get_static_capabilities(EBook * book)408 ebook_test_utils_book_get_static_capabilities (EBook *book)
409 {
410 GError *error = NULL;
411 const gchar *caps;
412
413 if (!(caps = e_book_get_static_capabilities (book, &error))) {
414 ESource *source;
415 const gchar *name;
416
417 source = e_book_get_source (book);
418 name = e_source_get_display_name (source);
419 g_warning (
420 "failed to get capabilities for addressbook: `%s': "
421 "%s", name, error->message);
422 exit (1);
423 }
424
425 return caps;
426 }
427
428 GList *
ebook_test_utils_book_get_supported_auth_methods(EBook * book)429 ebook_test_utils_book_get_supported_auth_methods (EBook *book)
430 {
431 GList *fields = NULL;
432 GError *error = NULL;
433
434 if (!e_book_get_supported_auth_methods (book, &fields, &error)) {
435 ESource *source;
436 const gchar *name;
437
438 source = e_book_get_source (book);
439 name = e_source_get_display_name (source);
440 g_warning (
441 "failed to get supported auth methods for "
442 "addressbook `%s': %s", name, error ? error->message : "Unknown error");
443 exit (1);
444 }
445
446 return fields;
447 }
448
449 static void
get_supported_auth_methods_cb(EBook * book,const GError * error,EList * methods,EBookTestClosure * closure)450 get_supported_auth_methods_cb (EBook *book,
451 const GError *error,
452 EList *methods,
453 EBookTestClosure *closure)
454 {
455 if (error) {
456 g_warning (
457 "failed to asynchronously get the supported auth "
458 "methods: status %d (%s)", error->code, error->message);
459 exit (1);
460 }
461
462 closure->list = methods;
463
464 test_print ("successfully asynchronously retrieved the supported auth "
465 "methods\n");
466
467 if (closure->cb)
468 (*closure->cb) (closure);
469 g_free (closure);
470 }
471
472 void
ebook_test_utils_book_async_get_supported_auth_methods(EBook * book,GSourceFunc callback,gpointer user_data)473 ebook_test_utils_book_async_get_supported_auth_methods (EBook *book,
474 GSourceFunc callback,
475 gpointer user_data)
476 {
477 EBookTestClosure *closure;
478
479 closure = g_new0 (EBookTestClosure, 1);
480 closure->cb = callback;
481 closure->user_data = user_data;
482 if (!e_book_get_supported_auth_methods_async (book,
483 (EBookEListAsyncCallback) get_supported_auth_methods_cb,
484 closure)) {
485 g_warning ("failed to set up async getSupportedAuthMethods");
486 exit (1);
487 }
488 }
489
490 GList *
ebook_test_utils_book_get_supported_fields(EBook * book)491 ebook_test_utils_book_get_supported_fields (EBook *book)
492 {
493 GList *fields = NULL;
494 GError *error = NULL;
495
496 if (!e_book_get_supported_fields (book, &fields, &error)) {
497 ESource *source;
498 const gchar *name;
499
500 source = e_book_get_source (book);
501 name = e_source_get_display_name (source);
502 g_warning (
503 "failed to get supported fields for addressbook "
504 "`%s': %s", name, error->message);
505 exit (1);
506 }
507
508 return fields;
509 }
510
511 static void
get_supported_fields_cb(EBook * book,const GError * error,EList * fields,EBookTestClosure * closure)512 get_supported_fields_cb (EBook *book,
513 const GError *error,
514 EList *fields,
515 EBookTestClosure *closure)
516 {
517 if (error) {
518 g_warning (
519 "failed to asynchronously get the supported fields: "
520 "status %d (%s)", error->code, error->message);
521 exit (1);
522 }
523
524 closure->list = fields;
525
526 test_print ("successfully asynchronously retrieved the supported fields\n");
527
528 if (closure->cb)
529 (*closure->cb) (closure);
530 g_free (closure);
531 }
532
533 void
ebook_test_utils_book_async_get_supported_fields(EBook * book,GSourceFunc callback,gpointer user_data)534 ebook_test_utils_book_async_get_supported_fields (EBook *book,
535 GSourceFunc callback,
536 gpointer user_data)
537 {
538 EBookTestClosure *closure;
539
540 closure = g_new0 (EBookTestClosure, 1);
541 closure->cb = callback;
542 closure->user_data = user_data;
543 if (!e_book_get_supported_fields_async (book,
544 (EBookEListAsyncCallback) get_supported_fields_cb,
545 closure)) {
546 g_warning ("failed to set up async getSupportedFields");
547 exit (1);
548 }
549 }
550
551 void
ebook_test_utils_book_remove_contact(EBook * book,const gchar * uid)552 ebook_test_utils_book_remove_contact (EBook *book,
553 const gchar *uid)
554 {
555 GError *error = NULL;
556
557 if (!e_book_remove_contact (book, uid, &error)) {
558 ESource *source;
559 const gchar *name;
560
561 source = e_book_get_source (book);
562 name = e_source_get_display_name (source);
563 g_warning (
564 "failed to remove contact '%s' from addressbook: "
565 "`%s': %s", uid, name, error->message);
566 exit (1);
567 }
568 }
569
570 static void
remove_contact_cb(EBook * book,const GError * error,EBookTestClosure * closure)571 remove_contact_cb (EBook *book,
572 const GError *error,
573 EBookTestClosure *closure)
574 {
575 if (error) {
576 g_warning (
577 "failed to asynchronously remove the contact: "
578 "status %d (%s)", error->code, error->message);
579 exit (1);
580 }
581
582 test_print ("successfully asynchronously removed the contact\n");
583
584 if (closure->cb)
585 (*closure->cb) (closure);
586
587 g_free (closure);
588 }
589
590 void
ebook_test_utils_book_async_remove_contact(EBook * book,EContact * contact,GSourceFunc callback,gpointer user_data)591 ebook_test_utils_book_async_remove_contact (EBook *book,
592 EContact *contact,
593 GSourceFunc callback,
594 gpointer user_data)
595 {
596 EBookTestClosure *closure;
597
598 closure = g_new0 (EBookTestClosure, 1);
599 closure->cb = callback;
600 closure->user_data = user_data;
601 if (!e_book_remove_contact_async (book, contact,
602 (EBookAsyncCallback) remove_contact_cb,
603 closure)) {
604 g_warning (
605 "failed to set up async removeContacts "
606 "(for a single contact)");
607 exit (1);
608 }
609 }
610
611 static void
remove_contact_by_id_cb(EBook * book,const GError * error,EBookTestClosure * closure)612 remove_contact_by_id_cb (EBook *book,
613 const GError *error,
614 EBookTestClosure *closure)
615 {
616 if (error) {
617 g_warning (
618 "failed to asynchronously remove the contact by id: "
619 "status %d (%s)", error->code, error->message);
620 exit (1);
621 }
622
623 test_print ("successfully asynchronously removed the contact by id\n");
624
625 if (closure->cb)
626 (*closure->cb) (closure);
627
628 g_free (closure);
629 }
630
631 void
ebook_test_utils_book_async_remove_contact_by_id(EBook * book,const gchar * uid,GSourceFunc callback,gpointer user_data)632 ebook_test_utils_book_async_remove_contact_by_id (EBook *book,
633 const gchar *uid,
634 GSourceFunc callback,
635 gpointer user_data)
636 {
637 EBookTestClosure *closure;
638
639 closure = g_new0 (EBookTestClosure, 1);
640 closure->cb = callback;
641 closure->user_data = user_data;
642 if (!e_book_remove_contact_by_id_async (book, uid,
643 (EBookAsyncCallback) remove_contact_by_id_cb,
644 closure)) {
645 g_warning ("failed to set up async removeContacts (by id)");
646 exit (1);
647 }
648 }
649
650 void
ebook_test_utils_book_remove_contacts(EBook * book,GList * ids)651 ebook_test_utils_book_remove_contacts (EBook *book,
652 GList *ids)
653 {
654 GError *error = NULL;
655
656 if (!e_book_remove_contacts (book, ids, &error)) {
657 ESource *source;
658 const gchar *name;
659
660 source = e_book_get_source (book);
661 name = e_source_get_display_name (source);
662 g_warning (
663 "failed to remove contacts from addressbook: `%s': %s",
664 name, error->message);
665 exit (1);
666 }
667 }
668
669 static void
remove_contacts_cb(EBook * book,const GError * error,EBookTestClosure * closure)670 remove_contacts_cb (EBook *book,
671 const GError *error,
672 EBookTestClosure *closure)
673 {
674 if (error) {
675 g_warning (
676 "failed to asynchronously remove the contacts: "
677 "status %d (%s)", error->code, error->message);
678 exit (1);
679 }
680
681 test_print ("successfully asynchronously removed the contacts\n");
682
683 if (closure->cb)
684 (*closure->cb) (closure);
685
686 g_free (closure);
687 }
688
689 void
ebook_test_utils_book_async_remove_contacts(EBook * book,GList * uids,GSourceFunc callback,gpointer user_data)690 ebook_test_utils_book_async_remove_contacts (EBook *book,
691 GList *uids,
692 GSourceFunc callback,
693 gpointer user_data)
694 {
695 EBookTestClosure *closure;
696
697 closure = g_new0 (EBookTestClosure, 1);
698 closure->cb = callback;
699 closure->user_data = user_data;
700 if (!e_book_remove_contacts_async (book, uids,
701 (EBookAsyncCallback) remove_contacts_cb,
702 closure)) {
703 g_warning ("failed to set up async removeContacts");
704 exit (1);
705 }
706 }
707
708 void
ebook_test_utils_book_get_book_view(EBook * book,EBookQuery * query,EBookView ** view)709 ebook_test_utils_book_get_book_view (EBook *book,
710 EBookQuery *query,
711 EBookView **view)
712 {
713 GError *error = NULL;
714
715 if (!e_book_get_book_view (book, query, NULL, -1, view, &error)) {
716 ESource *source;
717 const gchar *name;
718
719 source = e_book_get_source (book);
720 name = e_source_get_display_name (source);
721
722 g_warning (
723 "failed to get view for addressbook: `%s': %s",
724 name, error->message);
725 exit (1);
726 }
727 }
728
729 static void
get_book_view_cb(EBook * book,const GError * error,EBookView * view,EBookTestClosure * closure)730 get_book_view_cb (EBook *book,
731 const GError *error,
732 EBookView *view,
733 EBookTestClosure *closure)
734 {
735 if (error) {
736 g_warning (
737 "failed to asynchronously get book view for the "
738 "book: status %d (%s)", error->code, error->message);
739 exit (1);
740 }
741
742 closure->view = view;
743
744 test_print ("successfully asynchronously retrieved the book view\n");
745 if (closure->cb)
746 (*closure->cb) (closure);
747 }
748
749 void
ebook_test_utils_book_async_get_book_view(EBook * book,EBookQuery * query,GSourceFunc callback,gpointer user_data)750 ebook_test_utils_book_async_get_book_view (EBook *book,
751 EBookQuery *query,
752 GSourceFunc callback,
753 gpointer user_data)
754 {
755 EBookTestClosure *closure;
756
757 closure = g_new0 (EBookTestClosure, 1);
758 closure->cb = callback;
759 closure->user_data = user_data;
760 if (!e_book_get_book_view_async (book, query, NULL, -1, (EBookBookViewAsyncCallback) get_book_view_cb, closure)) {
761 g_warning ("failed to set up book view retrieval");
762 exit (1);
763 }
764 }
765