Chris@0: /* $Id$ Chris@0: Chris@0: Part of SWI-Prolog Chris@0: Chris@0: Author: Jan Wielemaker Chris@0: E-mail: wielemak@science.uva.nl Chris@0: WWW: http://www.swi-prolog.org Chris@0: Copyright (C): 2004-2006, University of Amsterdam Chris@0: Chris@0: This program is free software; you can redistribute it and/or Chris@0: modify it under the terms of the GNU General Public License Chris@0: as published by the Free Software Foundation; either version 2 Chris@0: of the License, or (at your option) any later version. Chris@0: Chris@0: This program is distributed in the hope that it will be useful, Chris@0: but WITHOUT ANY WARRANTY; without even the implied warranty of Chris@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Chris@0: GNU General Public License for more details. Chris@0: Chris@0: You should have received a copy of the GNU Lesser General Public Chris@0: License along with this library; if not, write to the Free Software Chris@0: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Chris@0: Chris@0: As a special exception, if you link this library with other files, Chris@0: compiled with a Free Software compiler, to produce an executable, this Chris@0: library does not by itself cause the resulting executable to be covered Chris@0: by the GNU General Public License. This exception does not however Chris@0: invalidate any other reasons why the executable file might be covered by Chris@0: the GNU General Public License. Chris@0: */ Chris@0: Chris@0: :- module(test_manifest, Chris@0: [ current_manifest/1, % ?Manifest Chris@0: current_test/2, % ?Manifest, ?Test Chris@0: Chris@0: test_name/2, % ?Test, ?Name Chris@0: test_query/2, % +Test, -QueryCodes Chris@0: Chris@0: test_query_file/2, % +Test, -QueryFile Chris@0: test_data_file/2, % +Test, -DataFile Chris@0: test_result_file/2, % +Test, -ResultFile Chris@0: Chris@0: % EDIT Chris@0: show_test/1, % NameOrURL Chris@0: edit_test/1, % NameOrURL Chris@0: show_test_data/1, % NameOrURL Chris@0: edit_test_data/1, % NameOrURL Chris@0: edit_test_result/1, % NameOrURL Chris@0: Chris@0: % LOAD Chris@0: load_manifests/1, % +RootManifest Chris@0: Chris@0: % UTIL Chris@0: load_triples_to_db/1, % +FileOrURL Chris@0: load_triples/2, % +FileOrURL, -Triples Chris@0: file_url/2 % ?File, ?URL Chris@0: ]). Chris@0: :- use_module(library(rdf)). Chris@0: :- use_module(library(url)). Chris@0: :- use_module(library('semweb/rdf_db')). Chris@0: :- use_module(library('semweb/rdfs')). Chris@0: :- use_module(rdf_turtle). Chris@0: Chris@0: :- dynamic Chris@0: mf_rdf/3. Chris@0: :- rdf_meta Chris@0: mf_rdf(r, r, o). Chris@0: Chris@0: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@0: Generic code to deal with W3C/Semantic web test manifests. These are RDF Chris@0: files in either RDF/XML or Turtle format. Chris@0: Chris@0: As we have to do reasoning on the complete graph and frequently clear Chris@0: the graph during testing we keep the triples for the manifest in the Chris@0: Prolog database as mf_rdf(S,P,O). Chris@0: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ Chris@0: Chris@0: Chris@0: % namespaces used to process the manifests and test suite. Chris@0: :- rdf_register_ns(mf, Chris@0: 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#'). Chris@0: :- rdf_register_ns(mfx, Chris@0: 'http://jena.hpl.hp.com/2005/05/test-manifest-extra#'). Chris@0: :- rdf_register_ns(qt, Chris@0: 'http://www.w3.org/2001/sw/DataAccess/tests/test-query#'). Chris@0: :- rdf_register_ns(r, Chris@0: 'http://www.w3.org/2001/sw/DataAccess/tests/result-set#'). Chris@0: Chris@0: % namespaces used in some of the test-suites to enhance readability. Chris@0: :- rdf_register_ns(tbool, Chris@0: 'http://www.w3.org/2001/sw/DataAccess/tests/data/ValueTesting/boolean-0#'). Chris@0: :- rdf_register_ns(texttype, Chris@0: 'http://www.w3.org/2001/sw/DataAccess/tests/data/ValueTesting/extendedType-0#'). Chris@0: :- rdf_register_ns(tpromote, 'http://www.w3.org/2001/sw/DataAccess/tests/data/ValueTesting/typePromotion-0#'). Chris@0: :- rdf_register_ns(ex, 'http://example.org/#'). Chris@0: Chris@0: Chris@0: data_dir('Tests/sparql/data-xml'). Chris@0: Chris@0: Chris@0: /******************************* Chris@0: * QUERY * Chris@0: *******************************/ Chris@0: Chris@0: %% current_manifest(?Manifest) Chris@0: % Chris@0: % True if Manifest is a test-manifest Chris@0: Chris@0: current_manifest(Manifest) :- Chris@0: mf_rdf(Manifest, rdf:type, mf:'Manifest'). Chris@0: Chris@0: %% current_test(?Manifest, ?Test) Chris@0: % Chris@0: % True if Test is a test in Manifest. Chris@0: Chris@0: current_test(Manifest, Test) :- Chris@0: current_manifest(Manifest), Chris@0: mf_rdf(Manifest, mf:entries, Collection), Chris@0: mf_member(Test, Collection). Chris@0: Chris@0: Chris@0: %% test_name(?Test, ?Name) Chris@0: % Chris@0: % True if Name is the name associated with Test. Chris@0: Chris@0: test_name(Test, Name) :- Chris@0: var(Test), var(Name), !, Chris@0: mf_rdf(Test, mf:name, literal(Name)). Chris@0: test_name(Test, Name) :- Chris@0: mf_rdf(Test, mf:name, literal(Name)), !. Chris@0: Chris@0: Chris@0: %% test_query_file(+Test, -File) Chris@0: % Chris@0: % Get the file containing the query of Test Chris@0: Chris@0: test_query_file(Test, File) :- % Normal cases Chris@0: mf_rdf(Test, mf:action, Action), Chris@0: mf_rdf(Action, qt:query, FileURI), Chris@0: parse_url(FileURI, Parts), !, Chris@0: memberchk(path(File), Parts). Chris@0: test_query_file(Test, File) :- % SyntaxDev cases Chris@0: mf_rdf(Test, mf:action, FileURI), Chris@0: parse_url(FileURI, Parts), !, Chris@0: memberchk(path(File), Parts). Chris@0: Chris@0: Chris@0: %% test_data_file(+Test, -File) Chris@0: % Chris@0: % Get the file containing the data for Test Chris@0: Chris@0: test_data_file(Test, File) :- Chris@0: mf_rdf(Test, mf:action, Action), Chris@0: mf_rdf(Action, qt:data, FileURI), Chris@0: parse_url(FileURI, Parts), !, Chris@0: memberchk(path(File), Parts). Chris@0: Chris@0: Chris@0: %% test_result_file(+Test, -File) Chris@0: % Chris@0: % Test containg the result Chris@0: Chris@0: test_result_file(Test, File) :- Chris@0: mf_rdf(Test, mf:result, FileURI), Chris@0: parse_url(FileURI, Parts), !, Chris@0: memberchk(path(File), Parts). Chris@0: Chris@0: Chris@0: %% test_query(+Test, -QueryCodes) Chris@0: Chris@0: test_query(Test, Codes) :- Chris@0: test_query_file(Test, File), !, Chris@0: read_file_to_codes(File, Codes, []). Chris@0: test_query(Test, _) :- Chris@0: format('Cannot get query for test ~q~n', [Test]), Chris@0: fail. Chris@0: Chris@0: Chris@0: /******************************* Chris@0: * LIST/EDIT * Chris@0: *******************************/ Chris@0: Chris@0: show_test(Name) :- Chris@0: test_name(Test, Name), !, Chris@0: show_test(Test). Chris@0: show_test(Test) :- Chris@0: test_query(Test, Codes), Chris@0: format('~s', [Codes]). Chris@0: Chris@0: Chris@0: edit_test(Name) :- Chris@0: test_name(Test, Name), !, Chris@0: edit_test(Test). Chris@0: edit_test(Test) :- Chris@0: test_query_file(Test, File), Chris@0: edit(file(File)). Chris@0: Chris@0: show_test_data(Name) :- Chris@0: test_name(Test, Name), !, Chris@0: show_test_data(Test). Chris@0: show_test_data(Test) :- Chris@0: test_data_file(Test, File), Chris@0: read_file_to_codes(File, Codes, []), Chris@0: format('~s', [Codes]). Chris@0: Chris@0: edit_test_data(Name) :- Chris@0: test_name(Test, Name), !, Chris@0: edit_test_data(Test). Chris@0: edit_test_data(Test) :- Chris@0: test_data_file(Test, File), Chris@0: edit(file(File)). Chris@0: Chris@0: edit_test_result(Name) :- Chris@0: test_name(Test, Name), !, Chris@0: edit_test_result(Test). Chris@0: edit_test_result(Test) :- Chris@0: test_result_file(Test, File), Chris@0: edit(file(File)). Chris@0: Chris@0: Chris@0: /************a******************* Chris@0: * LOAD MANIFEST * Chris@0: *******************************/ Chris@0: Chris@0: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Chris@0: TBD: This should move in the generic semantic libraries, connected to Chris@0: the core using a plugin extension mechanism. Chris@0: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ Chris@0: Chris@0: %% load_manifests(+RootOrAlias) Chris@0: % Chris@0: % Load the manifest files Chris@0: Chris@0: load_manifests(dawg) :- !, Chris@0: data_dir(Dir), Chris@0: atom_concat(Dir, '/manifest.{ttl,rdf}', Pattern), Chris@0: expand_file_name(Pattern, [File]), Chris@0: file_url(File, URL), Chris@0: load_manifests(URL). Chris@0: load_manifests(arq) :- !, Chris@0: file_url('../ARQ/testing/ARQ/manifest-arq.ttl', URL), Chris@0: load_manifests(URL). Chris@0: load_manifests(Root) :- Chris@0: retractall(mf_rdf(_,_,_)), Chris@0: rdf_reset_db, Chris@0: load_schemas, Chris@0: load_manifest(Root), Chris@0: forall(rdf(S,P,O), assert(mf_rdf(S,P,O))), Chris@0: rdf_reset_db, Chris@0: test_statistics. Chris@0: Chris@0: test_statistics :- Chris@0: findall(M, current_manifest(M), Ms), Chris@0: length(Ms, MN), Chris@0: findall(T, current_test(_, T), Ts), Chris@0: length(Ts, TN), Chris@0: format('Loaded ~D manifests with ~D tests~n', [MN, TN]). Chris@0: Chris@0: load_schemas :- Chris@0: data_dir(Dir), Chris@0: atom_concat(Dir, '/test-manifest.rdf', S1), Chris@0: atom_concat(Dir, '/test-dawg.rdf', S2), Chris@0: atom_concat(Dir, '/test-query.rdf', S3), Chris@0: maplist(load_triples_to_db, [S1,S2,S3]). Chris@0: Chris@0: load_manifest(URL) :- Chris@0: format('Loading ~w ...~n', [URL]), Chris@0: load_triples_to_db(URL), Chris@0: sub_manifests(URL, SubManifests), Chris@0: forall(member(S, SubManifests), Chris@0: load_manifest(S)). Chris@0: Chris@0: sub_manifests(URL, List) :- Chris@0: rdf(URL, mfx:include, Collection), !, Chris@0: findall(S, rdfs_member(S, Collection), List). Chris@0: sub_manifests(_, []). Chris@0: Chris@0: Chris@0: Chris@0: /******************************* Chris@0: * LOAD FILES * Chris@0: *******************************/ Chris@0: Chris@0: %% load_triples_to_db(+File) Chris@0: % Chris@0: % Load triples from a file into a the RDF database Chris@0: Chris@0: load_triples_to_db(URL) :- Chris@0: file_url(File, URL), !, Chris@0: load_triples_to_db(File). Chris@0: load_triples_to_db(File) :- Chris@0: file_name_extension(_, Ext, File), Chris@0: ( load_triples_to_db(Ext, File) Chris@0: -> true Chris@0: ; assert(user:load_failed(File)) Chris@0: ). Chris@0: Chris@0: load_triples_to_db(rdf, File) :- !, % RDF/XML Chris@0: rdf_load(File, [silent(true)]). Chris@0: load_triples_to_db(ttl, File) :- !, % Turtle Chris@0: absolute_file_name(File, Path), Chris@0: rdf_load_turtle_file(File, Triples, []), Chris@0: maplist(assert_triple(Path), Triples). Chris@0: load_triples_to_db(n3, File) :- !, % Turtle Chris@0: absolute_file_name(File, Path), Chris@0: rdf_load_turtle_file(File, Triples, []), Chris@0: maplist(assert_triple(Path), Triples). Chris@0: Chris@0: assert_triple(DB, rdf(S,P,O)) :- Chris@0: rdf_assert(S,P,O, DB). Chris@0: Chris@0: %% load_triples(+File, -RDFList) Chris@0: % Chris@0: % Load file into a list of rdf(S,P,O) terms Chris@0: Chris@0: load_triples(File, Triples) :- Chris@0: file_name_extension(_, Ext, File), Chris@0: load_triples(Ext, File, Triples). Chris@0: Chris@0: load_triples(rdf, File, Triples) :- !, Chris@0: load_rdf(File, Triples). Chris@0: load_triples(ttl, File, Triples) :- !, Chris@0: rdf_load_turtle_file(File, Triples, []). Chris@0: Chris@0: Chris@0: /******************************* Chris@0: * URL * Chris@0: *******************************/ Chris@0: Chris@0: file_url(File, URL) :- Chris@0: ground(File), !, Chris@0: absolute_file_name(File, Path), Chris@0: atom_concat('file://', Path, URL). Chris@0: file_url(File, URL) :- Chris@0: atom_concat('file://', File, URL). Chris@0: Chris@0: Chris@0: /******************************* Chris@0: * UTIL * Chris@0: *******************************/ Chris@0: Chris@0: mf_member(Element, Set) :- Chris@0: mf_rdf(Set, rdf:first, Element). Chris@0: mf_member(Element, Set) :- Chris@0: mf_rdf(Set, rdf:rest, Tail), Chris@0: mf_member(Element, Tail).