annotate jamendo/sparql-archived/SeRQL/test_sparql.pl @ 27:d95e683fbd35 tip

Enable CORS on urispace redirects as well
author Chris Cannam
date Tue, 20 Feb 2018 14:52:02 +0000
parents df9685986338
children
rev   line source
Chris@0 1 /* $Id$
Chris@0 2
Chris@0 3 Part of SWI-Prolog
Chris@0 4
Chris@0 5 Author: Jan Wielemaker
Chris@0 6 E-mail: wielemak@science.uva.nl
Chris@0 7 WWW: http://www.swi-prolog.org
Chris@0 8 Copyright (C): 2006, University of Amsterdam
Chris@0 9
Chris@0 10 This program is free software; you can redistribute it and/or
Chris@0 11 modify it under the terms of the GNU General Public License
Chris@0 12 as published by the Free Software Foundation; either version 2
Chris@0 13 of the License, or (at your option) any later version.
Chris@0 14
Chris@0 15 This program is distributed in the hope that it will be useful,
Chris@0 16 but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 18 GNU General Public License for more details.
Chris@0 19
Chris@0 20 You should have received a copy of the GNU Lesser General Public
Chris@0 21 License along with this library; if not, write to the Free Software
Chris@0 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Chris@0 23
Chris@0 24 As a special exception, if you link this library with other files,
Chris@0 25 compiled with a Free Software compiler, to produce an executable, this
Chris@0 26 library does not by itself cause the resulting executable to be covered
Chris@0 27 by the GNU General Public License. This exception does not however
Chris@0 28 invalidate any other reasons why the executable file might be covered by
Chris@0 29 the GNU General Public License.
Chris@0 30 */
Chris@0 31
Chris@0 32 :- module(test_sparql,
Chris@0 33 [ sparql_parse/3, % +Text, -Query, +Options
Chris@0 34
Chris@0 35 load_manifests/1, % Load 'arq' or 'dawg' manifests
Chris@0 36
Chris@0 37 show_test/1, % +NameOrIRI
Chris@0 38 show_test_data/1, % +NameOrIRI
Chris@0 39 edit_test_data/1, % +NameOrIRI
Chris@0 40 edit_test_result/1, % +NameOrIRI
Chris@0 41 edit_test/1, % +NameOrIRI
Chris@0 42 list_tests/1, % +Class
Chris@0 43
Chris@0 44 % SYNTAX TESTS
Chris@0 45 syntax_test/1, % +NameOrIRI
Chris@0 46 syntax_test/2, % +NameOrIRI, -Query
Chris@0 47 run_syntax_tests/0,
Chris@0 48 test_query_listing/0,
Chris@0 49 test_query_listing/1, % +NameOrIRI
Chris@0 50
Chris@0 51 % QUERY TESTS
Chris@0 52 run_query_tests/0,
Chris@0 53 query_test/1 % +NameOrIRI
Chris@0 54 ]).
Chris@0 55 :- use_module(sparql_grammar).
Chris@0 56 :- use_module(sparql).
Chris@0 57 :- use_module(library('semweb/rdf_db')).
Chris@0 58 :- use_module(library('semweb/rdfs')).
Chris@0 59 :- use_module(library('url')).
Chris@0 60 :- use_module(test_manifest).
Chris@0 61 :- use_module(sparql_xml_result).
Chris@0 62 :- use_module(rdf_entailment, []).
Chris@0 63 :- use_module(no_entailment, []).
Chris@0 64
Chris@0 65 :- dynamic
Chris@0 66 failed_result/2,
Chris@0 67 passed/1,
Chris@0 68 failed/1,
Chris@0 69 skipped/1.
Chris@0 70
Chris@0 71 %% blocked(?Name)
Chris@0 72 %
Chris@0 73 % Blocked tests
Chris@0 74
Chris@0 75 :- multifile
Chris@0 76 blocked/1.
Chris@0 77
Chris@0 78 blocked('extendedType-literal-ne').
Chris@0 79 blocked('typePromotion-decimal-decimal-pass').
Chris@0 80 blocked('extendedType-ne-fail').
Chris@0 81 % Requires named graphs
Chris@0 82 blocked('untrusted-graphs-002').
Chris@0 83 blocked('untrusted-graphs-004').
Chris@0 84 blocked('untrusted-graphs-005').
Chris@0 85 blocked('source-query-001').
Chris@0 86 blocked('source-query-002').
Chris@0 87 blocked('source-query-003').
Chris@0 88 blocked('source-query-005').
Chris@0 89 blocked('dawg-source-simple-001').
Chris@0 90 blocked('dawg-source-simple-002').
Chris@0 91 blocked('dawg-source-simple-003').
Chris@0 92 blocked('dawg-source-simple-004').
Chris@0 93 blocked('dawg-source-simple-005').
Chris@0 94 % Requires xsd:dateTime semantics
Chris@0 95 blocked('sparql-query-example-Testing-Values-RDFterm-equal-2').
Chris@0 96 blocked('sparql-query-example-Testing-Values-1').
Chris@0 97 % ARQ tests with .srj result file
Chris@0 98 blocked('strlen - 1').
Chris@0 99 blocked('strlen - 2').
Chris@0 100
Chris@0 101
Chris@0 102 /*******************************
Chris@0 103 * QUERY TESTS *
Chris@0 104 *******************************/
Chris@0 105
Chris@0 106 % TBD: As we have to have an empty database we must first collect
Chris@0 107 % all info in the Prolog database :-( Alternatively we need a way
Chris@0 108 % to set the current database (thread-local!)
Chris@0 109
Chris@0 110 % run_query_tests
Chris@0 111 %
Chris@0 112 % Load all manifests and execute the tests.
Chris@0 113
Chris@0 114 run_query_tests :-
Chris@0 115 clean_tests,
Chris@0 116 run_all_query_tests.
Chris@0 117
Chris@0 118 run_all_query_tests :-
Chris@0 119 ( current_test(_, Test),
Chris@0 120 test_name(Test, Name),
Chris@0 121 ( blocked(Name)
Chris@0 122 -> assert(skipped(Test)),
Chris@0 123 fail
Chris@0 124 ; true
Chris@0 125 ),
Chris@0 126 query_test(Test),
Chris@0 127 fail ; true
Chris@0 128 ),
Chris@0 129
Chris@0 130 findall(T, passed(T), Passed), length(Passed, NPassed),
Chris@0 131 findall(T, failed(T), Failed), length(Failed, NFailed),
Chris@0 132 findall(T, skipped(T), Skipped), length(Skipped, NSkipped),
Chris@0 133 format('Passed: ~D; failed: ~D; skipped ~D~n',
Chris@0 134 [NPassed, NFailed, NSkipped]).
Chris@0 135
Chris@0 136 query_test(Name) :-
Chris@0 137 test_name(Test, Name), !,
Chris@0 138 query_test(Test).
Chris@0 139 query_test(Test) :-
Chris@0 140 test_name(Test, Name),
Chris@0 141 format('~`=t BEGIN ~q ~`=t~72|~n', [Name]),
Chris@0 142 test_query(Test, Query),
Chris@0 143 % Compile the query
Chris@0 144 ( catch(sparql_compile(Query, Compiled,
Chris@0 145 [ type(Type),
Chris@0 146 entailment(none)
Chris@0 147 ]), E, true)
Chris@0 148 -> ( var(E)
Chris@0 149 -> true
Chris@0 150 ; print_message(error, E),
Chris@0 151 assert(failed(Test)),
Chris@0 152 fail
Chris@0 153 )
Chris@0 154 ; format('FAILED to compile ~q~n', [Name]),
Chris@0 155 assert(failed(Test)),
Chris@0 156 fail
Chris@0 157 ),
Chris@0 158 % get the correct result
Chris@0 159 result_to_prolog(Type, Test, PrologResult),
Chris@0 160 % load the data
Chris@0 161 rdf_reset_db,
Chris@0 162 ( test_data_file(Test, DataFile)
Chris@0 163 -> load_triples_to_db(DataFile)
Chris@0 164 ; true
Chris@0 165 ),
Chris@0 166
Chris@0 167 flag(c, C, C+1),
Chris@0 168 % run the query
Chris@0 169 catch(findall(Result, sparql_run(Compiled, Result), Results),
Chris@0 170 E, true),
Chris@0 171 ( var(E)
Chris@0 172 -> % compare the result
Chris@0 173 compare_results(Test, Type, PrologResult, Results)
Chris@0 174 ; print_message(error, E),
Chris@0 175 assert(failed(Test)),
Chris@0 176 fail
Chris@0 177 ).
Chris@0 178
Chris@0 179
Chris@0 180 %% compare_results(+Test, +Type, +Correct, +Results)
Chris@0 181 %
Chris@0 182 % NOTE: Some tests (notably syntax tests) do not have results. In
Chris@0 183 % that case Results is bound to no_result and we do not compare.
Chris@0 184
Chris@0 185 compare_results(_, _, no_result, _) :- !.
Chris@0 186 compare_results(Test, ask, ask(Bool), [Bool]) :- !,
Chris@0 187 assert(passed(Test)).
Chris@0 188 compare_results(Test, Type, select(ColNames, Rows), Result) :-
Chris@0 189 Type = select(MyColNames),
Chris@0 190 same_colnames(ColNames, MyColNames, Map),
Chris@0 191 ( Map == nomap
Chris@0 192 -> RowsMyOrder = Rows
Chris@0 193 ; map_rows(Rows, Map, RowsMyOrder)
Chris@0 194 ),
Chris@0 195 var_blank_nodes_in_rows(RowsMyOrder, RowsMyOrderV),
Chris@0 196 var_blank_nodes_in_rows(Result, ResultV),
Chris@0 197 sort(RowsMyOrderV, OkRows), % TBD: match blank nodes!
Chris@0 198 sort(ResultV, MyRows),
Chris@0 199 match_rows(MyRows, OkRows, MyExtra, OkExtra), !,
Chris@0 200 ( MyExtra == [],
Chris@0 201 OkExtra == []
Chris@0 202 -> assert(passed(Test))
Chris@0 203 ; test_name(Test, Name),
Chris@0 204 format('~`=t ~q ~`=t~72|~n', [Name]),
Chris@0 205 format('TYPE: ~q~n', [Type]),
Chris@0 206 format('MISSED: ~p~n', [OkExtra]),
Chris@0 207 format('EXTRA: ~p~n', [MyExtra]),
Chris@0 208 format('~`=t~72|~n~n', []),
Chris@0 209 assert(failed(Test))
Chris@0 210 ).
Chris@0 211 compare_results(Test, Type, Correct, Result) :-
Chris@0 212 test_name(Test, Name),
Chris@0 213 format('~`=t ~q ~`=t~72|~n', [Name]),
Chris@0 214 format('TYPE: ~q~n', [Type]),
Chris@0 215 format('CORRECT: ~p~n', [Correct]),
Chris@0 216 format('WE: ~p~n', [Result]),
Chris@0 217 format('~`=t~72|~n~n', []),
Chris@0 218 assert(failed(Test)).
Chris@0 219
Chris@0 220 %% same_colnames(+Names1, +Names2, -Map)
Chris@0 221 %
Chris@0 222 % Is true if Names1 and Names2 contain the same names in possibly
Chris@0 223 % different order. If the order is diffent, Map is unified to a
Chris@0 224 % term map(RowLeft, RowRight), where variable bindings between the
Chris@0 225 % row-terms express the mapping between the rows.
Chris@0 226
Chris@0 227 same_colnames(Names, Names, nomap) :- !.
Chris@0 228 same_colnames(Names1, Names2, map(R1,R2)) :-
Chris@0 229 msort(Names1, S),
Chris@0 230 msort(Names2, S),
Chris@0 231 length(Names1, Len),
Chris@0 232 functor(R1, row, Len),
Chris@0 233 functor(R2, row, Len),
Chris@0 234 fill_vars(Names1, 1, Names2, R1, R2).
Chris@0 235
Chris@0 236 fill_vars([], _, _, _, _).
Chris@0 237 fill_vars([H|T], I, Names, R1, R2) :-
Chris@0 238 arg(I, R1, V),
Chris@0 239 nth1(I2, Names, H),
Chris@0 240 arg(I2, R2, V),
Chris@0 241 IN is I + 1,
Chris@0 242 fill_vars(T, IN, Names, R1, R2).
Chris@0 243
Chris@0 244 map_rows([], _, []).
Chris@0 245 map_rows([H0|T0], Map, [H|T]) :-
Chris@0 246 copy_term(Map, map(H0, H)),
Chris@0 247 map_rows(T0, Map, T).
Chris@0 248
Chris@0 249
Chris@0 250 %% var_blank_nodes_in_rows(+Rows0, -Rows)
Chris@0 251 %
Chris@0 252 % Substitute blank nodes in rows by variables. Note that blank
Chris@0 253 % nodes of multiple rows are not related.
Chris@0 254
Chris@0 255 var_blank_nodes_in_rows([], []).
Chris@0 256 var_blank_nodes_in_rows([H0|T0], [H|T]) :-
Chris@0 257 var_blank_nodes(H0, H),
Chris@0 258 var_blank_nodes(T0, T).
Chris@0 259
Chris@0 260
Chris@0 261 %% var_blank_nodes(+Term, -VarBlanks)
Chris@0 262 %
Chris@0 263 % Process Term, replacing blank nodes with variables.
Chris@0 264
Chris@0 265 var_blank_nodes(Term0, Term) :-
Chris@0 266 empty_assoc(Vars),
Chris@0 267 var_blank_nodes(Term0, Vars, _, Term).
Chris@0 268
Chris@0 269 var_blank_nodes(BN, Vars0, Vars, V) :-
Chris@0 270 rdf_is_bnode(BN), !,
Chris@0 271 ( get_assoc(BN, Vars0, V)
Chris@0 272 -> Vars = Vars0
Chris@0 273 ; put_assoc(BN, Vars0, V, Vars)
Chris@0 274 ).
Chris@0 275 var_blank_nodes(Term0, Vars0, Vars, Term) :-
Chris@0 276 compound(Term0), !,
Chris@0 277 functor(Term0, Name, Arity),
Chris@0 278 functor(Term, Name, Arity),
Chris@0 279 var_blank_nodes_args(0, Arity, Term0, Vars0, Vars, Term).
Chris@0 280 var_blank_nodes(Term, Vars, Vars, Term).
Chris@0 281
Chris@0 282 var_blank_nodes_args(I, I, _, Vars, Vars, _) :- !.
Chris@0 283 var_blank_nodes_args(I0, Arity, Term0, Vars0, Vars, Term) :-
Chris@0 284 I is I0 + 1,
Chris@0 285 arg(I, Term0, A0),
Chris@0 286 var_blank_nodes(A0, Vars0, Vars1, A),
Chris@0 287 arg(I, Term, A),
Chris@0 288 var_blank_nodes_args(I, Arity, Term0, Vars1, Vars, Term).
Chris@0 289
Chris@0 290
Chris@0 291 %% match_rows(+Rows0, +Rows1, -Extra1, -Extra2)
Chris@0 292 %
Chris@0 293 % Succeed if both sets of rows are the same. Note that there may
Chris@0 294 % be blank nodes in the rows. These are already substituted by
Chris@0 295 % Prolog variables. This is basically a permutation problem. First
Chris@0 296 % we decide to which row each row can match. Then we sort them to
Chris@0 297 % the lowest number of matches and finally we start the
Chris@0 298 % non-deterministic matching process.
Chris@0 299
Chris@0 300 match_rows(Rows1, Rows2, Extra1, Extra2) :-
Chris@0 301 candidate_matches(Rows1, Rows2, Extra1, Extra1Tail, Candidates),
Chris@0 302 keysort(Candidates, Sorted),
Chris@0 303 same_rows(Sorted, Rows2, Extra1Tail, Extra2).
Chris@0 304
Chris@0 305 candidate_matches([], _, E, E, []).
Chris@0 306 candidate_matches([H0|T0], Rows, E0, E, [L-Rs|T]) :-
Chris@0 307 setof(R, member_row(H0, R, Rows), Rs), !,
Chris@0 308 length(Rs, L),
Chris@0 309 candidate_matches(T0, Rows, E0, E, T).
Chris@0 310 candidate_matches([H0|T0], Rows, [H0|E0], E, T) :-
Chris@0 311 candidate_matches(T0, Rows, E0, E, T).
Chris@0 312
Chris@0 313 same_rows(E, [], E, []) :- !.
Chris@0 314 same_rows([], E, [], E) :- !.
Chris@0 315 same_rows([_-Rs|T], Rows, E1, E2) :-
Chris@0 316 member(R, Rs),
Chris@0 317 select_eq(R, Rows, Rest),
Chris@0 318 same_rows(T, Rest, E1, E2), !.
Chris@0 319
Chris@0 320 select_eq(V, Set, Rest) :-
Chris@0 321 select(X, Set, Rest),
Chris@0 322 V == X.
Chris@0 323
Chris@0 324 member_row(R, R1, Rows) :-
Chris@0 325 member(R1, Rows),
Chris@0 326 same_row(R, R1).
Chris@0 327
Chris@0 328 same_row(R, R) :- !.
Chris@0 329 same_row(R1, R2) :-
Chris@0 330 forall(arg(I, R1, A1),
Chris@0 331 ( arg(I, R2, A2),
Chris@0 332 same_value(A1, A2))).
Chris@0 333
Chris@0 334 same_value(V, V) :- !.
Chris@0 335 same_value(literal(type(T,V1)), literal(type(T,V2))) :-
Chris@0 336 xsdp_numeric_uri(T, _),
Chris@0 337 to_number(V1, N1),
Chris@0 338 to_number(V2, N2),
Chris@0 339 N1 =:= N2.
Chris@0 340
Chris@0 341 to_number(a, _) :- !, fail. % catch variables
Chris@0 342 to_number(N, N) :-
Chris@0 343 number(N), !.
Chris@0 344 to_number(A, N) :-
Chris@0 345 catch(atom_number(A, N), _, fail).
Chris@0 346
Chris@0 347
Chris@0 348 /*******************************
Chris@0 349 * RDF RESULTS *
Chris@0 350 *******************************/
Chris@0 351
Chris@0 352 %% result_to_prolog(+Type, +Test, -Result)
Chris@0 353 %
Chris@0 354 % Turn the RDF result into a more manageble form. For CONSTRUCT
Chris@0 355 % and DESCRIBE queries the result is a set of triples. For the
Chris@0 356 % others the format is described below:
Chris@0 357 %
Chris@0 358 % # ASK
Chris@0 359 %% ask(Bool)
Chris@0 360 %
Chris@0 361 % # SELECT
Chris@0 362 % select([Name1, ...],
Chris@0 363 % [ row(V1, ...),
Chris@0 364 % ...
Chris@0 365 % ])
Chris@0 366
Chris@0 367 result_to_prolog(Type, Test, Result) :-
Chris@0 368 ( test_result_file(Test, ResultFile)
Chris@0 369 -> ( file_name_extension(_, Ext, ResultFile),
Chris@0 370 ( Ext == srx
Chris@0 371 -> sparql_read_xml_result(ResultFile, Result)
Chris@0 372 ; ( Type == construct
Chris@0 373 ; Type == describe
Chris@0 374 )
Chris@0 375 -> load_triples(ResultFile, Result)
Chris@0 376 ; rdf_reset_db,
Chris@0 377 load_triples_to_db(ResultFile),
Chris@0 378 prolog_result(Result),
Chris@0 379 rdf_reset_db
Chris@0 380 )
Chris@0 381 -> true
Chris@0 382 ; test_name(Test, Name),
Chris@0 383 format('FAILED to interpret results for ~q~n', [Name]),
Chris@0 384 assert(failed_result(Test, ResultFile)),
Chris@0 385 fail
Chris@0 386 )
Chris@0 387 ; Result = no_result
Chris@0 388 ).
Chris@0 389
Chris@0 390 prolog_result(ask(True)) :-
Chris@0 391 rdf(Result, rdf:type, r:'ResultSet'),
Chris@0 392 rdf(Result, r:boolean, literal(type(xsd:boolean, True))), !.
Chris@0 393 prolog_result(select(ColNames, Rows)) :-
Chris@0 394 rdf(Result, rdf:type, r:'ResultSet'),
Chris@0 395 colnames(Result, ColNames),
Chris@0 396 result_rows(Result, ColNames, Rows).
Chris@0 397
Chris@0 398 colnames(Result, ColNames) :-
Chris@0 399 findall(N, rdf(Result, r:resultVariable, literal(N)), ColNames).
Chris@0 400
Chris@0 401 result_rows(Result, ColNames, Rows) :-
Chris@0 402 findall(R, result_row(Result, ColNames, R), Rows).
Chris@0 403
Chris@0 404 result_row(Result, ColNames, Row) :-
Chris@0 405 rdf(Result, r:solution, S),
Chris@0 406 result_values(ColNames, S, Values),
Chris@0 407 Row =.. [row|Values].
Chris@0 408
Chris@0 409 result_values([], _, []).
Chris@0 410 result_values([Name|Names], S, [Value|Values]) :-
Chris@0 411 ( rdf(S, r:binding, Binding),
Chris@0 412 rdf(Binding, r:variable, literal(Name)),
Chris@0 413 rdf(Binding, r:value, Value)
Chris@0 414 -> true
Chris@0 415 ; Value = '$null$'
Chris@0 416 ),
Chris@0 417 result_values(Names, S, Values).
Chris@0 418
Chris@0 419
Chris@0 420 /*******************************
Chris@0 421 * SYNTAX TESTS *
Chris@0 422 *******************************/
Chris@0 423
Chris@0 424 data_dir('Tests/sparql/data-xml').
Chris@0 425
Chris@0 426 % run_syntax_tests/0
Chris@0 427 %
Chris@0 428 % Load both the SyntaxDev and all normal tests and runs them
Chris@0 429 % through the parser. Does not involve any semantic checking.
Chris@0 430
Chris@0 431 run_syntax_tests :-
Chris@0 432 clean_tests,
Chris@0 433 load_syntax_manifests,
Chris@0 434 run_all_syntax_tests.
Chris@0 435
Chris@0 436 load_syntax_manifests :-
Chris@0 437 load_manifests(arq),
Chris@0 438 dev_manifest_files(Files),
Chris@0 439 maplist(load_triples_to_db, Files).
Chris@0 440
Chris@0 441 dev_manifest_files(Files) :-
Chris@0 442 data_dir(Dir),
Chris@0 443 atom_concat(Dir, '/SyntaxDev/*/manifest.{ttl,rdf}', Pattern),
Chris@0 444 expand_file_name(Pattern, Files).
Chris@0 445
Chris@0 446
Chris@0 447 /*******************************
Chris@0 448 * RUNNING TESTS *
Chris@0 449 *******************************/
Chris@0 450
Chris@0 451 run_all_syntax_tests :-
Chris@0 452 forall(current_test(_, Test),
Chris@0 453 (blocked_test(Test) -> true ; syntax_test(Test))),
Chris@0 454 findall(T, passed(T), Passed), length(Passed, NPassed),
Chris@0 455 findall(T, failed(T), Failed), length(Failed, NFailed),
Chris@0 456 findall(T, skipped(T), Skipped), length(Skipped, NSkipped),
Chris@0 457 format('Passed: ~D; failed: ~D; skipped ~D~n',
Chris@0 458 [NPassed, NFailed, NSkipped]).
Chris@0 459
Chris@0 460 syntax_test(Name) :-
Chris@0 461 syntax_test(Name, _Query).
Chris@0 462
Chris@0 463 syntax_test(Name, Query) :-
Chris@0 464 test_name(Test, Name), !,
Chris@0 465 syntax_test(Test, Query).
Chris@0 466 syntax_test(Test, Query) :-
Chris@0 467 test_query(Test, Codes),
Chris@0 468 syntax_test(Test, Codes, Query).
Chris@0 469
Chris@0 470 blocked_test(Test) :-
Chris@0 471 test_name(Test, Name),
Chris@0 472 blocked(Name).
Chris@0 473
Chris@0 474 syntax_test(Test, Codes, Query) :-
Chris@0 475 pos_syntax_test(Test), !,
Chris@0 476 ( catch(sparql_parse(Codes, Query, []), E, true)
Chris@0 477 -> ( var(E)
Chris@0 478 -> assert(passed(Test))
Chris@0 479 ; test_name(Test, Name),
Chris@0 480 format('PARSE TEST ERROR: ~w: ', [Name]),
Chris@0 481 print_message(error, E),
Chris@0 482 assert(failed(Test))
Chris@0 483 )
Chris@0 484 ; assert(failed(Test)),
Chris@0 485 test_name(Test, Name),
Chris@0 486 format('PARSE TEST FAILED: ~q~n', [Name])
Chris@0 487 ).
Chris@0 488 syntax_test(Test, Codes, Query) :-
Chris@0 489 neg_syntax_test(Test), !,
Chris@0 490 ( catch(sparql_parse(Codes, Query, []), E, true)
Chris@0 491 -> ( nonvar(E)
Chris@0 492 -> assert(passed(Test))
Chris@0 493 ; rdf_has(Test, mf:name, literal(Name)),
Chris@0 494 format('NEG TEST SUCCEEDED: ~w: ', [Name]),
Chris@0 495 assert(failed(Test))
Chris@0 496 )
Chris@0 497 ; assert(failed(Test)),
Chris@0 498 rdf_has(Test, mf:name, Name),
Chris@0 499 format('NEG TEST FAILED WITHOUT ERROR: ~w: ', [Name])
Chris@0 500 ).
Chris@0 501 syntax_test(Test, _, _) :-
Chris@0 502 assert(skipped(Test)).
Chris@0 503
Chris@0 504 pos_syntax_test(Test) :- % SyntaxDev
Chris@0 505 rdfs_individual_of(Test, mfx:'TestSyntax'), !.
Chris@0 506 pos_syntax_test(Test) :- % Semantic tests
Chris@0 507 rdf_has(Test, mf:action, Action),
Chris@0 508 rdf_has(Action, qt:query, _), !.
Chris@0 509
Chris@0 510 neg_syntax_test(Test) :-
Chris@0 511 rdfs_individual_of(Test, mfx:'TestBadSyntax'), !.
Chris@0 512
Chris@0 513
Chris@0 514 /*******************************
Chris@0 515 * QUERY LISTING *
Chris@0 516 *******************************/
Chris@0 517
Chris@0 518 test_query_listing :-
Chris@0 519 ( current_test(_, Test),
Chris@0 520 pos_syntax_test(Test),
Chris@0 521 test_query_listing(Test),
Chris@0 522 fail ; true
Chris@0 523 ).
Chris@0 524
Chris@0 525 test_query_listing(Name) :-
Chris@0 526 test_name(Test, Name), !,
Chris@0 527 test_query_listing(Test).
Chris@0 528 test_query_listing(Test) :-
Chris@0 529 test_name(Test, Name),
Chris@0 530 test_query(Test, Codes),
Chris@0 531 format('~`=t ~w ~`=t~72|~n', [Name]),
Chris@0 532 format('~s', [Codes]),
Chris@0 533 format('~`-t~72|~n'),
Chris@0 534 ( catch(sparql_parse(Codes, Query, []), E, true)
Chris@0 535 -> ( var(E)
Chris@0 536 -> list_query(Query)
Chris@0 537 ; print_message(error, E)
Chris@0 538 )
Chris@0 539 ; format('FAILED TO PARSE~n')
Chris@0 540 ),
Chris@0 541 format('~`=t~72|~n~n').
Chris@0 542
Chris@0 543 list_query(select(Vars, _, Query, _)) :-
Chris@0 544 portray_clause(select(Vars) :- Query).
Chris@0 545 list_query(construct(Templ, _, Query, _)) :-
Chris@0 546 portray_clause(construct(Templ) :- Query).
Chris@0 547 list_query(ask(_, Query)) :-
Chris@0 548 portray_clause(ask :- Query).
Chris@0 549 list_query(describe(Vars, _, Query, _)) :-
Chris@0 550 portray_clause(describe(Vars) :- Query).
Chris@0 551
Chris@0 552
Chris@0 553 /*******************************
Chris@0 554 * GENERIC TEST STUFF *
Chris@0 555 *******************************/
Chris@0 556
Chris@0 557 clean_tests :-
Chris@0 558 retractall(failed_result(_, _)),
Chris@0 559 retractall(passed(_)),
Chris@0 560 retractall(failed(_)),
Chris@0 561 retractall(skipped(_)),
Chris@0 562 rdf_reset_db.
Chris@0 563
Chris@0 564 list_tests(passed) :-
Chris@0 565 forall(passed(Test),
Chris@0 566 ( test_name(Test, Name),
Chris@0 567 format('PASSED: ~q~n', [Name]))).
Chris@0 568 list_tests(failed) :-
Chris@0 569 forall(failed(Test),
Chris@0 570 ( test_name(Test, Name),
Chris@0 571 format('FAILED: ~q~n', [Name]))).
Chris@0 572 list_tests(skipped) :-
Chris@0 573 forall(skipped(Test),
Chris@0 574 ( test_name(Test, Name),
Chris@0 575 format('SKIPPED: ~q~n', [Name]))).
Chris@0 576
Chris@0 577
Chris@0 578 /*******************************
Chris@0 579 * DEBUG *
Chris@0 580 *******************************/
Chris@0 581
Chris@0 582 user:portray(String) :-
Chris@0 583 is_list(String),
Chris@0 584 length(String, Len),
Chris@0 585 Len > 3,
Chris@0 586 ascii_list(String),
Chris@0 587 format('"~s"', [String]).
Chris@0 588 user:portray(IRI) :-
Chris@0 589 atom(IRI),
Chris@0 590 rdf_global_id(NS:Local, IRI),
Chris@0 591 Local \== '',
Chris@0 592 format('~w:~w', [NS, Local]).
Chris@0 593
Chris@0 594 ascii_list([]).
Chris@0 595 ascii_list([H|T]) :-
Chris@0 596 ascii_char(H),
Chris@0 597 ascii_list(T).
Chris@0 598
Chris@0 599 ascii_char(C) :-
Chris@0 600 integer(C),
Chris@0 601 between(32, 127, C), !.
Chris@0 602 ascii_char(0'\r).
Chris@0 603 ascii_char(0'\n).
Chris@0 604 ascii_char(0'\t).