tracker-0.16.2/tests/libtracker-sparql/tracker-test.c

No issues found

  1 /*
  2  * Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
  3  *
  4  * This library is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) any later version.
  8  *
  9  * This library is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU General Public
 15  * License along with this library; if not, write to the
 16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 17  * Boston, MA  02110-1301, USA.
 18  */
 19 
 20 #include "config.h"
 21 
 22 #include <libtracker-sparql/tracker-sparql.h>
 23 
 24 typedef struct {
 25 	const gchar *input ;
 26 	const gchar *output;
 27 } ESCAPE_TEST_DATA;
 28 
 29 ESCAPE_TEST_DATA test_data []  = {
 30 	{ "SELECT \"a\"", "SELECT \\\"a\\\"" },
 31 	{ "SELECT ?u \t \n \r \b \f", "SELECT ?u \\t \\n \\r \\b \\f" },
 32 	{ NULL, NULL }
 33 };
 34 
 35 /* Used for the cursor_next_async test */
 36 static TrackerSparqlConnection *connection;
 37 static GMainLoop *main_loop;
 38 
 39 #if HAVE_TRACKER_FTS
 40 
 41 static GCancellable *cancellables[6] = { NULL, NULL, NULL, NULL };
 42 
 43 /* OK:   query 0 with either query 4 or 5.
 44  * FAIL: query 4 and 5 together (requires data to exist)
 45  */
 46 static const gchar *queries[6] = {
 47 	/* #1 */
 48 	"SELECT ?p WHERE { ?p tracker:indexed true }",
 49 	/* #2 */
 50 	"SELECT ?prefix ?ns WHERE { ?ns a tracker:Namespace ; tracker:prefix ?prefix }",
 51 	/* #3 */
 52 	"SELECT ?p WHERE { ?p tracker:fulltextIndexed true }",
 53 	/* #4 */
 54 	"SELECT"
 55 	"  ?u nie:url(?u)"
 56 	"  tracker:coalesce(nie:title(?u), nfo:fileName(?u), \"Unknown\")"
 57 	"  nfo:fileLastModified(?u)"
 58 	"  nfo:fileSize(?u)"
 59 	"  nie:url(?c) "
 60 	"WHERE { "
 61 	"  ?u fts:match \"love\" . "
 62 	"  ?u nfo:belongsToContainer ?c ; "
 63 	"     tracker:available true . "
 64 	"} "
 65 	"ORDER BY DESC(fts:rank(?u)) "
 66 	"OFFSET 0 LIMIT 100",
 67 	/* #5 */
 68 	"SELECT"
 69 	"  ?song"
 70 	"  nie:url(?song)"
 71 	"  tracker:coalesce(nie:title(?song), nfo:fileName(?song), \"Unknown\")"
 72 	"  fn:string-join((?performer, ?album), \" - \")"
 73 	"  nfo:duration(?song)"
 74 	"  ?tooltip "
 75 	"WHERE {"
 76 	"  ?match fts:match \"love\""
 77 	"  {"
 78 	"    ?song nmm:musicAlbum ?match"
 79 	"  } UNION {"
 80 	"    ?song nmm:performer ?match"
 81 	"  } UNION {"
 82 	"    ?song a nfo:Audio ."
 83 	"    ?match a nfo:Audio"
 84 	"    FILTER (?song = ?match)"
 85 	"  }"
 86 	"  ?song nmm:performer [ nmm:artistName ?performer ] ;"
 87 	"        nmm:musicAlbum [ nie:title ?album ] ;"
 88 	"        nfo:belongsToContainer [ nie:url ?tooltip ]"
 89 	"} "
 90 	"ORDER BY DESC(fts:rank(?song)) DESC(nie:title(?song)) "
 91 	"OFFSET 0 LIMIT 100",
 92 	NULL
 93 };
 94 
 95 #endif /* HAVE_TRACKER_FTS */
 96 
 97 static void
 98 test_tracker_sparql_escape_string (void)
 99 {
100 	gint i;
101 	gchar *result;
102 
103 	for (i = 0; test_data[i].input != NULL; i++) {
104 		result = tracker_sparql_escape_string (test_data[i].input);
105 		g_assert_cmpstr (result, ==, test_data[i].output);
106 		g_free (result);
107 	}
108 }
109 
110 static void
111 test_tracker_sparql_escape_uri_vprintf (void)
112 {
113 	gchar *result;
114 
115 	result = tracker_sparql_escape_uri_printf ("test:uri:contact-%d", 14, NULL);
116 	g_assert_cmpstr (result, ==, "test:uri:contact-14");
117 	g_free (result);
118 }
119 
120 #if HAVE_TRACKER_FTS
121 
122 static void test_tracker_sparql_cursor_next_async_query (gint query);
123 
124 static void
125 test_tracker_sparql_cursor_next_async_cb (GObject      *source,
126                                           GAsyncResult *result,
127                                           gpointer      user_data)
128 {
129 	TrackerSparqlCursor *cursor;
130 	GError *error = NULL;
131 	gboolean success;
132 	static gint finished = 0;
133 	static gint next = 0;
134 	gint next_to_cancel = 1;
135 	gint query;
136 
137 	query = GPOINTER_TO_INT(user_data);
138 
139 	g_assert (result != NULL);
140 	success = tracker_sparql_cursor_next_finish (TRACKER_SPARQL_CURSOR (source),
141 	                                             result,
142 	                                             &error);
143 
144 	if (finished == 1 && next == next_to_cancel) {
145 		g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
146 		g_print ("Got Cancellation GError\n");
147 	} else {
148 		g_assert_no_error (error);
149 	}
150 
151 	cursor = TRACKER_SPARQL_CURSOR (source);
152 	g_assert (cursor != NULL);
153 
154 	g_print ("  %d: %s\n",
155 	         query,
156 	         tracker_sparql_cursor_get_string (cursor, 0, NULL));
157 
158 	if (!success) {
159 		finished++;
160 		next = 0;
161 
162 		g_print ("Finished %d\n", finished);
163 
164 		if (finished == 1 || finished == 2) {
165 			test_tracker_sparql_cursor_next_async_query (finished);
166 		} else if (finished == 3) {
167 			g_main_loop_quit (main_loop);
168 		}
169 	} else {
170 		tracker_sparql_cursor_next_async (cursor,
171 		                                  cancellables[query],
172 		                                  test_tracker_sparql_cursor_next_async_cb,
173 		                                  user_data);
174 
175 		next++;
176 
177 		/* Random number here for next_count_to_cancel is "2",
178 		 * just want to do this mid-cursor iteration
179 		 */
180 		if (next == next_to_cancel && finished == 1) {
181 			/* Cancel */
182 			g_print ("Cancelling cancellable:%p at count:%d\n",
183 			         cancellables[query],
184 			         next);
185 			g_cancellable_cancel (cancellables[query]);
186 		}
187 	}
188 }
189 
190 static void
191 test_tracker_sparql_cursor_next_async_query (gint query)
192 {
193 	TrackerSparqlCursor *cursor;
194 	GError *error = NULL;
195 
196 	g_print ("ASYNC query %d starting:\n", query);
197 
198 	cancellables[query] = g_cancellable_new ();
199 	g_assert (cancellables[query] != NULL);
200 
201 	cursor = tracker_sparql_connection_query (connection,
202 	                                          queries[query],
203 	                                          NULL,
204 	                                          &error);
205 	g_assert_no_error (error);
206 	g_assert (cursor != NULL);
207 
208 	tracker_sparql_cursor_next_async (cursor,
209 	                                  cancellables[query],
210 	                                  test_tracker_sparql_cursor_next_async_cb,
211 	                                  GINT_TO_POINTER(query));
212 }
213 
214 static void
215 test_tracker_sparql_cursor_next_async (void)
216 {
217 	GError *error = NULL;
218 
219 	/* So, the idea here:
220 	 * 1. Test async cursor_next() call.
221 	 * 2. Make sure we can cancel a cursor_next() call and start a new query (was failing)
222 	 * 3. Handle multiple async queries + async cursor_next() calls.
223 	 */
224 
225 	if (G_UNLIKELY (connection == NULL)) {
226 		connection = tracker_sparql_connection_get (NULL, &error);
227 		g_assert_no_error (error);
228 		g_assert (connection != NULL);
229 	}
230 
231 	test_tracker_sparql_cursor_next_async_query (0);
232 }
233 
234 #endif /* HAVE_TRACKER_FTS */
235 
236 static void
237 test_tracker_sparql_connection_locking_sync (void)
238 {
239 	TrackerSparqlConnection *c1, *c2, *c3;
240 
241 	c1 = tracker_sparql_connection_get (NULL, NULL);
242 	c2 = tracker_sparql_connection_get (NULL, NULL);
243 	c3 = tracker_sparql_connection_get (NULL, NULL);
244 	g_assert (c1 == c2);
245 	g_assert (c2 == c3);
246 
247 	g_object_unref (c1);
248 	g_object_unref (c2);
249 	g_object_unref (c3);
250 }
251 
252 static TrackerSparqlConnection *c1 = NULL;
253 static TrackerSparqlConnection *c2 = NULL;
254 static TrackerSparqlConnection *c3 = NULL;
255 
256 static void
257 test_tracker_sparql_connection_locking_async_cb (GObject      *source,
258                                                  GAsyncResult *result,
259                                                  gpointer      user_data)
260 {
261 	TrackerSparqlConnection *connection;
262 	TrackerSparqlConnection *connection_waiting;
263 	GError *error = NULL;
264 
265 	g_assert (result != NULL);
266 	connection = tracker_sparql_connection_get_finish (result, &error);
267 	g_assert_no_error (error);
268 	g_assert (connection != NULL);
269 
270 	if (!c1) {
271 		g_print ("GOT connection #1, waiting connection:%p (expecting NULL)\n", user_data);
272 		c1 = connection;
273 	} else if (!c2) {
274 		g_print ("GOT connection #2, waiting connection:%p (expecting NULL)\n", user_data);
275 		c2 = connection;
276 	}
277 
278 	connection_waiting = user_data;
279 	g_assert (connection_waiting == NULL);
280 }
281 
282 static void
283 test_tracker_sparql_connection_locking_async (void)
284 {
285 	tracker_sparql_connection_get_async (NULL, test_tracker_sparql_connection_locking_async_cb, c2);
286 	tracker_sparql_connection_get_async (NULL, test_tracker_sparql_connection_locking_async_cb, c3);
287 	c3 = tracker_sparql_connection_get (NULL, NULL);
288 	g_assert (c3 != NULL);
289 }
290 
291 static void
292 test_tracker_sparql_nb237150_cb (GObject      *source_object,
293                                  GAsyncResult *result,
294                                  gpointer      user_data)
295 {
296 	/* Not actually worried about this being called */
297 	g_print ("Called back for #%d\n", GPOINTER_TO_INT(user_data));
298 }
299 
300 static void
301 test_tracker_sparql_nb237150 (void)
302 {
303 	/* Test NB#237150 - Second tracker_sparql_connection_get_async never returns */
304 	if (g_test_trap_fork (G_USEC_PER_SEC * 2, G_TEST_TRAP_SILENCE_STDOUT)) {
305 		g_print ("\n");
306 		g_print ("Calling #1 - tracker_sparql_connection_get_async()\n");
307 		tracker_sparql_connection_get_async (NULL, test_tracker_sparql_nb237150_cb, GINT_TO_POINTER(1));
308 
309 		g_print ("Calling #2 - tracker_sparql_connection_get_async()\n");
310 		tracker_sparql_connection_get_async (NULL, test_tracker_sparql_nb237150_cb, GINT_TO_POINTER(2));
311 
312 		g_print ("Calling both finished\n");
313 
314 		exit (0); /* successful test run */
315 	}
316 
317 	g_test_trap_assert_passed ();
318 	g_test_trap_assert_stdout ("*Calling #1*");
319 	g_test_trap_assert_stdout ("*Calling #2*");
320 	g_test_trap_assert_stdout ("*Calling both finished*");
321 }
322 
323 static void
324 test_tracker_sparql_connection_interleaved (void)
325 {
326 	GError *error = NULL;
327 
328 	TrackerSparqlCursor *cursor1;
329 	TrackerSparqlCursor *cursor2;
330 	TrackerSparqlConnection *connection;
331 
332 	const gchar* query = "select ?u {?u a rdfs:Resource .}";
333 
334 	connection = tracker_sparql_connection_get (NULL, &error);
335 	g_assert_no_error (error);
336 
337 	cursor1 = tracker_sparql_connection_query (connection, query, 0, &error);
338 	g_assert_no_error (error);
339 
340 	/* intentionally not freeing cursor1 here */
341 	g_object_unref(connection);
342 
343 	connection = tracker_sparql_connection_get (NULL, &error);
344 	g_assert_no_error (error);
345 
346 	cursor2 = tracker_sparql_connection_query (connection, query, 0, &error);
347 	g_assert_no_error (error);
348 
349 	g_object_unref(connection);
350 
351 	g_object_unref(cursor2);
352 	g_object_unref(cursor1);
353 }
354 
355 gint
356 main (gint argc, gchar **argv)
357 {
358 	int result;
359 
360 	g_test_init (&argc, &argv, NULL);
361 
362 #if HAVE_TRACKER_FTS
363 	main_loop = g_main_loop_new (NULL, FALSE);
364 	g_assert (main_loop != NULL);
365 #endif
366 
367 	/* NOTE: this first test must come BEFORE any others because
368 	 * connections are cached by libtracker-sparql.
369 	 */
370 	g_test_add_func ("/libtracker-sparql/tracker/test_tracker_sparql_nb237150",
371 	                 test_tracker_sparql_nb237150);
372 	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_escape_string", 
373 	                 test_tracker_sparql_escape_string);
374 	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_escape_uri_vprintf",
375 	                 test_tracker_sparql_escape_uri_vprintf);
376 	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_connection_interleaved",
377 	                 test_tracker_sparql_connection_interleaved);
378 	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_connection_locking_sync",
379 	                 test_tracker_sparql_connection_locking_sync);
380 	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_connection_locking_async",
381 	                 test_tracker_sparql_connection_locking_async);
382 
383 #if HAVE_TRACKER_FTS
384 	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_cursor_next_async",
385 	                 test_tracker_sparql_cursor_next_async);
386 #endif
387 
388 	result = g_test_run ();
389 
390 #if HAVE_TRACKER_FTS
391 	g_main_loop_run (main_loop);
392 
393 	if (connection) {
394 		g_object_unref (connection);
395 	}
396 #endif
397 
398 	return result;
399 }