/*
* 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.graph;
import static org.apache.jena.testing_framework.GraphHelper.assertContainsAll ;
import static org.apache.jena.testing_framework.GraphHelper.assertIsomorphic ;
import static org.apache.jena.testing_framework.GraphHelper.assertOmitsAll ;
import static org.apache.jena.testing_framework.GraphHelper.graphAddTxn ;
import static org.apache.jena.testing_framework.GraphHelper.graphWith ;
import static org.apache.jena.testing_framework.GraphHelper.iteratorToSet ;
import static org.apache.jena.testing_framework.GraphHelper.memGraph ;
import static org.apache.jena.testing_framework.GraphHelper.node ;
import static org.apache.jena.testing_framework.GraphHelper.nodeSet ;
import static org.apache.jena.testing_framework.GraphHelper.triple ;
import static org.apache.jena.testing_framework.GraphHelper.tripleArray ;
import static org.apache.jena.testing_framework.GraphHelper.tripleSet ;
import static org.apache.jena.testing_framework.GraphHelper.txnBegin ;
import static org.apache.jena.testing_framework.GraphHelper.txnCommit ;
import static org.apache.jena.testing_framework.GraphHelper.txnRollback ;
import static org.apache.jena.testing_framework.TestUtils.assertDiffer ;
import static org.junit.Assert.assertEquals ;
import static org.junit.Assert.assertFalse ;
import static org.junit.Assert.assertNotEquals ;
import static org.junit.Assert.assertNotNull ;
import static org.junit.Assert.assertSame ;
import static org.junit.Assert.assertTrue ;
import static org.junit.Assert.fail ;
import java.io.InputStream ;
import java.net.MalformedURLException ;
import java.net.URISyntaxException ;
import java.util.Arrays ;
import java.util.Iterator ;
import java.util.List ;
import java.util.Set ;
import java.util.function.Function ;
import org.apache.jena.graph.impl.LiteralLabelFactory ;
import org.apache.jena.mem.TrackingTripleIterator ;
import org.apache.jena.rdf.model.Model ;
import org.apache.jena.rdf.model.ModelFactory ;
import org.apache.jena.rdf.model.impl.ReifierStd ;
import org.apache.jena.shared.ClosedException ;
import org.apache.jena.shared.DeleteDeniedException ;
import org.apache.jena.shared.PrefixMapping ;
import org.apache.jena.testing_framework.AbstractGraphProducer ;
import org.apache.jena.testing_framework.NodeCreateUtils ;
import org.apache.jena.util.iterator.ClosableIterator ;
import org.apache.jena.util.iterator.ExtendedIterator ;
import org.junit.After ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
import org.xenei.junit.contract.Contract ;
import org.xenei.junit.contract.ContractTest ;
/**
* Graph contract test.
*/
@Contract(Graph.class)
public class GraphContractTest<T extends Graph> {
private static final Logger LOG = LoggerFactory
.getLogger(GraphContractTest.class);
private AbstractGraphProducer<T> producer;
protected RecordingGraphListener GL = new RecordingGraphListener();
@Contract.Inject
public final void setGraphContractTestProducer(
AbstractGraphProducer<T> graphProducer) {
producer = graphProducer;
}
@After
public final void afterGraphContractTest() {
producer.cleanUp();
GL.clear();
}
@ContractTest
public void testAdd_Triple() {
Graph graph = producer.newInstance();
graph.getEventManager().register(GL);
txnBegin(graph);
graph.add(triple("S P O"));
txnCommit(graph);
GL.assertHasStart("add", graph, triple("S P O"));
assertTrue("Graph should contain <S P O>",
graph.contains(triple("S P O")));
}
/**
* Inference graphs can not be truly empty.
*
* @param g
* @param b
*/
private void assertEmpty(Graph g, Graph b) {
if (b.isEmpty()) {
assertTrue("Graph should be empty", g.isEmpty());
} else {
assertEquals("Graph should be in base state", b.find(Triple.ANY)
.toList(), g.find(Triple.ANY).toList());
}
}
/**
* Inference graphs can not be truly empty
*
* @param g
* @param b
*/
private void assertNotEmpty(Graph g, Graph b) {
if (b.isEmpty()) {
assertFalse("Graph not should be empty", g.isEmpty());
} else {
assertNotEquals("Graph should not be in base state",
b.find(Triple.ANY).toList(), g.find(Triple.ANY).toList());
}
}
/**
* Test that clear works, in the presence of inferencing graphs that mean
* emptyness isn't available. This is why we go round the houses and test
* that expected ~= initialContent + addedStuff - removed - initialContent.
*/
@ContractTest
public void testClear() {
Graph graph = producer.newInstance();
Graph base = copy(graph);
graph.getEventManager().register(GL);
txnBegin(graph);
graph.clear();
txnCommit(graph);
assertEmpty(graph, base);
GL.assertHasStart("someEvent", graph, GraphEvents.removeAll);
GL.clear();
// test after adding
graph = graphWith(producer.newInstance(),
"S P O; S e:ff 27; _1 P P3; S4 P4 'en'");
graph.getEventManager().register(GL);
txnBegin(graph);
graph.clear();
txnCommit(graph);
assertEmpty(graph, base);
if (GL.contains("delete")) {
// deletes are listed -- ensure all deletes are listed
GL.assertContains("delete", graph, triple("S P O"));
GL.assertContains("delete", graph, triple("S e:ff 27"));
GL.assertContains("delete", graph, triple("_1 P P3"));
GL.assertContains("delete", graph, triple("S4 P4 'en'"));
}
GL.assertHasEnd("someEvent", graph, GraphEvents.removeAll);
GL.clear();
}
@ContractTest
public void testClose() {
Graph graph = graphWith(producer.newInstance(),
"S P O; S P2 O2; S3 P P3");
graph.getEventManager().register(GL);
assertFalse("Graph was constructed closed", graph.isClosed());
graph.close();
assertTrue("Graph should be closed", graph.isClosed());
// exception may be thrown on begin or on execution.
try {
txnBegin(graph);
try {
graph.add(triple("S P O"));
fail("added when closed");
} catch (Exception expected) {
GL.assertEmpty();
// expected
} finally {
txnRollback(graph);
}
} catch (Exception expected) {
GL.assertEmpty();
// expected
}
try {
txnBegin(graph);
try {
graph.delete(triple("x R y"));
fail("delete when closed");
} catch (ClosedException c) {
// Expected
} finally {
txnRollback(graph);
GL.assertEmpty();
}
} catch (Exception expected) {
GL.assertEmpty();
// expected
}
try {
txnBegin(graph);
try {
graph.add(triple("x R y"));
fail("add when closed");
} catch (ClosedException c) { /* as required */
} finally {
txnRollback(graph);
GL.assertEmpty();
}
} catch (Exception expected) {
GL.assertEmpty();
// expected
}
try {
txnBegin(graph);
try {
graph.contains(triple("x R y"));
fail("contains[triple] when closed");
} catch (ClosedException c) { /* as required */
} finally {
txnRollback(graph);
GL.assertEmpty();
}
} catch (Exception expected) {
GL.assertEmpty();
// expected
}
try {
txnBegin(graph);
try {
graph.contains(Node.ANY, Node.ANY, Node.ANY);
fail("contains[SPO] when closed");
} catch (ClosedException c) { /* as required */
} finally {
txnRollback(graph);
GL.assertEmpty();
}
} catch (Exception expected) {
GL.assertEmpty();
// expected
}
try {
txnBegin(graph);
try {
graph.find(triple("x R y"));
fail("find [triple] when closed");
} catch (ClosedException c) { /* as required */
} finally {
txnRollback(graph);
GL.assertEmpty();
}
} catch (Exception expected) {
GL.assertEmpty();
// expected
}
try {
txnBegin(graph);
try {
graph.find(Node.ANY, Node.ANY, Node.ANY);
fail("find[SPO] when closed");
} catch (ClosedException c) { /* as required */
} finally {
txnRollback(graph);
GL.assertEmpty();
}
} catch (Exception expected) {
GL.assertEmpty();
// expected
}
try {
txnBegin(graph);
try {
graph.size();
fail("size when closed (" + this.getClass() + ")");
} catch (ClosedException c) { /* as required */
} finally {
txnRollback(graph);
GL.assertEmpty();
}
} catch (Exception expected) {
GL.assertEmpty();
// expected
}
}
@ContractTest
public void testContains_Node_Node_Node() {
Graph graph = graphWith(producer.newInstance(),
"S P O; S2 P2 O2; S3 P3 O3");
assertTrue(graph.contains(node("S"), node("P"), node("O")));
assertFalse(graph.contains(node("S"), node("P"), node("O2")));
assertFalse(graph.contains(node("S"), node("P2"), node("O")));
assertFalse(graph.contains(node("S2"), node("P"), node("O")));
assertTrue(graph.contains(Node.ANY, Node.ANY, Node.ANY));
assertTrue(graph.contains(Node.ANY, Node.ANY, node("O")));
assertTrue(graph.contains(Node.ANY, node("P"), Node.ANY));
assertTrue(graph.contains(node("S"), Node.ANY, Node.ANY));
}
@ContractTest
public void testContains_Node_Node_Node_RepeatedSubjectDoesNotConceal() {
Graph g = graphWith(producer.newInstance(), "s P o; s Q r");
Node s = node("s");
Node P = node("P");
Node o = node("o");
Node Q = node("Q");
Node r = node("r");
Node any = node("??");
assertTrue(g.contains(s, P, o));
assertTrue(g.contains(s, Q, r));
assertTrue(g.contains(any, P, o));
assertTrue(g.contains(any, Q, r));
assertTrue(g.contains(any, P, any));
assertTrue(g.contains(any, Q, any));
}
@ContractTest
public void testContains_Node_Node_Node_ByValue() {
Node x = node("x");
Node P = node("P");
if (producer.newInstance().getCapabilities()
.handlesLiteralTyping()) {
Graph g1 = graphWith(producer.newInstance(),
"x P '1'xsd:integer");
assertTrue(
String.format(
"literal type equality failed, does %s really implement literal typing",
g1.getClass()), g1.contains(x, P,
node("'01'xsd:int")));
//
Graph g2 = graphWith(producer.newInstance(), "x P '1'xsd:int");
assertTrue("Literal equality with '1'xsd:integer failed",
g2.contains(x, P, node("'1'xsd:integer")));
//
Graph g3 = graphWith(producer.newInstance(),
"x P '123'xsd:string");
assertTrue("Literal equality with '123' failed",
g3.contains(x, P, node("'123'")));
}
}
@ContractTest
public void testContains_Node_Node_Node_Concrete() {
Node s = node("s");
Node P = node("P");
Node o = node("o");
Node _x = node("_x");
Node _R = node("_R");
Node _y = node("_y");
Node x = node("x");
Node S = node("S");
Graph g = graphWith(producer.newInstance(),
"s P o; _x _R _y; x S 0");
assertTrue("Graph should have contained s P o", g.contains(s, P, o));
assertTrue("Graph should have contained _x _R _y",
g.contains(_x, _R, _y));
assertTrue("Graph should have contained x S 'O'",
g.contains(x, S, node("0")));
/* */
assertFalse(g.contains(s, P, node("Oh")));
assertFalse(g.contains(S, P, node("O")));
assertFalse(g.contains(s, node("p"), o));
assertFalse(g.contains(_x, node("_r"), _y));
assertFalse(g.contains(x, S, node("1")));
}
@ContractTest
public void testContains_Node_Node_Node_Fluid() {
Node x = node("x");
Node R = node("R");
Node P = node("P");
Node y = node("y");
Node a = node("a");
Node b = node("b");
Graph g = graphWith(producer.newInstance(), "x R y; a P b");
assertTrue(g.contains(Node.ANY, R, y));
assertTrue(g.contains(x, Node.ANY, y));
assertTrue(g.contains(x, R, Node.ANY));
assertTrue(g.contains(Node.ANY, P, b));
assertTrue(g.contains(a, Node.ANY, b));
assertTrue(g.contains(a, P, Node.ANY));
assertTrue(g.contains(Node.ANY, R, y));
/* */
assertFalse(g.contains(Node.ANY, R, b));
assertFalse(g.contains(a, Node.ANY, y));
assertFalse(g.contains(x, P, Node.ANY));
assertFalse(g.contains(Node.ANY, R, x));
assertFalse(g.contains(x, Node.ANY, R));
assertFalse(g.contains(a, node("S"), Node.ANY));
}
@ContractTest
public void testContains_Triple() {
Graph graph = graphWith(producer.newInstance(),
"S P O; S2 P2 O2; S3 P3 O3");
assertTrue(graph.contains(triple("S P O")));
assertFalse(graph.contains(triple("S P O2")));
assertFalse(graph.contains(triple("S P2 O")));
assertFalse(graph.contains(triple("S2 P O")));
assertTrue(graph.contains(Triple.ANY));
assertTrue(graph.contains(new Triple(Node.ANY, Node.ANY, node("O"))));
assertTrue(graph.contains(new Triple(Node.ANY, node("P"), Node.ANY)));
assertTrue(graph.contains(new Triple(node("S"), Node.ANY, Node.ANY)));
}
@ContractTest
public void testContains_Triple_RepeatedSubjectDoesNotConceal() {
Graph g = graphWith(producer.newInstance(), "s P o; s Q r");
assertTrue(g.contains(triple("s P o")));
assertTrue(g.contains(triple("s Q r")));
assertTrue(g.contains(triple("?? P o")));
assertTrue(g.contains(triple("?? Q r")));
assertTrue(g.contains(triple("?? P ??")));
assertTrue(g.contains(triple("?? Q ??")));
}
@ContractTest
public void testContains_Triple_ByValue() {
if (producer.newInstance().getCapabilities()
.handlesLiteralTyping()) {
Graph g1 = graphWith(producer.newInstance(),
"x P '1'xsd:integer");
assertTrue(
String.format(
"did not find x P '01'xsd:int, does %s really implement literal typing",
g1.getClass()),
g1.contains(triple("x P '01'xsd:int")));
//
Graph g2 = graphWith(producer.newInstance(), "x P '1'xsd:int");
assertTrue("did not find x P '1'xsd:integer",
g2.contains(triple("x P '1'xsd:integer")));
//
Graph g3 = graphWith(producer.newInstance(),
"x P '123'xsd:string");
assertTrue("did not find x P '123'xsd:string",
g3.contains(triple("x P '123'")));
}
}
@ContractTest
public void testContains_Triple_Concrete() {
Graph g = graphWith(producer.newInstance(),
"s P o; _x _R _y; x S 0");
assertTrue(g.contains(triple("s P o")));
assertTrue(g.contains(triple("_x _R _y")));
assertTrue(g.contains(triple("x S 0")));
/* */
assertFalse(g.contains(triple("s P Oh")));
assertFalse(g.contains(triple("S P O")));
assertFalse(g.contains(triple("s p o")));
assertFalse(g.contains(triple("_x _r _y")));
assertFalse(g.contains(triple("x S 1")));
}
@ContractTest
public void testContains_Triple_Fluid() {
Graph g = graphWith(producer.newInstance(), "x R y; a P b");
assertTrue(g.contains(triple("?? R y")));
assertTrue(g.contains(triple("x ?? y")));
assertTrue(g.contains(triple("x R ??")));
assertTrue(g.contains(triple("?? P b")));
assertTrue(g.contains(triple("a ?? b")));
assertTrue(g.contains(triple("a P ??")));
assertTrue(g.contains(triple("?? R y")));
/* */
assertFalse(g.contains(triple("?? R b")));
assertFalse(g.contains(triple("a ?? y")));
assertFalse(g.contains(triple("x P ??")));
assertFalse(g.contains(triple("?? R x")));
assertFalse(g.contains(triple("x ?? R")));
assertFalse(g.contains(triple("a S ??")));
}
/**
* Inference graphs can not be empty
*/
@ContractTest
public void testDelete_Triple() {
Graph graph = graphWith(producer.newInstance(),
"S P O; S2 P2 O2; S3 P3 O3");
Graph base = producer.newInstance();
graph.getEventManager().register(GL);
txnBegin(graph);
graph.delete(triple("S P O"));
txnCommit(graph);
GL.assertContains("delete", graph, triple("S P O"));
assertFalse("Graph should not contain <S P O>",
graph.contains(triple("S P O")));
assertNotEmpty(graph, base);
assertTrue("Graph should contain <S2 P2 O2>",
graph.contains(triple("S2 P2 O2")));
assertTrue("Graph should contain <S3 P3 O3>",
graph.contains(triple("S3 P3 O3")));
// should not modify anything on wildcard delete
GL.clear();
try {
txnBegin(graph);
graph.delete(new Triple(node("S2"), node("P2"), Node.ANY));
txnCommit(graph);
} catch (DeleteDeniedException expected) {
txnRollback(graph);
}
assertTrue("Graph should contain <S2 P2 O2>",
graph.contains(triple("S2 P2 O2")));
assertTrue("Graph should contain <S3 P3 O3>",
graph.contains(triple("S3 P3 O3")));
GL.assertHas("delete", graph, new Triple(node("S2"), node("P2"),
Node.ANY));
}
@ContractTest
public void testDelete_Triple_FromNothing() {
Graph g = producer.newInstance();
g.getEventManager().register(GL);
txnBegin(g);
g.delete(triple("quint rdf:subject S"));
txnCommit(g);
GL.assertContains("delete", g, triple("quint rdf:subject S"));
}
@ContractTest
public void testDependsOn() {
Graph g = producer.newInstance();
Graph[] depGraphs = producer.getDependsOn(g);
if (depGraphs != null) {
for (Graph dg : depGraphs) {
assertTrue(
String.format("Graph %s should depend upon %s", g, dg),
g.dependsOn(dg));
}
}
depGraphs = producer.getNotDependsOn(g);
if (depGraphs != null) {
for (Graph dg : depGraphs) {
assertFalse(String.format("Graph %s should not depend upon %s",
g, dg), g.dependsOn(dg));
}
}
}
@ContractTest
public void testFind_Node_Node_Node() {
Graph graph = graphWith(producer.newInstance(),
"S P O; S2 P2 O2; S3 P3 O3");
List<Triple> s = graph.find(Node.ANY, Node.ANY, Node.ANY).toList();
assertEquals(3, s.size());
List<Triple> expected = Arrays.asList(new Triple[] { triple("S P O"),
triple("S2 P2 O2"), triple("S3 P3 O3") });
assertTrue("Missing some values",
expected.containsAll(s) && s.containsAll(expected));
s = graph.find(node("S"), Node.ANY, Node.ANY).toList();
assertEquals(1, s.size());
assertTrue("Missing some values", s.contains(triple("S P O")));
s = graph.find(Node.ANY, node("P"), Node.ANY).toList();
assertEquals(1, s.size());
assertTrue("Missing some values", s.contains(triple("S P O")));
s = graph.find(Node.ANY, Node.ANY, node("O")).toList();
assertEquals(1, s.size());
assertTrue("Missing some values", s.contains(triple("S P O")));
s = graph.find(node("S2"), node("P2"), node("O2")).toList();
assertEquals(1, s.size());
assertTrue("Missing some values", s.contains(triple("S2 P2 O2")));
s = graph.find(node("S2"), node("P3"), node("O2")).toList();
assertEquals(0, s.size());
s = graph.find(Node.ANY, node("P3"), node("O2")).toList();
assertEquals(0, s.size());
s = graph.find(node("S3"), Node.ANY, node("O2")).toList();
assertEquals(0, s.size());
s = graph.find(node("S3"), node("P2"), Node.ANY).toList();
assertEquals(0, s.size());
}
@ContractTest
public void testFind_Node_Node_Node_ByFluidTriple() {
Node x = node("x");
Node y = node("y");
Node z = node("z");
Graph g = graphWith(producer.newInstance(), "x y z ");
Set<Triple> expect = tripleSet("x y z");
assertEquals(expect, g.find(Node.ANY, y, z).toSet());
assertEquals(expect, g.find(x, Node.ANY, z).toSet());
assertEquals(expect, g.find(x, y, Node.ANY).toSet());
}
@ContractTest
public void testFind_Node_Node_Node_ProgrammaticValues() {
Graph g = producer.newInstance();
if (g.getCapabilities().handlesLiteralTyping()) {
Node ab = NodeFactory.createLiteral(LiteralLabelFactory
.createTypedLiteral(new Byte((byte) 42)));
Node as = NodeFactory.createLiteral(LiteralLabelFactory
.createTypedLiteral(new Short((short) 42)));
Node ai = NodeFactory.createLiteral(LiteralLabelFactory
.createTypedLiteral(new Integer(42)));
Node al = NodeFactory.createLiteral(LiteralLabelFactory
.createTypedLiteral(new Long(42)));
Node SB = NodeCreateUtils.create("SB");
Node SS = NodeCreateUtils.create("SS");
Node SI = NodeCreateUtils.create("SI");
Node SL = NodeCreateUtils.create("SL");
Node P = NodeCreateUtils.create("P");
txnBegin(g);
try {
g.add(Triple.create(SB, P, ab));
g.add(Triple.create(SS, P, as));
g.add(Triple.create(SI, P, ai));
g.add(Triple.create(SL, P, al));
} catch (Exception e) {
txnRollback(g);
fail(e.getMessage());
}
txnCommit(g);
assertEquals(
String.format(
"Should have found 4 elements, does %s really implement literal typing",
g.getClass()),
4,
iteratorToSet(
g.find(Node.ANY, P, NodeCreateUtils.create("42")))
.size());
}
}
@ContractTest
public void testFind_Node_Node_Node_MatchLanguagedLiteralCaseInsensitive() {
Graph m = graphWith(producer.newInstance(), "a p 'chat'en");
if (m.getCapabilities().handlesLiteralTyping()) {
Node chaten = node("'chat'en"), chatEN = node("'chat'EN");
assertDiffer(chaten, chatEN);
assertTrue(chaten.sameValueAs(chatEN));
assertEquals(chaten.getIndexingValue(), chatEN.getIndexingValue());
assertEquals(1, m.find(Node.ANY, Node.ANY, chaten).toList().size());
assertEquals(1, m.find(Node.ANY, Node.ANY, chatEN).toList().size());
}
}
@ContractTest
public void testFind_Node_Node_Node_NoMatchAgainstUnlanguagesLiteral() {
Graph m = graphWith(producer.newInstance(),
"a p 'chat'en; a p 'chat'");
if (m.getCapabilities().handlesLiteralTyping()) {
Node chaten = node("'chat'en"), chatEN = node("'chat'EN");
assertDiffer(chaten, chatEN);
assertTrue(chaten.sameValueAs(chatEN));
assertEquals(chaten.getIndexingValue(), chatEN.getIndexingValue());
assertEquals(1, m.find(Node.ANY, Node.ANY, chaten).toList().size());
assertEquals(1, m.find(Node.ANY, Node.ANY, chatEN).toList().size());
}
}
@ContractTest
public void testFind_Triple() {
Graph graph = graphWith(producer.newInstance(),
"S P O; S2 P2 O2; S3 P3 O3");
List<Triple> s = graph.find(Triple.ANY).toList();
assertEquals(3, s.size());
List<Triple> expected = Arrays.asList(new Triple[] { triple("S P O"),
triple("S2 P2 O2"), triple("S3 P3 O3") });
assertTrue("Missing some values", expected.containsAll(s));
s = graph.find(new Triple(node("S"), Node.ANY, Node.ANY)).toList();
assertEquals(1, s.size());
assertTrue("Missing some values", s.contains(triple("S P O")));
s = graph.find(new Triple(Node.ANY, node("P"), Node.ANY)).toList();
assertEquals(1, s.size());
assertTrue("Missing some values", s.contains(triple("S P O")));
s = graph.find(new Triple(Node.ANY, Node.ANY, node("O"))).toList();
assertEquals(1, s.size());
assertTrue("Missing some values", s.contains(triple("S P O")));
s = graph.find(new Triple(node("S2"), node("P2"), node("O2"))).toList();
assertEquals(1, s.size());
assertTrue("Missing some values", s.contains(triple("S2 P2 O2")));
s = graph.find(new Triple(node("S2"), node("P3"), node("O2"))).toList();
assertEquals(0, s.size());
s = graph.find(new Triple(Node.ANY, node("P3"), node("O2"))).toList();
assertEquals(0, s.size());
s = graph.find(new Triple(node("S3"), Node.ANY, node("O2"))).toList();
assertEquals(0, s.size());
s = graph.find(new Triple(node("S3"), node("P2"), Node.ANY)).toList();
assertEquals(0, s.size());
}
@ContractTest
public void testFind_Triple_ByFluidTriple() {
Graph g = graphWith(producer.newInstance(), "x y z ");
Set<Triple> expect = tripleSet("x y z");
assertEquals(expect, g.find(triple("?? y z")).toSet());
assertEquals(expect, g.find(triple("x ?? z")).toSet());
assertEquals(expect, g.find(triple("x y ??")).toSet());
}
@ContractTest
public void testFind_Triple_ProgrammaticValues() {
Graph g = producer.newInstance();
if (g.getCapabilities().handlesLiteralTyping()) {
Node ab = NodeFactory.createLiteral(LiteralLabelFactory
.createTypedLiteral(new Byte((byte) 42)));
Node as = NodeFactory.createLiteral(LiteralLabelFactory
.createTypedLiteral(new Short((short) 42)));
Node ai = NodeFactory.createLiteral(LiteralLabelFactory
.createTypedLiteral(new Integer(42)));
Node al = NodeFactory.createLiteral(LiteralLabelFactory
.createTypedLiteral(new Long(42)));
Node SB = NodeCreateUtils.create("SB");
Node SS = NodeCreateUtils.create("SS");
Node SI = NodeCreateUtils.create("SI");
Node SL = NodeCreateUtils.create("SL");
Node P = NodeCreateUtils.create("P");
txnBegin(g);
try {
g.add(Triple.create(SB, P, ab));
g.add(Triple.create(SS, P, as));
g.add(Triple.create(SI, P, ai));
g.add(Triple.create(SL, P, al));
} catch (Exception e) {
txnRollback(g);
fail(e.getMessage());
}
txnCommit(g);
assertEquals(
String.format(
"Should have found 4 elements, does %s really implement literal typing",
g.getClass()),
4,
iteratorToSet(
g.find(new Triple(Node.ANY, P, NodeCreateUtils
.create("42")))).size());
}
}
@ContractTest
public void testFind_Triple_MatchLanguagedLiteralCaseInsensitive() {
Graph m = graphWith(producer.newInstance(), "a p 'chat'en");
//if (m.getCapabilities().handlesLiteralTyping()) {
Node chaten = node("'chat'en"), chatEN = node("'chat'EN");
assertDiffer(chaten, chatEN);
assertTrue(chaten.sameValueAs(chatEN));
assertEquals(chaten.getIndexingValue(), chatEN.getIndexingValue());
assertEquals(1, m.find(new Triple(Node.ANY, Node.ANY, chaten))
.toList().size());
assertEquals(1, m.find(new Triple(Node.ANY, Node.ANY, chatEN))
.toList().size());
//}
}
@ContractTest
public void testFind_Triple_NoMatchAgainstUnlanguagesLiteral() {
Graph m = graphWith(producer.newInstance(),
"a p 'chat'en; a p 'chat'");
//if (m.getCapabilities().handlesLiteralTyping()) {
Node chaten = node("'chat'en"), chatEN = node("'chat'EN");
assertDiffer(chaten, chatEN);
assertTrue(chaten.sameValueAs(chatEN));
assertEquals(chaten.getIndexingValue(), chatEN.getIndexingValue());
assertEquals(1, m.find(new Triple(Node.ANY, Node.ANY, chaten))
.toList().size());
assertEquals(1, m.find(new Triple(Node.ANY, Node.ANY, chatEN))
.toList().size());
//}
}
@ContractTest
public void testGetCapabilities() {
Graph g = producer.newInstance();
Capabilities c = g.getCapabilities();
assertNotNull("Capabilities are not returned", c);
try {
c.sizeAccurate();
} catch (Exception e) {
fail("sizeAccurate() threw Exception: " + e.toString());
}
try {
c.addAllowed();
} catch (Exception e) {
fail("addAllowed() threw Exception: " + e.toString());
}
try {
c.addAllowed(true);
} catch (Exception e) {
fail("addAllowed( boolean ) threw Exception: " + e.toString());
}
try {
c.deleteAllowed();
} catch (Exception e) {
fail("deleteAllowed() threw Exception: " + e.toString());
}
try {
c.deleteAllowed(true);
} catch (Exception e) {
fail("deleteAllowed( boolean ) threw Exception: " + e.toString());
}
try {
c.canBeEmpty();
} catch (Exception e) {
fail("canBeEmpty() threw Exception: " + e.toString());
}
}
@ContractTest
public void testGetEventManager() {
assertNotNull("Must return an EventManager", producer
.newInstance().getEventManager());
}
@ContractTest
public void testGetPrefixMapping() {
Graph g = producer.newInstance();
PrefixMapping pm = g.getPrefixMapping();
assertNotNull("Must return prefix mapping", pm);
assertSame("getPrefixMapping must always return the same object", pm,
g.getPrefixMapping());
pm.setNsPrefix("pfx1", "http://example.com/");
pm.setNsPrefix("pfx2", "scheme:rope/string#");
// assert same after adding to other mapl
assertSame("getPrefixMapping must always return the same object", pm,
g.getPrefixMapping());
}
@ContractTest
public void testGetStatisticsHandler() {
Graph g = producer.newInstance();
GraphStatisticsHandler sh = g.getStatisticsHandler();
if (sh != null) {
assertSame(
"getStatisticsHandler must always return the same object",
sh, g.getStatisticsHandler());
}
}
@ContractTest
public void testGetTransactionHandler() {
Graph g = producer.newInstance();
assertNotNull("Must return a Transaction handler",
g.getTransactionHandler());
}
@ContractTest
public void testIsClosed() {
Graph g = producer.newInstance();
assertFalse("Graph created in closed state", g.isClosed());
g.close();
assertTrue("Graph does not report closed state after close called",
g.isClosed());
}
@ContractTest
public void testIsEmpty() {
Graph g = producer.newInstance();
if (!g.isEmpty()) {
LOG.warn(String.format(
"Graph type %s can not be empty (Empty test skipped)",
g.getClass()));
} else {
graphAddTxn(g, "S P O");
assertFalse("Graph reports empty after add", g.isEmpty());
txnBegin(g);
g.add(NodeCreateUtils.createTriple("Foo B C"));
g.delete(NodeCreateUtils.createTriple("S P O"));
txnCommit(g);
assertFalse("Should not report empty", g.isEmpty());
txnBegin(g);
g.delete(NodeCreateUtils.createTriple("Foo B C"));
txnCommit(g);
assertTrue("Should report empty after all entries deleted",
g.isEmpty());
}
}
@ContractTest
public void testIsIsomorphicWith_Graph() {
Graph graph = producer.newInstance();
Graph g2 = memGraph();
assertTrue("Empty graphs should be isomorphic",
graph.isIsomorphicWith(g2));
graph = graphWith(producer.newInstance(),
"S P O; S2 P2 O2; S3 P3 O3");
g2 = graphWith("S3 P3 O3; S2 P2 O2; S P O");
assertTrue("Should be isomorphic", graph.isIsomorphicWith(g2));
txnBegin(graph);
graph.add(triple("_1, P4 S4"));
txnCommit(graph);
txnBegin(g2);
g2.add(triple("_2, P4 S4"));
txnCommit(g2);
assertTrue("Should be isomorphic after adding anonymous nodes",
graph.isIsomorphicWith(g2));
txnBegin(graph);
graph.add(triple("_1, P3 S4"));
txnCommit(graph);
txnBegin(g2);
g2.add(triple("_2, P4 S4"));
txnCommit(g2);
assertFalse("Should not be isomorphic", graph.isIsomorphicWith(g2));
}
private Graph copy(Graph g) {
Graph result = producer.newInstance();
txnBegin(result);
GraphUtil.addInto(result, g);
txnCommit(result);
return result;
}
private Graph remove(Graph toUpdate, Graph toRemove) {
txnBegin(toUpdate);
GraphUtil.deleteFrom(toUpdate, toRemove);
txnCommit(toUpdate);
return toUpdate;
}
/**
* Test that remove(s, p, o) works, in the presence of inferencing graphs
* that mean emptyness isn't available. This is why we go round the houses
* and test that expected ~= initialContent + addedStuff - removed -
* initialContent.
*/
@ContractTest
public void testRemove_Node_Node_Node() {
for (int i = 0; i < cases.length; i += 1)
for (int j = 0; j < 3; j += 1) {
Graph content = producer.newInstance();
Graph baseContent = copy(content);
graphAddTxn(content, cases[i][0]);
Triple remove = triple(cases[i][1]);
Graph expected = graphWith(cases[i][2]);
Triple[] removed = tripleArray(cases[i][3]);
content.getEventManager().register(GL);
GL.clear();
txnBegin(content);
content.remove(remove.getSubject(), remove.getPredicate(),
remove.getObject());
txnCommit(content);
// check for optional delete notifications
if (GL.contains("delete")) {
// if it contains any it must contain all.
for (Triple t : removed) {
GL.assertContains("delete", content, t);
}
}
GL.assertHasEnd(
"someEvent",
content,
GraphEvents.remove(remove.getSubject(),
remove.getPredicate(), remove.getObject()));
content.getEventManager().unregister(GL);
Graph finalContent = remove(copy(content), baseContent);
assertIsomorphic(cases[i][1], expected, finalContent);
}
}
@ContractTest
public void testRemove_ByIterator() {
testRemove("?? ?? ??", "?? ?? ??");
testRemove("S ?? ??", "S ?? ??");
testRemove("S ?? ??", "?? P ??");
testRemove("S ?? ??", "?? ?? O");
testRemove("?? P ??", "S ?? ??");
testRemove("?? P ??", "?? P ??");
testRemove("?? P ??", "?? ?? O");
testRemove("?? ?? O", "S ?? ??");
testRemove("?? ?? O", "?? P ??");
testRemove("?? ?? O", "?? ?? O");
}
private void testRemove(String findRemove, String findCheck) {
Graph g = graphWith(producer.newInstance(), "S P O");
ExtendedIterator<Triple> it = g.find(NodeCreateUtils
.createTriple(findRemove));
try {
it.next();
it.remove();
it.close();
assertEquals("remove with " + findRemove + ":", 0, g.size());
assertFalse(g.contains(NodeCreateUtils.createTriple(findCheck)));
} catch (UnsupportedOperationException e) {
it.close();
assertFalse(
"delete failed but capailities indicates it should work", g
.getCapabilities().iteratorRemoveAllowed());
}
}
/**
* This test case was generated by Ian and was caused by GraphMem not
* keeping up with changes to the find interface.
*/
@ContractTest
public void testFindAndContains() {
Graph g = producer.newInstance();
Node r = NodeCreateUtils.create("r"), s = NodeCreateUtils.create("s"), p = NodeCreateUtils
.create("P");
txnBegin(g);
try {
g.add(Triple.create(r, p, s));
txnCommit(g);
assertTrue(g.contains(r, p, Node.ANY));
assertEquals(1, g.find(r, p, Node.ANY).toList().size());
} catch (Exception e) {
txnRollback(g);
fail(e.getMessage());
}
}
/**
* Check that contains respects by-value semantics.
*/
@ContractTest
public void testAGraph() {
String title = this.getClass().getName();
Graph g = producer.newInstance();
int baseSize = g.size();
graphAddTxn(g, "x R y; p S q; a T b");
/* */
assertContainsAll(title + ": simple graph", g, "x R y; p S q; a T b");
assertEquals(title + ": size", baseSize + 3, g.size());
graphAddTxn(g,
"spindizzies lift cities; Diracs communicate instantaneously");
assertEquals(title + ": size after adding", baseSize + 5, g.size());
txnBegin(g);
g.delete(triple("x R y"));
g.delete(triple("a T b"));
txnCommit(g);
assertEquals(title + ": size after deleting", baseSize + 3, g.size());
assertContainsAll(title + ": modified simple graph", g,
"p S q; spindizzies lift cities; Diracs communicate instantaneously");
assertOmitsAll(title + ": modified simple graph", g, "x R y; a T b");
/* */
ClosableIterator<Triple> it = g.find(Node.ANY, node("lift"), Node.ANY);
assertTrue(title + ": finds some triple(s)", it.hasNext());
assertEquals(title + ": finds a 'lift' triple",
triple("spindizzies lift cities"), it.next());
assertFalse(title + ": finds exactly one triple", it.hasNext());
it.close();
}
// public void testStuff()
// {
// // testAGraph( "StoreMem", new GraphMem() );
// // testAGraph( "StoreMemBySubject", new GraphMem() );
// // String [] empty = new String [] {};
// // Graph g = graphWith( "x R y; p S q; a T b" );
// // /* */
// // assertContainsAll( "simple graph", g, "x R y; p S q; a T b" );
// // graphAdd( g,
// "spindizzies lift cities; Diracs communicate instantaneously" );
// // g.delete( triple( "x R y" ) );
// // g.delete( triple( "a T b" ) );
// // assertContainsAll( "modified simple graph", g,
// "p S q; spindizzies lift cities; Diracs communicate instantaneously" );
// // assertOmitsAll( "modified simple graph", g, "x R y; a T b" );
// }
// /**
// Test that Graphs have transaction support methods, and that if they fail
// on some g they fail because they do not support the operation.
// */
// @ContractTest
// public void testHasTransactions()
// {
// Graph g = producer.newInstance();
// TransactionHandler th = g.getTransactionHandler();
// th.transactionsSupported();
// try { th.begin(); } catch (UnsupportedOperationException x) {}
// try { th.abort(); } catch (UnsupportedOperationException x) {}
// try { th.begin(); th.commit(); } catch (UnsupportedOperationException x)
// {}
// /* */
// Command cmd = new Command()
// { @Override
// public Object execute() { return null; } };
// try { th.executeInTransaction( cmd ); }
// catch (UnsupportedOperationException x) {}
// }
//
// @ContractTest
// public void testExecuteInTransactionCatchesThrowable()
// {Graph g = producer.newInstance();
// TransactionHandler th = g.getTransactionHandler();
// if (th.transactionsSupported())
// {
// Command cmd = new Command()
// { @Override
// public Object execute() throws Error { throw new Error(); } };
// try { th.executeInTransaction( cmd ); }
// catch (JenaException x) {}
// }
// }
@ContractTest
public void testAddWithReificationPreamble() {
Graph g = producer.newInstance();
txnBegin(g);
xSPO(g);
txnCommit(g);
assertFalse(g.isEmpty());
}
protected void xSPOyXYZ(Graph g) {
xSPO(g);
ReifierStd.reifyAs(g, NodeCreateUtils.create("y"),
NodeCreateUtils.createTriple("X Y Z"));
}
protected void aABC(Graph g) {
ReifierStd.reifyAs(g, NodeCreateUtils.create("a"),
NodeCreateUtils.createTriple("Foo B C"));
}
protected void xSPO(Graph g) {
ReifierStd.reifyAs(g, NodeCreateUtils.create("x"),
NodeCreateUtils.createTriple("S P O"));
}
@ContractTest
public void failingTestDoubleRemoveAll() {
final Graph g = producer.newInstance();
if (g.getCapabilities().iteratorRemoveAllowed()) {
try {
graphAddTxn(g, "c S d; e:ff GGG hhhh; _i J 27; Ell Em 'en'");
Iterator<Triple> it = new TrackingTripleIterator(
g.find(Triple.ANY)) {
@Override
public void remove() {
super.remove(); // removes current
g.delete(current); // no-op.
}
};
while (it.hasNext()) {
it.next();
it.remove();
}
assertTrue(g.isEmpty());
} catch (UnsupportedOperationException e) {
fail("Error attempting to remove nodes " + e.getMessage());
}
}
}
/**
* Test cases for RemoveSPO(); each entry is a triple (add, remove, result).
* <ul>
* <li>add - the triples to add to the graph to start with
* <li>remove - the pattern to use in the removal
* <li>result - the triples that should remain in the graph
* </ul>
*/
protected static String[][] cases = { { "x R y", "x R y", "", "x R y" },
{ "x R y; a P b", "x R y", "a P b", "x R y" },
{ "x R y; a P b", "?? R y", "a P b", "x R y" },
{ "x R y; a P b", "x R ??", "a P b", "x R y" },
{ "x R y; a P b", "x ?? y", "a P b", "x R y" },
{ "x R y; a P b", "?? ?? ??", "", "x R y; a P b" },
{ "x R y; a P b; c P d", "?? P ??", "x R y", "a P b; c P d" },
{ "x R y; a P b; x S y", "x ?? ??", "a P b", "x R y; x S y" }, };
/**
* testIsomorphism from file data
*
* @throws URISyntaxException
* @throws MalformedURLException
*/
@ContractTest
public void testIsomorphismFile() throws URISyntaxException, MalformedURLException {
testIsomorphismXMLFile(1, true);
testIsomorphismXMLFile(2, true);
testIsomorphismXMLFile(3, true);
testIsomorphismXMLFile(4, true);
testIsomorphismXMLFile(5, false);
testIsomorphismXMLFile(6, false);
testIsomorphismNTripleFile(7, true);
testIsomorphismNTripleFile(8, false);
}
private void testIsomorphismNTripleFile(int i, boolean result) {
testIsomorphismFile(i, "N-TRIPLE", "nt", result);
}
private void testIsomorphismXMLFile(int i, boolean result) {
testIsomorphismFile(i, "RDF/XML", "rdf", result);
}
private InputStream getInputStream(int n, int n2, String suffix) {
String urlStr = String.format("regression/testModelEquals/%s-%s.%s", n,
n2, suffix);
return GraphContractTest.class.getClassLoader().getResourceAsStream(
urlStr);
}
private void testIsomorphismFile(int n, String lang, String suffix, boolean result) {
Graph g1 = producer.newInstance();
Graph g2 = producer.newInstance();
Model m1 = ModelFactory.createModelForGraph(g1);
Model m2 = ModelFactory.createModelForGraph(g2);
m1.read(getInputStream(n, 1, suffix), "http://www.example.org/", lang);
m2.read(getInputStream(n, 2, suffix), "http://www.example.org/", lang);
boolean rslt = g1.isIsomorphicWith(g2) == result;
if (!rslt) {
System.out.println("g1:");
m1.write(System.out, "N-TRIPLE");
System.out.println("g2:");
m2.write(System.out, "N-TRIPLE");
}
assertTrue("Isomorphism test failed", rslt);
}
protected Graph getClosed() {
Graph result = producer.newInstance();
result.close();
return result;
}
// @ContractTest
// public void testTransactionCommit()
// {
// Graph g = producer.newInstance();
// if (g.getTransactionHandler().transactionsSupported())
// {
// Graph initial = graphWithTxn( "initial hasValue 42; also hasURI hello" );
// Graph extra = graphWithTxn( "extra hasValue 17; also hasURI world" );
// //File foo = FileUtils.tempFileName( "fileGraph", ".nt" );
//
// //Graph g = new FileGraph( foo, true, true );
//
// GraphUtil.addInto( g, initial );
// g.getTransactionHandler().begin();
// GraphUtil.addInto( g, extra );
// g.getTransactionHandler().commit();
// Graph union = graphWithTxn( "" );
// GraphUtil.addInto(union, initial );
// GraphUtil.addInto(union, extra );
// assertIsomorphic( union, g );
// //Model inFile = ModelFactory.createDefaultModel();
// //inFile.read( "file:///" + foo, "N-TRIPLES" );
// //assertIsomorphic( union, inFile.getGraph() );
// }
// }
//
// @ContractTest
// public void testTransactionAbort()
// {
// Graph g = producer.newInstance();
// if (g.getTransactionHandler().transactionsSupported())
// {
// Graph initial = graphWithTxn( "initial hasValue 42; also hasURI hello" );
// Graph extra = graphWithTxn( "extra hasValue 17; also hasURI world" );
// File foo = FileUtils.tempFileName( "fileGraph", ".n3" );
// //Graph g = new FileGraph( foo, true, true );
// GraphUtil.addInto( g, initial );
// g.getTransactionHandler().begin();
// GraphUtil.addInto( g, extra );
// g.getTransactionHandler().abort();
// assertIsomorphic( initial, g );
// }
// }
//
// @ContractTest
// public void testTransactionCommitThenAbort()
// {
// Graph g = producer.newInstance();
// if (g.getTransactionHandler().transactionsSupported())
// {
// Graph initial = graphWithTxn( "Foo pings B; B pings C" );
// Graph extra = graphWithTxn( "C pingedBy B; fileGraph rdf:type Graph" );
// //Graph g = producer.newInstance();
// //File foo = FileUtils.tempFileName( "fileGraph", ".nt" );
// //Graph g = new FileGraph( foo, true, true );
// g.getTransactionHandler().begin();
// GraphUtil.addInto( g, initial );
// g.getTransactionHandler().commit();
// g.getTransactionHandler().begin();
// GraphUtil.addInto( g, extra );
// g.getTransactionHandler().abort();
// assertIsomorphic( initial, g );
// //Model inFile = ModelFactory.createDefaultModel();
// // inFile.read( "file:///" + foo, "N-TRIPLES" );
// //assertIsomorphic( initial, inFile.getGraph() );
// }
// }
/**
* This test exposed that the update-existing-graph functionality was broken
* if the target graph already contained any statements with a subject S
* appearing as subject in the source graph - no further Spo statements were
* added.
*/
@ContractTest
public void testPartialUpdate() {
Graph source = graphWith(producer.newInstance(), "a R b; b S e");
Graph dest = graphWith(producer.newInstance(), "b R d");
GraphExtract e = new GraphExtract(TripleBoundary.stopNowhere);
e.extractInto(dest, node("a"), source);
assertIsomorphic(
graphWith(producer.newInstance(), "a R b; b S e; b R d"),
dest);
}
/**
* Ensure that triples removed by calling .remove() on the iterator returned
* by a find() will generate deletion notifications.
*/
@ContractTest
public void testIterator_Remove() {
Graph graph = graphWith(producer.newInstance(), "a R b; b S e");
if (graph.getCapabilities().iteratorRemoveAllowed()) {
try {
graph.getEventManager().register(GL);
txnBegin(graph);
Triple toRemove = triple("a R b");
ExtendedIterator<Triple> rtr = graph.find(toRemove);
assertTrue("ensure a(t least) one triple", rtr.hasNext());
rtr.next();
rtr.remove();
rtr.close();
GL.assertHas("delete", graph, toRemove);
} catch (UnsupportedOperationException e) {
fail("Error attempting to remove nodes " + e.getMessage());
}
}
}
@ContractTest
public void testTransactionHandler_Commit() {
Graph g = producer.newInstance();
if (g.getTransactionHandler().transactionsSupported()) {
Graph initial = graphWith(producer.newInstance(),
"initial hasValue 42; also hasURI hello");
Graph extra = graphWith(producer.newInstance(),
"extra hasValue 17; also hasURI world");
GraphUtil.addInto(g, initial);
g.getTransactionHandler().begin();
GraphUtil.addInto(g, extra);
g.getTransactionHandler().commit();
Graph union = memGraph();
GraphUtil.addInto(union, initial);
GraphUtil.addInto(union, extra);
assertIsomorphic(union, g);
// Model inFiIProducer<TransactionHandler>le =
// ModelFactory.createDefaultModel();
// inFile.read( "file:///" + foo, "N-TRIPLES" );
// assertIsomorphic( union, inFile.getGraph() );
}
}
@ContractTest
public void testTransactionHandler_Abort() {
Graph g = producer.newInstance();
if (g.getTransactionHandler().transactionsSupported()) {
Graph initial = graphWith(producer.newInstance(),
"initial hasValue 42; also hasURI hello");
Graph extra = graphWith(producer.newInstance(),
"extra hasValue 17; also hasURI world");
GraphUtil.addInto(g, initial);
g.getTransactionHandler().begin();
GraphUtil.addInto(g, extra);
g.getTransactionHandler().abort();
assertIsomorphic(initial, g);
}
}
@ContractTest
public void testTransactionHandler_CommitThenAbort() {
Graph g = producer.newInstance();
if (g.getTransactionHandler().transactionsSupported()) {
Graph initial = graphWith(producer.newInstance(),
"Foo pings B; B pings C");
Graph extra = graphWith(producer.newInstance(),
"C pingedBy B; fileGraph rdf:type Graph");
g.getTransactionHandler().begin();
GraphUtil.addInto(g, initial);
g.getTransactionHandler().commit();
g.getTransactionHandler().begin();
GraphUtil.addInto(g, extra);
g.getTransactionHandler().abort();
assertIsomorphic(initial, g);
// Model inFile = ModelFactory.createDefaultModel();
// inFile.read( "file:///" + foo, "N-TRIPLES" );
// assertIsomorphic( initial, inFile.getGraph() );
}
}
//
// Test that literal typing works when supported
//
// used to find the object set from the returned set for literal testing
private static final Function<Triple, Node> getObject = new Function<Triple, Node>() {
@Override
public Node apply(Triple t) {
return t.getObject();
}
};
private void testLiteralTypingBasedFind(final String data, final int size,
final String search, final String results, boolean reqLitType) {
Graph g = producer.newInstance();
if (!reqLitType || g.getCapabilities().handlesLiteralTyping()) {
graphWith(g, data);
Node literal = NodeCreateUtils.create(search);
//
assertEquals("graph has wrong size", size, g.size());
Set<Node> got = g.find(Node.ANY, Node.ANY, literal)
.mapWith(getObject).toSet();
assertEquals(nodeSet(results), got);
}
}
@ContractTest
public void testLiteralTypingBasedFind() {
testLiteralTypingBasedFind("a P 'simple'", 1, "'simple'", "'simple'",
false);
testLiteralTypingBasedFind("a P 'simple'xsd:string", 1, "'simple'",
"'simple'xsd:string", true);
testLiteralTypingBasedFind("a P 'simple'", 1, "'simple'xsd:string",
"'simple'", true);
// ensure that adding identical strings one with type yields single result
// and that querying with or without type works
testLiteralTypingBasedFind("a P 'simple'xsd:string", 1,
"'simple'xsd:string", "'simple'xsd:string", false);
testLiteralTypingBasedFind("a P 'simple'; a P 'simple'xsd:string", 1,
"'simple'", "'simple'xsd:string", true);
testLiteralTypingBasedFind("a P 'simple'; a P 'simple'xsd:string", 1,
"'simple'xsd:string", "'simple'", true);
testLiteralTypingBasedFind("a P 'simple'; a P 'simple'xsd:string", 1,
"'simple'", "'simple'", true);
testLiteralTypingBasedFind("a P 'simple'; a P 'simple'xsd:string", 1,
"'simple'xsd:string", "'simple'xsd:string", true);
testLiteralTypingBasedFind("a P 1", 1, "1", "1", false);
testLiteralTypingBasedFind("a P '1'xsd:float", 1, "'1'xsd:float",
"'1'xsd:float", false);
testLiteralTypingBasedFind("a P '1'xsd:double", 1, "'1'xsd:double",
"'1'xsd:double", false);
testLiteralTypingBasedFind("a P '1'xsd:float", 1, "'1'xsd:float",
"'1'xsd:float", false);
testLiteralTypingBasedFind("a P '1.1'xsd:float", 1, "'1'xsd:float", "",
false);
testLiteralTypingBasedFind("a P '1'xsd:double", 1, "'1'xsd:int", "",
false);
testLiteralTypingBasedFind("a P 'abc'rdf:XMLLiteral", 1, "'abc'", "",
false);
testLiteralTypingBasedFind("a P 'abc'", 1, "'abc'rdf:XMLLiteral", "",
false);
//
// floats & doubles are not compatible
//
testLiteralTypingBasedFind("a P '1'xsd:float", 1, "'1'xsd:double", "",
false);
testLiteralTypingBasedFind("a P '1'xsd:double", 1, "'1'xsd:float", "",
false);
testLiteralTypingBasedFind("a P 1", 1, "'1'", "", false);
testLiteralTypingBasedFind("a P 1", 1, "'1'xsd:integer",
"'1'xsd:integer", false);
testLiteralTypingBasedFind("a P 1", 1, "'1'", "", false);
testLiteralTypingBasedFind("a P '1'xsd:short", 1, "'1'xsd:integer",
"'1'xsd:short", true);
testLiteralTypingBasedFind("a P '1'xsd:int", 1, "'1'xsd:integer",
"'1'xsd:int", true);
}
@ContractTest
public void testQuadRemove() {
Graph g = producer.newInstance();
assertEquals(0, g.size());
Triple s = triple("x rdf:subject s");
Triple p = triple("x rdf:predicate p");
Triple o = triple("x rdf:object o");
Triple t = triple("x rdf:type rdf:Statement");
txnBegin(g);
g.add(s);
g.add(p);
g.add(o);
g.add(t);
txnCommit(g);
assertEquals(4, g.size());
txnBegin(g);
g.delete(s);
g.delete(p);
g.delete(o);
g.delete(t);
txnCommit(g);
assertEquals(0, g.size());
}
@ContractTest
public void testSizeAfterRemove() {
Graph g = graphWith(producer.newInstance(), "x p y");
if (g.getCapabilities().iteratorRemoveAllowed()) {
try {
ExtendedIterator<Triple> it = g.find(triple("x ?? ??"));
it.removeNext();
assertEquals(0, g.size());
} catch (UnsupportedOperationException e) {
fail("Error attempting to remove nodes " + e.getMessage());
}
}
}
@ContractTest
public void testSingletonStatisticsWithSingleTriple() {
Graph g = graphWith(producer.newInstance(), "a P b");
GraphStatisticsHandler h = g.getStatisticsHandler();
if (h != null) {
assertEquals(1L, h.getStatistic(node("a"), Node.ANY, Node.ANY));
assertEquals(0L, h.getStatistic(node("x"), Node.ANY, Node.ANY));
//
assertEquals(1L, h.getStatistic(Node.ANY, node("P"), Node.ANY));
assertEquals(0L, h.getStatistic(Node.ANY, node("Q"), Node.ANY));
//
assertEquals(1L, h.getStatistic(Node.ANY, Node.ANY, node("b")));
assertEquals(0L, h.getStatistic(Node.ANY, Node.ANY, node("y")));
}
}
@ContractTest
public void testSingletonStatisticsWithSeveralTriples() {
Graph g = graphWith(producer.newInstance(),
"a P b; a P c; a Q b; x S y");
GraphStatisticsHandler h = g.getStatisticsHandler();
if (h != null) {
assertEquals(3L, h.getStatistic(node("a"), Node.ANY, Node.ANY));
assertEquals(1L, h.getStatistic(node("x"), Node.ANY, Node.ANY));
assertEquals(0L, h.getStatistic(node("y"), Node.ANY, Node.ANY));
//
assertEquals(2L, h.getStatistic(Node.ANY, node("P"), Node.ANY));
assertEquals(1L, h.getStatistic(Node.ANY, node("Q"), Node.ANY));
assertEquals(0L, h.getStatistic(Node.ANY, node("R"), Node.ANY));
//
assertEquals(2L, h.getStatistic(Node.ANY, Node.ANY, node("b")));
assertEquals(1L, h.getStatistic(Node.ANY, Node.ANY, node("c")));
assertEquals(0L, h.getStatistic(Node.ANY, Node.ANY, node("d")));
}
}
@ContractTest
public void testDoubletonStatisticsWithTriples() {
Graph g = graphWith(producer.newInstance(),
"a P b; a P c; a Q b; x S y");
GraphStatisticsHandler h = g.getStatisticsHandler();
if (h != null) {
assertEquals(-1L, h.getStatistic(node("a"), node("P"), Node.ANY));
assertEquals(-1L, h.getStatistic(Node.ANY, node("P"), node("b")));
assertEquals(-1L, h.getStatistic(node("a"), Node.ANY, node("b")));
//
assertEquals(0L, h.getStatistic(node("no"), node("P"), Node.ANY));
}
}
@ContractTest
public void testStatisticsWithOnlyVariables() {
testStatsWithAllVariables("");
testStatsWithAllVariables("a P b");
testStatsWithAllVariables("a P b; a P c");
testStatsWithAllVariables("a P b; a P c; a Q b; x S y");
}
private void testStatsWithAllVariables(String triples) {
Graph g = graphWith(producer.newInstance(), triples);
GraphStatisticsHandler h = g.getStatisticsHandler();
if (h != null) {
assertEquals(g.size(), h.getStatistic(Node.ANY, Node.ANY, Node.ANY));
}
}
@ContractTest
public void testStatsWithConcreteTriple() {
testStatsWithConcreteTriple(0, "x P y", "");
}
private void testStatsWithConcreteTriple(int expect, String triple,
String graph) {
Graph g = graphWith(producer.newInstance(), graph);
GraphStatisticsHandler h = g.getStatisticsHandler();
if (h != null) {
Triple t = triple(triple);
assertEquals(
expect,
h.getStatistic(t.getSubject(), t.getPredicate(),
t.getObject()));
}
}
@ContractTest
public void testBrokenIndexes() {
Graph g = graphWith(producer.newInstance(), "x R y; x S z");
if (g.getCapabilities().iteratorRemoveAllowed()) {
try {
ExtendedIterator<Triple> it = g.find(Node.ANY, Node.ANY,
Node.ANY);
it.removeNext();
it.removeNext();
assertFalse(g.find(node("x"), Node.ANY, Node.ANY).hasNext());
assertFalse(g.find(Node.ANY, node("R"), Node.ANY).hasNext());
assertFalse(g.find(Node.ANY, Node.ANY, node("y")).hasNext());
} catch (UnsupportedOperationException e) {
fail("Error attempting to remove nodes " + e.getMessage());
}
}
}
@ContractTest
public void testBrokenSubject() {
Graph g = graphWith(producer.newInstance(), "x brokenSubject y");
if (g.getCapabilities().iteratorRemoveAllowed()) {
try {
ExtendedIterator<Triple> it = g.find(node("x"), Node.ANY,
Node.ANY);
it.removeNext();
assertFalse(g.find(Node.ANY, Node.ANY, Node.ANY).hasNext());
} catch (UnsupportedOperationException e) {
fail("Error attempting to remove nodes " + e.getMessage());
}
}
}
@ContractTest
public void testBrokenPredicate() {
Graph g = graphWith(producer.newInstance(), "x brokenPredicate y");
if (g.getCapabilities().iteratorRemoveAllowed()) {
try {
ExtendedIterator<Triple> it = g.find(Node.ANY,
node("brokenPredicate"), Node.ANY);
it.removeNext();
assertFalse(g.find(Node.ANY, Node.ANY, Node.ANY).hasNext());
} catch (UnsupportedOperationException e) {
fail("Error attempting to remove nodes " + e.getMessage());
}
}
}
@ContractTest
public void testBrokenObject() {
Graph g = graphWith(producer.newInstance(), "x brokenObject y");
if (g.getCapabilities().iteratorRemoveAllowed()) {
try {
ExtendedIterator<Triple> it = g.find(Node.ANY, Node.ANY,
node("y"));
it.removeNext();
assertFalse(g.find(Node.ANY, Node.ANY, Node.ANY).hasNext());
} catch (UnsupportedOperationException e) {
fail("Error attempting to remove nodes " + e.getMessage());
}
}
}
}