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

No issues found

  1 /*
  2  * Copyright (C) 2009, 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 <string.h>
 23 #include <locale.h>
 24 
 25 #include <glib.h>
 26 #include <gio/gio.h>
 27 
 28 #include <libtracker-common/tracker-common.h>
 29 
 30 #include <libtracker-data/tracker-data-manager.h>
 31 #include <libtracker-data/tracker-data-query.h>
 32 #include <libtracker-data/tracker-data-update.h>
 33 #include <libtracker-data/tracker-data.h>
 34 #include <libtracker-data/tracker-sparql-query.h>
 35 
 36 typedef struct _TestInfo TestInfo;
 37 
 38 struct _TestInfo {
 39 	const gchar *test_name;
 40 	const gchar *data;
 41 	gboolean expect_query_error;
 42 	gboolean expect_update_error;
 43 };
 44 
 45 const TestInfo tests[] = {
 46 	{ "aggregates/aggregate-1", "aggregates/data-1", FALSE },
 47 	{ "aggregates/aggregate-distinct-1", "aggregates/data-1", FALSE },
 48 	{ "aggregates/aggregate-group-1", "aggregates/data-1", FALSE },
 49 	{ "algebra/two-nested-opt", "algebra/two-nested-opt", FALSE },
 50 	{ "algebra/two-nested-opt-alt", "algebra/two-nested-opt", FALSE },
 51 	{ "algebra/opt-filter-3", "algebra/opt-filter-3", FALSE },
 52 	{ "algebra/filter-placement-1", "algebra/data-2", FALSE },
 53 	{ "algebra/filter-placement-2", "algebra/data-2", FALSE },
 54 	{ "algebra/filter-placement-3", "algebra/data-2", FALSE },
 55 	{ "algebra/filter-placement-3a", "algebra/data-2", FALSE },
 56 	{ "algebra/filter-nested-1", "algebra/data-1", FALSE },
 57 	{ "algebra/filter-nested-2", "algebra/data-1", FALSE },
 58 	{ "algebra/filter-scope-1", "algebra/data-2", FALSE },
 59 	{ "algebra/filter-in-1", "algebra/data-2", FALSE },
 60 	{ "algebra/filter-in-2", "algebra/data-2", FALSE },
 61 	{ "algebra/filter-in-3", "algebra/data-2", FALSE },
 62 	{ "algebra/filter-in-4", "algebra/data-2", FALSE },
 63 	{ "algebra/filter-in-5", "algebra/data-2", FALSE },
 64 	{ "algebra/var-scope-join-1", "algebra/var-scope-join-1", FALSE },
 65 	{ "anon/query", "anon/data", FALSE },
 66 	{ "anon/query-2", "anon/data", FALSE },
 67 	{ "ask/ask-1", "ask/data", FALSE },
 68 	{ "basic/base-prefix-3", "basic/data-1", FALSE },
 69 	{ "basic/compare-cast", "basic/data-1", FALSE },
 70 	{ "basic/predicate-variable", "basic/data-1", FALSE },
 71 	{ "basic/predicate-variable-2", "basic/data-1", FALSE },
 72 	{ "basic/predicate-variable-3", "basic/data-1", FALSE },
 73 	{ "basic/predicate-variable-4", "basic/data-1", FALSE },
 74 	{ "bnode-coreference/query", "bnode-coreference/data", FALSE },
 75 	{ "bound/bound1", "bound/data", FALSE },
 76 	{ "datetime/delete-1", "datetime/data-3", FALSE },
 77 	{ "datetime/functions-localtime-1", "datetime/data-1", FALSE },
 78 	{ "datetime/functions-timezone-1", "datetime/data-2", FALSE },
 79 	{ "datetime/functions-timezone-2", "datetime/data-2", FALSE },
 80 	{ "expr-ops/query-ge-1", "expr-ops/data", FALSE },
 81 	{ "expr-ops/query-le-1", "expr-ops/data", FALSE },
 82 	{ "expr-ops/query-minus-1", "expr-ops/data", FALSE },
 83 	{ "expr-ops/query-mul-1", "expr-ops/data", FALSE },
 84 	{ "expr-ops/query-plus-1", "expr-ops/data", FALSE },
 85 	{ "expr-ops/query-unminus-1", "expr-ops/data", FALSE },
 86 	{ "expr-ops/query-unplus-1", "expr-ops/data", FALSE },
 87 	{ "expr-ops/query-res-1", "expr-ops/data", FALSE },
 88 	{ "functions/functions-property-1", "functions/data-1", FALSE },
 89 	{ "functions/functions-tracker-1", "functions/data-1", FALSE },
 90 	{ "functions/functions-tracker-2", "functions/data-2", FALSE },
 91 	{ "functions/functions-tracker-loc-1", "functions/data-3", FALSE },
 92 	{ "functions/functions-xpath-1", "functions/data-1", FALSE },
 93 	{ "functions/functions-xpath-2", "functions/data-1", FALSE },
 94 	{ "functions/functions-xpath-3", "functions/data-1", FALSE },
 95 	{ "functions/functions-xpath-4", "functions/data-1", FALSE },
 96 	{ "functions/functions-xpath-5", "functions/data-1", FALSE },
 97 	{ "functions/functions-xpath-6", "functions/data-1", FALSE },
 98 	{ "functions/functions-xpath-7", "functions/data-1", FALSE },
 99 	{ "functions/functions-xpath-8", "functions/data-1", FALSE },
100 	{ "functions/functions-xpath-9", "functions/data-1", FALSE },
101 	{ "graph/graph-1", "graph/data-1", FALSE },
102 	{ "graph/graph-2", "graph/data-2", FALSE },
103 	{ "graph/graph-3", "graph/data-3", FALSE },
104 	{ "graph/graph-4", "graph/data-3", FALSE },
105 	{ "graph/graph-4", "graph/data-4", FALSE },
106 	{ "optional/q-opt-complex-1", "optional/complex-data-1", FALSE },
107 	{ "optional/simple-optional-triple", "optional/simple-optional-triple", FALSE },
108 	{ "regex/regex-query-001", "regex/regex-data-01", FALSE },
109 	{ "regex/regex-query-002", "regex/regex-data-01", FALSE },
110 	{ "sort/query-sort-1", "sort/data-sort-1", FALSE },
111 	{ "sort/query-sort-2", "sort/data-sort-1", FALSE },
112 	{ "sort/query-sort-3", "sort/data-sort-3", FALSE },
113 	{ "sort/query-sort-4", "sort/data-sort-4", FALSE },
114 	{ "sort/query-sort-5", "sort/data-sort-4", FALSE },
115 	{ "sort/query-sort-6", "sort/data-sort-4", FALSE },
116 	{ "sort/query-sort-7", "sort/data-sort-1", FALSE },
117 	{ "sort/query-sort-8", "sort/data-sort-5", FALSE },
118 	{ "subqueries/subqueries-1", "subqueries/data-1", FALSE },
119 	{ "subqueries/subqueries-union-1", "subqueries/data-1", FALSE },
120 	{ "subqueries/subqueries-union-2", "subqueries/data-1", FALSE },
121 	/* Bracket error after WHERE */
122 	{ "error/query-error-1", "error/query-error-1", TRUE, FALSE },
123 	/* Unknown property */
124 	{ "error/query-error-2", "error/query-error-2", TRUE, FALSE },
125 	{ "error/update-error-query-1", "error/update-error-1", FALSE, TRUE },
126 
127 	{ "turtle/turtle-query-001", "turtle/turtle-data-001", FALSE },
128 	{ "turtle/turtle-query-002", "turtle/turtle-data-002", FALSE },
129 	{ NULL }
130 };
131 
132 static int
133 strstr_i (const char *a, const char *b)
134 {
135 	return strstr (a, b) != NULL ? 1 : 0;
136 }
137 
138 static void
139 check_result (TrackerDBCursor *cursor,
140               const TestInfo *test_info,
141               const gchar *results_filename,
142               GError *error)
143 {
144 	int (*comparer) (const char *a, const char *b);
145 	GString *test_results;
146 	gchar *results;
147 	GError *nerror = NULL;
148 
149 	if (test_info->expect_query_error) {
150 		comparer = strstr_i;
151 		g_assert (error != NULL);
152 	} else {
153 		comparer = strcmp;
154 		g_assert_no_error (error);
155 	}
156 
157 	g_file_get_contents (results_filename, &results, NULL, &nerror);
158 	g_assert_no_error (nerror);
159 	g_clear_error (&nerror);
160 
161 	/* compare results with reference output */
162 
163 	test_results = g_string_new ("");
164 
165 	if (cursor) {
166 		gint col;
167 
168 		while (tracker_db_cursor_iter_next (cursor, NULL, &error)) {
169 			for (col = 0; col < tracker_db_cursor_get_n_columns (cursor); col++) {
170 				const gchar *str;
171 
172 				if (col > 0) {
173 					g_string_append (test_results, "\t");
174 				}
175 
176 				str = tracker_db_cursor_get_string (cursor, col, NULL);
177 				if (str != NULL) {
178 					/* bound variable */
179 					g_string_append_printf (test_results, "\"%s\"", str);
180 				}
181 			}
182 
183 			g_string_append (test_results, "\n");
184 		}
185 	} else if (test_info->expect_query_error) {
186 		g_string_append (test_results, error->message);
187 		g_clear_error (&error);
188 	}
189 
190 	if (comparer (results, test_results->str)) {
191 		/* print result difference */
192 		gchar *quoted_results;
193 		gchar *command_line;
194 		gchar *quoted_command_line;
195 		gchar *shell;
196 		gchar *diff;
197 
198 		quoted_results = g_shell_quote (test_results->str);
199 		command_line = g_strdup_printf ("echo -n %s | diff -u %s -", quoted_results, results_filename);
200 		quoted_command_line = g_shell_quote (command_line);
201 		shell = g_strdup_printf ("sh -c %s", quoted_command_line);
202 		g_spawn_command_line_sync (shell, &diff, NULL, NULL, &error);
203 		g_assert_no_error (error);
204 
205 		g_error ("%s", diff);
206 
207 		g_free (quoted_results);
208 		g_free (command_line);
209 		g_free (quoted_command_line);
210 		g_free (shell);
211 		g_free (diff);
212 	}
213 
214 	g_string_free (test_results, TRUE);
215 	g_free (results);
216 }
217 
218 static void
219 test_sparql_query (gconstpointer test_data)
220 {
221 	TrackerDBCursor *cursor;
222 	const TestInfo *test_info;
223 	GError *error;
224 	gchar *data_filename;
225 	gchar *query, *query_filename;
226 	gchar *results_filename;
227 	gchar *prefix, *data_prefix, *test_prefix;
228 	const gchar *test_schemas[2] = { NULL, NULL };
229 
230 	error = NULL;
231 	test_info = test_data;
232 
233 	/* initialization */
234 	prefix = g_build_path (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "libtracker-data", NULL);
235 	data_prefix = g_build_filename (prefix, test_info->data, NULL);
236 	test_prefix = g_build_filename (prefix, test_info->test_name, NULL);
237 	g_free (prefix);
238 
239 	test_schemas[0] = data_prefix;
240 
241 	tracker_db_journal_set_rotating (FALSE, G_MAXSIZE, NULL);
242 
243 	tracker_data_manager_init (TRACKER_DB_MANAGER_FORCE_REINDEX,
244 	                           test_schemas,
245 	                           NULL, FALSE, FALSE,
246 	                           100, 100, NULL, NULL, NULL, &error);
247 
248 	g_assert_no_error (error);
249 
250 	/* data_path = g_build_path (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "libtracker-data", NULL); */
251 
252 	/* load data set */
253 	data_filename = g_strconcat (data_prefix, ".ttl", NULL);
254 	if (g_file_test (data_filename, G_FILE_TEST_IS_REGULAR)) {
255 		tracker_turtle_reader_load (data_filename, &error);
256 		g_assert_no_error (error);
257 	} else {
258 		/* no .ttl available, assume .rq with SPARQL Update */
259 		gchar *data;
260 
261 		g_free (data_filename);
262 
263 		data_filename = g_strconcat (data_prefix, ".rq", NULL);
264 		g_file_get_contents (data_filename, &data, NULL, &error);
265 		g_assert_no_error (error);
266 
267 		tracker_data_update_sparql (data, &error);
268 		if (test_info->expect_update_error) {
269 			g_assert (error != NULL);
270 			g_clear_error (&error);
271 		} else {
272 			g_assert_no_error (error);
273 		}
274 
275 		g_free (data);
276 	}
277 
278 	query_filename = g_strconcat (test_prefix, ".rq", NULL);
279 	g_file_get_contents (query_filename, &query, NULL, &error);
280 	g_assert_no_error (error);
281 
282 	results_filename = g_strconcat (test_prefix, ".out", NULL);
283 
284 	/* perform actual query */
285 
286 	cursor = tracker_data_query_sparql_cursor (query, &error);
287 
288 	check_result (cursor, test_info, results_filename, error);
289 
290 	g_free (query_filename);
291 	g_free (query);
292 
293 	query_filename = g_strconcat (test_prefix, ".extra.rq", NULL);
294 	if (g_file_get_contents (query_filename, &query, NULL, NULL)) {
295 		g_object_unref (cursor);
296 		cursor = tracker_data_query_sparql_cursor (query, &error);
297 		g_assert_no_error (error);
298 		g_free (results_filename);
299 		results_filename = g_strconcat (test_prefix, ".extra.out", NULL);
300 		check_result (cursor, test_info, results_filename, error);
301 	}
302 
303 	g_free (data_prefix);
304 	g_free (test_prefix);
305 
306 	if (cursor) {
307 		g_object_unref (cursor);
308 	}
309 
310 	/* cleanup */
311 
312 	g_free (data_filename);
313 	g_free (query_filename);
314 	g_free (query);
315 	g_free (results_filename);
316 
317 	tracker_data_manager_shutdown ();
318 }
319 
320 int
321 main (int argc, char **argv)
322 {
323 	gint result;
324 	gint i;
325 	gchar *current_dir;
326 
327 	g_test_init (&argc, &argv, NULL);
328 
329 	setlocale (LC_COLLATE, "en_US.utf8");
330 
331 	current_dir = g_get_current_dir ();
332 
333 	g_setenv ("XDG_DATA_HOME", current_dir, TRUE);
334 	g_setenv ("XDG_CACHE_HOME", current_dir, TRUE);
335 	g_setenv ("TRACKER_DB_ONTOLOGIES_DIR", TOP_SRCDIR "/data/ontologies/", TRUE);
336 
337 	g_free (current_dir);
338 
339 	/* add test cases */
340 	for (i = 0; tests[i].test_name; i++) {
341 		gchar *testpath;
342 
343 #ifndef HAVE_LIBICU
344 		/* Skip tests which fail collation tests and are known
345 		 * to do so. For more details see:
346 		 *
347 		 * https://bugzilla.gnome.org/show_bug.cgi?id=636074
348 		 */
349 		if (strcmp (tests[i].test_name, "functions/functions-xpath-2") == 0) {
350 			continue;
351 		}
352 #endif
353 
354 		testpath = g_strconcat ("/libtracker-data/sparql/", tests[i].test_name, NULL);
355 		g_test_add_data_func (testpath, &tests[i], test_sparql_query);
356 		g_free (testpath);
357 	}
358 
359 	/* run tests */
360 	result = g_test_run ();
361 
362 	/* clean up */
363 	g_print ("Removing temporary data\n");
364 	g_spawn_command_line_sync ("rm -R tracker/", NULL, NULL, NULL, NULL);
365 
366 	return result;
367 }