1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  */
16 
17 #include <stdlib.h>
18 #include <locale.h>
19 #include <libebook/libebook.h>
20 
21 #include "e-test-server-utils.h"
22 #include "test-book-cache-utils.h"
23 
24 static void
test_fill_cache(TCUFixture * fixture,EContact ** out_contact)25 test_fill_cache (TCUFixture *fixture,
26 		 EContact **out_contact)
27 {
28 	tcu_add_contact_from_test_case (fixture, "custom-1", out_contact);
29 	tcu_add_contact_from_test_case (fixture, "custom-3", NULL);
30 	tcu_add_contact_from_test_case (fixture, "custom-9", NULL);
31 }
32 
33 enum {
34 	EXPECT_DEFAULT		= (0),
35 	EXPECT_CUSTOM_1		= (1 << 0),
36 	EXPECT_CUSTOM_9		= (1 << 1),
37 	EXPECT_SIMPLE_1		= (1 << 2),
38 	EXPECT_SIMPLE_2		= (1 << 3),
39 	HAS_SEARCH_DATA		= (1 << 4),
40 	HAS_META_CONTACTS	= (1 << 5),
41 	SKIP_CONTACT_PUT	= (1 << 6)
42 };
43 
44 static void
test_check_search_result(const GSList * list,guint32 flags)45 test_check_search_result (const GSList *list,
46 			  guint32 flags)
47 {
48 	gboolean expect_custom_1 = (flags & EXPECT_CUSTOM_1) != 0;
49 	gboolean expect_custom_9 = (flags & EXPECT_CUSTOM_9) != 0;
50 	gboolean expect_simple_1 = (flags & EXPECT_SIMPLE_1) != 0;
51 	gboolean expect_simple_2 = (flags & EXPECT_SIMPLE_2) != 0;
52 	gboolean has_search_data = (flags & HAS_SEARCH_DATA) != 0;
53 	gboolean has_meta_contacts = (flags & HAS_META_CONTACTS) != 0;
54 	gboolean have_custom_1 = FALSE;
55 	gboolean have_custom_3 = FALSE;
56 	gboolean have_custom_9 = FALSE;
57 	gboolean have_simple_1 = FALSE;
58 	gboolean have_simple_2 = FALSE;
59 	const GSList *link;
60 
61 	for (link = list; link; link = g_slist_next (link)) {
62 		const gchar *uid;
63 
64 		if (has_search_data) {
65 			EBookCacheSearchData *sd = link->data;
66 			EContact *contact;
67 
68 			g_assert (sd != NULL);
69 			g_assert (sd->uid != NULL);
70 			g_assert (sd->vcard != NULL);
71 
72 			uid = sd->uid;
73 
74 			contact = e_contact_new_from_vcard (sd->vcard);
75 			g_assert (E_IS_CONTACT (contact));
76 			g_assert_cmpstr (uid, ==, e_contact_get_const (contact, E_CONTACT_UID));
77 
78 			if (has_meta_contacts) {
79 				g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_REV));
80 				g_assert_null (e_contact_get_const (contact, E_CONTACT_EMAIL_1));
81 			} else {
82 				g_assert_nonnull (e_contact_get_const (contact, E_CONTACT_EMAIL_1));
83 			}
84 
85 			g_clear_object (&contact);
86 		} else {
87 			uid = link->data;
88 		}
89 
90 		g_assert_nonnull (uid);
91 
92 		if (g_str_equal (uid, "custom-1")) {
93 			g_assert (expect_custom_1);
94 			g_assert (!have_custom_1);
95 			have_custom_1 = TRUE;
96 		} else if (g_str_equal (uid, "custom-3")) {
97 			g_assert (!have_custom_3);
98 			have_custom_3 = TRUE;
99 		} else if (g_str_equal (uid, "custom-9")) {
100 			g_assert (expect_custom_9);
101 			g_assert (!have_custom_9);
102 			have_custom_9 = TRUE;
103 		} else if (g_str_equal (uid, "simple-1")) {
104 			g_assert (expect_simple_1);
105 			g_assert (!have_simple_1);
106 			have_simple_1 = TRUE;
107 		} else if (g_str_equal (uid, "simple-2")) {
108 			g_assert (expect_simple_2);
109 			g_assert (!have_simple_2);
110 			have_simple_2 = TRUE;
111 		} else {
112 			/* It's not supposed to be NULL, but it will print the value of 'uid' */
113 			g_assert_cmpstr (uid, ==, NULL);
114 		}
115 	}
116 
117 	g_assert ((expect_custom_1 && have_custom_1) || (!expect_custom_1 && !have_custom_1));
118 	g_assert ((expect_custom_9 && have_custom_9) || (!expect_custom_9 && !have_custom_9));
119 	g_assert ((expect_simple_1 && have_simple_1) || (!expect_simple_1 && !have_simple_1));
120 	g_assert ((expect_simple_2 && have_simple_2) || (!expect_simple_2 && !have_simple_2));
121 	g_assert (have_custom_3);
122 }
123 
124 static void
test_basic_cursor(TCUFixture * fixture,guint32 flags,const gchar * sexp)125 test_basic_cursor (TCUFixture *fixture,
126 		   guint32 flags,
127 		   const gchar *sexp)
128 {
129 	EContactField sort_fields[] = { E_CONTACT_FAMILY_NAME, E_CONTACT_GIVEN_NAME };
130 	EBookCursorSortType sort_types[] = { E_BOOK_CURSOR_SORT_ASCENDING, E_BOOK_CURSOR_SORT_ASCENDING };
131 	EBookCacheCursor *cursor;
132 	gint total = -1, position = -1, expect_total;
133 	GSList *list;
134 	GError *error = NULL;
135 
136 	expect_total = 1 +
137 		(((flags & EXPECT_CUSTOM_1) != 0) ? 1 : 0) +
138 		(((flags & EXPECT_CUSTOM_9) != 0) ? 1 : 0) +
139 		(((flags & EXPECT_SIMPLE_1) != 0) ? 1 : 0) +
140 		(((flags & EXPECT_SIMPLE_2) != 0) ? 1 : 0);
141 
142 	cursor = e_book_cache_cursor_new (fixture->book_cache, sexp, sort_fields, sort_types, 2, &error);
143 	g_assert_no_error (error);
144 	g_assert_nonnull (cursor);
145 
146 	g_assert (e_book_cache_cursor_calculate (fixture->book_cache, cursor, &total, &position, NULL, &error));
147 	g_assert_no_error (error);
148 	g_assert_cmpint (total, ==, expect_total);
149 	g_assert_cmpint (position, ==, 0);
150 
151 	g_assert_cmpint (e_book_cache_cursor_step (fixture->book_cache, cursor, E_BOOK_CACHE_CURSOR_STEP_FETCH,
152 		E_BOOK_CACHE_CURSOR_ORIGIN_CURRENT, total, &list, NULL, &error), ==, total);
153 	g_assert_no_error (error);
154 	g_assert_cmpint (g_slist_length (list), ==, total);
155 
156 	test_check_search_result (list, flags | HAS_SEARCH_DATA);
157 
158 	g_slist_free_full (list, e_book_cache_search_data_free);
159 	e_book_cache_cursor_free (fixture->book_cache, cursor);
160 }
161 
162 static void
test_basic_search(TCUFixture * fixture,guint32 flags)163 test_basic_search (TCUFixture *fixture,
164 		   guint32 flags)
165 {
166 	EBookQuery *query;
167 	GSList *list = NULL;
168 	gchar *sexp;
169 	gint expect_total;
170 	GError *error = NULL;
171 
172 	expect_total = 2 +
173 		((flags & EXPECT_CUSTOM_1) != 0 ? 1 : 0) +
174 		((flags & EXPECT_SIMPLE_1) != 0 ? 1 : 0) +
175 		((flags & EXPECT_SIMPLE_2) != 0 ? 1 : 0);
176 
177 	/* All contacts first */
178 	g_assert (e_book_cache_search (fixture->book_cache, NULL, FALSE, &list, NULL, &error));
179 	g_assert_no_error (error);
180 	g_assert_cmpint (g_slist_length (list), ==, expect_total);
181 	test_check_search_result (list, flags | EXPECT_CUSTOM_9 | HAS_SEARCH_DATA);
182 	g_slist_free_full (list, e_book_cache_search_data_free);
183 	list = NULL;
184 
185 	g_assert (e_book_cache_search (fixture->book_cache, NULL, TRUE, &list, NULL, &error));
186 	g_assert_no_error (error);
187 	g_assert_cmpint (g_slist_length (list), ==, expect_total);
188 	test_check_search_result (list, flags | EXPECT_CUSTOM_9 | HAS_SEARCH_DATA | HAS_META_CONTACTS);
189 	g_slist_free_full (list, e_book_cache_search_data_free);
190 	list = NULL;
191 
192 	g_assert (e_book_cache_search_uids (fixture->book_cache, NULL, &list, NULL, &error));
193 	g_assert_no_error (error);
194 	g_assert_cmpint (g_slist_length (list), ==, expect_total);
195 	test_check_search_result (list, flags | EXPECT_CUSTOM_9);
196 	g_slist_free_full (list, g_free);
197 	list = NULL;
198 
199 	test_basic_cursor (fixture, flags | EXPECT_CUSTOM_9, NULL);
200 
201 	/* Only Brown, aka custom-3, as an autocomplete query */
202 	query = e_book_query_field_test (E_CONTACT_FULL_NAME, E_BOOK_QUERY_CONTAINS, "Brown");
203 	sexp = e_book_query_to_string (query);
204 	e_book_query_unref (query);
205 
206 	g_assert (e_book_cache_search (fixture->book_cache, sexp, FALSE, &list, NULL, &error));
207 	g_assert_no_error (error);
208 	g_assert_cmpint (g_slist_length (list), ==, 1);
209 	test_check_search_result (list, HAS_SEARCH_DATA);
210 	g_slist_free_full (list, e_book_cache_search_data_free);
211 	list = NULL;
212 
213 	g_assert (e_book_cache_search (fixture->book_cache, sexp, TRUE, &list, NULL, &error));
214 	g_assert_no_error (error);
215 	g_assert_cmpint (g_slist_length (list), ==, 1);
216 	test_check_search_result (list, HAS_SEARCH_DATA | HAS_META_CONTACTS);
217 	g_slist_free_full (list, e_book_cache_search_data_free);
218 	list = NULL;
219 
220 	g_assert (e_book_cache_search_uids (fixture->book_cache, sexp, &list, NULL, &error));
221 	g_assert_no_error (error);
222 	g_assert_cmpint (g_slist_length (list), ==, 1);
223 	test_check_search_result (list, EXPECT_DEFAULT);
224 	g_slist_free_full (list, g_free);
225 	list = NULL;
226 
227 	test_basic_cursor (fixture, EXPECT_DEFAULT, sexp);
228 
229 	g_free (sexp);
230 
231 	/* Only Brown, aka custom-3, as a regular query */
232 	query = e_book_query_field_test (E_CONTACT_EMAIL, E_BOOK_QUERY_CONTAINS, "brown");
233 	sexp = e_book_query_to_string (query);
234 	e_book_query_unref (query);
235 
236 	g_assert (e_book_cache_search (fixture->book_cache, sexp, FALSE, &list, NULL, &error));
237 	g_assert_no_error (error);
238 	g_assert_cmpint (g_slist_length (list), ==, 1);
239 	test_check_search_result (list, HAS_SEARCH_DATA);
240 	g_slist_free_full (list, e_book_cache_search_data_free);
241 	list = NULL;
242 
243 	g_assert (e_book_cache_search (fixture->book_cache, sexp, TRUE, &list, NULL, &error));
244 	g_assert_no_error (error);
245 	g_assert_cmpint (g_slist_length (list), ==, 1);
246 	test_check_search_result (list, HAS_SEARCH_DATA | HAS_META_CONTACTS);
247 	g_slist_free_full (list, e_book_cache_search_data_free);
248 	list = NULL;
249 
250 	g_assert (e_book_cache_search_uids (fixture->book_cache, sexp, &list, NULL, &error));
251 	g_assert_no_error (error);
252 	g_assert_cmpint (g_slist_length (list), ==, 1);
253 	test_check_search_result (list, EXPECT_DEFAULT);
254 	g_slist_free_full (list, g_free);
255 	list = NULL;
256 
257 	test_basic_cursor (fixture, EXPECT_DEFAULT, sexp);
258 
259 	g_free (sexp);
260 
261 	/* Invalid expression */
262 	g_assert (!e_book_cache_search (fixture->book_cache, "invalid expression here", TRUE, &list, NULL, &error));
263 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_INVALID_QUERY);
264 	g_assert_null (list);
265 	g_clear_error (&error);
266 
267 	g_assert (!e_book_cache_search_uids (fixture->book_cache, "invalid expression here", &list, NULL, &error));
268 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_INVALID_QUERY);
269 	g_assert_null (list);
270 	g_clear_error (&error);
271 }
272 
273 /* Expects pairs of UID (gchar *) and EOfflineState (gint), terminated by NULL */
274 static void
275 test_check_offline_changes (TCUFixture *fixture,
276 			    ...) G_GNUC_NULL_TERMINATED;
277 
278 static void
test_check_offline_changes(TCUFixture * fixture,...)279 test_check_offline_changes (TCUFixture *fixture,
280 			    ...)
281 {
282 	GSList *changes, *link;
283 	va_list args;
284 	GHashTable *expects;
285 	const gchar *uid;
286 	GError *error = NULL;
287 
288 	changes = e_cache_get_offline_changes (E_CACHE (fixture->book_cache), NULL, &error);
289 
290 	g_assert_no_error (error);
291 
292 	expects = g_hash_table_new (g_str_hash, g_str_equal);
293 
294 	va_start (args, fixture);
295 	uid = va_arg (args, const gchar *);
296 	while (uid) {
297 		gint state = va_arg (args, gint);
298 
299 		g_hash_table_insert (expects, (gpointer) uid, GINT_TO_POINTER (state));
300 		uid = va_arg (args, const gchar *);
301 	}
302 	va_end (args);
303 
304 	g_assert_cmpint (g_slist_length (changes), ==, g_hash_table_size (expects));
305 
306 	for (link = changes; link; link = g_slist_next (link)) {
307 		ECacheOfflineChange *change = link->data;
308 		gint expect_state;
309 
310 		g_assert_nonnull (change);
311 		g_assert (g_hash_table_contains (expects, change->uid));
312 
313 		expect_state = GPOINTER_TO_INT (g_hash_table_lookup (expects, change->uid));
314 		g_assert_cmpint (expect_state, ==, change->state);
315 	}
316 
317 	g_slist_free_full (changes, e_cache_offline_change_free);
318 	g_hash_table_destroy (expects);
319 }
320 
321 static EOfflineState
test_check_offline_state(TCUFixture * fixture,const gchar * uid,EOfflineState expect_offline_state)322 test_check_offline_state (TCUFixture *fixture,
323 			  const gchar *uid,
324 			  EOfflineState expect_offline_state)
325 {
326 	EOfflineState offline_state;
327 	GError *error = NULL;
328 
329 	offline_state = e_cache_get_offline_state (E_CACHE (fixture->book_cache), uid, NULL, &error);
330 	g_assert_cmpint (offline_state, ==, expect_offline_state);
331 
332 	if (offline_state == E_OFFLINE_STATE_UNKNOWN) {
333 		g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
334 		g_clear_error (&error);
335 	} else {
336 		g_assert_no_error (error);
337 	}
338 
339 	return offline_state;
340 }
341 
342 static void
test_check_edit_saved(TCUFixture * fixture,const gchar * uid,const gchar * rev_value)343 test_check_edit_saved (TCUFixture *fixture,
344 		       const gchar *uid,
345 		       const gchar *rev_value)
346 {
347 	EContact *contact = NULL;
348 	GError *error = NULL;
349 
350 	g_assert (e_book_cache_get_contact (fixture->book_cache, uid, FALSE, &contact, NULL, &error));
351 	g_assert_no_error (error);
352 	g_assert_nonnull (contact);
353 	g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_REV), ==, rev_value);
354 
355 	g_clear_object (&contact);
356 
357 	g_assert (e_book_cache_get_contact (fixture->book_cache, uid, TRUE, &contact, NULL, &error));
358 	g_assert_no_error (error);
359 	g_assert_nonnull (contact);
360 	g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_REV), ==, rev_value);
361 
362 	g_clear_object (&contact);
363 }
364 
365 static void
test_verify_storage(TCUFixture * fixture,const gchar * uid,const gchar * expect_rev,const gchar * expect_extra,EOfflineState expect_offline_state)366 test_verify_storage (TCUFixture *fixture,
367 		     const gchar *uid,
368 		     const gchar *expect_rev,
369 		     const gchar *expect_extra,
370 		     EOfflineState expect_offline_state)
371 {
372 	EContact *contact = NULL;
373 	EOfflineState offline_state;
374 	gchar *vcard, *saved_rev = NULL, *saved_extra = NULL;
375 	GError *error = NULL;
376 
377 	if (expect_offline_state == E_OFFLINE_STATE_LOCALLY_DELETED ||
378 	    expect_offline_state == E_OFFLINE_STATE_UNKNOWN) {
379 		g_assert (!e_book_cache_get_contact (fixture->book_cache, uid, FALSE, &contact, NULL, &error));
380 		g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
381 		g_assert_null (contact);
382 
383 		g_clear_error (&error);
384 	} else {
385 		g_assert (e_book_cache_get_contact (fixture->book_cache, uid, FALSE, &contact, NULL, &error));
386 		g_assert_no_error (error);
387 		g_assert_nonnull (contact);
388 	}
389 
390 	offline_state = test_check_offline_state (fixture, uid, expect_offline_state);
391 
392 	if (offline_state == E_OFFLINE_STATE_UNKNOWN) {
393 		g_assert (!e_cache_contains (E_CACHE (fixture->book_cache), uid, E_CACHE_EXCLUDE_DELETED));
394 		g_assert (!e_cache_contains (E_CACHE (fixture->book_cache), uid, E_CACHE_INCLUDE_DELETED));
395 		test_check_offline_changes (fixture, NULL);
396 		return;
397 	}
398 
399 	g_assert (e_book_cache_get_contact_extra (fixture->book_cache, uid, &saved_extra, NULL, &error));
400 	g_assert_no_error (error);
401 
402 	g_assert_cmpstr (saved_extra, ==, expect_extra);
403 	g_assert_cmpstr (e_contact_get_const (contact, E_CONTACT_REV), ==, expect_rev);
404 
405 	g_clear_object (&contact);
406 
407 	vcard = e_cache_get (E_CACHE (fixture->book_cache), uid, &saved_rev, NULL, NULL, &error);
408 	g_assert_no_error (error);
409 	g_assert_nonnull (vcard);
410 	g_assert_nonnull (saved_rev);
411 
412 	g_assert_cmpstr (saved_rev, ==, expect_rev);
413 
414 	g_free (vcard);
415 	g_free (saved_rev);
416 	g_free (saved_extra);
417 
418 	if (expect_offline_state == E_OFFLINE_STATE_SYNCED)
419 		test_check_offline_changes (fixture, NULL);
420 	else
421 		test_check_offline_changes (fixture, uid, expect_offline_state, NULL);
422 }
423 
424 static void
test_offline_basics(TCUFixture * fixture,gconstpointer user_data)425 test_offline_basics (TCUFixture *fixture,
426 		     gconstpointer user_data)
427 {
428 	EOfflineState states[] = {
429 		E_OFFLINE_STATE_LOCALLY_CREATED,
430 		E_OFFLINE_STATE_LOCALLY_MODIFIED,
431 		E_OFFLINE_STATE_LOCALLY_DELETED,
432 		E_OFFLINE_STATE_SYNCED
433 	};
434 	EContact *contact = NULL;
435 	gint ii;
436 	const gchar *uid;
437 	gchar *saved_extra = NULL, *tmp;
438 	guint32 custom_flags;
439 	GSList *uids = NULL;
440 	GError *error = NULL;
441 
442 	/* Basic ECache stuff */
443 	e_cache_set_version (E_CACHE (fixture->book_cache), 123);
444 	g_assert_cmpint (e_cache_get_version (E_CACHE (fixture->book_cache)), ==, 123);
445 
446 	e_cache_set_revision (E_CACHE (fixture->book_cache), "rev-321");
447 	tmp = e_cache_dup_revision (E_CACHE (fixture->book_cache));
448 	g_assert_cmpstr ("rev-321", ==, tmp);
449 	g_free (tmp);
450 
451 	g_assert (e_cache_set_key (E_CACHE (fixture->book_cache), "my-key-str", "key-str-value", &error));
452 	g_assert_no_error (error);
453 
454 	tmp = e_cache_dup_key (E_CACHE (fixture->book_cache), "my-key-str", &error);
455 	g_assert_no_error (error);
456 	g_assert_cmpstr ("key-str-value", ==, tmp);
457 	g_free (tmp);
458 
459 	g_assert (e_cache_set_key_int (E_CACHE (fixture->book_cache), "version", 567, &error));
460 	g_assert_no_error (error);
461 
462 	g_assert_cmpint (e_cache_get_key_int (E_CACHE (fixture->book_cache), "version", &error), ==, 567);
463 	g_assert_no_error (error);
464 
465 	g_assert_cmpint (e_cache_get_version (E_CACHE (fixture->book_cache)), ==, 123);
466 
467 	/* Add in online */
468 	test_fill_cache (fixture, &contact);
469 	g_assert_nonnull (contact);
470 
471 	uid = e_contact_get_const (contact, E_CONTACT_UID);
472 	g_assert_nonnull (uid);
473 
474 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
475 	g_assert_no_error (error);
476 
477 	g_assert (e_book_cache_set_contact_extra (fixture->book_cache, uid, "extra-0", NULL, &error));
478 	g_assert_no_error (error);
479 
480 	g_assert (e_book_cache_get_contact_extra (fixture->book_cache, uid, &saved_extra, NULL, &error));
481 	g_assert_no_error (error);
482 	g_assert_cmpstr (saved_extra, ==, "extra-0");
483 
484 	g_free (saved_extra);
485 	saved_extra = NULL;
486 
487 	g_assert (e_book_cache_get_uids_with_extra (fixture->book_cache, "extra-0", &uids, NULL, &error));
488 	g_assert_no_error (error);
489 	g_assert_cmpint (g_slist_length (uids), ==, 1);
490 	g_assert_cmpstr (uids->data, ==, uid);
491 
492 	g_slist_free_full (uids, g_free);
493 	uids = NULL;
494 
495 	e_contact_set (contact, E_CONTACT_REV, "rev-0");
496 
497 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
498 
499 	test_check_offline_changes (fixture, NULL);
500 
501 	/* Try change status */
502 	for (ii = 0; ii < G_N_ELEMENTS (states); ii++) {
503 		g_assert (e_cache_set_offline_state (E_CACHE (fixture->book_cache), uid, states[ii], NULL, &error));
504 		g_assert_no_error (error);
505 
506 		test_check_offline_state (fixture, uid, states[ii]);
507 
508 		if (states[ii] != E_OFFLINE_STATE_SYNCED)
509 			test_check_offline_changes (fixture, uid, states[ii], NULL);
510 
511 		if (states[ii] == E_OFFLINE_STATE_LOCALLY_DELETED) {
512 			g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 2);
513 			g_assert_no_error (error);
514 
515 			g_assert (!e_cache_contains (E_CACHE (fixture->book_cache), uid, E_CACHE_EXCLUDE_DELETED));
516 
517 			g_assert (e_book_cache_set_contact_extra (fixture->book_cache, uid, "extra-1", NULL, &error));
518 			g_assert_no_error (error);
519 
520 			g_assert (e_book_cache_get_contact_extra (fixture->book_cache, uid, &saved_extra, NULL, &error));
521 			g_assert_no_error (error);
522 			g_assert_cmpstr (saved_extra, ==, "extra-1");
523 
524 			g_free (saved_extra);
525 			saved_extra = NULL;
526 
527 			g_assert (e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 123, NULL, &error));
528 			g_assert_no_error (error);
529 
530 			custom_flags = 0;
531 			g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, &error));
532 			g_assert_no_error (error);
533 			g_assert_cmpint (custom_flags, ==, 123);
534 
535 			/* Search when locally deleted */
536 			test_basic_search (fixture, EXPECT_DEFAULT);
537 		} else {
538 			g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
539 			g_assert_no_error (error);
540 
541 			g_assert (e_cache_contains (E_CACHE (fixture->book_cache), uid, E_CACHE_EXCLUDE_DELETED));
542 
543 			/* Search when locally available */
544 			test_basic_search (fixture, EXPECT_CUSTOM_1);
545 		}
546 
547 		g_assert (e_cache_contains (E_CACHE (fixture->book_cache), uid, E_CACHE_INCLUDE_DELETED));
548 
549 		g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 3);
550 		g_assert_no_error (error);
551 	}
552 
553 	test_check_offline_changes (fixture, NULL);
554 
555 	/* Edit in online */
556 	e_contact_set (contact, E_CONTACT_REV, "rev-1");
557 
558 	g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_ONLINE, NULL, &error));
559 	g_assert_no_error (error);
560 
561 	test_verify_storage (fixture, uid, "rev-1", NULL, E_OFFLINE_STATE_SYNCED);
562 	test_check_offline_changes (fixture, NULL);
563 
564 	e_contact_set (contact, E_CONTACT_REV, "rev-2");
565 
566 	g_assert (e_book_cache_put_contact (fixture->book_cache, contact, "extra-2", 0, E_CACHE_IS_ONLINE, NULL, &error));
567 	g_assert_no_error (error);
568 
569 	test_verify_storage (fixture, uid, "rev-2", "extra-2", E_OFFLINE_STATE_SYNCED);
570 	test_check_offline_changes (fixture, NULL);
571 
572 	g_assert (e_book_cache_get_uids_with_extra (fixture->book_cache, "extra-2", &uids, NULL, &error));
573 	g_assert_no_error (error);
574 	g_assert_cmpint (g_slist_length (uids), ==, 1);
575 	g_assert_cmpstr (uids->data, ==, uid);
576 
577 	g_slist_free_full (uids, g_free);
578 	uids = NULL;
579 
580 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
581 	g_assert_no_error (error);
582 
583 	g_assert (e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 234, NULL, &error));
584 	g_assert_no_error (error);
585 
586 	custom_flags = 0;
587 	g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, &error));
588 	g_assert_no_error (error);
589 	g_assert_cmpint (custom_flags, ==, 234);
590 
591 	/* Search before delete */
592 	test_basic_search (fixture, EXPECT_CUSTOM_1);
593 
594 	/* Delete in online */
595 	g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_ONLINE, NULL, &error));
596 	g_assert_no_error (error);
597 
598 	g_assert (!e_cache_set_offline_state (E_CACHE (fixture->book_cache), uid, E_OFFLINE_STATE_LOCALLY_MODIFIED, NULL, &error));
599 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
600 	g_clear_error (&error);
601 
602 	test_verify_storage (fixture, uid, NULL, NULL, E_OFFLINE_STATE_UNKNOWN);
603 	test_check_offline_changes (fixture, NULL);
604 
605 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 2);
606 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 2);
607 	g_assert_no_error (error);
608 
609 	g_assert (!e_book_cache_set_contact_extra (fixture->book_cache, uid, "extra-3", NULL, &error));
610 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
611 	g_clear_error (&error);
612 
613 	g_assert (!e_book_cache_get_contact_extra (fixture->book_cache, uid, &saved_extra, NULL, &error));
614 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
615 	g_assert_null (saved_extra);
616 	g_clear_error (&error);
617 
618 	g_assert (!e_book_cache_get_uids_with_extra (fixture->book_cache, "extra-3", &uids, NULL, &error));
619 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
620 	g_assert_null (uids);
621 	g_clear_error (&error);
622 
623 	g_assert (!e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 456, NULL, &error));
624 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
625 	g_clear_error (&error);
626 
627 	g_assert (!e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, &error));
628 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
629 	g_clear_error (&error);
630 
631 	g_clear_object (&contact);
632 
633 	/* Search after delete */
634 	test_basic_search (fixture, EXPECT_DEFAULT);
635 }
636 
637 static void
test_offline_add_one(TCUFixture * fixture,const gchar * case_name,gint expect_total,guint32 flags,EContact ** out_contact)638 test_offline_add_one (TCUFixture *fixture,
639 		      const gchar *case_name,
640 		      gint expect_total,
641 		      guint32 flags,
642 		      EContact **out_contact)
643 {
644 	EContact *contact = NULL;
645 	const gchar *uid;
646 	GError *error = NULL;
647 
648 	if (!(flags & SKIP_CONTACT_PUT)) {
649 		contact = tcu_new_contact_from_test_case (case_name);
650 		g_assert_nonnull (contact);
651 
652 		uid = e_contact_get_const (contact, E_CONTACT_UID);
653 		g_assert_nonnull (uid);
654 
655 		test_check_offline_state (fixture, uid, E_OFFLINE_STATE_UNKNOWN);
656 
657 		/* Add a contact in offline */
658 		g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_OFFLINE, NULL, &error));
659 		g_assert_no_error (error);
660 	} else {
661 		uid = case_name;
662 	}
663 
664 	if ((flags & EXPECT_SIMPLE_1) != 0) {
665 		test_check_offline_state (fixture, uid, E_OFFLINE_STATE_LOCALLY_CREATED);
666 	} else {
667 		test_check_offline_state (fixture, uid, E_OFFLINE_STATE_UNKNOWN);
668 	}
669 
670 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, expect_total);
671 	g_assert_no_error (error);
672 
673 	test_basic_search (fixture, flags);
674 
675 	if (out_contact)
676 		*out_contact = contact;
677 	else
678 		g_clear_object (&contact);
679 }
680 
681 static void
test_offline_add(TCUFixture * fixture,gconstpointer user_data)682 test_offline_add (TCUFixture *fixture,
683 		  gconstpointer user_data)
684 {
685 	GError *error = NULL;
686 
687 	/* Add in online */
688 	test_fill_cache (fixture, NULL);
689 
690 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
691 	g_assert_no_error (error);
692 
693 	test_check_offline_changes (fixture, NULL);
694 
695 	/* Add the first in offline */
696 	test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, NULL);
697 
698 	test_check_offline_changes (fixture,
699 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
700 		NULL);
701 
702 	/* Add the second in offline */
703 	test_offline_add_one (fixture, "simple-2", 5, EXPECT_SIMPLE_1 | EXPECT_SIMPLE_2 | EXPECT_CUSTOM_1, NULL);
704 
705 	test_check_offline_changes (fixture,
706 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
707 		"simple-2", E_OFFLINE_STATE_LOCALLY_CREATED,
708 		NULL);
709 }
710 
711 static void
test_offline_add_edit(TCUFixture * fixture,gconstpointer user_data)712 test_offline_add_edit (TCUFixture *fixture,
713 		       gconstpointer user_data)
714 {
715 	EContact *contact = NULL;
716 	GError *error = NULL;
717 
718 	/* Add in online */
719 	test_fill_cache (fixture, NULL);
720 
721 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
722 	g_assert_no_error (error);
723 
724 	test_check_offline_changes (fixture, NULL);
725 
726 	/* Add in offline */
727 	test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, &contact);
728 	g_assert_nonnull (contact);
729 
730 	test_check_offline_changes (fixture,
731 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
732 		NULL);
733 
734 	/* Modify added in offline */
735 	e_contact_set (contact, E_CONTACT_REV, "rev-2");
736 
737 	g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_OFFLINE, NULL, &error));
738 	g_assert_no_error (error);
739 
740 	test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, NULL);
741 
742 	test_check_offline_changes (fixture,
743 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
744 		NULL);
745 
746 	test_check_edit_saved (fixture, "simple-1", "rev-2");
747 
748 	g_clear_object (&contact);
749 }
750 
751 static void
test_offline_add_delete(TCUFixture * fixture,gconstpointer user_data)752 test_offline_add_delete (TCUFixture *fixture,
753 			 gconstpointer user_data)
754 {
755 	EContact *contact = NULL;
756 	guint32 custom_flags = 0;
757 	const gchar *uid;
758 	GError *error = NULL;
759 
760 	/* Add in online */
761 	test_fill_cache (fixture, NULL);
762 
763 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
764 	g_assert_no_error (error);
765 
766 	test_check_offline_changes (fixture, NULL);
767 
768 	/* Add in offline */
769 	test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, &contact);
770 	g_assert_nonnull (contact);
771 
772 	test_check_offline_changes (fixture,
773 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
774 		NULL);
775 
776 	uid = e_contact_get_const (contact, E_CONTACT_UID);
777 	g_assert_nonnull (uid);
778 
779 	/* Delete added in offline */
780 
781 	g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 1, E_CACHE_IS_OFFLINE, NULL, &error));
782 	g_assert_no_error (error);
783 
784 	g_assert (!e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, &error));
785 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
786 	g_clear_error (&error);
787 
788 	test_offline_add_one (fixture, "simple-1", 3, EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, NULL);
789 
790 	test_check_offline_changes (fixture, NULL);
791 
792 	/* Add in online */
793 
794 	g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 333, E_CACHE_IS_ONLINE, NULL, &error));
795 	g_assert_no_error (error);
796 
797 	custom_flags = 0;
798 	g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, &error));
799 	g_assert_no_error (error);
800 	g_assert_cmpint (custom_flags, ==, 333);
801 
802 	/* Delete in offline */
803 
804 	g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 246, E_CACHE_IS_OFFLINE, NULL, &error));
805 	g_assert_no_error (error);
806 
807 	custom_flags = 0;
808 	g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, &error));
809 	g_assert_no_error (error);
810 	g_assert_cmpint (custom_flags, ==, 246);
811 
812 	g_clear_object (&contact);
813 }
814 
815 static void
test_offline_add_delete_add(TCUFixture * fixture,gconstpointer user_data)816 test_offline_add_delete_add (TCUFixture *fixture,
817 			     gconstpointer user_data)
818 {
819 	EContact *contact = NULL;
820 	const gchar *uid;
821 	GError *error = NULL;
822 
823 	/* Add in online */
824 	test_fill_cache (fixture, NULL);
825 
826 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
827 	g_assert_no_error (error);
828 
829 	test_check_offline_changes (fixture, NULL);
830 
831 	/* Add in offline */
832 	test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, &contact);
833 	g_assert_nonnull (contact);
834 
835 	test_check_offline_changes (fixture,
836 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
837 		NULL);
838 
839 	uid = e_contact_get_const (contact, E_CONTACT_UID);
840 	g_assert_nonnull (uid);
841 
842 	/* Delete added in offline */
843 	g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, &error));
844 	g_assert_no_error (error);
845 
846 	test_offline_add_one (fixture, "simple-1", 3, EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, NULL);
847 
848 	test_check_offline_changes (fixture, NULL);
849 
850 	g_clear_object (&contact);
851 
852 	/* Add in offline again */
853 	test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, NULL);
854 
855 	test_check_offline_changes (fixture,
856 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
857 		NULL);
858 }
859 
860 static void
test_offline_add_resync(TCUFixture * fixture,gconstpointer user_data)861 test_offline_add_resync (TCUFixture *fixture,
862 			 gconstpointer user_data)
863 {
864 	GError *error = NULL;
865 
866 	/* Add in online */
867 	test_fill_cache (fixture, NULL);
868 
869 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
870 	g_assert_no_error (error);
871 
872 	test_check_offline_changes (fixture, NULL);
873 
874 	/* Add in offline */
875 	test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, NULL);
876 
877 	test_check_offline_changes (fixture,
878 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
879 		NULL);
880 
881 	/* Resync all offline changes */
882 	g_assert (e_cache_clear_offline_changes (E_CACHE (fixture->book_cache), NULL, &error));
883 	g_assert_no_error (error);
884 
885 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 4);
886 	g_assert_no_error (error);
887 
888 	test_basic_search (fixture, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1);
889 	test_check_offline_changes (fixture, NULL);
890 	test_check_offline_state (fixture, "simple-1", E_OFFLINE_STATE_SYNCED);
891 }
892 
893 static void
test_offline_edit_common(TCUFixture * fixture,gchar ** out_uid)894 test_offline_edit_common (TCUFixture *fixture,
895 			  gchar **out_uid)
896 {
897 	EContact *contact = NULL;
898 	guint32 custom_flags = 0;
899 	const gchar *uid;
900 	GError *error = NULL;
901 
902 	/* Add in online */
903 	test_fill_cache (fixture, &contact);
904 	g_assert_nonnull (contact);
905 
906 	uid = e_contact_get_const (contact, E_CONTACT_UID);
907 	g_assert_nonnull (uid);
908 
909 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
910 	g_assert_no_error (error);
911 
912 	test_check_offline_changes (fixture, NULL);
913 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
914 
915 	custom_flags = 0;
916 	g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, &error));
917 	g_assert_no_error (error);
918 	g_assert_cmpint (custom_flags, ==, 0);
919 
920 	/* Modify in offline */
921 	e_contact_set (contact, E_CONTACT_REV, "rev-2");
922 
923 	g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 369, E_CACHE_IS_OFFLINE, NULL, &error));
924 	g_assert_no_error (error);
925 
926 	custom_flags = 0;
927 	g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, &error));
928 	g_assert_no_error (error);
929 	g_assert_cmpint (custom_flags, ==, 369);
930 
931 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
932 	g_assert_no_error (error);
933 
934 	test_check_edit_saved (fixture, uid, "rev-2");
935 
936 	test_basic_search (fixture, EXPECT_CUSTOM_1);
937 	test_check_offline_changes (fixture,
938 		uid, E_OFFLINE_STATE_LOCALLY_MODIFIED,
939 		NULL);
940 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_LOCALLY_MODIFIED);
941 
942 	if (out_uid)
943 		*out_uid = g_strdup (uid);
944 
945 	g_clear_object (&contact);
946 }
947 
948 static void
test_offline_edit(TCUFixture * fixture,gconstpointer user_data)949 test_offline_edit (TCUFixture *fixture,
950 		   gconstpointer user_data)
951 {
952 	test_offline_edit_common (fixture, NULL);
953 }
954 
955 static void
test_offline_edit_delete(TCUFixture * fixture,gconstpointer user_data)956 test_offline_edit_delete (TCUFixture *fixture,
957 			  gconstpointer user_data)
958 {
959 	EContact *contact = NULL;
960 	gchar *uid = NULL;
961 	GError *error = NULL;
962 
963 	test_offline_edit_common (fixture, &uid);
964 
965 	/* Delete the modified contact in offline */
966 	g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, &error));
967 	g_assert_no_error (error);
968 
969 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 2);
970 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 3);
971 	g_assert_no_error (error);
972 
973 	test_basic_search (fixture, EXPECT_DEFAULT);
974 	test_check_offline_changes (fixture,
975 		uid, E_OFFLINE_STATE_LOCALLY_DELETED,
976 		NULL);
977 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_LOCALLY_DELETED);
978 
979 	g_assert (!e_book_cache_get_contact (fixture->book_cache, uid, FALSE, &contact, NULL, &error));
980 	g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
981 	g_assert_null (contact);
982 
983 	g_clear_error (&error);
984 	g_free (uid);
985 }
986 
987 static void
test_offline_edit_resync(TCUFixture * fixture,gconstpointer user_data)988 test_offline_edit_resync (TCUFixture *fixture,
989 			  gconstpointer user_data)
990 {
991 	gchar *uid = NULL;
992 	GError *error = NULL;
993 
994 	test_offline_edit_common (fixture, &uid);
995 
996 	/* Resync all offline changes */
997 	g_assert (e_cache_clear_offline_changes (E_CACHE (fixture->book_cache), NULL, &error));
998 	g_assert_no_error (error);
999 
1000 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
1001 	g_assert_no_error (error);
1002 
1003 	test_basic_search (fixture, EXPECT_CUSTOM_1);
1004 	test_check_offline_changes (fixture, NULL);
1005 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
1006 
1007 	g_free (uid);
1008 }
1009 
1010 static void
test_offline_delete(TCUFixture * fixture,gconstpointer user_data)1011 test_offline_delete (TCUFixture *fixture,
1012 		     gconstpointer user_data)
1013 {
1014 	EContact *contact = NULL;
1015 	const gchar *uid;
1016 	GError *error = NULL;
1017 
1018 	/* Add in online */
1019 	test_fill_cache (fixture, &contact);
1020 	g_assert_nonnull (contact);
1021 
1022 	uid = e_contact_get_const (contact, E_CONTACT_UID);
1023 	g_assert_nonnull (uid);
1024 
1025 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
1026 	g_assert_no_error (error);
1027 
1028 	test_check_offline_changes (fixture, NULL);
1029 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
1030 
1031 	/* Delete in offline */
1032 	g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, &error));
1033 	g_assert_no_error (error);
1034 
1035 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 2);
1036 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 3);
1037 	g_assert_no_error (error);
1038 
1039 	test_basic_search (fixture, EXPECT_DEFAULT);
1040 	test_check_offline_changes (fixture,
1041 		uid, E_OFFLINE_STATE_LOCALLY_DELETED,
1042 		NULL);
1043 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_LOCALLY_DELETED);
1044 
1045 	g_clear_object (&contact);
1046 }
1047 
1048 static void
test_offline_delete_add(TCUFixture * fixture,gconstpointer user_data)1049 test_offline_delete_add (TCUFixture *fixture,
1050 			 gconstpointer user_data)
1051 {
1052 	EContact *contact = NULL;
1053 	const gchar *uid;
1054 	GError *error = NULL;
1055 
1056 	/* Add in online */
1057 	test_fill_cache (fixture, &contact);
1058 	g_assert_nonnull (contact);
1059 
1060 	uid = e_contact_get_const (contact, E_CONTACT_UID);
1061 	g_assert_nonnull (uid);
1062 
1063 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
1064 	g_assert_no_error (error);
1065 
1066 	test_check_offline_changes (fixture, NULL);
1067 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
1068 
1069 	/* Delete locally created in offline */
1070 	test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, NULL);
1071 	g_assert (e_book_cache_remove_contact (fixture->book_cache, "simple-1", 0, E_CACHE_IS_OFFLINE, NULL, &error));
1072 	g_assert_no_error (error);
1073 
1074 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
1075 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 3);
1076 	g_assert_no_error (error);
1077 
1078 	test_basic_search (fixture, EXPECT_CUSTOM_1);
1079 	test_check_offline_changes (fixture, NULL);
1080 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
1081 	test_check_offline_state (fixture, "simple-1", E_OFFLINE_STATE_UNKNOWN);
1082 
1083 	/* Delete synced in offline */
1084 	g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, &error));
1085 	g_assert_no_error (error);
1086 
1087 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 2);
1088 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 3);
1089 	g_assert_no_error (error);
1090 
1091 	test_basic_search (fixture, EXPECT_DEFAULT);
1092 	test_check_offline_changes (fixture,
1093 		uid, E_OFFLINE_STATE_LOCALLY_DELETED,
1094 		NULL);
1095 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_LOCALLY_DELETED);
1096 
1097 	/* Add one in offline */
1098 	test_offline_add_one (fixture, "simple-1", 3, EXPECT_SIMPLE_1, NULL);
1099 
1100 	test_check_offline_changes (fixture,
1101 		uid, E_OFFLINE_STATE_LOCALLY_DELETED,
1102 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
1103 		NULL);
1104 
1105 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_LOCALLY_DELETED);
1106 	test_check_offline_state (fixture, "simple-1", E_OFFLINE_STATE_LOCALLY_CREATED);
1107 
1108 	/* Modify the previous contact and add it again */
1109 	e_contact_set (contact, E_CONTACT_REV, "rev-3");
1110 
1111 	g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_OFFLINE, NULL, &error));
1112 	g_assert_no_error (error);
1113 
1114 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 4);
1115 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 4);
1116 	g_assert_no_error (error);
1117 
1118 	test_check_edit_saved (fixture, uid, "rev-3");
1119 
1120 	test_basic_search (fixture, EXPECT_CUSTOM_1 | EXPECT_SIMPLE_1);
1121 	test_check_offline_changes (fixture,
1122 		uid, E_OFFLINE_STATE_LOCALLY_MODIFIED,
1123 		"simple-1", E_OFFLINE_STATE_LOCALLY_CREATED,
1124 		NULL);
1125 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_LOCALLY_MODIFIED);
1126 	test_check_offline_state (fixture, "simple-1", E_OFFLINE_STATE_LOCALLY_CREATED);
1127 
1128 	g_clear_object (&contact);
1129 }
1130 
1131 static void
test_offline_delete_resync(TCUFixture * fixture,gconstpointer user_data)1132 test_offline_delete_resync (TCUFixture *fixture,
1133 			    gconstpointer user_data)
1134 {
1135 	EContact *contact = NULL;
1136 	const gchar *uid;
1137 	GError *error = NULL;
1138 
1139 	/* Add in online */
1140 	test_fill_cache (fixture, &contact);
1141 	g_assert_nonnull (contact);
1142 
1143 	uid = e_contact_get_const (contact, E_CONTACT_UID);
1144 	g_assert_nonnull (uid);
1145 
1146 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 3);
1147 	g_assert_no_error (error);
1148 
1149 	test_check_offline_changes (fixture, NULL);
1150 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
1151 
1152 	/* Delete in offline */
1153 	g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, &error));
1154 	g_assert_no_error (error);
1155 
1156 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 2);
1157 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 3);
1158 	g_assert_no_error (error);
1159 
1160 	test_basic_search (fixture, EXPECT_DEFAULT);
1161 	test_check_offline_changes (fixture,
1162 		uid, E_OFFLINE_STATE_LOCALLY_DELETED,
1163 		NULL);
1164 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_LOCALLY_DELETED);
1165 
1166 	/* Resync all offline changes */
1167 	e_cache_clear_offline_changes (E_CACHE (fixture->book_cache), NULL, &error);
1168 	g_assert_no_error (error);
1169 
1170 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, &error), ==, 2);
1171 	g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_INCLUDE_DELETED, NULL, &error), ==, 2);
1172 	g_assert_no_error (error);
1173 
1174 	test_basic_search (fixture, EXPECT_DEFAULT);
1175 	test_check_offline_changes (fixture, NULL);
1176 	test_check_offline_state (fixture, uid, E_OFFLINE_STATE_UNKNOWN);
1177 
1178 	g_clear_object (&contact);
1179 }
1180 
1181 gint
main(gint argc,gchar ** argv)1182 main (gint argc,
1183       gchar **argv)
1184 {
1185 	TCUClosure closure = { NULL };
1186 
1187 #if !GLIB_CHECK_VERSION (2, 35, 1)
1188 	g_type_init ();
1189 #endif
1190 	g_test_init (&argc, &argv, NULL);
1191 	g_test_bug_base ("https://gitlab.gnome.org/GNOME/evolution-data-server/");
1192 
1193 	tcu_read_args (argc, argv);
1194 
1195 	/* Ensure that the client and server get the same locale */
1196 	g_assert (g_setenv ("LC_ALL", "en_US.UTF-8", TRUE));
1197 	setlocale (LC_ALL, "");
1198 
1199 	g_test_add ("/EBookCache/Offline/Basics", TCUFixture, &closure,
1200 		tcu_fixture_setup, test_offline_basics, tcu_fixture_teardown);
1201 	g_test_add ("/EBookCache/Offline/Add", TCUFixture, &closure,
1202 		tcu_fixture_setup, test_offline_add, tcu_fixture_teardown);
1203 	g_test_add ("/EBookCache/Offline/AddEdit", TCUFixture, &closure,
1204 		tcu_fixture_setup, test_offline_add_edit, tcu_fixture_teardown);
1205 	g_test_add ("/EBookCache/Offline/AddDelete", TCUFixture, &closure,
1206 		tcu_fixture_setup, test_offline_add_delete, tcu_fixture_teardown);
1207 	g_test_add ("/EBookCache/Offline/AddDeleteAdd", TCUFixture, &closure,
1208 		tcu_fixture_setup, test_offline_add_delete_add, tcu_fixture_teardown);
1209 	g_test_add ("/EBookCache/Offline/AddResync", TCUFixture, &closure,
1210 		tcu_fixture_setup, test_offline_add_resync, tcu_fixture_teardown);
1211 	g_test_add ("/EBookCache/Offline/Edit", TCUFixture, &closure,
1212 		tcu_fixture_setup, test_offline_edit, tcu_fixture_teardown);
1213 	g_test_add ("/EBookCache/Offline/EditDelete", TCUFixture, &closure,
1214 		tcu_fixture_setup, test_offline_edit_delete, tcu_fixture_teardown);
1215 	g_test_add ("/EBookCache/Offline/EditResync", TCUFixture, &closure,
1216 		tcu_fixture_setup, test_offline_edit_resync, tcu_fixture_teardown);
1217 	g_test_add ("/EBookCache/Offline/Delete", TCUFixture, &closure,
1218 		tcu_fixture_setup, test_offline_delete, tcu_fixture_teardown);
1219 	g_test_add ("/EBookCache/Offline/DeleteAdd", TCUFixture, &closure,
1220 		tcu_fixture_setup, test_offline_delete_add, tcu_fixture_teardown);
1221 	g_test_add ("/EBookCache/Offline/DeleteResync", TCUFixture, &closure,
1222 		tcu_fixture_setup, test_offline_delete_resync, tcu_fixture_teardown);
1223 
1224 	return e_test_server_utils_run_full (argc, argv, 0);
1225 }
1226