319 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
| /*  Part of SWI-Prolog
 | |
| 
 | |
|     Author:        Jan Wielemaker
 | |
|     E-mail:        J.Wielemaker@uva.nl
 | |
|     WWW:           http://www.swi-prolog.org
 | |
|     Copyright (C): 2010, University of Amsterdam
 | |
| 
 | |
|     This program 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 program 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | |
| 
 | |
|     As a special exception, if you link this library with other files,
 | |
|     compiled with a Free Software compiler, to produce an executable, this
 | |
|     library does not by itself cause the resulting executable to be covered
 | |
|     by the GNU General Public License. This exception does not however
 | |
|     invalidate any other reasons why the executable file might be covered by
 | |
|     the GNU General Public License.
 | |
| */
 | |
| 
 | |
| :- module(test_rdf,
 | |
| 	  [ suite/1,			% +Test-number
 | |
| 	    test_dir/1,			% +Directory
 | |
| 	    test_file/1,		% +File
 | |
| 	    time_file/1,		% +File
 | |
| 	    passed/1,			% +Test-numberOrFile
 | |
| 	    test_rdf/0,			% run whole suite
 | |
| 	    show_ok/1			% +Test
 | |
| 	  ]).
 | |
| 
 | |
| :- multifile
 | |
| 	user:file_search_path/2.
 | |
| 
 | |
| user:file_search_path(library, .).
 | |
| user:file_search_path(library, '../sgml').
 | |
| user:file_search_path(library, '../clib').
 | |
| user:file_search_path(library, '..').
 | |
| user:file_search_path(foreign, '../sgml').
 | |
| user:file_search_path(foreign, '../clib').
 | |
| user:file_search_path(foreign, '../semweb').
 | |
| 
 | |
| :- use_module(library(sgml)).
 | |
| :- use_module(library(semweb/rdf_compare)).
 | |
| :- use_module(library(rdf_parser)).
 | |
| :- use_module(library(rdf_triple)).
 | |
| :- use_module(library(rdf)).
 | |
| :- use_module(pretty_print).
 | |
| 
 | |
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | |
| Test file for the SWI-Prolog RDF parser.  Toplevel predicates:
 | |
| 
 | |
| 	# test/0
 | |
