/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.reasoner.test;
import java.io.*;
import java.util.Iterator;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.jena.rdf.model.* ;
import org.apache.jena.reasoner.* ;
import org.apache.jena.reasoner.ValidityReport.Report ;
import org.apache.jena.reasoner.rulesys.RDFSFBRuleReasonerFactory ;
import org.apache.jena.reasoner.rulesys.RDFSRuleReasonerFactory ;
import org.apache.jena.vocabulary.* ;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Test the set of admissable RDFS reasoners.
*/
public class TestRDFSReasoners extends ReasonerTestBase {
/** Base URI for the test names */
public static final String NAMESPACE = "http://www.hpl.hp.com/semweb/2003/query_tester/";
protected static Logger logger = LoggerFactory.getLogger(TestReasoners.class);
/**
* Boilerplate for junit
*/
public TestRDFSReasoners( String name ) {
super( name );
}
/**
* Boilerplate for junit.
* This is its own test suite
*/
public static TestSuite suite() {
TestSuite suite = new TestSuite();
try {
// FB reasoner doesn't support validation so the full set of wg tests are
// commented out
// constructRDFWGtests(suite, RDFSFBRuleReasonerFactory.theInstance(), null);
constructQuerytests(suite, "rdfs/manifest-nodirect-noresource.rdf", RDFSFBRuleReasonerFactory.theInstance(), null);
Resource config = newResource().addProperty(ReasonerVocabulary.PROPenableCMPScan, "true" ); // TODO make boolean value work
// config.addProperty(ReasonerVocabulary.PROPtraceOn, true);
constructRDFWGtests(suite, RDFSRuleReasonerFactory.theInstance(), null);
constructQuerytests(suite, "rdfs/manifest-standard.rdf", RDFSRuleReasonerFactory.theInstance(), config);
suite.addTest(new TestRDFSMisc(RDFSRuleReasonerFactory.theInstance(), null));
Resource configFull = newResource().addProperty(ReasonerVocabulary.PROPsetRDFSLevel, ReasonerVocabulary.RDFS_FULL);
constructQuerytests(suite, "rdfs/manifest.rdf", RDFSRuleReasonerFactory.theInstance(), configFull);
// This test was needed for the brief time the rdfs12 rules might have been in the standard
// That's no longer true but left comment out because we might want them for OWL someday
// constructQuerytests(suite, "rdfs/manifest-rdfs12.rdf", RDFSRuleReasonerFactory.theInstance(), configFull);
Resource configSimple = newResource().addProperty(ReasonerVocabulary.PROPsetRDFSLevel, ReasonerVocabulary.RDFS_SIMPLE);
constructQuerytests(suite, "rdfs/manifest-simple.rdf", RDFSRuleReasonerFactory.theInstance(), configSimple);
// Single test case used in debugging, subsumed by above
// constructSingleQuerytests(suite,
// "rdfs/manifest.rdf",
// "http://www.hpl.hp.com/semweb/2003/query_tester/rdfs/test13",
// RDFSRuleReasonerFactory.theInstance(),
// configFull);
} catch (IOException e) {
// failed to even built the test harness
logger.error("Failed to construct RDFS test harness", e);
}
return suite;
}
/**
* Build a single named query test
*/
private static void constructSingleQuerytests(TestSuite suite, String manifest, String test, ReasonerFactory rf, Resource config) throws IOException {
ReasonerTester tester = new ReasonerTester(manifest);
Reasoner r = rf.create(config);
suite.addTest(new TestReasonerFromManifest(tester, test, r));
}
/**
* Build the query tests for the given reasoner.
*/
private static void constructQuerytests(TestSuite suite, String manifest, ReasonerFactory rf, Resource config) throws IOException {
ReasonerTester tester = new ReasonerTester(manifest);
Reasoner r = rf.create(config);
for ( String test : tester.listTests() )
{
suite.addTest( new TestReasonerFromManifest( tester, test, r ) );
}
}
/**
* Build the working group tests for the given reasoner.
*/
private static void constructRDFWGtests(TestSuite suite, ReasonerFactory rf, Resource config) throws IOException {
WGReasonerTester tester = new WGReasonerTester("Manifest.rdf");
for ( String test : tester.listTests() )
{
suite.addTest( new TestReasonerWG( tester, test, rf, config ) );
}
}
/**
* Build the query tests for the given reasoner.
*/
public static void constructQuerytests(TestSuite suite, String manifest, Reasoner reasoner) throws IOException {
ReasonerTester tester = new ReasonerTester(manifest);
for ( String test : tester.listTests() )
{
suite.addTest( new TestReasonerFromManifest( tester, test, reasoner ) );
}
}
/**
* Inner class defining a test framework for invoking a single locally
* defined query-over-inference test.
*/
static class TestReasonerFromManifest extends TestCase {
/** The tester which already has the test manifest loaded */
ReasonerTester tester;
/** The name of the specific test to run */
String test;
/** The factory for the reasoner type under test */
Reasoner reasoner;
/** Constructor */
TestReasonerFromManifest(ReasonerTester tester, String test, Reasoner reasoner) {
super(test);
this.tester = tester;
this.test = test;
this.reasoner = reasoner;
}
/**
* The test runner
*/
@Override
public void runTest() throws IOException {
tester.runTest(test, reasoner, this);
}
}
/**
* Inner class defining a test framework for invoking a single
* RDFCore working group test.
*/
static class TestReasonerWG extends TestCase {
/** The tester which already has the test manifest loaded */
WGReasonerTester tester;
/** The name of the specific test to run */
String test;
/** The factory for the reasoner type under test */
ReasonerFactory reasonerFactory;
/** An optional configuration model */
Resource config;
/** Constructor */
TestReasonerWG(WGReasonerTester tester, String test,
ReasonerFactory reasonerFactory, Resource config) {
super(test);
this.tester = tester;
this.test = test;
this.reasonerFactory = reasonerFactory;
this.config = config;
}
/**
* The test runner
*/
@Override
public void runTest() throws IOException {
tester.runTest(test, reasonerFactory, this, config);
}
}
/**
* Inner class defining the misc extra tests needed to check out a
* candidate RDFS reasoner.
*/
static class TestRDFSMisc extends TestCase {
/** The factory for the reasoner type under test */
ReasonerFactory reasonerFactory;
/** An optional configuration model */
Resource config;
/** Constructor */
TestRDFSMisc(ReasonerFactory reasonerFactory, Resource config) {
super("TestRDFSMisc");
this.reasonerFactory = reasonerFactory;
this.config = config;
}
/**
* The test runner
*/
@Override
public void runTest() throws IOException {
ReasonerTester tester = new ReasonerTester("rdfs/manifest.rdf");
// Test effect of switching off property scan - should break container property test case
Resource configuration = newResource();
if (config != null) {
for (StmtIterator i = config.listProperties(); i.hasNext();) {
Statement s = i.nextStatement();
configuration.addProperty(s.getPredicate(), s.getObject());
}
}
configuration.addProperty(ReasonerVocabulary.PROPenableCMPScan, "false");
assertTrue("scanproperties off",
!tester.runTest(NAMESPACE + "rdfs/test17", reasonerFactory, null, configuration));
// Check capabilities description
Reasoner r = reasonerFactory.create(null);
assertTrue(r.supportsProperty(RDFS.subClassOf));
assertTrue(r.supportsProperty(RDFS.domain));
assertTrue(r.supportsProperty(RDFS.range));
// Datatype tests
assertTrue( ! doTestRDFSDTRange("dttest1.nt", reasonerFactory));
assertTrue( ! doTestRDFSDTRange("dttest2.nt", reasonerFactory));
assertTrue( doTestRDFSDTRange("dttest3.nt", reasonerFactory));
}
/**
* Helper for dt range testing - loads a file, validates it using RDFS/DT
* and returns error status of the result
*/
private boolean doTestRDFSDTRange(String file, ReasonerFactory rf) throws IOException {
String langType = "RDF/XML";
if (file.endsWith(".nt")) {
langType = "N-TRIPLE";
} else if (file.endsWith("n3")) {
langType = "N3";
}
Model m = ModelFactory.createDefaultModel();
Reader reader = new BufferedReader(new FileReader("testing/reasoners/rdfs/"+file));
m.read(reader, WGReasonerTester.BASE_URI + file, langType);
InfGraph g = rf.create(null).bind(m.getGraph());
ValidityReport report = g.validate();
if (!report.isValid()) {
logger.debug("Validation error report:");
for (Iterator<Report> i = report.getReports(); i.hasNext(); ) {
logger.debug(i.next().toString());
}
}
return report.isValid();
}
}
}