summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2020-09-30 12:17:35 +0000
committerSam Thursfield <sam@afuera.me.uk>2020-09-30 12:17:35 +0000
commit4405523d7947c1076d0abbb51365bf5506060eb3 (patch)
tree6bf5e81ffb57b47df3d71084447c501546a8bf38
parenta88617112519b1764a9c7d5777e717492746bfd9 (diff)
parent1f1528c36aabb41093cb1a1e35135970a1d707cb (diff)
downloadtracker-4405523d7947c1076d0abbb51365bf5506060eb3.tar.gz
Merge branch 'wip/carlosg/more-tests' into 'master'
Add some more tests See merge request GNOME/tracker!319
-rw-r--r--.gitlab-ci.yml10
-rw-r--r--src/libtracker-data/tracker-sparql.c1
-rw-r--r--src/libtracker-sparql/bus/tracker-bus.vala52
-rw-r--r--src/libtracker-sparql/tracker-connection.c4
-rw-r--r--src/portal/tracker-portal.c35
-rw-r--r--tests/flatpak-info2
-rw-r--r--tests/functional-tests/configuration.json.in2
-rw-r--r--tests/functional-tests/configuration.py2
-rw-r--r--tests/functional-tests/fixtures.py115
-rw-r--r--tests/functional-tests/meson.build3
-rw-r--r--tests/functional-tests/portal.py62
-rw-r--r--tests/libtracker-data/functions/functions-builtin-ceil-1.out1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-ceil-1.rq1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-floor-1.out1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-floor-1.rq1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-hash-1.out1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-hash-1.rq8
-rw-r--r--tests/libtracker-data/functions/functions-builtin-lcase-1.out1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-lcase-1.rq1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-strafter-1.out1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-strafter-1.rq1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-strbefore-1.out1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-strbefore-1.rq1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-ucase-1.out1
-rw-r--r--tests/libtracker-data/functions/functions-builtin-ucase-1.rq1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-3.out1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-3.rq3
-rw-r--r--tests/libtracker-data/functions/functions-tracker-4.out1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-4.rq1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-5.out1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-5.rq1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-6.out1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-6.rq7
-rw-r--r--tests/libtracker-data/functions/functions-tracker-7.out1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-7.rq7
-rw-r--r--tests/libtracker-data/functions/functions-tracker-8.out1
-rw-r--r--tests/libtracker-data/functions/functions-tracker-8.rq22
-rw-r--r--tests/libtracker-data/sort/data-title-sort-1.ttl11
-rw-r--r--tests/libtracker-data/sort/query-title-sort-1.out3
-rw-r--r--tests/libtracker-data/sort/query-title-sort-1.rq4
-rw-r--r--tests/libtracker-data/tracker-sparql-test.c16
-rw-r--r--tests/meson.build6
-rw-r--r--tests/services/meson.build8
-rw-r--r--tests/services/org.freedesktop.portal.Tracker.service.in5
-rw-r--r--tests/test-bus.conf.in21
45 files changed, 395 insertions, 35 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4a592dd59..192b5b888 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -67,12 +67,16 @@ coverage-analysis:
allow_failure: true
script:
- dnf install -y gcovr
- - su tracker -c 'mkdir coverage-build'
+ - su tracker -c 'mkdir -p coverage-build/coveragereport'
- su tracker -c 'cd coverage-build; meson .. -Db_lto=true -Db_coverage=true'
- su tracker -c 'cd coverage-build; ninja'
- su tracker -c 'cd coverage-build; env LANG=C.UTF-8 LC_ALL=C.UTF-8 dbus-run-session eatmydata meson test --print-errorlogs ${MESON_TEST_EXTRA_ARGS}'
- - su tracker -c 'cd coverage-build; gcovr --root=.. --exclude=../tests --exclude=../utils --exclude=../examples'
- coverage: '/^TOTAL.*\s+(\d+\%)$/'
+ - su tracker -c 'cd coverage-build; gcovr --html-details --print-summary --root=.. --exclude=../docs/reference --exclude=../tests --exclude=../utils --exclude=../examples --output coveragereport/index.html'
+ coverage: '/^lines: (\d+\.\d+\%)/'
+ artifacts:
+ when: always
+ paths:
+ - coverage-build/coveragereport
coverity:
stage: analysis
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index ab2d7d735..5e26b2f28 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -7741,6 +7741,7 @@ handle_custom_function (TrackerSparql *sparql,
} else if (g_str_equal (function, TRACKER_NS "title-order")) {
_call_rule (sparql, NAMED_RULE_ArgList, error);
_append_string (sparql, "COLLATE " TRACKER_TITLE_COLLATION_NAME " ");
+ sparql->current_state->expression_type = TRACKER_PROPERTY_TYPE_UNKNOWN;
} else if (g_str_equal (function, TRACKER_NS "ascii-lower-case")) {
sparql->current_state->convert_to_string = TRUE;
_append_string (sparql, "lower (");
diff --git a/src/libtracker-sparql/bus/tracker-bus.vala b/src/libtracker-sparql/bus/tracker-bus.vala
index e3cd3b2f7..0cd8362a8 100644
--- a/src/libtracker-sparql/bus/tracker-bus.vala
+++ b/src/libtracker-sparql/bus/tracker-bus.vala
@@ -49,37 +49,39 @@ public class Tracker.Bus.Connection : Tracker.Sparql.Connection {
// ensure that error domain is registered with GDBus
new Sparql.Error.INTERNAL ("");
- var message = new DBusMessage.method_call (dbus_name, object_path, DBUS_PEER_IFACE, "Ping");
+ // If this environment variable is present, we always go via the portal,
+ if (Environment.get_variable("TRACKER_TEST_PORTAL_FLATPAK_INFO") == null) {
+ var message = new DBusMessage.method_call (dbus_name, object_path, DBUS_PEER_IFACE, "Ping");
- try {
- this.bus.send_message_with_reply_sync (message, 0, timeout, null).to_gerror();
- this.dbus_name = dbus_name;
- this.object_path = object_path;
- } catch (GLib.Error e) {
- if (GLib.FileUtils.test ("/.flatpak-info", GLib.FileTest.EXISTS)) {
- /* We are in a flatpak sandbox, check going through the portal */
-
- if (object_path == "/org/freedesktop/Tracker3/Endpoint")
- object_path = null;
+ try {
+ this.bus.send_message_with_reply_sync (message, 0, timeout, null).to_gerror();
+ this.dbus_name = dbus_name;
+ this.object_path = object_path;
+ return;
+ } catch (GLib.Error e) {
+ if (!GLib.FileUtils.test ("/.flatpak-info", GLib.FileTest.EXISTS)) {
+ throw e;
+ }
+ }
+ }
- string uri = Tracker.util_build_dbus_uri (GLib.BusType.SESSION, dbus_name, object_path);
- message = new DBusMessage.method_call (PORTAL_NAME, PORTAL_PATH, PORTAL_IFACE, "CreateSession");
- message.set_body (new Variant ("(s)", uri));
+ /* We are in a flatpak sandbox, check going through the portal */
+ if (object_path == "/org/freedesktop/Tracker3/Endpoint")
+ object_path = null;
- var reply = this.bus.send_message_with_reply_sync (message, 0, timeout, null);
+ string uri = Tracker.util_build_dbus_uri (GLib.BusType.SESSION, dbus_name, object_path);
+ var message = new DBusMessage.method_call (PORTAL_NAME, PORTAL_PATH, PORTAL_IFACE, "CreateSession");
+ message.set_body (new Variant ("(s)", uri));
- reply.to_gerror();
+ var reply = this.bus.send_message_with_reply_sync (message, 0, timeout, null);
+ reply.to_gerror();
- var variant = reply.get_body ();
- variant.get_child(0, "o", out object_path);
+ var variant = reply.get_body ();
+ variant.get_child(0, "o", out object_path);
- this.dbus_name = PORTAL_NAME;
- this.object_path = object_path;
- this.sandboxed = true;
- } else {
- throw e;
- }
- }
+ this.dbus_name = PORTAL_NAME;
+ this.object_path = object_path;
+ this.sandboxed = true;
}
static void pipe (out UnixInputStream input, out UnixOutputStream output) throws IOError {
diff --git a/src/libtracker-sparql/tracker-connection.c b/src/libtracker-sparql/tracker-connection.c
index df7f387fd..8df18b895 100644
--- a/src/libtracker-sparql/tracker-connection.c
+++ b/src/libtracker-sparql/tracker-connection.c
@@ -99,8 +99,8 @@ tracker_sparql_connection_class_init (TrackerSparqlConnectionClass *klass)
/**
* tracker_sparql_connection_new:
* @flags: values from #TrackerSparqlConnectionFlags
- * @store: the directory that contains the database as a #GFile, or %NULL
- * @ontology: the directory that contains the database schemas as a #GFile, or %NULL
+ * @store: (nullable): the directory that contains the database as a #GFile, or %NULL
+ * @ontology: (nullable): the directory that contains the database schemas as a #GFile, or %NULL
* @cancellable: (nullable): a #GCancellable, or %NULL
* @error: pointer to a #GError
*
diff --git a/src/portal/tracker-portal.c b/src/portal/tracker-portal.c
index 2e58a7228..4faeaae0b 100644
--- a/src/portal/tracker-portal.c
+++ b/src/portal/tracker-portal.c
@@ -48,6 +48,7 @@ struct _TrackerPortal
GCancellable *cancellable;
GArray *sessions;
guint64 session_ids;
+ gchar *test_flatpak_info;
};
enum
@@ -130,6 +131,7 @@ tracker_portal_finalize (GObject *object)
portal->register_id = 0;
}
+ g_clear_pointer (&portal->test_flatpak_info, g_free);
g_clear_object (&portal->dbus_connection);
g_clear_pointer (&portal->node_info,
g_dbus_node_info_unref);
@@ -174,6 +176,15 @@ tracker_portal_init (TrackerPortal *portal)
{
portal->sessions = g_array_new (FALSE, TRUE, sizeof (TrackerSession));
g_array_set_clear_func (portal->sessions, clear_session);
+
+ /* This envvar is used for testing purposes. We do not count on it
+ * being set on real sessions, as the portal is an autostart service
+ * and inherits the session environment. If someone could change the
+ * session environment for malicious intents, this seems a smaller
+ * concern.
+ */
+ portal->test_flatpak_info = g_strdup (g_getenv ("TRACKER_TEST_PORTAL_FLATPAK_INFO"));
+ unsetenv ("TRACKER_TEST_PORTAL_FLATPAK_INFO");
}
static void
@@ -196,7 +207,8 @@ endpoint_closed_cb (TrackerPortalEndpoint *endpoint,
}
static GStrv
-load_client_configuration (GDBusMethodInvocation *invocation,
+load_client_configuration (TrackerPortal *portal,
+ GDBusMethodInvocation *invocation,
const gchar *service_uri,
GError **error)
{
@@ -204,8 +216,18 @@ load_client_configuration (GDBusMethodInvocation *invocation,
GError *inner_error = NULL;
GStrv graphs;
- flatpak_info = tracker_invocation_lookup_app_info_sync (invocation,
- NULL, &inner_error);
+ if (portal->test_flatpak_info) {
+ flatpak_info = g_key_file_new ();
+ if (!g_key_file_load_from_file (flatpak_info,
+ portal->test_flatpak_info,
+ G_KEY_FILE_NONE,
+ &inner_error))
+ g_clear_pointer (&flatpak_info, g_key_file_unref);
+ } else {
+ flatpak_info = tracker_invocation_lookup_app_info_sync (invocation,
+ NULL, &inner_error);
+ }
+
if (!flatpak_info) {
GStrv default_graphs = { NULL };
@@ -241,6 +263,11 @@ load_client_configuration (GDBusMethodInvocation *invocation,
if (!graphs) {
g_debug ("Service '%s' not found in Tracker policy", service_uri);
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "Service '%s' not found in Tracker policy",
+ service_uri);
return NULL;
}
@@ -275,7 +302,7 @@ portal_iface_method_call (GDBusConnection *connection,
g_variant_get (parameters, "(s)", &uri);
g_debug ("Creating session for service URI '%s'", uri);
- graphs = load_client_configuration (invocation, uri, &error);
+ graphs = load_client_configuration (portal, invocation, uri, &error);
if (!graphs) {
g_debug ("Session rejected by policy");
g_dbus_method_invocation_return_gerror (invocation, error);
diff --git a/tests/flatpak-info b/tests/flatpak-info
new file mode 100644
index 000000000..943933657
--- /dev/null
+++ b/tests/flatpak-info
@@ -0,0 +1,2 @@
+[Policy Tracker3]
+dbus:org.freedesktop.PortalTest=tracker:Allowed
diff --git a/tests/functional-tests/configuration.json.in b/tests/functional-tests/configuration.json.in
index 6ec1d72e1..ecbea53ca 100644
--- a/tests/functional-tests/configuration.json.in
+++ b/tests/functional-tests/configuration.json.in
@@ -1,5 +1,7 @@
{
"TEST_CLI_DIR": "@TEST_CLI_DIR@",
"TEST_ONTOLOGIES_DIR": "@TEST_ONTOLOGIES_DIR@",
+ "TEST_DBUS_DAEMON_CONFIG_FILE": "@TEST_DBUS_DAEMON_CONFIG_FILE@",
+ "TEST_PORTAL_FLATPAK_INFO": "@TEST_PORTAL_FLATPAK_INFO@",
"TRACKER_VERSION": "@TRACKER_VERSION@"
}
diff --git a/tests/functional-tests/configuration.py b/tests/functional-tests/configuration.py
index a9bc7ccc9..cb1bc9a2b 100644
--- a/tests/functional-tests/configuration.py
+++ b/tests/functional-tests/configuration.py
@@ -38,6 +38,8 @@ if 'TRACKER_FUNCTIONAL_TEST_CONFIG' not in os.environ:
with open(os.environ['TRACKER_FUNCTIONAL_TEST_CONFIG']) as f:
config = json.load(f)
+TEST_DBUS_DAEMON_CONFIG_FILE = config['TEST_DBUS_DAEMON_CONFIG_FILE']
+TEST_PORTAL_FLATPAK_INFO = config['TEST_PORTAL_FLATPAK_INFO']
def cli_dir():
return config['TEST_CLI_DIR']
diff --git a/tests/functional-tests/fixtures.py b/tests/functional-tests/fixtures.py
index 08d16da17..8c16b40b4 100644
--- a/tests/functional-tests/fixtures.py
+++ b/tests/functional-tests/fixtures.py
@@ -32,6 +32,7 @@ import logging
import os
import pathlib
import multiprocessing
+import threading
import shutil
import subprocess
import sys
@@ -148,6 +149,120 @@ class TrackerSparqlBusTest (ut.TestCase):
shutil.rmtree(self.tmpdir, ignore_errors=True)
+class TrackerPortalTest(ut.TestCase):
+ @classmethod
+ def database_process_fn(self, service_name, in_queue, out_queue, dbus_address):
+ # This runs in a separate process and provides a clean Tracker database
+ # exported over D-Bus to the main test process.
+
+ log.info("Started database thread")
+
+ bus = Gio.DBusConnection.new_for_address_sync(
+ dbus_address,
+ Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT |
+ Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION, None, None)
+
+ conn = Tracker.SparqlConnection.new(
+ Tracker.SparqlConnectionFlags.NONE,
+ None,
+ Gio.File.new_for_path(cfg.ontologies_dir()),
+ None)
+
+ endpoint = Tracker.EndpointDBus.new(conn, bus, None, None)
+
+ bus.call_sync(
+ 'org.freedesktop.DBus',
+ '/org/freedesktop/DBus',
+ 'org.freedesktop.DBus',
+ 'RequestName',
+ GLib.Variant('(su)', (service_name, 0x4)),
+ None, 0, -1, None)
+
+ loop = GLib.MainLoop.new(None, False)
+
+ def pop_update(message_queue):
+ try:
+ sparql = message_queue.get_nowait()
+ if sparql is None:
+ loop.quit()
+ conn.update(sparql, None)
+ out_queue.put(None)
+ except Exception:
+ pass
+ return GLib.SOURCE_CONTINUE
+
+ GLib.timeout_add (50, pop_update, in_queue)
+ out_queue.put(None)
+ loop.run()
+
+ bus.close(None)
+
+ def setUp(self):
+ extra_env = {}
+ extra_env['TRACKER_TEST_PORTAL_FLATPAK_INFO'] = cfg.TEST_PORTAL_FLATPAK_INFO
+
+ self.message_queues = {}
+ self.connections = {}
+ self.sandbox = trackertestutils.helpers.TrackerDBusSandbox(
+ session_bus_config_file=cfg.TEST_DBUS_DAEMON_CONFIG_FILE, extra_env=extra_env)
+
+ self.sandbox.start()
+
+ self.bus = self.sandbox.get_session_bus_connection()
+ self.dbus_address = self.sandbox.get_session_bus_address()
+
+ try:
+ log.info("Starting portal")
+ self._portal_proxy = Gio.DBusProxy.new_sync(
+ self.bus,
+ Gio.DBusProxyFlags.NONE, None,
+ 'org.freedesktop.portal.Tracker',
+ '/org/freedesktop/portal/Tracker',
+ 'org.freedesktop.portal.Tracker',
+ None)
+
+ except Exception:
+ self.sandbox.stop()
+ raise
+
+ def tearDown(self):
+ for service in self.message_queues:
+ self.stop_service(service)
+ self.sandbox.stop()
+
+ def start_service(self, service_name):
+ in_queue = multiprocessing.Queue()
+ out_queue = multiprocessing.Queue()
+ thread = threading.Thread(
+ target=self.database_process_fn,
+ args=(service_name, out_queue, in_queue, self.dbus_address))
+ thread.start()
+ in_queue.get()
+ self.message_queues[service_name] = [ in_queue, out_queue ]
+
+ def stop_service(self, service_name):
+ queues = self.message_queues[service_name]
+ if queues is not None:
+ queues[1].put(None)
+
+ def update(self, service_name, sparql):
+ if sparql is not None:
+ # Updates go through the message queue, bypassing the sandbox
+ queues = self.message_queues[service_name]
+ if queues is not None:
+ queues[1].put(sparql)
+ queues[0].get()
+
+ def query(self, service_name, sparql):
+ if service_name not in self.connections:
+ conn = Tracker.SparqlConnection.bus_new(service_name, None, self.bus)
+ store = trackertestutils.helpers.StoreHelper(conn)
+ self.connections[service_name] = store
+ else:
+ store = self.connections[service_name]
+
+ return store.query(sparql)
+
class CliError(Exception):
pass
diff --git a/tests/functional-tests/meson.build b/tests/functional-tests/meson.build
index 89b78756d..4cdc911a7 100644
--- a/tests/functional-tests/meson.build
+++ b/tests/functional-tests/meson.build
@@ -6,6 +6,8 @@ config_json_full_path = join_paths(meson.current_build_dir(), 'configuration.jso
testconf.set('TEST_CLI_DIR', tracker_uninstalled_cli_dir)
testconf.set('TEST_ONTOLOGIES_DIR', tracker_uninstalled_nepomuk_ontologies_dir)
+testconf.set('TEST_DBUS_DAEMON_CONFIG_FILE', build_root / 'tests' / 'test-bus.conf')
+testconf.set('TEST_PORTAL_FLATPAK_INFO', source_root / 'tests' / 'flatpak-info')
testconf.set('TRACKER_VERSION', meson.project_version())
config_json = configure_file(
@@ -28,6 +30,7 @@ functional_tests = [
'collation',
'ontology-changes',
'cli',
+ 'portal',
]
test_env = environment()
diff --git a/tests/functional-tests/portal.py b/tests/functional-tests/portal.py
new file mode 100644
index 000000000..a4e82820f
--- /dev/null
+++ b/tests/functional-tests/portal.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2020, Carlos Garnacho <carlosg@gnome.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# 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 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.
+#
+
+"""
+Test portal
+"""
+
+from gi.repository import GLib
+
+import unittest
+
+import configuration
+import fixtures
+
+class TestPortal(fixtures.TrackerPortalTest):
+ def test_01_forbidden(self):
+ self.start_service('org.freedesktop.Inaccessible')
+ self.assertRaises(
+ GLib.Error, self.query,
+ 'org.freedesktop.Inaccessible',
+ 'select ?u { BIND (1 AS ?u) }')
+
+ def test_02_allowed(self):
+ self.start_service('org.freedesktop.PortalTest')
+ res = self.query(
+ 'org.freedesktop.PortalTest',
+ 'select ?u { BIND (1 AS ?u) }')
+ self.assertEqual(len(res), 1)
+ self.assertEqual(res[0][0], '1')
+
+ def test_03_graph_access(self):
+ self.start_service('org.freedesktop.PortalTest')
+ self.update(
+ 'org.freedesktop.PortalTest',
+ 'CREATE GRAPH tracker:Disallowed;' +
+ 'INSERT { GRAPH tracker:Disallowed { <a> a nfo:FileDataObject } };' +
+ 'CREATE GRAPH tracker:Allowed;' +
+ 'INSERT { GRAPH tracker:Allowed { <b> a nfo:FileDataObject } }')
+ res = self.query(
+ 'org.freedesktop.PortalTest',
+ 'select ?u { ?u a rdfs:Resource }')
+ self.assertEqual(len(res), 1)
+ self.assertEqual(res[0][0], 'b')
+
+
+if __name__ == '__main__':
+ fixtures.tracker_test_main()
diff --git a/tests/libtracker-data/functions/functions-builtin-ceil-1.out b/tests/libtracker-data/functions/functions-builtin-ceil-1.out
new file mode 100644
index 000000000..d4caba38f
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-ceil-1.out
@@ -0,0 +1 @@
+"4.0" "5.0" "5.0" "6.0"
diff --git a/tests/libtracker-data/functions/functions-builtin-ceil-1.rq b/tests/libtracker-data/functions/functions-builtin-ceil-1.rq
new file mode 100644
index 000000000..857cf68ee
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-ceil-1.rq
@@ -0,0 +1 @@
+SELECT (CEIL(4.0) AS ?a) (CEIL(4.5) AS ?b) (CEIL(4.999999999) AS ?c) (CEIL(5.000000001) AS ?d) {}
diff --git a/tests/libtracker-data/functions/functions-builtin-floor-1.out b/tests/libtracker-data/functions/functions-builtin-floor-1.out
new file mode 100644
index 000000000..471e90cf9
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-floor-1.out
@@ -0,0 +1 @@
+"4.0" "4.0" "4.0" "5.0"
diff --git a/tests/libtracker-data/functions/functions-builtin-floor-1.rq b/tests/libtracker-data/functions/functions-builtin-floor-1.rq
new file mode 100644
index 000000000..2b7b65b1e
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-floor-1.rq
@@ -0,0 +1 @@
+SELECT (FLOOR(4.0) AS ?a) (FLOOR(4.5) AS ?b) (FLOOR(4.999999999) AS ?c) (FLOOR(5.000000001) AS ?d) {}
diff --git a/tests/libtracker-data/functions/functions-builtin-hash-1.out b/tests/libtracker-data/functions/functions-builtin-hash-1.out
new file mode 100644
index 000000000..739594c83
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-hash-1.out
@@ -0,0 +1 @@
+"900150983cd24fb0d6963f7d28e17f72" "a9993e364706816aba3e25717850c26c9cd0d89d" "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7" "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
diff --git a/tests/libtracker-data/functions/functions-builtin-hash-1.rq b/tests/libtracker-data/functions/functions-builtin-hash-1.rq
new file mode 100644
index 000000000..35b728ba8
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-hash-1.rq
@@ -0,0 +1,8 @@
+SELECT
+ (MD5('abc') AS ?md5)
+ (SHA1('abc') AS ?sha1)
+ (SHA256('abc') AS ?sha256)
+ (SHA384('abc') AS ?sha384)
+ (SHA512('abc') AS ?sha512)
+{
+}
diff --git a/tests/libtracker-data/functions/functions-builtin-lcase-1.out b/tests/libtracker-data/functions/functions-builtin-lcase-1.out
new file mode 100644
index 000000000..f6d67cdc1
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-lcase-1.out
@@ -0,0 +1 @@
+"hello" "москва"
diff --git a/tests/libtracker-data/functions/functions-builtin-lcase-1.rq b/tests/libtracker-data/functions/functions-builtin-lcase-1.rq
new file mode 100644
index 000000000..87cf47b0b
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-lcase-1.rq
@@ -0,0 +1 @@
+SELECT (LCASE('HELLO') AS ?str1) (LCASE('МОСКВА') AS ?str2) {}
diff --git a/tests/libtracker-data/functions/functions-builtin-strafter-1.out b/tests/libtracker-data/functions/functions-builtin-strafter-1.out
new file mode 100644
index 000000000..0bb47714e
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-strafter-1.out
@@ -0,0 +1 @@
+"cd"
diff --git a/tests/libtracker-data/functions/functions-builtin-strafter-1.rq b/tests/libtracker-data/functions/functions-builtin-strafter-1.rq
new file mode 100644
index 000000000..2ecd458f4
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-strafter-1.rq
@@ -0,0 +1 @@
+SELECT (STRAFTER('abcd', 'b') AS ?str) {}
diff --git a/tests/libtracker-data/functions/functions-builtin-strbefore-1.out b/tests/libtracker-data/functions/functions-builtin-strbefore-1.out
new file mode 100644
index 000000000..231f150c5
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-strbefore-1.out
@@ -0,0 +1 @@
+"a"
diff --git a/tests/libtracker-data/functions/functions-builtin-strbefore-1.rq b/tests/libtracker-data/functions/functions-builtin-strbefore-1.rq
new file mode 100644
index 000000000..5d565cae2
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-strbefore-1.rq
@@ -0,0 +1 @@
+SELECT (STRBEFORE('abcd', 'b') AS ?str) {}
diff --git a/tests/libtracker-data/functions/functions-builtin-ucase-1.out b/tests/libtracker-data/functions/functions-builtin-ucase-1.out
new file mode 100644
index 000000000..984e73e01
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-ucase-1.out
@@ -0,0 +1 @@
+"HELLO" "МОСКВА"
diff --git a/tests/libtracker-data/functions/functions-builtin-ucase-1.rq b/tests/libtracker-data/functions/functions-builtin-ucase-1.rq
new file mode 100644
index 000000000..ca9d89971
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-builtin-ucase-1.rq
@@ -0,0 +1 @@
+SELECT (UCASE('hello') AS ?str1) (UCASE('москва') AS ?str2) {}
diff --git a/tests/libtracker-data/functions/functions-tracker-3.out b/tests/libtracker-data/functions/functions-tracker-3.out
new file mode 100644
index 000000000..826861551
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-3.out
@@ -0,0 +1 @@
+"true"
diff --git a/tests/libtracker-data/functions/functions-tracker-3.rq b/tests/libtracker-data/functions/functions-tracker-3.rq
new file mode 100644
index 000000000..718d4b1be
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-3.rq
@@ -0,0 +1,3 @@
+SELECT ?eq {
+ BIND ((tracker:case-fold('AbCdEfGh') = tracker:case-fold('aBcDeFgH')) AS ?eq)
+}
diff --git a/tests/libtracker-data/functions/functions-tracker-4.out b/tests/libtracker-data/functions/functions-tracker-4.out
new file mode 100644
index 000000000..b54d1763e
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-4.out
@@ -0,0 +1 @@
+"abcd"
diff --git a/tests/libtracker-data/functions/functions-tracker-4.rq b/tests/libtracker-data/functions/functions-tracker-4.rq
new file mode 100644
index 000000000..a4b94357d
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-4.rq
@@ -0,0 +1 @@
+SELECT (tracker:ascii-lower-case ('ABCD') AS ?str) {}
diff --git a/tests/libtracker-data/functions/functions-tracker-5.out b/tests/libtracker-data/functions/functions-tracker-5.out
new file mode 100644
index 000000000..35320426e
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-5.out
@@ -0,0 +1 @@
+"aeiou"
diff --git a/tests/libtracker-data/functions/functions-tracker-5.rq b/tests/libtracker-data/functions/functions-tracker-5.rq
new file mode 100644
index 000000000..17dd03004
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-5.rq
@@ -0,0 +1 @@
+SELECT (tracker:unaccent ('áêïoù') AS ?str) {}
diff --git a/tests/libtracker-data/functions/functions-tracker-6.out b/tests/libtracker-data/functions/functions-tracker-6.out
new file mode 100644
index 000000000..3c1dfc33e
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-6.out
@@ -0,0 +1 @@
+"true" "false" "false" "false"
diff --git a/tests/libtracker-data/functions/functions-tracker-6.rq b/tests/libtracker-data/functions/functions-tracker-6.rq
new file mode 100644
index 000000000..f7ed7f908
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-6.rq
@@ -0,0 +1,7 @@
+SELECT
+ (tracker:uri-is-parent ('file:///', 'file:///a') AS ?a)
+ (tracker:uri-is-parent ('file:///a', 'file:///b') AS ?b)
+ (tracker:uri-is-parent ('file:///a', 'file:///') AS ?c)
+ (tracker:uri-is-parent ('file:///', 'file:///a/b') AS ?d)
+{
+}
diff --git a/tests/libtracker-data/functions/functions-tracker-7.out b/tests/libtracker-data/functions/functions-tracker-7.out
new file mode 100644
index 000000000..e255b526a
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-7.out
@@ -0,0 +1 @@
+"true" "false" "false" "true"
diff --git a/tests/libtracker-data/functions/functions-tracker-7.rq b/tests/libtracker-data/functions/functions-tracker-7.rq
new file mode 100644
index 000000000..cdf10d716
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-7.rq
@@ -0,0 +1,7 @@
+SELECT
+ (tracker:uri-is-descendant ('file:///', 'file:///a') AS ?a)
+ (tracker:uri-is-descendant ('file:///a', 'file:///b') AS ?b)
+ (tracker:uri-is-descendant ('file:///a', 'file:///') AS ?c)
+ (tracker:uri-is-descendant ('file:///', 'file:///a/b') AS ?d)
+{
+}
diff --git a/tests/libtracker-data/functions/functions-tracker-8.out b/tests/libtracker-data/functions/functions-tracker-8.out
new file mode 100644
index 000000000..a16d4a495
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-8.out
@@ -0,0 +1 @@
+"true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true" "true"
diff --git a/tests/libtracker-data/functions/functions-tracker-8.rq b/tests/libtracker-data/functions/functions-tracker-8.rq
new file mode 100644
index 000000000..c874b731c
--- /dev/null
+++ b/tests/libtracker-data/functions/functions-tracker-8.rq
@@ -0,0 +1,22 @@
+SELECT
+ ?nfd1 ?nfd2 ?nfd3
+ ?nfc1 ?nfc2 ?nfc3
+ ?nfkd1 ?nfkd2 ?nfkd3
+ ?nfkc1 ?nfkc2 ?nfkc3
+{
+ # From http://www.unicode.org/reports/tr15/#Compatibility_Composite_Figure
+ BIND ((tracker:normalize ('\ufb01', 'nfd') = '\ufb01') AS ?nfd1) .
+ BIND ((tracker:normalize ('\ufb01', 'nfc') = '\ufb01') AS ?nfc1) .
+ BIND ((tracker:normalize ('\ufb01', 'nfkd') = '\u0066\u0069') AS ?nfkd1) .
+ BIND ((tracker:normalize ('\ufb01', 'nfkc') = '\u0066\u0069') AS ?nfkc1) .
+
+ BIND ((tracker:normalize ('\u0032\u2075', 'nfd') = '\u0032\u2075') AS ?nfd2) .
+ BIND ((tracker:normalize ('\u0032\u2075', 'nfc') = '\u0032\u2075') AS ?nfc2) .
+ BIND ((tracker:normalize ('\u0032\u2075', 'nfkd') = '\u0032\u0035') AS ?nfkd2) .
+ BIND ((tracker:normalize ('\u0032\u2075', 'nfkc') = '\u0032\u0035') AS ?nfkc2) .
+
+ BIND ((tracker:normalize ('\u1e9b\u0323', 'nfd') = '\u017f\u0323\u0307') AS ?nfd3) .
+ BIND ((tracker:normalize ('\u1e9b\u0323', 'nfc') = '\u1e9b\u0323') AS ?nfc3) .
+ BIND ((tracker:normalize ('\u1e9b\u0323', 'nfkd') = '\u0073\u0323\u0307') AS ?nfkd3) .
+ BIND ((tracker:normalize ('\u1e9b\u0323', 'nfkc') = '\u1e69') AS ?nfkc3) .
+}
diff --git a/tests/libtracker-data/sort/data-title-sort-1.ttl b/tests/libtracker-data/sort/data-title-sort-1.ttl
new file mode 100644
index 000000000..e877edbe8
--- /dev/null
+++ b/tests/libtracker-data/sort/data-title-sort-1.ttl
@@ -0,0 +1,11 @@
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+
+_:a a owl:Thing .
+_:b a owl:Thing .
+_:c a owl:Thing .
+
+_:a foaf:name "The Shining".
+_:b foaf:name "Lord Of The Rings" .
+_:c foaf:name "The Lord Of The Flies" .
diff --git a/tests/libtracker-data/sort/query-title-sort-1.out b/tests/libtracker-data/sort/query-title-sort-1.out
new file mode 100644
index 000000000..20749b4df
--- /dev/null
+++ b/tests/libtracker-data/sort/query-title-sort-1.out
@@ -0,0 +1,3 @@
+"The Lord Of The Flies"
+"Lord Of The Rings"
+"The Shining"
diff --git a/tests/libtracker-data/sort/query-title-sort-1.rq b/tests/libtracker-data/sort/query-title-sort-1.rq
new file mode 100644
index 000000000..8256937c3
--- /dev/null
+++ b/tests/libtracker-data/sort/query-title-sort-1.rq
@@ -0,0 +1,4 @@
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+SELECT ?name
+WHERE { ?x foaf:name ?name }
+ORDER BY tracker:title-order(?name)
diff --git a/tests/libtracker-data/tracker-sparql-test.c b/tests/libtracker-data/tracker-sparql-test.c
index ca36c3798..4024e105a 100644
--- a/tests/libtracker-data/tracker-sparql-test.c
+++ b/tests/libtracker-data/tracker-sparql-test.c
@@ -114,6 +114,12 @@ const TestInfo tests[] = {
{ "functions/functions-property-1", "functions/data-1", FALSE },
{ "functions/functions-tracker-1", "functions/data-1", FALSE },
{ "functions/functions-tracker-2", "functions/data-2", FALSE },
+ { "functions/functions-tracker-3", "functions/data-2", FALSE },
+ { "functions/functions-tracker-4", "functions/data-2", FALSE },
+ { "functions/functions-tracker-5", "functions/data-2", FALSE },
+ { "functions/functions-tracker-6", "functions/data-2", FALSE },
+ { "functions/functions-tracker-7", "functions/data-2", FALSE },
+ { "functions/functions-tracker-8", "functions/data-2", FALSE },
{ "functions/functions-tracker-loc-1", "functions/data-3", FALSE },
{ "functions/functions-xpath-1", "functions/data-1", FALSE },
{ "functions/functions-xpath-2", "functions/data-1", FALSE },
@@ -134,6 +140,13 @@ const TestInfo tests[] = {
{ "functions/functions-datatypes-2", "functions/data-2", FALSE },
{ "functions/functions-datatypes-3", "functions/data-3", FALSE },
{ "functions/functions-datatypes-4", "functions/data-4", FALSE },
+ { "functions/functions-builtin-hash-1", "functions/data-1", FALSE },
+ { "functions/functions-builtin-ucase-1", "functions/data-1", FALSE },
+ { "functions/functions-builtin-lcase-1", "functions/data-1", FALSE },
+ { "functions/functions-builtin-strbefore-1", "functions/data-1", FALSE },
+ { "functions/functions-builtin-strafter-1", "functions/data-1", FALSE },
+ { "functions/functions-builtin-ceil-1", "functions/data-1", FALSE },
+ { "functions/functions-builtin-floor-1", "functions/data-1", FALSE },
/* Graph semantics and operations */
{ "graph/graph-1", "graph/data-1", FALSE },
{ "graph/graph-2", "graph/data-2", FALSE },
@@ -197,6 +210,7 @@ const TestInfo tests[] = {
{ "sort/query-sort-7", "sort/data-sort-1", FALSE },
{ "sort/query-sort-8", "sort/data-sort-5", FALSE },
{ "sort/query-sort-9", "sort/data-sort-5", FALSE },
+ { "sort/query-title-sort-1", "sort/data-title-sort-1", FALSE },
{ "subqueries/subqueries-1", "subqueries/data-1", FALSE },
{ "subqueries/subqueries-union-1", "subqueries/data-1", FALSE },
{ "subqueries/subqueries-union-2", "subqueries/data-1", FALSE },
@@ -532,7 +546,7 @@ main (int argc, char **argv)
gint result;
gint i;
- setlocale (LC_COLLATE, "en_US.utf8");
+ setlocale (LC_ALL, "en_US.utf8");
current_dir = g_get_current_dir ();
tests_data_dir = g_build_filename (current_dir, "sparql-test-data-XXXXXX", NULL);
diff --git a/tests/meson.build b/tests/meson.build
index e0647d9f2..562204efe 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -1,5 +1,10 @@
tests = []
+test_bus_conf_file = configure_file(
+ input: 'test-bus.conf.in',
+ output: 'test-bus.conf',
+ configuration: conf)
+
subdir('common')
subdir('gvdb')
@@ -8,6 +13,7 @@ subdir('libtracker-data')
subdir('libtracker-fts')
subdir('libtracker-sparql')
subdir('functional-tests')
+subdir('services')
foreach t: tests
test_name = t.get('name')
diff --git a/tests/services/meson.build b/tests/services/meson.build
new file mode 100644
index 000000000..623ec5243
--- /dev/null
+++ b/tests/services/meson.build
@@ -0,0 +1,8 @@
+# This directory contains service files used by dbus-daemon to automatically
+# activate the daemons as needed. These files are used when running Tracker
+# from the build tree.
+
+tracker_test_xdg_portal_service_file = configure_file(
+ input: 'org.freedesktop.portal.Tracker.service.in',
+ output: 'org.freedesktop.portal.Tracker.service',
+ configuration: conf)
diff --git a/tests/services/org.freedesktop.portal.Tracker.service.in b/tests/services/org.freedesktop.portal.Tracker.service.in
new file mode 100644
index 000000000..b7aab5796
--- /dev/null
+++ b/tests/services/org.freedesktop.portal.Tracker.service.in
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=org.freedesktop.portal.Tracker
+Exec=@abs_top_builddir@/src/portal/tracker-xdg-portal-3
+SystemdService=tracker-xdg-portal-3.service
+
diff --git a/tests/test-bus.conf.in b/tests/test-bus.conf.in
new file mode 100644
index 000000000..2f4b2ef1b
--- /dev/null
+++ b/tests/test-bus.conf.in
@@ -0,0 +1,21 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+
+ <listen>unix:tmpdir=./</listen>
+
+ <servicedir>@abs_top_builddir@/tests/services/</servicedir>
+ <standard_session_servicedirs/>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+</busconfig>