diff options
Diffstat (limited to 'tests/libtracker-sparql/tracker-sparql-test.c')
-rw-r--r-- | tests/libtracker-sparql/tracker-sparql-test.c | 440 |
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; +} |