summaryrefslogtreecommitdiff
path: root/tests/libtracker-sparql/tracker-sparql-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/libtracker-sparql/tracker-sparql-test.c')
-rw-r--r--tests/libtracker-sparql/tracker-sparql-test.c440
1 files changed, 440 insertions, 0 deletions
diff --git a/tests/libtracker-sparql/tracker-sparql-test.c b/tests/libtracker-sparql/tracker-sparql-test.c
new file mode 100644
index 000000000..5cd4b7ace
--- /dev/null
+++ b/tests/libtracker-sparql/tracker-sparql-test.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include <locale.h>
+
+#include <glib-object.h>
+
+#include <libtracker-sparql/tracker-sparql.h>
+
+typedef struct {
+ const gchar *input ;
+ const gchar *output;
+} ESCAPE_TEST_DATA;
+
+ESCAPE_TEST_DATA test_data [] = {
+ { "SELECT \"a\"", "SELECT \\\"a\\\"" },
+ { "SELECT ?u \t \n \r \b \f", "SELECT ?u \\t \\n \\r \\b \\f" },
+ { NULL, NULL }
+};
+
+/* Used for the cursor_next_async test */
+static TrackerSparqlConnection *connection;
+static GMainLoop *main_loop;
+
+#if HAVE_TRACKER_FTS
+
+static GCancellable *cancellables[6] = { NULL, NULL, NULL, NULL };
+
+/* OK: query 0 with either query 4 or 5.
+ * FAIL: query 4 and 5 together (requires data to exist)
+ */
+static const gchar *queries[6] = {
+ /* #1 */
+ "SELECT ?p WHERE { ?p tracker:indexed true }",
+ /* #2 */
+ "SELECT ?prefix ?ns WHERE { ?ns a tracker:Namespace ; tracker:prefix ?prefix }",
+ /* #3 */
+ "SELECT ?p WHERE { ?p tracker:fulltextIndexed true }",
+ /* #4 */
+ "SELECT"
+ " ?u nie:url(?u)"
+ " tracker:coalesce(nie:title(?u), nfo:fileName(?u), \"Unknown\")"
+ " nfo:fileLastModified(?u)"
+ " nfo:fileSize(?u)"
+ " nie:url(?c) "
+ "WHERE { "
+ " ?u fts:match \"love\" . "
+ " ?u nfo:belongsToContainer ?c ; "
+ " tracker:available true . "
+ "} "
+ "ORDER BY DESC(fts:rank(?u)) "
+ "OFFSET 0 LIMIT 100",
+ /* #5 */
+ "SELECT"
+ " ?song"
+ " nie:url(?song)"
+ " tracker:coalesce(nie:title(?song), nfo:fileName(?song), \"Unknown\")"
+ " fn:string-join((?performer, ?album), \" - \")"
+ " nfo:duration(?song)"
+ " ?tooltip "
+ "WHERE {"
+ " ?match fts:match \"love\""
+ " {"
+ " ?song nmm:musicAlbum ?match"
+ " } UNION {"
+ " ?song nmm:performer ?match"
+ " } UNION {"
+ " ?song a nfo:Audio ."
+ " ?match a nfo:Audio"
+ " FILTER (?song = ?match)"
+ " }"
+ " ?song nmm:performer [ nmm:artistName ?performer ] ;"
+ " nmm:musicAlbum [ nie:title ?album ] ;"
+ " nfo:belongsToContainer [ nie:url ?tooltip ]"
+ "} "
+ "ORDER BY DESC(fts:rank(?song)) DESC(nie:title(?song)) "
+ "OFFSET 0 LIMIT 100",
+ NULL
+};
+
+#endif /* HAVE_TRACKER_FTS */
+
+static void
+test_tracker_sparql_escape_string (void)
+{
+ gint i;
+ gchar *result;
+
+ for (i = 0; test_data[i].input != NULL; i++) {
+ result = tracker_sparql_escape_string (test_data[i].input);
+ g_assert_cmpstr (result, ==, test_data[i].output);
+ g_free (result);
+ }
+}
+
+static void
+test_tracker_sparql_escape_uri_vprintf (void)
+{
+ gchar *result;
+
+ result = tracker_sparql_escape_uri_printf ("test:uri:contact-%d", 14, NULL);
+ g_assert_cmpstr (result, ==, "test:uri:contact-14");
+ g_free (result);
+}
+
+#if HAVE_TRACKER_FTS
+
+static void test_tracker_sparql_cursor_next_async_query (gint query);
+
+static void
+test_tracker_sparql_cursor_next_async_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TrackerSparqlCursor *cursor;
+ GError *error = NULL;
+ gboolean success;
+ static gint finished = 0;
+ static gint next = 0;
+ gint next_to_cancel = 1;
+ gint query;
+
+ query = GPOINTER_TO_INT(user_data);
+
+ g_assert (result != NULL);
+ success = tracker_sparql_cursor_next_finish (TRACKER_SPARQL_CURSOR (source),
+ result,
+ &error);
+
+ if (finished == 1 && next == next_to_cancel) {
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_print ("Got Cancellation GError\n");
+ } else {
+ g_assert_no_error (error);
+ }
+
+ cursor = TRACKER_SPARQL_CURSOR (source);
+ g_assert (cursor != NULL);
+
+ g_print (" %d: %s\n",
+ query,
+ tracker_sparql_cursor_get_string (cursor, 0, NULL));
+
+ if (!success) {
+ finished++;
+ next = 0;
+
+ g_print ("Finished %d\n", finished);
+
+ if (finished == 1 || finished == 2) {
+ test_tracker_sparql_cursor_next_async_query (finished);
+ } else if (finished == 3) {
+ g_main_loop_quit (main_loop);
+ }
+ } else {
+ next++;
+
+ /* Random number here for next_count_to_cancel is "2",
+ * just want to do this mid-cursor iteration
+ */
+ if (next == next_to_cancel && finished == 1) {
+ /* Cancel */
+ g_print ("Cancelling cancellable:%p at count:%d\n",
+ cancellables[query],
+ next);
+ g_cancellable_cancel (cancellables[query]);
+ }
+
+ tracker_sparql_cursor_next_async (cursor,
+ cancellables[query],
+ test_tracker_sparql_cursor_next_async_cb,
+ user_data);
+ }
+}
+
+static void
+test_tracker_sparql_cursor_next_async_query (gint query)
+{
+ TrackerSparqlCursor *cursor;
+ GError *error = NULL;
+
+ g_print ("ASYNC query %d starting:\n", query);
+
+ cancellables[query] = g_cancellable_new ();
+ g_assert (cancellables[query] != NULL);
+
+ cursor = tracker_sparql_connection_query (connection,
+ queries[query],
+ NULL,
+ &error);
+ g_assert_no_error (error);
+ g_assert (cursor != NULL);
+
+ tracker_sparql_cursor_next_async (cursor,
+ cancellables[query],
+ test_tracker_sparql_cursor_next_async_cb,
+ GINT_TO_POINTER(query));
+}
+
+static void
+test_tracker_sparql_cursor_next_async (void)
+{
+ GError *error = NULL;
+
+ /* So, the idea here:
+ * 1. Test async cursor_next() call.
+ * 2. Make sure we can cancel a cursor_next() call and start a new query (was failing)
+ * 3. Handle multiple async queries + async cursor_next() calls.
+ */
+
+ if (G_UNLIKELY (connection == NULL)) {
+ connection = tracker_sparql_connection_get (NULL, &error);
+ g_assert_no_error (error);
+ g_assert (connection != NULL);
+ }
+
+ test_tracker_sparql_cursor_next_async_query (0);
+}
+
+#endif /* HAVE_TRACKER_FTS */
+
+static void
+test_tracker_sparql_connection_locking_sync (void)
+{
+ TrackerSparqlConnection *c1, *c2, *c3;
+
+ c1 = tracker_sparql_connection_get (NULL, NULL);
+ c2 = tracker_sparql_connection_get (NULL, NULL);
+ c3 = tracker_sparql_connection_get (NULL, NULL);
+ g_assert (c1 == c2);
+ g_assert (c2 == c3);
+
+ g_object_unref (c1);
+ g_object_unref (c2);
+ g_object_unref (c3);
+}
+
+static TrackerSparqlConnection *c1 = NULL;
+static TrackerSparqlConnection *c2 = NULL;
+static TrackerSparqlConnection *c3 = NULL;
+
+static void
+test_tracker_sparql_connection_locking_async_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TrackerSparqlConnection *connection;
+ TrackerSparqlConnection *connection_waiting;
+ GError *error = NULL;
+
+ g_assert (result != NULL);
+ connection = tracker_sparql_connection_get_finish (result, &error);
+ g_assert_no_error (error);
+ g_assert (connection != NULL);
+
+ if (!c1) {
+ g_print ("GOT connection #1, waiting connection:%p (expecting NULL)\n", user_data);
+ c1 = connection;
+ } else if (!c2) {
+ g_print ("GOT connection #2, waiting connection:%p (expecting NULL)\n", user_data);
+ c2 = connection;
+ }
+
+ connection_waiting = user_data;
+ g_assert (connection_waiting == NULL);
+}
+
+static void
+test_tracker_sparql_connection_locking_async (void)
+{
+ tracker_sparql_connection_get_async (NULL, test_tracker_sparql_connection_locking_async_cb, c2);
+ tracker_sparql_connection_get_async (NULL, test_tracker_sparql_connection_locking_async_cb, c3);
+ c3 = tracker_sparql_connection_get (NULL, NULL);
+ g_assert (c3 != NULL);
+}
+
+static void
+test_tracker_sparql_nb237150_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TrackerSparqlConnection *connection;
+ GError *error = NULL;
+ static gboolean had_1 = FALSE;
+ static gboolean had_2 = FALSE;
+
+ connection = tracker_sparql_connection_get_finish (result, &error);
+ g_assert_no_error (error);
+ g_assert (connection != NULL);
+
+ /* Not actually worried about this being called */
+ g_print ("Called back for #%d\n", GPOINTER_TO_INT(user_data));
+
+ if (GPOINTER_TO_INT(user_data) == 1)
+ had_1 = TRUE;
+ if (GPOINTER_TO_INT(user_data) == 2)
+ had_2 = TRUE;
+
+ if (had_1 && had_2) {
+ g_print ("Called back ALL\n");
+ g_main_loop_quit (main_loop);
+ }
+}
+
+static void
+test_tracker_sparql_nb237150_subprocess (void)
+{
+ g_print ("\n");
+ g_print ("Calling #1 - tracker_sparql_connection_get_async()\n");
+ tracker_sparql_connection_get_async (NULL, test_tracker_sparql_nb237150_cb, GINT_TO_POINTER(1));
+
+ g_print ("Calling #2 - tracker_sparql_connection_get_async()\n");
+ tracker_sparql_connection_get_async (NULL, test_tracker_sparql_nb237150_cb, GINT_TO_POINTER(2));
+
+ g_print ("Calling both finished\n");
+}
+
+static void
+test_tracker_sparql_nb237150 (void)
+{
+ /* Test NB#237150 - Second tracker_sparql_connection_get_async
+ * never returns
+ */
+ g_test_trap_subprocess ("/libtracker-sparql/tracker-sparql/nb237150/subprocess",
+ G_USEC_PER_SEC * 2,
+ G_TEST_SUBPROCESS_INHERIT_STDOUT);
+
+ g_test_trap_assert_passed ();
+
+ /* Check we called the functions in the test */
+ g_test_trap_assert_stdout ("*Calling #1*");
+ g_test_trap_assert_stdout ("*Calling #2*");
+ g_test_trap_assert_stdout ("*Calling both finished*");
+
+ /* Check the callbacks from the functions we called were
+ * called in the test */
+ g_test_trap_assert_stdout ("*Called back for #1*");
+ g_test_trap_assert_stdout ("*Called back for #2*");
+ g_test_trap_assert_stdout ("*Called back ALL*");
+}
+
+static void
+test_tracker_sparql_connection_interleaved (void)
+{
+ GError *error = NULL;
+
+ TrackerSparqlCursor *cursor1;
+ TrackerSparqlCursor *cursor2;
+ TrackerSparqlConnection *connection;
+
+ const gchar* query = "select ?u {?u a rdfs:Resource .}";
+
+ connection = tracker_sparql_connection_get (NULL, &error);
+ g_assert_no_error (error);
+
+ cursor1 = tracker_sparql_connection_query (connection, query, 0, &error);
+ g_assert_no_error (error);
+
+ /* intentionally not freeing cursor1 here */
+ g_object_unref(connection);
+
+ connection = tracker_sparql_connection_get (NULL, &error);
+ g_assert_no_error (error);
+
+ cursor2 = tracker_sparql_connection_query (connection, query, 0, &error);
+ g_assert_no_error (error);
+
+ g_object_unref(connection);
+
+ g_object_unref(cursor2);
+ g_object_unref(cursor1);
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ int result;
+
+ setlocale (LC_ALL, "");
+
+ g_test_init (&argc, &argv, NULL);
+
+#if HAVE_TRACKER_FTS
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_assert (main_loop != NULL);
+#endif
+
+ /* NOTE: this first test must come BEFORE any others because
+ * connections are cached by libtracker-sparql.
+ */
+ g_test_add_func ("/libtracker-sparql/tracker-sparql/nb237150",
+ test_tracker_sparql_nb237150);
+ g_test_add_func ("/libtracker-sparql/tracker-sparql/nb237150/subprocess",
+ test_tracker_sparql_nb237150_subprocess);
+ g_test_add_func ("/libtracker-sparql/tracker-sparql/tracker_sparql_escape_string",
+ test_tracker_sparql_escape_string);
+ g_test_add_func ("/libtracker-sparql/tracker-sparql/tracker_sparql_escape_uri_vprintf",
+ test_tracker_sparql_escape_uri_vprintf);
+ g_test_add_func ("/libtracker-sparql/tracker-sparql/tracker_sparql_connection_interleaved",
+ test_tracker_sparql_connection_interleaved);
+ g_test_add_func ("/libtracker-sparql/tracker-sparql/tracker_sparql_connection_locking_sync",
+ test_tracker_sparql_connection_locking_sync);
+ g_test_add_func ("/libtracker-sparql/tracker-sparql/tracker_sparql_connection_locking_async",
+ test_tracker_sparql_connection_locking_async);
+
+#if HAVE_TRACKER_FTS
+ g_test_add_func ("/libtracker-sparql/tracker-sparql/tracker_sparql_cursor_next_async",
+ test_tracker_sparql_cursor_next_async);
+#endif
+
+ result = g_test_run ();
+
+#if HAVE_TRACKER_FTS
+ g_main_loop_run (main_loop);
+
+ if (connection) {
+ g_object_unref (connection);
+ }
+#endif
+
+ return result;
+}