| 	Run all tests from the `suite' directory and validate the
 | |
| 	the result if the correct result is stored in a .ok file.
 | |
| 
 | |
| 	# suite(N)
 | |
| 	Run test on suite/t<N>.rdf, showing RDF, intermediate
 | |
| 	representation and triples on the console.
 | |
| 
 | |
| 	# passed(N)
 | |
| 	Parse suite/t<N>.rdf and save the result in suite/t<N>.ok
 | |
| 
 | |
| The intention is to write  tests,  use   suite/1  to  make sure they are
 | |
| parsed correctly and then run passed/1 to   save  the correct answer, so
 | |
| running test/0 can validate all results.
 | |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 | |
| 
 | |
| suite(N) :-
 | |
| 	atomic_list_concat(['suite/t', N, '.rdf'], File),
 | |
| 	test_file(File).
 | |
| 
 | |
| test_file(File) :-
 | |
| 	rdf_reset_ids,
 | |
| 	format('************* Test ~w ***~n', [File]),
 | |
| 	cat(File),
 | |
| 	load_structure(File,
 | |
| 		       [ RDFElement ],
 | |
| 		       [ dialect(xmlns),
 | |
| 			 space(sgml)
 | |
| 		       ]),
 | |
| 	rdf_start_file([], Cleanup),
 | |
| 	make_rdf_state([base_uri('http://test.org/test/')], State, _),
 | |
| 	xml_to_plrdf(RDFElement, RDF, State),
 | |
| 	rdf_end_file(Cleanup),
 | |
| 	format('============= Prolog term ==============~n', []),
 | |
| 	pretty_print(RDF),
 | |
| 	rdf_triples(RDF, Triples),
 | |
| 	format('============= Triples ==================~n', []),
 | |
| 	write_triples(Triples).
 | |
| 
 | |
| time_file(File) :-
 | |
| 	time(load_rdf(File, Triples)),
 | |
| 	length(Triples, Len),
 | |
| 	format('Created ~w triples~n', [Len]).
 | |
| 
 | |
| passed(Id) :-
 | |
| 	integer(Id), !,
 | |
| 	atomic_list_concat(['suite/t', Id, '.rdf'], File),
 | |
| 	passed(File).
 | |
| passed(File) :-
 | |
| 	rdf_reset_ids,
 | |
| 	ok_file(File, OkFile),
 | |
| 	load_rdf(File, Triples),
 | |
| 	open(OkFile, write, Fd, [encoding(utf8)]),
 | |
| 	save_triples(Triples, Fd),
 | |
| 	close(Fd),
 | |
| 	length(Triples, N),
 | |
| 	format('Saved ~d triples to ~w~n', [N, OkFile]).
 | |
| 
 | |
| :- dynamic failed/1.
 | |
| 
 | |
| test_rdf :-
 | |
| 	test(load_rdf),
 | |
| 	test(process_rdf).
 | |
| 
 | |
| test(How) :-
 | |
| 	retractall(failed(_)),
 | |
| 	test_dir(suite, How),
 | |
| 	findall(F, failed(F), Failed),
 | |
| 	(   Failed == []
 | |
| 	->  true
 | |
| 	;   length(Failed, N),
 | |
| 	    format('ERROR: ~w tests failed~n', [N]),
 | |
| 	    fail
 | |
| 	).
 | |
| 
 | |
| 
 | |
| test_dir(Dir) :-
 | |
| 	test_dir(Dir, load_rdf).
 | |
| 
 | |
| test_dir(Dir, How) :-
 | |
| 	format('Tests from "~w" [~w]: ', [Dir, How]),
 | |
| 	atom_concat(Dir, '/*.rdf', Pattern),
 | |
| 	expand_file_name(Pattern, TestFiles),
 | |
| 	maplist(test(How), TestFiles),
 | |
| 	format(' done~n').
 | |
| 
 | |
| test(How, File) :-
 | |
| 	format('.'), flush_output,
 | |
| 	rdf_reset_ids,
 | |
| 	ok_file(File, OkFile),
 | |
| 	(   call(How, File, Triples)
 | |
| 	->  (   catch(open(OkFile, read, Fd, [encoding(utf8)]), _, fail)
 | |
| 	    ->  (   read_triples(Fd, OkTriples),
 | |
| 		    close(Fd),
 | |
| 		    rdf_equal_graphs(Triples, OkTriples, _Subst)
 | |
| 		->  true
 | |
| 		;   assert(failed(File)),
 | |
| 		    format('~N~w: WRONG ANSWER~n', [File])
 | |
| 		)
 | |
| 	    ;	format('~N~w: (no .ok file)~n', [File])
 | |
| 	    )
 | |
| 	;   assert(failed(File)),
 | |
| 	    format('~N~w: PARSE FAILED~n', [File])
 | |
| 	).
 | |
| 
 | |
| ok_file(File, OkFile) :-
 | |
| 	file_base_name(File, BaseFile),
 | |
| 	file_name_extension(Base, _, BaseFile),
 | |
| 	file_directory_name(File, Dir),
 | |
| 	atomic_list_concat([Dir, /, ok, /, Base, '.ok'], OkFile).
 | |
| 
 | |
| 
 | |
| save_triples([], _).
 | |
| save_triples([H|T], Fd) :-
 | |
| 	format(Fd, '~q.~n', [H]),
 | |
| 	save_triples(T, Fd).
 | |
| 
 | |
| read_triples(Fd, Terms) :-
 | |
| 	read(Fd, T0),
 | |
| 	read_triples(T0, Fd, Terms).
 | |
| 
 | |
| read_triples(end_of_file, _, []) :- !.
 | |
| read_triples(rdf(S0,P0,O0), Fd, [rdf(S,P,O)|R]) :-
 | |
| 	global_ref(S0, S),
 | |
| 	global_ref(P0, P),
 | |
| 	global_obj(O0, O),
 | |
| 	read(Fd, T1),
 | |
| 	read_triples(T1, Fd, R).
 | |
| 
 | |
| global_ref(rdf:Local, Global) :-
 | |
| 	rdf_name_space(NS), !,
 | |
| 	atom_concat(NS, Local, Global).
 | |
| global_ref(NS:Local, Global) :- !,
 | |
| 	atom_concat(NS, Local, Global).
 | |
| global_ref(URI, URI).
 | |
| 
 | |
| global_obj(literal(X), literal(X)) :- !.
 | |
| global_obj(Local, Global) :-
 | |
| 	global_ref(Local, Global).
 | |
| 
 | |
| 
 | |
| write_triples([]) :- !.
 | |
| write_triples([H|T]) :- !,
 | |
| 	write_triple(H),
 | |
| 	write_triples(T).
 | |
| 
 | |
| write_triple(Triple) :-
 | |
| 	is_rdf_triple(Triple), !,
 | |
| 	Triple = rdf(S,P,O),
 | |
| 	format('{~q, ~q, ~q}~n', [S,P,O]).
 | |
| write_triple(Triple) :-
 | |
| 	format('@@@@@ Bad Triple: ~p~n', [Triple]),
 | |
| 	fail.
 | |
| 
 | |
| cat(File) :-
 | |
| 	open(File, read, Fd),
 | |
| 	copy_stream_data(Fd, user_output),
 | |
| 	close(Fd).
 | |
| 
 | |
| :- dynamic triple/1.
 | |
| 
 | |
| process_rdf(File, Triples) :-
 | |
| 	retractall(triple(_)),
 | |
| 	process_rdf(File, assert_triples, []),
 | |
| 	findall(T, retract(triple(T)), Triples).
 | |
| 
 | |
| assert_triples([], _).
 | |
| assert_triples([H|T], Loc) :-
 | |
| 	assert(triple(H)),
 | |
| 	assert_triples(T, Loc).
 | |
| 
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	      VALIDATE		*
 | |
| 		 *******************************/
 | |
| 
 | |
| is_rdf_triple(rdf(Subject, Predicate, Object)) :-
 | |
| 	is_subject(Subject),
 | |
| 	is_predicate(Predicate),
 | |
| 	is_object(Object).
 | |
| 
 | |
| is_subject(0) :- !, fail.		% Variables
 | |
| is_subject(URI) :- is_uri(URI), !.
 | |
| is_subject(each(URI)) :- is_uri(URI), !.
 | |
| is_subject(prefix(Pattern)) :-
 | |
| 	atom(Pattern), !.
 | |
| 
 | |
| is_predicate(0) :- !, fail.
 | |
| is_predicate(rdf:RdfPred) :- !,
 | |
| 	is_rdf_predicate(RdfPred).
 | |
| is_predicate(NS:Pred) :- !,
 | |
| 	atom(NS),
 | |
| 	atom(Pred).
 | |
| is_predicate(Pred) :-
 | |
| 	atom(Pred).
 | |
| 
 | |
| is_object(0) :- !,
 | |
| 	fail.
 | |
| is_object(literal(XML)) :- !,
 | |
| 	is_xml(XML).
 | |
| is_object(rdf:RdfType) :- !,
 | |
| 	is_rdf_type(RdfType).
 | |
| is_object(URI) :-
 | |
| 	is_uri(URI).
 | |
| 
 | |
| is_object(Subject) :-
 | |
| 	is_subject(Subject), !.
 | |
| is_object(Pred) :-
 | |
| 	is_predicate(Pred), !.
 | |
| 
 | |
| is_uri(URI) :- atom(URI).
 | |
| 
 | |
| is_xml(_XML). % for now
 | |
| 
 | |
| is_rdf_predicate(RdfPred) :- atom(RdfPred).
 | |
| 
 | |
| is_rdf_type(RdfType) :- atom(RdfType).
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	       UTIL		*
 | |
| 		 *******************************/
 | |
| 
 | |
| %	find_rdf(+XMLTerm, -RDFTerm)
 | |
| %
 | |
| %	If the document contains an embedded RDF term, return it, else
 | |
| %	return the whole document.  The latter is a bit dubious, but good
 | |
| %	for the purpose of this test-file
 | |
| 
 | |
| find_rdf(Term, RDFTerm) :-
 | |
| 	RDFTerm = element(NS:'RDF', _, _),
 | |
| 	term_member(RDFTerm, Term), !,
 | |
| 	(   rdf_name_space(NS)
 | |
| 	->  true
 | |
| 	;   assert(rdf_parser:rdf_name_space(NS)),
 | |
| 	    assert(new_rdf_namespace(NS))
 | |
| 	).
 | |
| find_rdf(Term, Term).
 | |
| 
 | |
| term_member(X, X).
 | |
| term_member(X, Compound) :-
 | |
| 	compound(Compound),
 | |
| 	arg(_, Compound, Arg),
 | |
| 	term_member(X, Arg).
 | |
| 
 | |
| 
 | |
| 		 /*******************************
 | |
| 		 *	    SHOW DIAGRAM	*
 | |
| 		 *******************************/
 | |
| 
 | |
| show_ok(Test) :-
 | |
| 	ok_file(Test, File),
 | |
| 	open(File, read, Fd, [encoding(utf8)]),
 | |
| 	read_triples(Fd, OkTriples),
 | |
| 	close(Fd),
 | |
| 	new(D, rdf_diagram(string('Ok for %s', File))),
 | |
| 	send(D, triples, OkTriples),
 | |
| 	send(D, open).
 | |
| 
 |