[evolution-data-server/cursor-staging: 16/20] Added tests for the low level cursor API
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/cursor-staging: 16/20] Added tests for the low level cursor API
- Date: Tue, 30 Jul 2013 17:42:47 +0000 (UTC)
commit f0b6a25af54871882832e2a3a7c46d3f2adb7709
Author: Tristan Van Berkom <tristanvb openismus com>
Date: Fri Apr 12 15:37:27 2013 +0900
Added tests for the low level cursor API
o test-sqlite-create-cursor
The new test case verifies that cursor creation is well protected
(cursor creation is denied for some queries and ordering requests).
o test-sqlite-cursor-move-by
This test case asserts that e_book_backend_sqlite_cursor_move_by()
works as expected. Consequently, a hand full of additional test
vcards were added for this.
o test-sqlite-cursor-set-target.c
This test case tests e_book_backend_sqlitedb_cursor_set_target().
The special case of setting a partial state is tested so that when
a cursor is setup to sort by "family_name, given_name" and the target
is set to "J", then we recieve results inclusive of the contact with
the family name "J".
o test-sqlite-cursor-calculate.c
This test verifies that e_book_backend_sqlitedb_cursor_calculate() report
the right position and total values when the cursor is moved, after the
target is set, after the addressbook is modified, for filtered and unfiltered
result sets.
o test-sqlite-cursor-set-sexp.c
This test verifies that invalid queries are rejected, and that a cursor
position is changed by the new sexp with the correct new filtered values
after applying a filter (sexp) to the cursor.
o Tests to ensure that localized data is properly migrated:
- test-sqlite-cursor-posix-initial
- test-sqlite-cursor-en-US-migrated
- test-sqlite-cursor-fr-CA-migrated
- test-sqlite-cursor-de-DE-migrated
- test-sqlite-cursor-posix-migrated
configure.ac | 1 +
tests/Makefile.am | 2 +-
tests/libebook/Makefile.am | 20 +
tests/libebook/data/vcards/sorted-1.vcf | 6 +
tests/libebook/data/vcards/sorted-10.vcf | 6 +
tests/libebook/data/vcards/sorted-11.vcf | 6 +
tests/libebook/data/vcards/sorted-12.vcf | 7 +
tests/libebook/data/vcards/sorted-13.vcf | 6 +
tests/libebook/data/vcards/sorted-14.vcf | 6 +
tests/libebook/data/vcards/sorted-15.vcf | 6 +
tests/libebook/data/vcards/sorted-16.vcf | 6 +
tests/libebook/data/vcards/sorted-17.vcf | 6 +
tests/libebook/data/vcards/sorted-18.vcf | 6 +
tests/libebook/data/vcards/sorted-19.vcf | 6 +
tests/libebook/data/vcards/sorted-2.vcf | 7 +
tests/libebook/data/vcards/sorted-20.vcf | 6 +
tests/libebook/data/vcards/sorted-3.vcf | 7 +
tests/libebook/data/vcards/sorted-4.vcf | 6 +
tests/libebook/data/vcards/sorted-5.vcf | 6 +
tests/libebook/data/vcards/sorted-6.vcf | 5 +
tests/libebook/data/vcards/sorted-7.vcf | 5 +
tests/libebook/data/vcards/sorted-8.vcf | 6 +
tests/libebook/data/vcards/sorted-9.vcf | 6 +
tests/libedata-book/Makefile.am | 114 +++
tests/libedata-book/data-test-utils.c | 756 ++++++++++++++++++++
tests/libedata-book/data-test-utils.h | 164 +++++
tests/libedata-book/test-sqlite-create-cursor.c | 131 ++++
tests/libedata-book/test-sqlite-cursor-calculate.c | 647 +++++++++++++++++
.../test-sqlite-cursor-change-locale.c | 52 ++
.../test-sqlite-cursor-de-DE-migrated.c | 32 +
.../test-sqlite-cursor-en-US-migrated.c | 33 +
.../test-sqlite-cursor-fr-CA-migrated.c | 32 +
.../test-sqlite-cursor-move-by-de-DE.c | 46 ++
.../test-sqlite-cursor-move-by-en-US.c | 63 ++
.../test-sqlite-cursor-move-by-fr-CA.c | 46 ++
.../test-sqlite-cursor-move-by-posix.c | 46 ++
.../test-sqlite-cursor-posix-initial.c | 35 +
.../test-sqlite-cursor-posix-migrated.c | 32 +
tests/libedata-book/test-sqlite-cursor-set-sexp.c | 104 +++
.../libedata-book/test-sqlite-cursor-set-target.c | 180 +++++
tests/libedata-book/test-sqlite-get-contact.c | 56 ++
41 files changed, 2712 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 91bb535..cd19a29 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1764,6 +1764,7 @@ services/evolution-calendar-factory/Makefile
services/evolution-source-registry/Makefile
services/evolution-user-prompter/Makefile
tests/Makefile
+tests/libedata-book/Makefile
tests/libebook/Makefile
tests/libebook-contacts/Makefile
tests/libebook/client/Makefile
diff --git a/tests/Makefile.am b/tests/Makefile.am
index bdad805..a370561 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = test-server-utils libedataserver libebook-contacts libebook libecal libedata-cal
+SUBDIRS = test-server-utils libedataserver libebook-contacts libedata-book libebook libecal libedata-cal
@GNOME_CODE_COVERAGE_RULES@
diff --git a/tests/libebook/Makefile.am b/tests/libebook/Makefile.am
index 8ccebc0..d3b47b6 100644
--- a/tests/libebook/Makefile.am
+++ b/tests/libebook/Makefile.am
@@ -62,6 +62,26 @@ EXTRA_DIST = \
$(srcdir)/data/vcards/name-only.vcf \
$(srcdir)/data/vcards/simple-1.vcf \
$(srcdir)/data/vcards/simple-2.vcf \
+ $(srcdir)/data/vcards/sorted-1.vcf \
+ $(srcdir)/data/vcards/sorted-2.vcf \
+ $(srcdir)/data/vcards/sorted-3.vcf \
+ $(srcdir)/data/vcards/sorted-4.vcf \
+ $(srcdir)/data/vcards/sorted-5.vcf \
+ $(srcdir)/data/vcards/sorted-6.vcf \
+ $(srcdir)/data/vcards/sorted-7.vcf \
+ $(srcdir)/data/vcards/sorted-8.vcf \
+ $(srcdir)/data/vcards/sorted-9.vcf \
+ $(srcdir)/data/vcards/sorted-10.vcf \
+ $(srcdir)/data/vcards/sorted-11.vcf \
+ $(srcdir)/data/vcards/sorted-12.vcf \
+ $(srcdir)/data/vcards/sorted-13.vcf \
+ $(srcdir)/data/vcards/sorted-14.vcf \
+ $(srcdir)/data/vcards/sorted-15.vcf \
+ $(srcdir)/data/vcards/sorted-16.vcf \
+ $(srcdir)/data/vcards/sorted-17.vcf \
+ $(srcdir)/data/vcards/sorted-18.vcf \
+ $(srcdir)/data/vcards/sorted-19.vcf \
+ $(srcdir)/data/vcards/sorted-20.vcf \
$(srcdir)/data/vcards/custom-1.vcf \
$(srcdir)/data/vcards/custom-2.vcf \
$(srcdir)/data/vcards/custom-3.vcf \
diff --git a/tests/libebook/data/vcards/sorted-1.vcf b/tests/libebook/data/vcards/sorted-1.vcf
new file mode 100644
index 0000000..bd4fdbf
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-1.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-1
+N:bad;First Name
+TEL;HOME:+1-221-5423789
+EMAIL;TYPE=home,work:micheal jackson com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-10.vcf b/tests/libebook/data/vcards/sorted-10.vcf
new file mode 100644
index 0000000..3fbb99b
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-10.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-10
+N:C;First Name
+TEL;HOME:+1-221-5423789
+EMAIL;TYPE=home,work:mister jackson com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-11.vcf b/tests/libebook/data/vcards/sorted-11.vcf
new file mode 100644
index 0000000..b820cc8
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-11.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-11
+FN:Ye Nameless One
+TEL;HOME:+1-221-5423789
+EMAIL;TYPE=home,work:name less com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-12.vcf b/tests/libebook/data/vcards/sorted-12.vcf
new file mode 100644
index 0000000..b600d03
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-12.vcf
@@ -0,0 +1,7 @@
+BEGIN:VCARD
+UID:sorted-12
+N:coté;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony com
+END:VCARD
+
diff --git a/tests/libebook/data/vcards/sorted-13.vcf b/tests/libebook/data/vcards/sorted-13.vcf
new file mode 100644
index 0000000..a13875c
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-13.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-13
+N:côte;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony org
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-14.vcf b/tests/libebook/data/vcards/sorted-14.vcf
new file mode 100644
index 0000000..cd803b5
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-14.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-14
+N:cote;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-15.vcf b/tests/libebook/data/vcards/sorted-15.vcf
new file mode 100644
index 0000000..403bc70
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-15.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-15
+N:black-bird;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony org
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-16.vcf b/tests/libebook/data/vcards/sorted-16.vcf
new file mode 100644
index 0000000..6e845db
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-16.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-16
+N:blackbird;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-17.vcf b/tests/libebook/data/vcards/sorted-17.vcf
new file mode 100644
index 0000000..5f62f4d
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-17.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-17
+N:black-birds;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-18.vcf b/tests/libebook/data/vcards/sorted-18.vcf
new file mode 100644
index 0000000..c3c3b69
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-18.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-18
+N:blackbirds;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-19.vcf b/tests/libebook/data/vcards/sorted-19.vcf
new file mode 100644
index 0000000..2971aa2
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-19.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-19
+N:Muffler;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony net
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-2.vcf b/tests/libebook/data/vcards/sorted-2.vcf
new file mode 100644
index 0000000..9a9b8a2
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-2.vcf
@@ -0,0 +1,7 @@
+BEGIN:VCARD
+UID:sorted-2
+N:Bad;First Name
+TEL;HOME:7654321
+EMAIL:janet jackson com
+EMAIL:janny jackson com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-20.vcf b/tests/libebook/data/vcards/sorted-20.vcf
new file mode 100644
index 0000000..2d4c8ee
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-20.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-20
+N:Müller;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony net
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-3.vcf b/tests/libebook/data/vcards/sorted-3.vcf
new file mode 100644
index 0000000..5f75eeb
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-3.vcf
@@ -0,0 +1,7 @@
+BEGIN:VCARD
+UID:sorted-3
+N:Bat;First Name
+TEL;HOME:+9999999
+EMAIL;TYPE=work:bobby brown org
+EMAIL;TYPE=home,work:bobby brown com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-4.vcf b/tests/libebook/data/vcards/sorted-4.vcf
new file mode 100644
index 0000000..888b89c
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-4.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-4
+N:bat;First Name
+TEL;TYPE=work,pref:+9999999
+EMAIL:big bobby brown org
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-5.vcf b/tests/libebook/data/vcards/sorted-5.vcf
new file mode 100644
index 0000000..bf6c11a
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-5.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-5
+N:bäd;First Name
+TEL;HOME:+6666666
+EMAIL;TYPE=home,work:james brown com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-6.vcf b/tests/libebook/data/vcards/sorted-6.vcf
new file mode 100644
index 0000000..2af7b7d
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-6.vcf
@@ -0,0 +1,5 @@
+BEGIN:VCARD
+UID:sorted-6
+N:Bäd;First Name
+TEL;HOME:ask Jenny for Lisa's number
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-7.vcf b/tests/libebook/data/vcards/sorted-7.vcf
new file mode 100644
index 0000000..4a9c3e6
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-7.vcf
@@ -0,0 +1,5 @@
+BEGIN:VCARD
+UID:sorted-7
+N:bät;First Name
+TEL;HOME:+49-89-7888 99
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-8.vcf b/tests/libebook/data/vcards/sorted-8.vcf
new file mode 100644
index 0000000..456181e
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-8.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-8
+N:Bät;First Name
+TEL;HOME:+31-221-5423789
+EMAIL;TYPE=home,work:purple pony com
+END:VCARD
diff --git a/tests/libebook/data/vcards/sorted-9.vcf b/tests/libebook/data/vcards/sorted-9.vcf
new file mode 100644
index 0000000..9a825d6
--- /dev/null
+++ b/tests/libebook/data/vcards/sorted-9.vcf
@@ -0,0 +1,6 @@
+BEGIN:VCARD
+UID:sorted-9
+N:côté;First Name
+TEL;HOME:514-845-8436
+EMAIL;TYPE=home,work:pink pony com
+END:VCARD
diff --git a/tests/libedata-book/Makefile.am b/tests/libedata-book/Makefile.am
new file mode 100644
index 0000000..75324f4
--- /dev/null
+++ b/tests/libedata-book/Makefile.am
@@ -0,0 +1,114 @@
+
+noinst_LTLIBRARIES = libdata-test-utils.la
+
+libdata_test_utils_la_SOURCES = \
+ data-test-utils.c \
+ data-test-utils.h \
+ $(NULL)
+
+libdata_test_utils_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/addressbook \
+ -I$(top_builddir)/addressbook \
+ -I$(top_srcdir)/calendar \
+ -I$(top_builddir)/calendar \
+ -I$(top_srcdir)/tests/libedataserver \
+ -I$(top_builddir)/tests/libedataserver \
+ -I$(top_srcdir)/tests/test-server-utils \
+ -I$(top_builddir)/tests/test-server-utils \
+ -I$(top_srcdir)/private \
+ -I$(top_builddir)/private \
+ -DBACKENDDIR=\"$(ebook_backenddir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DSRCDIR=\""$(abs_srcdir)"\" \
+ -DBUILDDIR=\""$(abs_topbuilddir)"\" \
+ $(EVOLUTION_ADDRESSBOOK_CFLAGS) \
+ $(GIO_UNIX_CFLAGS) \
+ $(CAMEL_CFLAGS) \
+ $(NULL)
+
+libdata_test_utils_la_LIBADD = \
+ $(top_builddir)/addressbook/libebook-contacts/libebook-contacts-1.2.la \
+ $(top_builddir)/addressbook/libedata-book/libedata-book-1.2.la \
+ $(top_builddir)/addressbook/libebook/libebook-1.2.la \
+ $(top_builddir)/tests/test-server-utils/libetestserverutils.la \
+ $(top_builddir)/private/libedbus-private.la \
+ $(EVOLUTION_ADDRESSBOOK_LIBS) \
+ $(GIO_UNIX_LIBS) \
+ $(CAMEL_LIBS) \
+ $(NULL)
+
+# Should be kept ordered approximately from least to most difficult/complex
+#
+# Note that these tests must be run in order:
+# test-sqlite-cursor-posix-initial,
+# test-sqlite-cursor-en-US-migrated,
+# test-sqlite-cursor-posix-migrated
+#
+# This is because each migrated test changes the
+# locale and reloads the same addressbook of the previous test.
+TESTS = \
+ test-sqlite-get-contact \
+ test-sqlite-create-cursor \
+ test-sqlite-cursor-move-by-posix \
+ test-sqlite-cursor-move-by-en-US \
+ test-sqlite-cursor-move-by-fr-CA \
+ test-sqlite-cursor-move-by-de-DE \
+ test-sqlite-cursor-set-target \
+ test-sqlite-cursor-calculate \
+ test-sqlite-cursor-set-sexp \
+ test-sqlite-cursor-posix-initial \
+ test-sqlite-cursor-en-US-migrated \
+ test-sqlite-cursor-fr-CA-migrated \
+ test-sqlite-cursor-de-DE-migrated \
+ test-sqlite-cursor-posix-migrated \
+ test-sqlite-cursor-change-locale
+
+noinst_PROGRAMS = $(TESTS)
+
+TEST_CPPFLAGS = \
+ $(libdata_test_utils_la_CPPFLAGS) \
+ $(EVOLUTION_ADDRESSBOOK_CPPFLAGS) \
+ $(NULL)
+
+TEST_LIBS = \
+ $(libdata_test_utils_la_LIBADD) \
+ libdata-test-utils.la \
+ $(top_builddir)/addressbook/libebook/libebook-1.2.la \
+ $(EVOLUTION_ADDRESSBOOK_LIBS) \
+ $(NULL)
+
+test_sqlite_get_contact_LDADD=$(TEST_LIBS)
+test_sqlite_get_contact_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_create_cursor_LDADD=$(TEST_LIBS)
+test_sqlite_create_cursor_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_move_by_posix_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_move_by_posix_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_move_by_en_US_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_move_by_en_US_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_move_by_fr_CA_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_move_by_fr_CA_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_move_by_de_DE_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_move_by_de_DE_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_set_target_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_set_target_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_calculate_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_calculate_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_set_sexp_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_set_sexp_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_posix_initial_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_posix_initial_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_en_US_migrated_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_en_US_migrated_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_fr_CA_migrated_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_fr_CA_migrated_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_de_DE_migrated_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_de_DE_migrated_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_posix_migrated_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_posix_migrated_CPPFLAGS=$(TEST_CPPFLAGS)
+test_sqlite_cursor_change_locale_LDADD=$(TEST_LIBS)
+test_sqlite_cursor_change_locale_CPPFLAGS=$(TEST_CPPFLAGS)
+
+-include $(top_srcdir)/git.mk
diff --git a/tests/libedata-book/data-test-utils.c b/tests/libedata-book/data-test-utils.c
new file mode 100644
index 0000000..c5f4c44
--- /dev/null
+++ b/tests/libedata-book/data-test-utils.c
@@ -0,0 +1,756 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2013, Openismus GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Tristan Van Berkom <tristanvb openismus com>
+ */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "data-test-utils.h"
+
+/* This forces the GType to be registered in a way that
+ * avoids a "statement with no effect" compiler warning.
+ * FIXME Use g_type_ensure() once we require GLib 2.34. */
+#define REGISTER_TYPE(type) \
+ (g_type_class_unref (g_type_class_ref (type)))
+
+
+#define SQLITEDB_EMAIL_ID "addressbook localbackend com"
+#define SQLITEDB_FOLDER_NAME "folder"
+
+gchar *
+new_vcard_from_test_case (const gchar *case_name)
+{
+ gchar *filename;
+ gchar *case_filename;
+ GFile * file;
+ GError *error = NULL;
+ gchar *vcard;
+
+ case_filename = g_strdup_printf ("%s.vcf", case_name);
+ filename = g_build_filename (SRCDIR, "..", "libebook", "data", "vcards", case_filename, NULL);
+ file = g_file_new_for_path (filename);
+ if (!g_file_load_contents (file, NULL, &vcard, NULL, NULL, &error))
+ g_error ("failed to read test contact file '%s': %s",
+ filename, error->message);
+
+ g_free (case_filename);
+ g_free (filename);
+ g_object_unref (file);
+
+ return vcard;
+}
+
+EContact *
+new_contact_from_test_case (const gchar *case_name)
+{
+ gchar *vcard;
+ EContact *contact = NULL;
+
+ vcard = new_vcard_from_test_case (case_name);
+ if (vcard)
+ contact = e_contact_new_from_vcard (vcard);
+ g_free (vcard);
+
+ return contact;
+}
+
+static gboolean
+contacts_are_equal_shallow (EContact *a,
+ EContact *b)
+{
+ const gchar *uid_a, *uid_b;
+
+ /* Avoid warnings if one or more are NULL, to make this function
+ * "NULL-friendly" */
+ if (!a && !b)
+ return TRUE;
+
+ if (!E_IS_CONTACT (a) || !E_IS_CONTACT (b))
+ return FALSE;
+
+ uid_a = e_contact_get_const (a, E_CONTACT_UID);
+ uid_b = e_contact_get_const (b, E_CONTACT_UID);
+
+ return g_strcmp0 (uid_a, uid_b) == 0;
+}
+
+gboolean
+add_contact_from_test_case_verify (EBookClient *book_client,
+ const gchar *case_name,
+ EContact **contact)
+{
+ EContact *contact_orig;
+ EContact *contact_final;
+ gchar *uid;
+ GError *error = NULL;
+
+ contact_orig = new_contact_from_test_case (case_name);
+
+ if (!e_book_client_add_contact_sync (book_client, contact_orig, &uid, NULL, &error))
+ g_error ("Failed to add contact: %s", error->message);
+
+ e_contact_set (contact_orig, E_CONTACT_UID, uid);
+
+ if (!e_book_client_get_contact_sync (book_client, uid, &contact_final, NULL, &error))
+ g_error ("Failed to get contact: %s", error->message);
+
+ /* verify the contact was added "successfully" (not thorough) */
+ g_assert (contacts_are_equal_shallow (contact_orig, contact_final));
+
+ if (contact)
+ *contact = contact_final;
+ else
+ g_object_unref (contact_final);
+ g_object_unref (contact_orig);
+ g_free (uid);
+
+ return TRUE;
+}
+
+static gchar *
+get_addressbook_directory (ESourceRegistry *registry,
+ ESource *source)
+{
+ ESource *builtin_source;
+ const gchar *user_data_dir;
+ const gchar *uid;
+ gchar *filename = NULL;
+
+ uid = e_source_get_uid (source);
+ g_return_val_if_fail (uid != NULL, NULL);
+
+ user_data_dir = e_get_user_data_dir ();
+
+ builtin_source = e_source_registry_ref_builtin_address_book (registry);
+
+ /* Special case directory for the builtin addressbook source */
+ if (builtin_source != NULL && e_source_equal (source, builtin_source))
+ uid = "system";
+
+ filename = g_build_filename (user_data_dir, "addressbook", uid, NULL);
+
+ if (builtin_source)
+ g_object_unref (builtin_source);
+
+ return filename;
+}
+
+static EBookBackendSqliteDB *
+open_sqlitedb (ESourceRegistry *registry,
+ ESource *source)
+{
+ EBookBackendSqliteDB *ebsdb;
+ GError *error;
+ gchar *dirname;
+
+ dirname = get_addressbook_directory (registry, source);
+ ebsdb = e_book_backend_sqlitedb_new (dirname,
+ SQLITEDB_EMAIL_ID,
+ SQLITEDB_FOLDER_ID,
+ SQLITEDB_FOLDER_NAME,
+ TRUE, &error);
+
+ if (!ebsdb)
+ g_error ("Failed to open SQLite backend: %s", error->message);
+
+ g_free (dirname);
+
+ return ebsdb;
+}
+
+void
+e_sqlitedb_fixture_setup (ESqliteDBFixture *fixture,
+ gconstpointer user_data)
+{
+ EBookClient *book_client;
+
+ e_test_server_utils_setup ((ETestServerFixture *)fixture, user_data);
+
+ book_client = E_TEST_SERVER_UTILS_SERVICE (fixture, EBookClient);
+ fixture->ebsdb = open_sqlitedb (((ETestServerFixture *)fixture)->registry,
+ e_client_get_source (E_CLIENT (book_client)));
+}
+
+void
+e_sqlitedb_fixture_teardown (ESqliteDBFixture *fixture,
+ gconstpointer user_data)
+{
+ g_object_unref (fixture->ebsdb);
+ e_test_server_utils_teardown ((ETestServerFixture *)fixture, user_data);
+}
+
+void
+e_sqlitedb_cursor_fixture_setup_book (ESource *scratch,
+ ETestServerClosure *closure)
+{
+ ESourceBackendSummarySetup *setup;
+
+ g_type_class_unref (g_type_class_ref (E_TYPE_SOURCE_BACKEND_SUMMARY_SETUP));
+ setup = e_source_get_extension (scratch, E_SOURCE_EXTENSION_BACKEND_SUMMARY_SETUP);
+ e_source_backend_summary_setup_set_summary_fields (setup,
+ E_CONTACT_FAMILY_NAME,
+ E_CONTACT_GIVEN_NAME,
+ E_CONTACT_EMAIL,
+ 0);
+ e_source_backend_summary_setup_set_indexed_fields (setup,
+ E_CONTACT_FAMILY_NAME, E_BOOK_INDEX_PREFIX,
+ E_CONTACT_GIVEN_NAME, E_BOOK_INDEX_PREFIX,
+ E_CONTACT_EMAIL, E_BOOK_INDEX_PREFIX,
+ 0);
+}
+
+void
+e_sqlitedb_cursor_fixture_setup (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ ETestServerFixture *base_fixture = (ETestServerFixture *)fixture;
+ ESqliteDBFixture *ebsdb_fixture = (ESqliteDBFixture *)fixture;
+ EbSdbCursorClosure *data = (EbSdbCursorClosure *)user_data;
+ EContactField sort_fields[] = { E_CONTACT_FAMILY_NAME, E_CONTACT_GIVEN_NAME };
+ EBookSortType sort_types[] = { data->sort_type, data->sort_type };
+ EBookClient *book_client;
+ GSList *contacts = NULL;
+ GError *error = NULL;
+ gint i;
+ gchar *sexp = NULL;
+ const gchar *source_name;
+
+ /* Support the migration tests */
+ source_name = g_getenv ("MIGRATION_TEST_SOURCE_NAME");
+ if (source_name != NULL)
+ base_fixture->source_name = g_strdup (source_name);
+
+ /* Setup the EBookClient, but don't open the EBookBackendSqliteDB until after
+ * we've specified the locale
+ */
+ e_test_server_utils_setup ((ETestServerFixture *)fixture, user_data);
+ book_client = E_TEST_SERVER_UTILS_SERVICE (fixture, EBookClient);
+
+ if (data->locale)
+ e_sqlitedb_cursor_fixture_set_locale (fixture, data->locale);
+ else
+ e_sqlitedb_cursor_fixture_set_locale (fixture, "en_US.UTF-8");
+
+ /* Now open the EBookBackendSqliteDB */
+ ebsdb_fixture->ebsdb = open_sqlitedb (((ETestServerFixture *)fixture)->registry,
+ e_client_get_source (E_CLIENT (book_client)));
+
+ for (i = 0; i < N_SORTED_CONTACTS; i++) {
+ gchar *case_name = g_strdup_printf ("sorted-%d", i + 1);
+ gchar *vcard;
+ EContact *contact;
+
+ vcard = new_vcard_from_test_case (case_name);
+ contact = e_contact_new_from_vcard (vcard);
+ contacts = g_slist_prepend (contacts, contact);
+ g_free (vcard);
+ g_free (case_name);
+
+ fixture->contacts[i] = contact;
+ }
+
+ if (!e_book_client_add_contacts_sync (book_client, contacts, NULL, NULL, &error)) {
+
+ /* Dont complain here, we re-use the same addressbook for multiple tests
+ * and we can't add the same contacts twice
+ */
+ if (g_error_matches (error, E_BOOK_CLIENT_ERROR,
+ E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS))
+ g_clear_error (&error);
+ else
+ g_error ("Failed to add test contacts: %s", error->message);
+ }
+
+ g_slist_free (contacts);
+
+ /* Allow a surrounding fixture setup to add a query here */
+ if (fixture->query) {
+ sexp = e_book_query_to_string (fixture->query);
+ e_book_query_unref (fixture->query);
+ fixture->query = NULL;
+ }
+
+ fixture->cursor = e_book_backend_sqlitedb_cursor_new (((ESqliteDBFixture *) fixture)->ebsdb,
+ SQLITEDB_FOLDER_ID,
+ sexp, sort_fields, sort_types, 2, &error);
+
+ g_free (sexp);
+
+ g_assert (fixture->cursor != NULL);
+}
+
+void
+e_sqlitedb_cursor_fixture_filtered_setup (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ fixture->query = e_book_query_field_test (E_CONTACT_EMAIL, E_BOOK_QUERY_ENDS_WITH, ".com");
+
+ e_sqlitedb_cursor_fixture_setup (fixture, user_data);
+}
+
+void
+e_sqlitedb_cursor_fixture_teardown (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ gint i;
+
+ for (i = 0; i < N_SORTED_CONTACTS; i++) {
+ if (fixture->contacts[i])
+ g_object_unref (fixture->contacts[i]);
+ }
+
+ if (fixture->locale1)
+ g_object_unref (fixture->locale1);
+
+ if (fixture->own_id > 0)
+ g_bus_unown_name (fixture->own_id);
+
+ e_book_backend_sqlitedb_cursor_free (((ESqliteDBFixture *) fixture)->ebsdb, fixture->cursor);
+ e_sqlitedb_fixture_teardown ((ESqliteDBFixture *)fixture, user_data);
+}
+
+typedef struct {
+ EbSdbCursorFixture *fixture;
+ const gchar *locale;
+} ChangeLocaleData;
+
+static void
+book_client_locale_change (EBookClient *book,
+ GParamSpec *pspec,
+ ChangeLocaleData *data)
+{
+ ETestServerFixture *base_fixture = (ETestServerFixture *)data->fixture;
+
+ if (!g_strcmp0 (e_book_client_get_locale (book), data->locale))
+ g_main_loop_quit (base_fixture->loop);
+}
+
+void
+e_sqlitedb_cursor_fixture_set_locale (EbSdbCursorFixture *fixture,
+ const gchar *locale)
+{
+ ETestServerFixture *base_fixture = (ETestServerFixture *)fixture;
+ EBookClient *book_client;
+ ChangeLocaleData data = { fixture, locale };
+ gulong handler_id;
+ gchar *strv[2] = { NULL, NULL };
+
+ book_client = E_TEST_SERVER_UTILS_SERVICE (fixture, EBookClient);
+
+ /* We're already in the right locale */
+ if (g_strcmp0 (locale, e_book_client_get_locale (book_client)) == 0)
+ return;
+
+ if (!fixture->locale1) {
+ GDBusConnection *bus;
+ GError *error = NULL;
+
+ /* We use the 'org.freedesktop.locale1 on the session bus instead
+ * of the system bus only for testing purposes... in real life
+ * this service is on the system bus.
+ */
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ if (!bus)
+ g_error ("Failed to get system bus: %s", error->message);
+
+ fixture->locale1 = e_dbus_locale1_skeleton_new ();
+
+ /* Set initial locale before exporting on the bus */
+ strv[0] = g_strdup_printf ("LANG=%s", locale);
+ e_dbus_locale1_set_locale (fixture->locale1, (const gchar * const *)strv);
+ g_free (strv[0]);
+
+ if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (fixture->locale1),
+ bus, "/org/freedesktop/locale1", &error))
+ g_error ("Failed to export org.freedesktop.locale1: %s", error->message);
+
+ fixture->own_id =
+ g_bus_own_name_on_connection (bus,
+ "org.freedesktop.locale1",
+ G_BUS_NAME_OWNER_FLAGS_REPLACE,
+ NULL, NULL, NULL, NULL);
+
+ g_object_unref (bus);
+ } else {
+ /* Send locale change message */
+ strv[0] = g_strdup_printf ("LANG=%s", locale);
+ e_dbus_locale1_set_locale (fixture->locale1, (const gchar * const *)strv);
+ g_free (strv[0]);
+ }
+
+ handler_id = g_signal_connect (book_client, "notify::locale",
+ G_CALLBACK (book_client_locale_change), &data);
+ g_main_loop_run (base_fixture->loop);
+ g_signal_handler_disconnect (book_client, handler_id);
+}
+
+static gint
+find_contact_data (EbSdbSearchData *data,
+ const gchar *uid)
+{
+ return g_strcmp0 (data->uid, uid);
+}
+
+void
+assert_contacts_order_slist (GSList *results,
+ GSList *uids)
+{
+ gint position = -1;
+ GSList *link, *l;
+
+ /* Assert that all passed UIDs are found in the
+ * results, and that those UIDs are in the
+ * specified order.
+ */
+ for (l = uids; l; l = l->next) {
+ const gchar *uid = l->data;
+ gint new_position;
+
+ link = g_slist_find_custom (results, uid, (GCompareFunc)find_contact_data);
+ if (!link)
+ g_error ("Specified uid '%s' was not found in results", uid);
+
+ new_position = g_slist_position (results, link);
+ g_assert_cmpint (new_position, >, position);
+ position = new_position;
+ }
+
+}
+
+void
+assert_contacts_order (GSList *results,
+ const gchar *first_uid,
+ ...)
+{
+ GSList *uids = NULL;
+ gchar *uid;
+ va_list args;
+
+ g_assert (first_uid);
+
+ uids = g_slist_append (uids, (gpointer)first_uid);
+
+ va_start (args, first_uid);
+ uid = va_arg (args, gchar*);
+ while (uid) {
+ uids = g_slist_append (uids, uid);
+ uid = va_arg (args, gchar*);
+ }
+ va_end (args);
+
+ assert_contacts_order_slist (results, uids);
+ g_slist_free (uids);
+}
+
+void
+print_results (GSList *results)
+{
+ GSList *l;
+
+ if (g_getenv ("TEST_DEBUG") == NULL)
+ return;
+
+ g_print ("\nPRINTING RESULTS:\n");
+
+ for (l = results; l; l = l->next) {
+ EbSdbSearchData *data = l->data;
+
+ g_print ("\n%s\n", data->vcard);
+ }
+
+ g_print ("\nRESULT LIST_FINISHED\n");
+}
+
+/********************************************
+ * Move By Test Helpers
+ ********************************************/
+#define DEBUG_FIXTURE 0
+
+static MoveByData *
+move_by_test_new_internal (const gchar *test_path,
+ const gchar *locale,
+ gsize struct_size)
+{
+ MoveByData *data;
+
+ data = g_slice_alloc0 (struct_size);
+ data->parent.parent.type = E_TEST_SERVER_ADDRESS_BOOK;
+ data->parent.parent.customize = e_sqlitedb_cursor_fixture_setup_book;
+ data->parent.locale = g_strdup (locale);
+ data->parent.sort_type = E_BOOK_SORT_ASCENDING;
+ data->path = g_strdup (test_path);
+ data->struct_size = struct_size;
+
+ /* Keep the work dir for migration tests */
+ if (g_getenv ("MIGRATION_TEST_SOURCE_NAME") != NULL)
+ data->parent.parent.keep_work_directory = TRUE;
+
+ return data;
+}
+
+static void
+move_by_test_free (MoveByData *data)
+{
+ g_free (data->path);
+ g_free ((gchar *)data->parent.locale);
+ g_slice_free1 (data->struct_size, data);
+}
+
+MoveByData *
+move_by_test_new (const gchar *test_path,
+ const gchar *locale)
+{
+ return move_by_test_new_internal (test_path, locale, sizeof (MoveByData));
+}
+
+MoveByData *
+move_by_test_new_full (const gchar *test_path,
+ const gchar *locale,
+ EBookSortType sort_type)
+{
+ MoveByData *data;
+
+ data = move_by_test_new_internal (test_path, locale, sizeof (MoveByData));
+ data->parent.sort_type = sort_type;
+
+ return data;
+}
+
+static void
+test_cursor_move_teardown (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ MoveByData *data = (MoveByData *)user_data;
+
+ e_sqlitedb_cursor_fixture_teardown (fixture, user_data);
+
+ move_by_test_free (data);
+}
+
+static void
+assert_move_by (EbSdbCursorFixture *fixture,
+ MoveByData *data,
+ gint i,
+ GSList *results)
+{
+ GSList *uids = NULL;
+ gint j, expected = 0;
+
+ /* Count the number of really expected results */
+ for (j = 0; j < ABS (data->counts[i]); j++) {
+ gint index = data->expected[i][j];
+
+ if (index < 0)
+ break;
+
+ expected++;
+ }
+
+ /* Assert the exact amount of requested results */
+ g_assert_cmpint (g_slist_length (results), ==, expected);
+
+#if DEBUG_FIXTURE
+ g_print ("%s: Constructing expected result list for a fetch of %d: ",
+ data->path, data->counts[i]);
+#endif
+ for (j = 0; j < ABS (data->counts[i]); j++) {
+ gint index = data->expected[i][j];
+ gchar *uid;
+
+ if (index < 0)
+ break;
+
+ uid = (gchar *)e_contact_get_const (fixture->contacts[index], E_CONTACT_UID);
+ uids = g_slist_append (uids, uid);
+
+#if DEBUG_FIXTURE
+ g_print ("%s ", uid);
+#endif
+
+ }
+#if DEBUG_FIXTURE
+ g_print ("\n");
+#endif
+
+ assert_contacts_order_slist (results, uids);
+ g_slist_free (uids);
+}
+
+static void
+test_move_by (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ MoveByData *data = (MoveByData *)user_data;
+ GSList *results = NULL;
+ GError *error = NULL;
+ gint i;
+ gint expected_position = 0, position;
+ gint total;
+
+ total = data->filtered ? N_FILTERED_CONTACTS : N_SORTED_CONTACTS;
+
+ for (i = 0; i < MAX_MOVE_BY_COUNTS && data->counts[i] != 0; i++) {
+
+ /* From the 0 position, a negative move starts from the end */
+ if (expected_position == 0 && data->counts[i] < 0)
+ expected_position = (total + 1) - ABS (data->counts[i]);
+ else
+ expected_position += data->counts[i];
+
+ if (expected_position > total || expected_position < 1)
+ expected_position = 0;
+
+ /* Try normal order */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ data->counts[i],
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ print_results (results);
+ assert_move_by (fixture, data, i, results);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, NULL, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+ g_assert_cmpint (expected_position, ==, position);
+
+ /* Try repeat last query */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_PREVIOUS,
+ data->counts[i],
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ print_results (results);
+ assert_move_by (fixture, data, i, results);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, NULL, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+ g_assert_cmpint (expected_position, ==, position);
+ }
+
+ /* One more, test reset API, the first batch from the beginning */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_RESET,
+ data->counts[0],
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ print_results (results);
+ assert_move_by (fixture, data, 0, results);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* From the 0 position, a negative move starts from the end */
+ if (data->counts[0] < 0)
+ expected_position = (total + 1) - ABS (data->counts[0]);
+ else
+ expected_position = data->counts[0];
+
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, NULL, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+ g_assert_cmpint (expected_position, ==, position);
+}
+
+static void
+move_by_test_add_assertion_va_list (MoveByData *data,
+ gint count,
+ va_list args)
+{
+ gint i, j;
+ gint expected;
+
+ for (i = 0; i < MAX_MOVE_BY_COUNTS; i++) {
+
+ /* Find the next available test slot */
+ if (data->counts[i] == 0) {
+ data->counts[i] = count;
+
+#if DEBUG_FIXTURE
+ g_print ("Adding assertion to test %d: %s\n", i + 1, data->path);
+ g_print (" Test will move by %d and expect: ", count);
+#endif
+ for (j = 0; j < ABS (count); j++) {
+ expected = va_arg (args, gint);
+
+#if DEBUG_FIXTURE
+ g_print ("%d ", expected);
+#endif
+ data->expected[i][j] = expected - 1;
+ }
+#if DEBUG_FIXTURE
+ g_print ("\n");
+#endif
+
+ break;
+ }
+ }
+
+ g_assert (i < MAX_MOVE_BY_COUNTS);
+}
+
+/* A positive of negative 'count' value
+ * followed by ABS (count) UID indexes.
+ *
+ * The indexes start at 1 so that they
+ * are easier to match up with the chart
+ * in data-test-utils.h
+ */
+void
+move_by_test_add_assertion (MoveByData *data,
+ gint count,
+ ...)
+{
+
+ va_list args;
+
+ va_start (args, count);
+ move_by_test_add_assertion_va_list (data, count, args);
+ va_end (args);
+}
+
+void
+move_by_test_add (MoveByData *data,
+ gboolean filtered)
+{
+ data->filtered = filtered;
+
+ g_test_add (data->path, EbSdbCursorFixture, data,
+ filtered ?
+ e_sqlitedb_cursor_fixture_filtered_setup :
+ e_sqlitedb_cursor_fixture_setup,
+ test_move_by,
+ test_cursor_move_teardown);
+}
+
diff --git a/tests/libedata-book/data-test-utils.h b/tests/libedata-book/data-test-utils.h
new file mode 100644
index 0000000..58d865f
--- /dev/null
+++ b/tests/libedata-book/data-test-utils.h
@@ -0,0 +1,164 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2013, Openismus GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Authors: Tristan Van Berkom <tristanvb openismus com>
+ */
+
+#ifndef DATA_TEST_UTILS_H
+#define DATA_TEST_UTILS_H
+
+#include <libebook/libebook.h>
+#include <libedata-book/libedata-book.h>
+#include "e-test-server-utils.h"
+#include "e-dbus-localed.h"
+
+/* This legend shows the add order, and various sort order of the sorted
+ * vcards. The UIDs of these contacts are formed as 'sorted-1', 'sorted-2' etc
+ * and the numbering of the contacts is according to the 'N' column in the
+ * following legend.
+ *
+ * The Email column indicates whether the contact has a .com email address
+ * (in order to test filtered cursor results) and corresponds to the natural
+ * order in the 'N' column.
+ *
+ * +-----------------------------------------------------------------------------------------------+
+ * | N | Email | Last Name | en_US_POSIX | en_US / de_DE | fr_CA | de_DE |
+ * | | | | | | | (phonebook) |
+ * +-----------------------------------------------------------------------------------------------+
+ * | 1 | Yes | bad | 11 | 11 | 11 | 11 |
+ * | 2 | Yes | Bad | Bad 2 | bad 1 | bad 1 | bad 1 |
+ * | 3 | Yes | Bat | Bäd 6 | Bad 2 | Bad 2 | Bad 2 |
+ * | 4 | No | bat | Bat 3 | bäd 5 | bäd 5 | bäd 5 |
+ * | 5 | Yes | bäd | Bät 8 | Bäd 6 | Bäd 6 | Bäd 6 |
+ * | 6 | No | Bäd | bad 1 | bat 4 | bat 4 | bät 7 |
+ * | 7 | No | bät | bäd 5 | Bat 3 | Bat 3 | Bät 8 |
+ * | 8 | Yes | Bät | bat 4 | bät 7 | bät 7 | bat 4 |
+ * | 9 | Yes | côté | bät 7 | Bät 8 | Bät 8 | Bat 3 |
+ * | 10 | Yes | C | black-bird 15 | black-bird 15 | black-bird 15 | black-bird 15 |
+ * | 11 | Yes | | black-birds 17 | black-birds 17 | black-birds 17 | black-birds 17 |
+ * | 12 | Yes | coté | blackbird 16 | blackbird 16 | blackbird 16 | blackbird 16 |
+ * | 13 | No | côte | blackbirds 18 | blackbirds 18 | blackbirds 18 | blackbirds 18 |
+ * | 14 | Yes | cote | C 10 | C 10 | C 10 | C 10 |
+ * | 15 | No | black-bird | cote 14 | cote 14 | cote 14 | cote 14 |
+ * | 16 | Yes | blackbird | coté 12 | coté 12 | côte 13 | coté 12 |
+ * | 17 | Yes | black-birds | côte 13 | côte 13 | coté 12 | côte 13 |
+ * | 18 | Yes | blackbirds | côté 9 | côté 9 | côté 9 | côté 9 |
+ * | 19 | No | Muffler | Muffler 19 | Muffler 19 | Muffler 19 | Müller 20 |
+ * | 20 | No | Müller | Müller 20 | Müller 20 | Müller 20 | Muffler 19 |
+ * +-----------------------------------------------------------------------------------------------+
+ *
+ * See this ICU demo to check additional sort ordering by ICU in various locales:
+ * http://demo.icu-project.org/icu-bin/locexp?_=en_US&d_=en&x=col
+ */
+
+#define SQLITEDB_FOLDER_ID "folder_id"
+#define N_SORTED_CONTACTS 20
+#define MAX_MOVE_BY_COUNTS 5
+
+/* 13 contacts in the test data have an email address ending with ".com" */
+#define N_FILTERED_CONTACTS 13
+
+
+typedef struct {
+ ETestServerFixture parent_fixture;
+
+ EBookBackendSqliteDB *ebsdb;
+} ESqliteDBFixture;
+
+typedef struct {
+ ESqliteDBFixture parent_fixture;
+
+ EbSdbCursor *cursor;
+ EContact *contacts[N_SORTED_CONTACTS];
+ EBookQuery *query;
+
+ EDBusLocale1 *locale1;
+ guint own_id;
+} EbSdbCursorFixture;
+
+typedef struct {
+ ETestServerClosure parent;
+
+ const gchar *locale;
+ EBookSortType sort_type;
+} EbSdbCursorClosure;
+
+typedef struct {
+ EbSdbCursorClosure parent;
+ gchar *path;
+
+ /* array of counts to move by, terminated with 0 or MAX_COUNTS */
+ gint counts[MAX_MOVE_BY_COUNTS];
+
+ /* For each move_by() command, an array of 'ABS (counts[i])' expected contacts */
+ gint expected[MAX_MOVE_BY_COUNTS][N_SORTED_CONTACTS];
+
+ /* Whether this is a filtered test */
+ gboolean filtered;
+
+ /* Private detail */
+ gsize struct_size;
+} MoveByData;
+
+void e_sqlitedb_fixture_setup (ESqliteDBFixture *fixture,
+ gconstpointer user_data);
+void e_sqlitedb_fixture_teardown (ESqliteDBFixture *fixture,
+ gconstpointer user_data);
+
+void e_sqlitedb_cursor_fixture_setup_book (ESource *scratch,
+ ETestServerClosure *closure);
+void e_sqlitedb_cursor_fixture_setup (EbSdbCursorFixture *fixture,
+ gconstpointer user_data);
+void e_sqlitedb_cursor_fixture_teardown (EbSdbCursorFixture *fixture,
+ gconstpointer user_data);
+void e_sqlitedb_cursor_fixture_set_locale (EbSdbCursorFixture *fixture,
+ const gchar *locale);
+
+/* Filters contacts with E_CONTACT_EMAIL ending with '.com' */
+void e_sqlitedb_cursor_fixture_filtered_setup (EbSdbCursorFixture *fixture,
+ gconstpointer user_data);
+
+
+gchar *new_vcard_from_test_case (const gchar *case_name);
+EContact *new_contact_from_test_case (const gchar *case_name);
+
+gboolean add_contact_from_test_case_verify (EBookClient *book_client,
+ const gchar *case_name,
+ EContact **contact);
+
+void assert_contacts_order_slist (GSList *results,
+ GSList *uids);
+void assert_contacts_order (GSList *results,
+ const gchar *first_uid,
+ ...) G_GNUC_NULL_TERMINATED;
+
+void print_results (GSList *results);
+
+/* MoveBy test helpers */
+void move_by_test_add_assertion (MoveByData *data,
+ gint count,
+ ...);
+MoveByData *move_by_test_new (const gchar *test_path,
+ const gchar *locale);
+MoveByData *move_by_test_new_full (const gchar *test_path,
+ const gchar *locale,
+ EBookSortType sort_type);
+void move_by_test_add (MoveByData *data,
+ gboolean filtered);
+
+#endif /* DATA_TEST_UTILS_H */
diff --git a/tests/libedata-book/test-sqlite-create-cursor.c b/tests/libedata-book/test-sqlite-create-cursor.c
new file mode 100644
index 0000000..3479e78
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-create-cursor.c
@@ -0,0 +1,131 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+static ETestServerClosure book_closure = { E_TEST_SERVER_ADDRESS_BOOK, NULL, 0 };
+
+static void
+test_create_cursor_empty_query (ESqliteDBFixture *fixture,
+ gconstpointer user_data)
+{
+ EbSdbCursor *cursor;
+ EContactField sort_fields[] = { E_CONTACT_FAMILY_NAME, E_CONTACT_GIVEN_NAME };
+ EBookSortType sort_types[] = { E_BOOK_SORT_ASCENDING, E_BOOK_SORT_ASCENDING };
+ GError *error = NULL;
+
+ cursor = e_book_backend_sqlitedb_cursor_new (fixture->ebsdb, SQLITEDB_FOLDER_ID, NULL,
+ sort_fields, sort_types, 2, &error);
+
+ g_assert (cursor != NULL);
+ e_book_backend_sqlitedb_cursor_free (fixture->ebsdb, cursor);
+}
+
+static void
+test_create_cursor_valid_query (ESqliteDBFixture *fixture,
+ gconstpointer user_data)
+{
+ EbSdbCursor *cursor;
+ EContactField sort_fields[] = { E_CONTACT_FAMILY_NAME, E_CONTACT_GIVEN_NAME };
+ EBookSortType sort_types[] = { E_BOOK_SORT_ASCENDING, E_BOOK_SORT_ASCENDING };
+ EBookQuery *query;
+ gchar *sexp;
+ GError *error = NULL;
+
+ query = e_book_query_field_test (E_CONTACT_FULL_NAME, E_BOOK_QUERY_IS, "James Brown");
+ sexp = e_book_query_to_string (query);
+
+ cursor = e_book_backend_sqlitedb_cursor_new (fixture->ebsdb, SQLITEDB_FOLDER_ID, sexp,
+ sort_fields, sort_types, 2, &error);
+
+ g_assert (cursor != NULL);
+ e_book_backend_sqlitedb_cursor_free (fixture->ebsdb, cursor);
+ g_free (sexp);
+ e_book_query_unref (query);
+}
+
+static void
+test_create_cursor_invalid_query (ESqliteDBFixture *fixture,
+ gconstpointer user_data)
+{
+ EbSdbCursor *cursor;
+ EContactField sort_fields[] = { E_CONTACT_FAMILY_NAME, E_CONTACT_GIVEN_NAME };
+ EBookSortType sort_types[] = { E_BOOK_SORT_ASCENDING, E_BOOK_SORT_ASCENDING };
+ EBookQuery *query;
+ gchar *sexp;
+ GError *error = NULL;
+
+ query = e_book_query_field_test (E_CONTACT_TEL, E_BOOK_QUERY_CONTAINS, "888");
+ sexp = e_book_query_to_string (query);
+
+ cursor = e_book_backend_sqlitedb_cursor_new (fixture->ebsdb, SQLITEDB_FOLDER_ID, sexp,
+ sort_fields, sort_types, 2, &error);
+
+ g_assert (cursor == NULL);
+ g_assert (error);
+ g_assert (g_error_matches (error, E_BOOK_SDB_ERROR, E_BOOK_SDB_ERROR_INVALID_QUERY));
+
+ g_free (sexp);
+ e_book_query_unref (query);
+}
+
+static void
+test_create_cursor_invalid_sort (ESqliteDBFixture *fixture,
+ gconstpointer user_data)
+{
+ EbSdbCursor *cursor;
+ EContactField sort_fields[] = { E_CONTACT_TEL };
+ EBookSortType sort_types[] = { E_BOOK_SORT_ASCENDING };
+ GError *error = NULL;
+
+ cursor = e_book_backend_sqlitedb_cursor_new (fixture->ebsdb, SQLITEDB_FOLDER_ID, NULL,
+ sort_fields, sort_types, 1, &error);
+
+ g_assert (cursor == NULL);
+ g_assert (error);
+ g_assert (g_error_matches (error, E_BOOK_SDB_ERROR, E_BOOK_SDB_ERROR_INVALID_QUERY));
+}
+
+static void
+test_create_cursor_missing_sort (ESqliteDBFixture *fixture,
+ gconstpointer user_data)
+{
+ EbSdbCursor *cursor;
+ GError *error = NULL;
+
+ cursor = e_book_backend_sqlitedb_cursor_new (fixture->ebsdb, SQLITEDB_FOLDER_ID, NULL, NULL, NULL, 0,
&error);
+
+ g_assert (cursor == NULL);
+ g_assert (error);
+ g_assert (g_error_matches (error, E_BOOK_SDB_ERROR, E_BOOK_SDB_ERROR_INVALID_QUERY));
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ /* Ensure that the client and server get the same locale */
+ g_assert (g_setenv ("LC_ALL", "en_US.UTF-8", TRUE));
+ setlocale (LC_ALL, "");
+
+ g_test_add ("/EbSdbCursor/Create/EmptyQuery", ESqliteDBFixture, &book_closure,
+ e_sqlitedb_fixture_setup, test_create_cursor_empty_query, e_sqlitedb_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Create/ValidQuery", ESqliteDBFixture, &book_closure,
+ e_sqlitedb_fixture_setup, test_create_cursor_valid_query, e_sqlitedb_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Create/InvalidQuery", ESqliteDBFixture, &book_closure,
+ e_sqlitedb_fixture_setup, test_create_cursor_invalid_query, e_sqlitedb_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Create/InvalidSort", ESqliteDBFixture, &book_closure,
+ e_sqlitedb_fixture_setup, test_create_cursor_invalid_sort, e_sqlitedb_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Create/MissingSort", ESqliteDBFixture, &book_closure,
+ e_sqlitedb_fixture_setup, test_create_cursor_missing_sort, e_sqlitedb_fixture_teardown);
+
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-calculate.c
b/tests/libedata-book/test-sqlite-cursor-calculate.c
new file mode 100644
index 0000000..fc9a99f
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-calculate.c
@@ -0,0 +1,647 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+static EbSdbCursorClosure ascending_closure = {
+ { E_TEST_SERVER_ADDRESS_BOOK, e_sqlitedb_cursor_fixture_setup_book, 0 },
+ NULL,
+ E_BOOK_SORT_ASCENDING
+};
+
+static EbSdbCursorClosure descending_closure = {
+ { E_TEST_SERVER_ADDRESS_BOOK, e_sqlitedb_cursor_fixture_setup_book, 0 },
+ NULL,
+ E_BOOK_SORT_DESCENDING
+};
+
+static void
+test_cursor_calculate_initial (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ g_assert_cmpint (position, ==, 0);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_move_forward (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 5,
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ /* Assert the first 5 contacts in en_US order */
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ assert_contacts_order (results,
+ "sorted-11",
+ "sorted-1",
+ "sorted-2",
+ "sorted-5",
+ "sorted-6",
+ NULL);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 0 + 5 = position 5, result index 4 (results[0, 1, 2, 3, 4]) */
+ g_assert_cmpint (position, ==, 5);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_move_backwards (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ -5,
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ /* Assert the last 5 contacts in en_US order */
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ assert_contacts_order (results,
+ "sorted-20",
+ "sorted-19",
+ "sorted-9",
+ "sorted-13",
+ "sorted-12",
+ NULL);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 20 - 5 = position 16 result index 15 (results[20, 19, 18, 17, 16]) */
+ g_assert_cmpint (position, ==, 16);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_back_and_forth (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 7,
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ g_assert_cmpint (g_slist_length (results), ==, 7);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 0 + 7 = position 7 result index 6 (results[0, 1, 2, 3, 4, 5, 6]) */
+ g_assert_cmpint (position, ==, 7);
+ g_assert_cmpint (total, ==, 20);
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ -4,
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ g_assert_cmpint (g_slist_length (results), ==, 4);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 7 - 4 = position 3 result index 2 (results[5, 4, 3, 2]) */
+ g_assert_cmpint (position, ==, 3);
+ g_assert_cmpint (total, ==, 20);
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 5,
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 3 + 5 = position 8 result index 7 (results[3, 4, 5, 6, 7]) */
+ g_assert_cmpint (position, ==, 8);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_partial_target (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GError *error = NULL;
+ gint position = 0, total = 0;
+ ECollator *collator;
+ gint n_labels;
+ const gchar *const *labels;
+
+ /* First verify our test... in en_US locale the label 'C' should exist with the index 3 */
+ collator = e_book_backend_sqlitedb_ref_collator (((ESqliteDBFixture *) fixture)->ebsdb);
+ labels = e_collator_get_index_labels (collator, &n_labels, NULL, NULL, NULL);
+ g_assert_cmpstr (labels[3], ==, "C");
+ e_collator_unref (collator);
+
+ /* Set the cursor at the start of family names beginning with 'C' */
+ e_book_backend_sqlitedb_cursor_set_target_alphabetic_index (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, 3);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* Position is 13, there are 13 contacts before the letter 'C' in en_US locale */
+ g_assert_cmpint (position, ==, 13);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_after_modification (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ book_client = E_TEST_SERVER_UTILS_SERVICE (fixture, EBookClient);
+
+ /* Set the cursor to point exactly 'blackbird' (which is the 12th contact) */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 12, NULL, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* blackbird is at position 12 in en_US locale */
+ g_assert_cmpint (position, ==, 12);
+ g_assert_cmpint (total, ==, 20);
+
+ /* Rename Muffler -> Jacob Appelbaum */
+ e_contact_set (fixture->contacts[19 - 1], E_CONTACT_FAMILY_NAME, "Appelbaum");
+ e_contact_set (fixture->contacts[19 - 1], E_CONTACT_GIVEN_NAME, "Jacob");
+ if (!e_book_client_modify_contact_sync (book_client, fixture->contacts[19 - 1], NULL, &error))
+ g_error ("modify contact sync: %s", error->message);
+
+ /* Rename Müller -> Sade Adu */
+ e_contact_set (fixture->contacts[20 - 1], E_CONTACT_FAMILY_NAME, "Adu");
+ e_contact_set (fixture->contacts[20 - 1], E_CONTACT_GIVEN_NAME, "Sade");
+ if (!e_book_client_modify_contact_sync (book_client, fixture->contacts[20 - 1], NULL, &error))
+ g_error ("modify contact sync: %s", error->message);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* blackbird is now at position 14 after moving 2 later contacts to begin with 'A' */
+ g_assert_cmpint (position, ==, 14);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_filtered_initial (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ g_assert_cmpint (position, ==, 0);
+ g_assert_cmpint (total, ==, 13);
+}
+
+static void
+test_cursor_calculate_filtered_move_forward (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 5, &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 0 + 5 = position 5, result index 4 (results[0, 1, 2, 3, 4]) */
+ g_assert_cmpint (position, ==, 5);
+ g_assert_cmpint (total, ==, 13);
+}
+
+static void
+test_cursor_calculate_filtered_move_backwards (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ -5,
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 13 - 5 = position 9 (results[13, 12, 11, 10, 9]) */
+ g_assert_cmpint (position, ==, 9);
+ g_assert_cmpint (total, ==, 13);
+}
+
+static void
+test_cursor_calculate_filtered_partial_target (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GError *error = NULL;
+ gint position = 0, total = 0;
+ ECollator *collator;
+ gint n_labels;
+ const gchar *const *labels;
+
+ /* First verify our test... in en_US locale the label 'C' should exist with the index 3 */
+ collator = e_book_backend_sqlitedb_ref_collator (((ESqliteDBFixture *) fixture)->ebsdb);
+ labels = e_collator_get_index_labels (collator, &n_labels, NULL, NULL, NULL);
+ g_assert_cmpstr (labels[3], ==, "C");
+ e_collator_unref (collator);
+
+ /* Set the cursor at the start of family names beginning with 'C' */
+ e_book_backend_sqlitedb_cursor_set_target_alphabetic_index (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, 3);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* There are 9 contacts before the letter 'C' in the en_US locale */
+ g_assert_cmpint (position, ==, 9);
+ g_assert_cmpint (total, ==, 13);
+}
+
+static void
+test_cursor_calculate_filtered_after_modification (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ book_client = E_TEST_SERVER_UTILS_SERVICE (fixture, EBookClient);
+
+ /* Set the cursor to point exactly 'blackbird' (which is the 8th contact when filtered) */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 8, NULL, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ /* 'blackbirds' -> Jacob Appelbaum */
+ e_contact_set (fixture->contacts[18 - 1], E_CONTACT_FAMILY_NAME, "Appelbaum");
+ e_contact_set (fixture->contacts[18 - 1], E_CONTACT_GIVEN_NAME, "Jacob");
+ if (!e_book_client_modify_contact_sync (book_client, fixture->contacts[18 - 1], NULL, &error))
+ g_error ("modify contact sync: %s", error->message);
+
+ /* 'black-birds' -> Sade Adu */
+ e_contact_set (fixture->contacts[17 - 1], E_CONTACT_FAMILY_NAME, "Adu");
+ e_contact_set (fixture->contacts[17 - 1], E_CONTACT_GIVEN_NAME, "Sade");
+ if (!e_book_client_modify_contact_sync (book_client, fixture->contacts[17 - 1], NULL, &error))
+ g_error ("modify contact sync: %s", error->message);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* blackbird is now at position 11 after moving 2 later contacts to begin with 'A' */
+ g_assert_cmpint (position, ==, 9);
+ g_assert_cmpint (total, ==, 13);
+}
+
+static void
+test_cursor_calculate_descending_move_forward (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 5,
+ &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ /* Assert the first 5 contacts in en_US order */
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ assert_contacts_order (results,
+ "sorted-20",
+ "sorted-19",
+ "sorted-9",
+ "sorted-13",
+ "sorted-12",
+ NULL);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 0 + 5 = position 5, result index 4 (results[0, 1, 2, 3, 4]) */
+ g_assert_cmpint (position, ==, 5);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_descending_move_backwards (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ /* Move cursor */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ -5, &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ /* Assert the last 5 contacts in en_US order */
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ assert_contacts_order (results,
+ "sorted-11",
+ "sorted-1",
+ "sorted-2",
+ "sorted-5",
+ "sorted-6",
+ NULL);
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* results 20 - 5 = position 16 result index 15 (results[20, 19, 18, 17, 16]) */
+ g_assert_cmpint (position, ==, 16);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_descending_partial_target (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GError *error = NULL;
+ gint position = 0, total = 0;
+ ECollator *collator;
+ gint n_labels;
+ const gchar *const *labels;
+
+ /* First verify our test... in en_US locale the label 'C' should exist with the index 3 */
+ collator = e_book_backend_sqlitedb_ref_collator (((ESqliteDBFixture *) fixture)->ebsdb);
+ labels = e_collator_get_index_labels (collator, &n_labels, NULL, NULL, NULL);
+ g_assert_cmpstr (labels[3], ==, "C");
+ e_collator_unref (collator);
+
+ /* Set the cursor at the start of family names beginning with 'C' */
+ e_book_backend_sqlitedb_cursor_set_target_alphabetic_index (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, 3);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* Position is 7, there are 7 contacts leading up to the last 'C' in en_US locale
+ * (when sorting in descending order) */
+ g_assert_cmpint (position, ==, 7);
+ g_assert_cmpint (total, ==, 20);
+}
+
+static void
+test_cursor_calculate_descending_after_modification (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ EBookClient *book_client;
+ GError *error = NULL;
+ gint position = 0, total = 0;
+
+ book_client = E_TEST_SERVER_UTILS_SERVICE (fixture, EBookClient);
+
+ /* Set the cursor to point exactly 'Bät' (which is the 12th contact in descending order) */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 12, NULL, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* 'Bät' is at position 12 in en_US locale (descending order) */
+ g_assert_cmpint (position, ==, 12);
+ g_assert_cmpint (total, ==, 20);
+
+ /* Rename Muffler -> Jacob Appelbaum */
+ e_contact_set (fixture->contacts[19 - 1], E_CONTACT_FAMILY_NAME, "Appelbaum");
+ e_contact_set (fixture->contacts[19 - 1], E_CONTACT_GIVEN_NAME, "Jacob");
+ if (!e_book_client_modify_contact_sync (book_client, fixture->contacts[19 - 1], NULL, &error))
+ g_error ("modify contact sync: %s", error->message);
+
+ /* Rename Müller -> Sade Adu */
+ e_contact_set (fixture->contacts[20 - 1], E_CONTACT_FAMILY_NAME, "Adu");
+ e_contact_set (fixture->contacts[20 - 1], E_CONTACT_GIVEN_NAME, "Sade");
+ if (!e_book_client_modify_contact_sync (book_client, fixture->contacts[20 - 1], NULL, &error))
+ g_error ("modify contact sync: %s", error->message);
+
+ /* Check new position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* 'Bät' is now at position 10 in descending order after moving 2 contacts to begin with 'A' */
+ g_assert_cmpint (position, ==, 10);
+ g_assert_cmpint (total, ==, 20);
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/EbSdbCursor/Calculate/Initial", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_initial,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/MoveForward", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_move_forward,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/MoveBackwards", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_move_backwards,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/BackAndForth", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_back_and_forth,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/AlphabeticTarget", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_partial_target,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/AfterModification", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_after_modification,
+ e_sqlitedb_cursor_fixture_teardown);
+
+ g_test_add ("/EbSdbCursor/Calculate/Filtered/Initial", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_filtered_setup,
+ test_cursor_calculate_filtered_initial,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Filtered/MoveForward", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_filtered_setup,
+ test_cursor_calculate_filtered_move_forward,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Filtered/MoveBackwards", EbSdbCursorFixture, &ascending_closure,
+ e_sqlitedb_cursor_fixture_filtered_setup,
+ test_cursor_calculate_filtered_move_backwards,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Filtered/AlphabeticTarget", EbSdbCursorFixture,
&ascending_closure,
+ e_sqlitedb_cursor_fixture_filtered_setup,
+ test_cursor_calculate_filtered_partial_target,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Filtered/AfterModification", EbSdbCursorFixture,
&ascending_closure,
+ e_sqlitedb_cursor_fixture_filtered_setup,
+ test_cursor_calculate_filtered_after_modification,
+ e_sqlitedb_cursor_fixture_teardown);
+
+ g_test_add ("/EbSdbCursor/Calculate/Descending/Initial", EbSdbCursorFixture, &descending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_initial,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Descending/MoveForward", EbSdbCursorFixture, &descending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_descending_move_forward,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Descending/MoveBackwards", EbSdbCursorFixture,
&descending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_descending_move_backwards,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Descending/BackAndForth", EbSdbCursorFixture, &descending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_back_and_forth,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Descending/AlphabeticTarget", EbSdbCursorFixture,
&descending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_descending_partial_target,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/Calculate/Descending/AfterModification", EbSdbCursorFixture,
&descending_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_calculate_descending_after_modification,
+ e_sqlitedb_cursor_fixture_teardown);
+
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-change-locale.c
b/tests/libedata-book/test-sqlite-cursor-change-locale.c
new file mode 100644
index 0000000..fd322ab
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-change-locale.c
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ g_assert (g_setenv ("MIGRATION_TEST_SOURCE_NAME", "migration-test-source", TRUE));
+
+ data = move_by_test_new ("/EbSdbCursor/ChangeLocale/POSIX", "POSIX");
+ move_by_test_add_assertion (data, 5, 11, 2, 6, 3, 8);
+ move_by_test_add_assertion (data, 5, 1, 5, 4, 7, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 12, 13, 9, 19, 20);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/ChangeLocale/en_US", "en_US.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 5, 4, 3, 7, 8, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 12, 13, 9, 19, 20);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/ChangeLocale/fr_CA", "fr_CA.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 5, 4, 3, 7, 8, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 13, 12, 9, 19, 20);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/ChangeLocale/de_DE", "de_DE.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 5, 7, 8, 4, 3, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 12, 13, 9, 20, 19);
+ move_by_test_add (data, FALSE);
+
+ /* On this case, we want to delete the work directory and start afresh */
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-de-DE-migrated.c
b/tests/libedata-book/test-sqlite-cursor-de-DE-migrated.c
new file mode 100644
index 0000000..9944ddc
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-de-DE-migrated.c
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ /* Ensure that the client and server get the same locale */
+ g_assert (g_setenv ("MIGRATION_TEST_SOURCE_NAME", "migration-test-source", TRUE));
+
+ data = move_by_test_new ("/EbSdbCursor/Locale/de_DE/Migrated", "de_DE.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 5, 7, 8, 4, 3, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 12, 13, 9, 20, 19);
+ move_by_test_add (data, FALSE);
+
+ /* On this case, we are using the migrated addressbook, don't delete it first */
+ return e_test_server_utils_run_full (E_TEST_SERVER_KEEP_WORK_DIRECTORY);
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-en-US-migrated.c
b/tests/libedata-book/test-sqlite-cursor-en-US-migrated.c
new file mode 100644
index 0000000..7e2f969
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-en-US-migrated.c
@@ -0,0 +1,33 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ /* Ensure that the client and server get the same locale */
+ g_assert (g_setenv ("MIGRATION_TEST_SOURCE_NAME", "migration-test-source", TRUE));
+
+ data = move_by_test_new ("/EbSdbCursor/Locale/en_US/Migrated", "en_US.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 5, 4, 3, 7, 8, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 12, 13, 9, 19, 20);
+ move_by_test_add (data, FALSE);
+
+ /* On this case, we are using the migrated addressbook, don't delete it first */
+ return e_test_server_utils_run_full (E_TEST_SERVER_KEEP_WORK_DIRECTORY);
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-fr-CA-migrated.c
b/tests/libedata-book/test-sqlite-cursor-fr-CA-migrated.c
new file mode 100644
index 0000000..bc1cc9b
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-fr-CA-migrated.c
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ /* Ensure that the client and server get the same locale */
+ g_assert (g_setenv ("MIGRATION_TEST_SOURCE_NAME", "migration-test-source", TRUE));
+
+ data = move_by_test_new ("/EbSdbCursor/Locale/fr_CA/Migrated", "fr_CA.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 5, 4, 3, 7, 8, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 13, 12, 9, 19, 20);
+ move_by_test_add (data, FALSE);
+
+ /* On this case, we are using the migrated addressbook, don't delete it first */
+ return e_test_server_utils_run_full (E_TEST_SERVER_KEEP_WORK_DIRECTORY);
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-move-by-de-DE.c
b/tests/libedata-book/test-sqlite-cursor-move-by-de-DE.c
new file mode 100644
index 0000000..d3fac4e
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-move-by-de-DE.c
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ data = move_by_test_new ("/EbSdbCursor/de_DE/Move/Forward", "de_DE.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 6, 7, 8, 4, 3, 15, 17);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/de_DE/Move/ForwardOnNameless", "de_DE.UTF-8");
+ move_by_test_add_assertion (data, 1, 11);
+ move_by_test_add_assertion (data, 3, 1, 2, 5);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/de_DE/Move/Backwards", "de_DE.UTF-8");
+ move_by_test_add_assertion (data, -5, 19, 20, 9, 13, 12);
+ move_by_test_add_assertion (data, -8, 14, 10, 18, 16, 17, 15, 3, 4);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/de_DE/Filtered/Move/Forward", "de_DE.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 8);
+ move_by_test_add_assertion (data, 8, 3, 17, 16, 18, 10, 14, 12, 9);
+ move_by_test_add (data, TRUE);
+
+ data = move_by_test_new ("/EbSdbCursor/de_DE/Filtered/Move/Backwards", "de_DE.UTF-8");
+ move_by_test_add_assertion (data, -5, 9, 12, 14, 10, 18);
+ move_by_test_add_assertion (data, -8, 16, 17, 3, 8, 5, 2, 1, 11);
+ move_by_test_add (data, TRUE);
+
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-move-by-en-US.c
b/tests/libedata-book/test-sqlite-cursor-move-by-en-US.c
new file mode 100644
index 0000000..dc8f4c0
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-move-by-en-US.c
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ data = move_by_test_new ("/EbSdbCursor/en_US/Move/Forward", "en_US.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 6, 4, 3, 7, 8, 15, 17);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/en_US/Move/ForwardOnNameless", "en_US.UTF-8");
+ move_by_test_add_assertion (data, 1, 11);
+ move_by_test_add_assertion (data, 3, 1, 2, 5);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/en_US/Move/Backwards", "en_US.UTF-8");
+ move_by_test_add_assertion (data, -5, 20, 19, 9, 13, 12);
+ move_by_test_add_assertion (data, -8, 14, 10, 18, 16, 17, 15, 8, 7);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/en_US/Filtered/Move/Forward", "en_US.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 3);
+ move_by_test_add_assertion (data, 8, 8, 17, 16, 18, 10, 14, 12, 9);
+ move_by_test_add (data, TRUE);
+
+ data = move_by_test_new ("/EbSdbCursor/en_US/Filtered/Move/Backwards", "en_US.UTF-8");
+ move_by_test_add_assertion (data, -5, 9, 12, 14, 10, 18);
+ move_by_test_add_assertion (data, -8, 16, 17, 8, 3, 5, 2, 1, 11);
+ move_by_test_add (data, TRUE);
+
+ data = move_by_test_new_full ("/EbSdbCursor/en_US/Move/Descending/Forward", "en_US.UTF-8",
+ E_BOOK_SORT_DESCENDING);
+ move_by_test_add_assertion (data, 5, 20, 19, 9, 13, 12);
+ move_by_test_add_assertion (data, 5, 14, 10, 18, 16, 17);
+ move_by_test_add_assertion (data, 5, 15, 8, 7, 3, 4);
+ move_by_test_add_assertion (data, 5, 6, 5, 2, 1, 11);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new_full ("/EbSdbCursor/en_US/Move/Descending/Forward/Loop", "en_US.UTF-8",
+ E_BOOK_SORT_DESCENDING);
+ move_by_test_add_assertion (data, 10, 20, 19, 9, 13, 12, 14, 10, 18, 16, 17);
+ move_by_test_add_assertion (data, 11, 15, 8, 7, 3, 4, 6, 5, 2, 1, 11, 0);
+
+ move_by_test_add_assertion (data, 10, 20, 19, 9, 13, 12, 14, 10, 18, 16, 17);
+ move_by_test_add_assertion (data, 10, 15, 8, 7, 3, 4, 6, 5, 2, 1, 11);
+ move_by_test_add (data, FALSE);
+
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-move-by-fr-CA.c
b/tests/libedata-book/test-sqlite-cursor-move-by-fr-CA.c
new file mode 100644
index 0000000..4d13e24
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-move-by-fr-CA.c
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ data = move_by_test_new ("/EbSdbCursor/fr_CA/Move/Forward", "fr_CA.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 6);
+ move_by_test_add_assertion (data, 6, 4, 3, 7, 8, 15, 17);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/fr_CA/Move/ForwardOnNameless", "fr_CA.UTF-8");
+ move_by_test_add_assertion (data, 1, 11);
+ move_by_test_add_assertion (data, 3, 1, 2, 5);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/fr_CA/Move/Backwards", "fr_CA.UTF-8");
+ move_by_test_add_assertion (data, -5, 20, 19, 9, 12, 13);
+ move_by_test_add_assertion (data, -8, 14, 10, 18, 16, 17, 15, 8, 7);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/fr_CA/Filtered/Move/Forward", "fr_CA.UTF-8");
+ move_by_test_add_assertion (data, 5, 11, 1, 2, 5, 3);
+ move_by_test_add_assertion (data, 8, 8, 17, 16, 18, 10, 14, 12, 9);
+ move_by_test_add (data, TRUE);
+
+ data = move_by_test_new ("/EbSdbCursor/fr_CA/Filtered/Move/Backwards", "fr_CA.UTF-8");
+ move_by_test_add_assertion (data, -5, 9, 12, 14, 10, 18);
+ move_by_test_add_assertion (data, -8, 16, 17, 8, 3, 5, 2, 1, 11);
+ move_by_test_add (data, TRUE);
+
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-move-by-posix.c
b/tests/libedata-book/test-sqlite-cursor-move-by-posix.c
new file mode 100644
index 0000000..01eed6a
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-move-by-posix.c
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ data = move_by_test_new ("/EbSdbCursor/POSIX/Move/Forward", "POSIX");
+ move_by_test_add_assertion (data, 5, 11, 2, 6, 3, 8);
+ move_by_test_add_assertion (data, 6, 1, 5, 4, 7, 15, 17);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/POSIX/Move/ForwardOnNameless", "POSIX");
+ move_by_test_add_assertion (data, 1, 11);
+ move_by_test_add_assertion (data, 3, 2, 6, 3);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/POSIX/Move/Backwards", "POSIX");
+ move_by_test_add_assertion (data, -5, 20, 19, 9, 13, 12);
+ move_by_test_add_assertion (data, -12, 14, 10, 18, 16, 17, 15, 7, 4, 5, 1, 8, 3);
+ move_by_test_add (data, FALSE);
+
+ data = move_by_test_new ("/EbSdbCursor/POSIX/Filtered/Move/Forward", "POSIX");
+ move_by_test_add_assertion (data, 5, 11, 2, 3, 8, 1);
+ move_by_test_add_assertion (data, 8, 5, 17, 16, 18, 10, 14, 12, 9);
+ move_by_test_add (data, TRUE);
+
+ data = move_by_test_new ("/EbSdbCursor/POSIX/Filtered/Move/Backwards", "POSIX");
+ move_by_test_add_assertion (data, -5, 9, 12, 14, 10, 18);
+ move_by_test_add_assertion (data, -8, 16, 17, 5, 1, 8, 3, 2, 11);
+ move_by_test_add (data, TRUE);
+
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-posix-initial.c
b/tests/libedata-book/test-sqlite-cursor-posix-initial.c
new file mode 100644
index 0000000..0703fa1
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-posix-initial.c
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ g_assert (g_setenv ("MIGRATION_TEST_SOURCE_NAME", "migration-test-source", TRUE));
+
+ /* This test actually creates the addressbook, subsequent migration tests dont
+ * recreate the contacts but rely on the addressbook to have migrated the sort keys
+ * into the new locales
+ */
+ data = move_by_test_new ("/EbSdbCursor/Locale/POSIX/Initial", "POSIX");
+ move_by_test_add_assertion (data, 5, 11, 2, 6, 3, 8);
+ move_by_test_add_assertion (data, 5, 1, 5, 4, 7, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 12, 13, 9, 19, 20);
+ move_by_test_add (data, FALSE);
+
+ /* On this case, we want to delete the work directory and start afresh */
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-posix-migrated.c
b/tests/libedata-book/test-sqlite-cursor-posix-migrated.c
new file mode 100644
index 0000000..31a5cb9
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-posix-migrated.c
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ MoveByData *data;
+
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ /* Ensure that the client and server get the same locale */
+ g_assert (g_setenv ("MIGRATION_TEST_SOURCE_NAME", "migration-test-source", TRUE));
+
+ data = move_by_test_new ("/EbSdbCursor/Locale/POSIX/Migrated", "POSIX");
+ move_by_test_add_assertion (data, 5, 11, 2, 6, 3, 8);
+ move_by_test_add_assertion (data, 5, 1, 5, 4, 7, 15);
+ move_by_test_add_assertion (data, 5, 17, 16, 18, 10, 14);
+ move_by_test_add_assertion (data, 5, 12, 13, 9, 19, 20);
+ move_by_test_add (data, FALSE);
+
+ /* On this case, we are using the migrated addressbook, don't delete it first */
+ return e_test_server_utils_run_full (E_TEST_SERVER_KEEP_WORK_DIRECTORY);
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-set-sexp.c
b/tests/libedata-book/test-sqlite-cursor-set-sexp.c
new file mode 100644
index 0000000..05dcc7f
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-set-sexp.c
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+static EbSdbCursorClosure book_closure = { { E_TEST_SERVER_ADDRESS_BOOK,
e_sqlitedb_cursor_fixture_setup_book, 0 }, FALSE };
+
+static void
+test_cursor_sexp_invalid (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GError *error = NULL;
+ EBookQuery *query;
+ gchar *sexp = NULL;
+
+ query = e_book_query_field_test (E_CONTACT_NICKNAME, E_BOOK_QUERY_BEGINS_WITH, "Kung Fu");
+ sexp = e_book_query_to_string (query);
+ e_book_query_unref (query);
+
+ if (e_book_backend_sqlitedb_cursor_set_sexp (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, sexp, &error))
+ g_error ("Succeeded in setting non-summarized field in the cursor query expression");
+
+ g_assert (error);
+ g_assert (g_error_matches (error, E_BOOK_SDB_ERROR, E_BOOK_SDB_ERROR_INVALID_QUERY));
+}
+
+static void
+test_cursor_sexp_calculate_position (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GError *error = NULL;
+ EBookQuery *query;
+ gint position = 0, total = 0;
+ gchar *sexp = NULL;
+ GSList *results = NULL, *node;
+ EbSdbSearchData *data;
+
+ /* Set the cursor to point exactly to 'blackbirds', which is the 12th contact in en_US */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_RESET,
+ 12, &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ /* Ensure we moved to the right contact */
+ node = g_slist_last (results);
+ g_assert (node);
+ data = node->data;
+ g_assert_cmpstr (data->uid, ==, "sorted-16");
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+
+ /* Check position */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* blackbird is at position 12 in an unfiltered en_US locale */
+ g_assert_cmpint (position, ==, 12);
+ g_assert_cmpint (total, ==, 20);
+
+ /* Set new sexp, only contacts with .com email addresses */
+ query = e_book_query_field_test (E_CONTACT_EMAIL, E_BOOK_QUERY_ENDS_WITH, ".com");
+ sexp = e_book_query_to_string (query);
+ e_book_query_unref (query);
+
+ if (!e_book_backend_sqlitedb_cursor_set_sexp (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, sexp, &error))
+ g_error ("Failed to set sexp: %s", error->message);
+
+ /* Check new position after modified sexp */
+ if (!e_book_backend_sqlitedb_cursor_calculate (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, &total, &position, &error))
+ g_error ("Error calculating cursor: %s", error->message);
+
+ /* 'blackbird' is now at position 8 out of 13, with a filtered set of contacts in en_US locale */
+ g_assert_cmpint (position, ==, 8);
+ g_assert_cmpint (total, ==, 13);
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/EbSdbCursor/SetSexp/Invalid", EbSdbCursorFixture, &book_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_sexp_invalid,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/SetSexp/CalculatePosition", EbSdbCursorFixture, &book_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_sexp_calculate_position,
+ e_sqlitedb_cursor_fixture_teardown);
+
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-cursor-set-target.c
b/tests/libedata-book/test-sqlite-cursor-set-target.c
new file mode 100644
index 0000000..69bc986
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-cursor-set-target.c
@@ -0,0 +1,180 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+static EbSdbCursorClosure book_closure = { { E_TEST_SERVER_ADDRESS_BOOK,
e_sqlitedb_cursor_fixture_setup_book, 0 }, FALSE };
+
+/*****************************************************
+ * Expect the same results twice *
+ *****************************************************/
+static void
+test_cursor_set_target_reset_cursor (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+
+ /* First batch */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 5, &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ print_results (results);
+
+ /* Assert the first 5 contacts in en_US order */
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ assert_contacts_order (results,
+ "sorted-11",
+ "sorted-1",
+ "sorted-2",
+ "sorted-5",
+ "sorted-6",
+ NULL);
+
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+ results = NULL;
+
+ /* Second batch reset (same results) */
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_RESET,
+ 5, &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ print_results (results);
+
+ /* Assert the first 5 contacts in en_US order again */
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ assert_contacts_order (results,
+ "sorted-11",
+ "sorted-1",
+ "sorted-2",
+ "sorted-5",
+ "sorted-6",
+ NULL);
+
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+}
+
+/*****************************************************
+ * Expect results with family name starting with 'C' *
+ *****************************************************/
+static void
+test_cursor_set_target_c_next_results (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ ECollator *collator;
+ gint n_labels;
+ const gchar *const *labels;
+
+ /* First verify our test... in en_US locale the label 'C' should exist with the index 3 */
+ collator = e_book_backend_sqlitedb_ref_collator (((ESqliteDBFixture *) fixture)->ebsdb);
+ labels = e_collator_get_index_labels (collator, &n_labels, NULL, NULL, NULL);
+ g_assert_cmpstr (labels[3], ==, "C");
+ e_collator_unref (collator);
+
+ /* Set the cursor at the start of family names beginning with 'C' */
+ e_book_backend_sqlitedb_cursor_set_target_alphabetic_index (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, 3);
+
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ 5, &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ print_results (results);
+
+ /* Assert that we got the results starting at C */
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ assert_contacts_order (results,
+ "sorted-10",
+ "sorted-14",
+ "sorted-12",
+ "sorted-13",
+ "sorted-9",
+ NULL);
+
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+}
+
+/*****************************************************
+ * Expect results before the letter 'C' *
+ *****************************************************/
+static void
+test_cursor_set_target_c_prev_results (EbSdbCursorFixture *fixture,
+ gconstpointer user_data)
+{
+ GSList *results = NULL;
+ GError *error = NULL;
+ ECollator *collator;
+ gint n_labels;
+ const gchar *const *labels;
+
+ /* First verify our test... in en_US locale the label 'C' should exist with the index 3 */
+ collator = e_book_backend_sqlitedb_ref_collator (((ESqliteDBFixture *) fixture)->ebsdb);
+ labels = e_collator_get_index_labels (collator, &n_labels, NULL, NULL, NULL);
+ g_assert_cmpstr (labels[3], ==, "C");
+ e_collator_unref (collator);
+
+ /* Set the cursor at the start of family names beginning with 'C' */
+ e_book_backend_sqlitedb_cursor_set_target_alphabetic_index (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor, 3);
+
+ if (!e_book_backend_sqlitedb_cursor_move_by (((ESqliteDBFixture *) fixture)->ebsdb,
+ fixture->cursor,
+ EBSDB_CURSOR_ORIGIN_CURRENT,
+ -5, &results, &error))
+ g_error ("Error fetching cursor results: %s", error->message);
+
+ print_results (results);
+
+ /* Assert that we got the results before C */
+ g_assert_cmpint (g_slist_length (results), ==, 5);
+ assert_contacts_order (results,
+ "sorted-18",
+ "sorted-16",
+ "sorted-17",
+ "sorted-15",
+ "sorted-8",
+ NULL);
+
+ g_slist_foreach (results, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
+ g_slist_free (results);
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add ("/EbSdbCursor/SetTarget/ResetCursor", EbSdbCursorFixture, &book_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_set_target_reset_cursor,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/SetTarget/Alphabetic/C/NextResults", EbSdbCursorFixture, &book_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_set_target_c_next_results,
+ e_sqlitedb_cursor_fixture_teardown);
+ g_test_add ("/EbSdbCursor/SetTarget/Alphabetic/C/PreviousResults", EbSdbCursorFixture, &book_closure,
+ e_sqlitedb_cursor_fixture_setup,
+ test_cursor_set_target_c_prev_results,
+ e_sqlitedb_cursor_fixture_teardown);
+
+ return e_test_server_utils_run ();
+}
diff --git a/tests/libedata-book/test-sqlite-get-contact.c b/tests/libedata-book/test-sqlite-get-contact.c
new file mode 100644
index 0000000..6736567
--- /dev/null
+++ b/tests/libedata-book/test-sqlite-get-contact.c
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#include <stdlib.h>
+#include <locale.h>
+#include <libebook/libebook.h>
+
+#include "data-test-utils.h"
+
+static ETestServerClosure book_closure = { E_TEST_SERVER_ADDRESS_BOOK, NULL, 0 };
+
+static void
+test_get_contact (ESqliteDBFixture *fixture,
+ gconstpointer user_data)
+{
+ EBookClient *book_client;
+ EContact *contact = NULL;
+ EContact *other;
+ GError *error = NULL;
+
+ book_client = E_TEST_SERVER_UTILS_SERVICE (fixture, EBookClient);
+
+ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact)) {
+ g_error ("Failed to get contact");
+ }
+
+ other = e_book_backend_sqlitedb_get_contact (fixture->ebsdb, SQLITEDB_FOLDER_ID,
+ (const gchar *)e_contact_get_const (contact,
E_CONTACT_UID),
+ NULL, NULL, &error);
+
+ if (!other)
+ g_error ("Failed to get contact with uid '%s': %s",
+ (const gchar *)e_contact_get_const (contact, E_CONTACT_UID),
+ error->message);
+
+ g_object_unref (contact);
+ g_object_unref (other);
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+#if !GLIB_CHECK_VERSION (2, 35, 1)
+ g_type_init ();
+#endif
+ g_test_init (&argc, &argv, NULL);
+
+ /* Ensure that the client and server get the same locale */
+ g_assert (g_setenv ("LC_ALL", "en_US.UTF-8", TRUE));
+ setlocale (LC_ALL, "");
+
+ g_test_add ("/EBookBackendSqliteDB/GetContact", ESqliteDBFixture, &book_closure,
+ e_sqlitedb_fixture_setup, test_get_contact, e_sqlitedb_fixture_teardown);
+
+ return e_test_server_utils_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]