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