You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by cl...@apache.org on 2015/05/23 08:58:14 UTC
[04/25] jena git commit: Added initial contract tests added
testing_framework
Added initial contract tests
added testing_framework
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/4d1b0d96
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/4d1b0d96
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/4d1b0d96
Branch: refs/heads/master
Commit: 4d1b0d96df6339bcb7fdab3f42453b5814c4c2a2
Parents: c32457d
Author: Claude Warren <cl...@apache.org>
Authored: Sun Apr 26 20:41:15 2015 +0100
Committer: Claude Warren <cl...@apache.org>
Committed: Sun Apr 26 20:41:15 2015 +0100
----------------------------------------------------------------------
jena-core/pom.xml | 396 ++--
.../apache/jena/graph/GraphContractTest.java | 1720 ++++++++++++++++++
.../graph/GraphEventManagerContractTest.java | 514 ++++++
.../jena/graph/GraphMakerContractTest.java | 314 ++++
.../graph/GraphWithPerformContractTest.java | 86 +
.../jena/graph/RecordingGraphListener.java | 92 +
.../graph/TransactionHandlerContractTest.java | 149 ++
.../apache/jena/graph/compose/DeltaTest.java | 110 ++
.../jena/graph/compose/DifferenceTest.java | 97 +
.../jena/graph/compose/IntersectionTest.java | 109 ++
.../apache/jena/graph/compose/UnionTest.java | 185 ++
.../jena/graph/impl/TestCollectionGraph.java | 42 +-
.../jena/graph/impl/TestWrappedGraph.java | 63 +
.../graph/impl/TripleStoreContractTest.java | 176 ++
.../apache/jena/mem/BunchMapContractTest.java | 163 ++
.../java/org/apache/jena/mem/GraphMemTest.java | 115 ++
.../apache/jena/mem/GraphTripleStoreTest.java | 51 +
.../jena/mem/TripleBunchContractTest.java | 205 +++
.../AbstractGraphProducer.java | 104 ++
.../AbstractInfModelProducer.java | 91 +
.../AbstractModelProducer.java | 88 +
.../AbstractRecordingListener.java | 190 ++
.../testing_framework/ContractTemplate.java | 17 +
.../GraphEventManagerProducerInterface.java | 35 +
.../jena/testing_framework/GraphHelper.java | 508 ++++++
.../GraphProducerInterface.java | 41 +
.../testing_framework/IContainerProducer.java | 19 +
.../testing_framework/IIteratorProducer.java | 42 +
.../jena/testing_framework/INodeProducer.java | 39 +
.../testing_framework/IResourceProducer.java | 10 +
.../testing_framework/IStatementProducer.java | 45 +
.../testing_framework/ITripleStoreProducer.java | 35 +
.../jena/testing_framework/ModelHelper.java | 409 +++++
.../jena/testing_framework/NodeCreateUtils.java | 177 ++
.../NodeProducerInterface.java | 32 +
.../jena/testing_framework/TestFileData.java | 380 ++++
.../jena/testing_framework/TestUtils.java | 320 ++++
.../testing_framework/manifest/Manifest.java | 228 +++
.../manifest/ManifestException.java | 48 +
.../manifest/ManifestFile.java | 38 +
.../manifest/ManifestItem.java | 53 +
.../manifest/ManifestItemHandler.java | 35 +
.../manifest/ManifestSuite.java | 143 ++
.../manifest/ManifestTest.java | 13 +
.../manifest/ManifestTestRunner.java | 75 +
.../jena/testing_framework/package-info.java | 109 ++
.../testing_framework/tuples/TupleItem.java | 84 +
.../jena/testing_framework/tuples/TupleSet.java | 274 +++
48 files changed, 8062 insertions(+), 207 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/4d1b0d96/jena-core/pom.xml
----------------------------------------------------------------------
diff --git a/jena-core/pom.xml b/jena-core/pom.xml
index 9deb931..1c2ff5a 100644
--- a/jena-core/pom.xml
+++ b/jena-core/pom.xml
@@ -1,203 +1,199 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <artifactId>jena-core</artifactId>
- <packaging>jar</packaging>
- <name>Apache Jena - Core</name>
- <version>3.0.0-SNAPSHOT</version>
-
- <parent>
- <groupId>org.apache.jena</groupId>
- <artifactId>jena-parent</artifactId>
- <version>14-SNAPSHOT</version>
- <relativePath>../jena-parent</relativePath>
- </parent>
-
- <description>Jena is a Java framework for building Semantic Web applications. It provides a programmatic environment for RDF, RDFS and OWL, SPARQL and includes a rule-based inference engine.</description>
-
- <properties>
- <maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ssZ</maven.build.timestamp.format>
- <build.time.xsd>${maven.build.timestamp}</build.time.xsd>
- </properties>
-
- <dependencies>
-
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.apache.jena</groupId>
- <artifactId>jena-iri</artifactId>
- <version>3.0.0-SNAPSHOT</version>
- </dependency>
-
- <dependency>
- <groupId>xerces</groupId>
- <artifactId>xercesImpl</artifactId>
- </dependency>
-
- </dependencies>
-
- <build>
-
- <resources>
-
- <!-- Legacy -->
- <resource>
- <directory>etc</directory>
- <targetPath>etc</targetPath>
- <filtering>false</filtering>
- </resource>
-
- <resource>
- <filtering>false</filtering>
- <directory>src/main/resources</directory>
- </resource>
-
- <resource>
- <directory>src/main/resources</directory>
- <includes>
- <include>org/apache/jena/jena-properties.xml</include>
- </includes>
- <filtering>true</filtering>
- </resource>
-
- </resources>
-
- <plugins>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <systemProperties>
- <property>
- <name>log4j.configuration</name>
- <value>jena-test-log4j.properties</value>
- </property>
- </systemProperties>
- <includes>
- <include>com/hp/hpl/jena/test/TestPackage.java</include>
- </includes>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-sources</id>
- <phase>package</phase>
- <goals>
- <goal>jar-no-fork</goal>
- </goals>
- </execution>
- <execution>
- <id>attach-sources-test</id>
- <phase>package</phase>
- <goals>
- <goal>test-jar-no-fork</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <configuration>
- <author>true</author>
- <version>true</version>
- <show>public</show>
- <quiet>true</quiet>
- <encoding>UTF-8</encoding>
- <windowtitle>Apache Jena</windowtitle>
- <doctitle>Apache Jena Core ${project.version}</doctitle>
- <bottom>Licenced under the Apache License, Version 2.0</bottom>
- <excludePackageNames>com.hp.hpl.jena.shared.*:*.impl:com.hp.hpl.jena.assembler.assemblers:*.exceptions:*.regexptrees:com.hp.hpl.jena.mem:com.hp.hpl.jena.mem.*:com.hp.hpl.jena.n3:com.hp.hpl.jena.n3.*:com.hp.hpl.jena.rdf.arp.*:com.hp.hpl.jena.util.*:jena.cmdline:jena.util</excludePackageNames>
- <groups>
- <group>
- <title>API - Application Programming Interface</title>
- <packages>com.hp.hpl.jena.db:com.hp.hpl.jena.rdf.model:com.hp.hpl.jena.rdf.listeners:com.hp.hpl.jena.rdf.arp:com.hp.hpl.jena.rdf.arp.lang:com.hp.hpl.jena.datatypes:com.hp.hpl.jena.datatypes.xsd:com.hp.hpl.jena.rdql:com.hp.hpl.jena.shared:com.hp.hpl.jena.vocabulary:com.hp.hpl.jena.xmloutput:com.hp.hpl.jena.ontology:com.hp.hpl.jena.ontology.daml:com.hp.hpl.jena.reasoner:com.hp.hpl.jena.reasoner.rulesys:com.hp.hpl.jena.reasoner.rulesys.builtins:com.hp.hpl.jena.reasoner.transitiveReasoner:com.hp.hpl.jena.reasoner.dig</packages>
- </group>
- <group>
- <title>SPI - System Programming Interface</title>
- <packages>com.hp.hpl.jena.enhanced:com.hp.hpl.jena.graph:com.hp.hpl.jena.graph.compose:com.hp.hpl.jena.graph.query:com.hp.hpl.jena.util:com.hp.hpl.jena.util.iterator</packages>
- </group>
- <group>
- <title>Command line tools</title>
- <packages>jena</packages>
- </group>
- <group>
- <title>Other Packages</title>
- <packages>com.hp.hpl.jena.assembler</packages>
- </group>
- </groups>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <!--
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- </plugin>
- <!- - see: http://maven.apache.org/guides/mini/guide-attached-tests.html - ->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- -->
- </plugins>
- </build>
+<!-- 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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jena-core</artifactId>
+ <packaging>jar</packaging>
+ <name>Apache Jena - Core</name>
+ <version>3.0.0-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-parent</artifactId>
+ <version>14-SNAPSHOT</version>
+ <relativePath>../jena-parent</relativePath>
+ </parent>
+
+ <description>Jena is a Java framework for building Semantic Web applications. It provides a programmatic environment for RDF, RDFS and OWL, SPARQL and includes a rule-based inference engine.</description>
+
+ <properties>
+ <maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ssZ</maven.build.timestamp.format>
+ <build.time.xsd>${maven.build.timestamp}</build.time.xsd>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-iri</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.xenei</groupId>
+ <artifactId>junit-contracts</artifactId>
+ <version>0.0.5</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.9.5</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+
+ <resources>
+
+ <!-- Legacy -->
+ <resource>
+ <directory>etc</directory>
+ <targetPath>etc</targetPath>
+ <filtering>false</filtering>
+ </resource>
+
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/resources</directory>
+ </resource>
+
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>org/apache/jena/jena-properties.xml</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+
+ </resources>
+
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <property>
+ <name>log4j.configuration</name>
+ <value>jena-test-log4j.properties</value>
+ </property>
+ </systemProperties>
+ <includes>
+ <include>com/hp/hpl/jena/test/TestPackage.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>attach-sources-test</id>
+ <phase>package</phase>
+ <goals>
+ <goal>test-jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <author>true</author>
+ <version>true</version>
+ <show>public</show>
+ <quiet>true</quiet>
+ <encoding>UTF-8</encoding>
+ <windowtitle>Apache Jena</windowtitle>
+ <doctitle>Apache Jena Core ${project.version}</doctitle>
+ <bottom>Licenced under the Apache License, Version 2.0</bottom>
+ <excludePackageNames>com.hp.hpl.jena.shared.*:*.impl:com.hp.hpl.jena.assembler.assemblers:*.exceptions:*.regexptrees:com.hp.hpl.jena.mem:com.hp.hpl.jena.mem.*:com.hp.hpl.jena.n3:com.hp.hpl.jena.n3.*:com.hp.hpl.jena.rdf.arp.*:com.hp.hpl.jena.util.*:jena.cmdline:jena.util</excludePackageNames>
+ <groups>
+ <group>
+ <title>API - Application Programming Interface</title>
+ <packages>com.hp.hpl.jena.db:com.hp.hpl.jena.rdf.model:com.hp.hpl.jena.rdf.listeners:com.hp.hpl.jena.rdf.arp:com.hp.hpl.jena.rdf.arp.lang:com.hp.hpl.jena.datatypes:com.hp.hpl.jena.datatypes.xsd:com.hp.hpl.jena.rdql:com.hp.hpl.jena.shared:com.hp.hpl.jena.vocabulary:com.hp.hpl.jena.xmloutput:com.hp.hpl.jena.ontology:com.hp.hpl.jena.ontology.daml:com.hp.hpl.jena.reasoner:com.hp.hpl.jena.reasoner.rulesys:com.hp.hpl.jena.reasoner.rulesys.builtins:com.hp.hpl.jena.reasoner.transitiveReasoner:com.hp.hpl.jena.reasoner.dig</packages>
+ </group>
+ <group>
+ <title>SPI - System Programming Interface</title>
+ <packages>com.hp.hpl.jena.enhanced:com.hp.hpl.jena.graph:com.hp.hpl.jena.graph.compose:com.hp.hpl.jena.graph.query:com.hp.hpl.jena.util:com.hp.hpl.jena.util.iterator</packages>
+ </group>
+ <group>
+ <title>Command line tools</title>
+ <packages>jena</packages>
+ </group>
+ <group>
+ <title>Other Packages</title>
+ <packages>com.hp.hpl.jena.assembler</packages>
+ </group>
+ </groups>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId>
+ </plugin> <!- - see: http://maven.apache.org/guides/mini/guide-attached-tests.html
+ - -> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId>
+ <executions> <execution> <goals> <goal>test-jar</goal> </goals> </execution>
+ </executions> </plugin> -->
+ </plugins>
+ </build>
</project>
http://git-wip-us.apache.org/repos/asf/jena/blob/4d1b0d96/jena-core/src/test/java/org/apache/jena/graph/GraphContractTest.java
----------------------------------------------------------------------
diff --git a/jena-core/src/test/java/org/apache/jena/graph/GraphContractTest.java b/jena-core/src/test/java/org/apache/jena/graph/GraphContractTest.java
new file mode 100644
index 0000000..cf79da5
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/graph/GraphContractTest.java
@@ -0,0 +1,1720 @@
+/*
+ * 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 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 org.junit.After;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xenei.junit.contract.Contract;
+import org.xenei.junit.contract.ContractTest;
+
+import static org.junit.Assert.*;
+
+import org.apache.jena.graph.Capabilities;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.GraphStatisticsHandler;
+import org.apache.jena.graph.GraphUtil;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.Triple;
+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.ContractTemplate;
+import org.apache.jena.testing_framework.NodeCreateUtils;
+import org.apache.jena.util.iterator.ClosableIterator;
+import org.apache.jena.util.iterator.ExtendedIterator;
+import org.apache.jena.util.iterator.Map1;
+
+import static org.apache.jena.testing_framework.GraphHelper.*;
+
+/**
+ * AbstractTestGraph provides a bunch of basic tests for something that purports
+ * to be a Graph. The abstract method getGraph must be overridden in subclasses
+ * to deliver a Graph of interest.
+ */
+@Contract(Graph.class)
+public class GraphContractTest<T extends Graph> extends
+ ContractTemplate<AbstractGraphProducer<T>> {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(GraphContractTest.class);
+
+ protected RecordingGraphListener GL = new RecordingGraphListener();
+
+ @Contract.Inject
+ public final void setGraphContractTestProducer(
+ AbstractGraphProducer<T> graphProducer) {
+ super.setProducer(graphProducer);
+ }
+
+ @After
+ public final void afterGraphContractTest() {
+ getProducer().cleanUp();
+ GL.clear();
+ }
+
+ @ContractTest
+ public void testAdd_Triple() {
+ Graph graph = getProducer().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 = getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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 (getProducer().newInstance().getCapabilities()
+ .handlesLiteralTyping()) {
+ Graph g1 = graphWith(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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 (getProducer().newInstance().getCapabilities()
+ .handlesLiteralTyping()) {
+ Graph g1 = graphWith(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().newInstance(),
+ "S P O; S2 P2 O2; S3 P3 O3");
+ Graph base = getProducer().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 = getProducer().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 = getProducer().newInstance();
+ Graph[] depGraphs = getProducer().getDependsOn(g);
+ if (depGraphs != null) {
+ for (Graph dg : depGraphs) {
+ assertTrue(
+ String.format("Graph %s should depend upon %s", g, dg),
+ g.dependsOn(dg));
+ }
+ }
+ depGraphs = getProducer().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(getProducer().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(getProducer().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 = getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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 = getProducer().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(getProducer().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(getProducer().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 = getProducer().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", getProducer()
+ .newInstance().getEventManager());
+ }
+
+ @ContractTest
+ public void testGetPrefixMapping() {
+ Graph g = getProducer().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 = getProducer().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 = getProducer().newInstance();
+ assertNotNull("Must return a Transaction handler",
+ g.getTransactionHandler());
+ }
+
+ @ContractTest
+ public void testIsClosed() {
+ Graph g = getProducer().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 = getProducer().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 = getProducer().newInstance();
+ Graph g2 = memGraph();
+ assertTrue("Empty graphs should be isomorphic",
+ graph.isIsomorphicWith(g2));
+
+ graph = graphWith(getProducer().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 = getProducer().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 = getProducer().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(getProducer().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 = getProducer().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 = getProducer().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 = getProducer().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 = getProducer().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 = getProducer().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 = getProducer().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 FileNotFoundException
+ */
+ @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)
+ throws URISyntaxException, MalformedURLException {
+ testIsomorphismFile(i, "N-TRIPLE", "nt", result);
+ }
+
+ private void testIsomorphismXMLFile(int i, boolean result)
+ throws URISyntaxException, MalformedURLException {
+ testIsomorphismFile(i, "RDF/XML", "rdf", result);
+
+ }
+
+ private InputStream getInputStream(int n, int n2, String suffix)
+ throws URISyntaxException, MalformedURLException {
+ 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) throws URISyntaxException, MalformedURLException {
+
+ Graph g1 = getProducer().newInstance();
+ Graph g2 = getProducer().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 = getProducer().newInstance();
+ result.close();
+ return result;
+ }
+
+ // @ContractTest
+ // public void testTransactionCommit()
+ // {
+ // Graph g = getProducer().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 = getProducer().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 = getProducer().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 = getProducer().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(getProducer().newInstance(), "a R b; b S e");
+ Graph dest = graphWith(getProducer().newInstance(), "b R d");
+ GraphExtract e = new GraphExtract(TripleBoundary.stopNowhere);
+ e.extractInto(dest, node("a"), source);
+ assertIsomorphic(
+ graphWith(getProducer().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(getProducer().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 = getProducer().newInstance();
+ if (g.getTransactionHandler().transactionsSupported()) {
+ Graph initial = graphWith(getProducer().newInstance(),
+ "initial hasValue 42; also hasURI hello");
+ Graph extra = graphWith(getProducer().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 = getProducer().newInstance();
+ if (g.getTransactionHandler().transactionsSupported()) {
+ Graph initial = graphWith(getProducer().newInstance(),
+ "initial hasValue 42; also hasURI hello");
+ Graph extra = graphWith(getProducer().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 = getProducer().newInstance();
+ if (g.getTransactionHandler().transactionsSupported()) {
+ Graph initial = graphWith(getProducer().newInstance(),
+ "Foo pings B; B pings C");
+ Graph extra = graphWith(getProducer().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 Map1<Triple, Node> getObject = new Map1<Triple, Node>() {
+ @Override
+ public Node map1(Triple o) {
+ return o.getObject();
+ }
+ };
+
+ private void testLiteralTypingBasedFind(final String data, final int size,
+ final String search, final String results, boolean reqLitType) {
+
+ Graph g = getProducer().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);
+ testLiteralTypingBasedFind("a P 'simple'xsd:string", 1,
+ "'simple'xsd:string", "'simple'xsd:string", false);
+// testLiteralTypingBasedFind("a P 'simple'; a P 'simple'xsd:string", 2,
+// "'simple'", "'simple' 'simple'xsd:string", true);
+// testLiteralTypingBasedFind("a P 'simple'; a P 'simple'xsd:string", 2,
+// "'simple'xsd:string", "'simple' 'simple'xsd:string", 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 = getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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(getProducer().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());
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/4d1b0d96/jena-core/src/test/java/org/apache/jena/graph/GraphEventManagerContractTest.java
----------------------------------------------------------------------
diff --git a/jena-core/src/test/java/org/apache/jena/graph/GraphEventManagerContractTest.java b/jena-core/src/test/java/org/apache/jena/graph/GraphEventManagerContractTest.java
new file mode 100644
index 0000000..426002d
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/graph/GraphEventManagerContractTest.java
@@ -0,0 +1,514 @@
+/*
+ * 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 java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.mockito.Mockito;
+import org.xenei.junit.contract.Contract;
+import org.xenei.junit.contract.ContractTest;
+
+import static org.junit.Assert.*;
+
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.GraphEventManager;
+import org.apache.jena.graph.Triple;
+import org.apache.jena.graph.Factory;
+import org.apache.jena.testing_framework.ContractTemplate;
+import org.apache.jena.testing_framework.GraphHelper;
+import org.xenei.junit.contract.IProducer;
+import org.apache.jena.testing_framework.NodeCreateUtils;
+
+import static org.apache.jena.testing_framework.GraphHelper.*;
+
+/**
+ * An abstract test that tests EventManager implementations to ensure they
+ * comply with the EventManager contract.
+ *
+ * Subclasses of this class must implement the getEventManagerProducer() method
+ * to create a new instance of the EventManager for testing.
+ */
+
+@Contract(GraphEventManager.class)
+public class GraphEventManagerContractTest<T extends GraphEventManager> extends
+ ContractTemplate<IProducer<T>> {
+
+ protected static final Triple[] tripleArray = tripleArray("S P O; Foo R B; X Q Y");
+
+ // the graph that is used as the source of the events.
+ private Graph mockGraph;
+ // The event manager we are working with.
+ private GraphEventManager gem;
+
+ public GraphEventManagerContractTest() {
+// setProducer(new IProducer<T>() {
+//
+// @SuppressWarnings("unchecked")
+// @Override
+// public T newInstance() {
+// return (T) Factory.createGraphMem().getEventManager();
+// }
+//
+// @Override
+// public void cleanUp() {
+// }
+// });
+
+ }
+
+ @Contract.Inject
+ public final void setGraphEventManagerContractTestProducer(
+ IProducer<T> producer) {
+ super.setProducer(producer);
+ }
+
+ @After
+ public final void afterGraphEventManagerContractTest() {
+ getProducer().cleanUp();
+ }
+
+ @Before
+ public final void beforeGraphEventManagerContractTest() {
+ mockGraph = Mockito.mock(Graph.class);
+ gem = getProducer().newInstance();
+ L = new RecordingGraphListener();
+ }
+
+ /**
+ * Test that when a listener is registered the same EventManager is
+ * returned.
+ */
+ @ContractTest
+ public void testEventRegister() {
+ assertSame(gem, gem.register(new RecordingGraphListener()));
+ }
+
+ /**
+ * Test that we can safely unregister a listener that isn't registered.
+ */
+ @ContractTest
+ public void testEventUnregister() {
+ assertSame(gem, gem.unregister(L));
+ }
+
+ /**
+ * Handy triple for test purposes.
+ */
+ protected Triple SPO = NodeCreateUtils.createTriple("S P O");
+
+ /**
+ * The RecordingListener that reports all the events sent from the
+ * EventManager.
+ */
+ protected RecordingGraphListener L;
+
+ /**
+ * Test that adding a triple is reported.
+ */
+ @ContractTest
+ public void testAddTriple() {
+ gem.register(L);
+ gem.notifyAddTriple(mockGraph, SPO);
+ L.assertHas(new Object[] { "add", mockGraph, SPO });
+ }
+
+ /**
+ * Test that deleting a triple is reported.
+ */
+ @ContractTest
+ public void testDeleteTriple() {
+ gem.register(L);
+ gem.notifyDeleteTriple(mockGraph, SPO);
+ L.assertHas(new Object[] { "delete", mockGraph, SPO });
+ }
+
+ /**
+ * Test that when 2 listeners are added both receive events.
+ */
+ @ContractTest
+ public void testTwoListeners() {
+ RecordingGraphListener L1 = new RecordingGraphListener();
+ RecordingGraphListener L2 = new RecordingGraphListener();
+ gem.register(L1).register(L2);
+ gem.notifyAddTriple(mockGraph, SPO);
+ L2.assertHas(new Object[] { "add", mockGraph, SPO });
+ L1.assertHas(new Object[] { "add", mockGraph, SPO });
+ }
+
+ /**
+ * Test that unregistering a listener after registering it results in it not
+ * receiving messages.
+ */
+ @ContractTest
+ public void testUnregisterWorks() {
+ gem.register(L).unregister(L);
+ gem.notifyAddTriple(mockGraph, SPO);
+ L.assertHas(new Object[] {});
+ }
+
+ /**
+ * Test that registering a listener twice results in the listener receiving
+ * the events twice.
+ */
+ @ContractTest
+ public void testRegisterTwice() {
+ gem.register(L).register(L);
+ gem.notifyAddTriple(mockGraph, SPO);
+ L.assertHas(new Object[] { "add", mockGraph, SPO, "add", mockGraph, SPO });
+ }
+
+ /**
+ * Test that registering a listener twice and unregistering it once will
+ * result in the listener receiving each event one time.
+ */
+ @ContractTest
+ public void testUnregisterOnce() {
+ gem.register(L).register(L).unregister(L);
+ gem.notifyDeleteTriple(mockGraph, SPO);
+ L.assertHas(new Object[] { "delete", mockGraph, SPO });
+ }
+
+ /**
+ * Test that adding an array is reported as adding an array.
+ */
+ @ContractTest
+ public void testAddArray() {
+ gem.register(L);
+ gem.notifyAddArray(mockGraph, tripleArray);
+ L.assertHas(new Object[] { "add[]", mockGraph, tripleArray });
+ }
+
+ /**
+ * Test that adding a list is reported as adding a list
+ */
+ @ContractTest
+ public void testAddList() {
+ gem.register(L);
+ List<Triple> elems = Arrays.asList(tripleArray);
+ gem.notifyAddList(mockGraph, elems);
+ L.assertHas(new Object[] { "addList", mockGraph, elems });
+ }
+
+ /**
+ * Test that deleting an array is reported as deleting an array.
+ */
+ @ContractTest
+ public void testDeleteArray() {
+ gem.register(L);
+ gem.notifyDeleteArray(mockGraph, tripleArray);
+ L.assertHas(new Object[] { "delete[]", mockGraph, tripleArray });
+ }
+
+ /**
+ * Test that deleting a list is reported as deleting a list.
+ */
+ @ContractTest
+ public void testDeleteList() {
+ gem.register(L);
+ List<Triple> elems = Arrays.asList(tripleArray);
+ gem.notifyDeleteList(mockGraph, elems);
+ L.assertHas(new Object[] { "deleteList", mockGraph, elems });
+ }
+
+ /**
+ * Test that adding a list as an iterator is reported as an add iterator.
+ */
+ @ContractTest
+ public void testAddListAsIterator() {
+ gem.register(L);
+ List<Triple> elems = Arrays.asList(tripleArray);
+ gem.notifyAddIterator(mockGraph, elems);
+ L.assertHas(new Object[] { "addIterator", mockGraph, elems });
+ }
+
+ /**
+ * Test that adding an iterator is reported as adding an iterator.
+ */
+ @ContractTest
+ public void testAddIterator() {
+ gem.register(L);
+ List<Triple> elems = Arrays.asList(tripleArray);
+ gem.notifyAddIterator(mockGraph, elems.iterator());
+ L.assertHas(new Object[] { "addIterator", mockGraph, elems });
+ }
+
+ /**
+ * Test that deleting an iterator is reported as a deleting an iterator.
+ */
+ @ContractTest
+ public void testDeleteIterator() {
+ gem.register(L);
+ List<Triple> elems = Arrays.asList(tripleArray);
+ gem.notifyDeleteIterator(mockGraph, elems.iterator());
+ L.assertHas(new Object[] { "deleteIterator", mockGraph, elems });
+ }
+
+ /**
+ * Test that deleting a list as an iterator is reported as deleting an
+ * iterator.
+ */
+ @ContractTest
+ public void testDeleteListAsIterator() {
+ gem.register(L);
+ List<Triple> elems = Arrays.asList(tripleArray);
+ gem.notifyDeleteIterator(mockGraph, elems);
+ L.assertHas(new Object[] { "deleteIterator", mockGraph, elems });
+ }
+
+ /**
+ * Test that adding a graph is reported as adding a graph.
+ */
+ @ContractTest
+ public void testAddGraph() {
+ gem.register(L);
+ Graph other = Mockito.mock(Graph.class);
+ gem.notifyAddGraph(mockGraph, other);
+ L.assertHas(new Object[] { "addGraph", mockGraph, other });
+ }
+
+ /**
+ * Test that deleting a graph is reported as deleting a graph.
+ */
+ @ContractTest
+ public void testDeleteGraph() {
+ gem.register(L);
+ Graph other = Mockito.mock(Graph.class);
+ gem.notifyDeleteGraph(mockGraph, other);
+ L.assertHas(new Object[] { "deleteGraph", mockGraph, other });
+ }
+
+ /**
+ * Test that sending a general event is reported as an event and the value
+ * is saved.
+ */
+ @ContractTest
+ public void testGeneralEvent() {
+ gem.register(L);
+ Object value = new int[] {};
+ gem.notifyEvent(mockGraph, value);
+ L.assertHas(new Object[] { "someEvent", mockGraph, value });
+ }
+
+ @ContractTest
+ public void testListening() {
+ assertFalse("Should not be listening", gem.listening());
+ gem.register(L);
+ assertTrue("Should be listening", gem.listening());
+ gem.unregister(L);
+ assertFalse("Should not be listening", gem.listening());
+ }
+
+ //
+ // Foo series of tests to check modifying the manger in mid notification
+ //
+
+ private ComeAndGoListener all[];
+
+ abstract private static class ComeAndGoListener implements GraphListener {
+
+ // Was I registered when start() was called, and have not been
+ // unregistered.
+ boolean inPlay = false;
+ // currently registered or not.
+ boolean registered = false;
+ boolean notified = false;
+
+ void register(GraphEventManager gem) {
+ registered = true;
+ gem.register(this);
+ }
+
+ void unregister(GraphEventManager gem) {
+ registered = false;
+ inPlay = false;
+ gem.unregister(this);
+ }
+
+ void start() {
+ if (registered)
+ inPlay = true;
+ }
+
+ void check() {
+ if (inPlay && !notified)
+ fail("listener that was in-play was not notified of adding triple.");
+ }
+
+ @Override
+ final public void notifyAddTriple(Graph g, Triple t) {
+ notified = true;
+ doSomeDamage();
+ }
+
+ abstract void doSomeDamage();
+
+ @Override
+ public void notifyAddArray(Graph g, Triple[] triples) {
+ }
+
+ @Override
+ public void notifyAddGraph(Graph g, Graph added) {
+ }
+
+ @Override
+ public void notifyAddIterator(Graph g, Iterator<Triple> it) {
+ }
+
+ @Override
+ public void notifyAddList(Graph g, List<Triple> triples) {
+ }
+
+ @Override
+ public void notifyDeleteArray(Graph g, Triple[] triples) {
+ }
+
+ @Override
+ public void notifyDeleteGraph(Graph g, Graph removed) {
+ }
+
+ @Override
+ public void notifyDeleteIterator(Graph g, Iterator<Triple> it) {
+ }
+
+ @Override
+ public void notifyDeleteList(Graph g, List<Triple> L) {
+ }
+
+ @Override
+ public void notifyDeleteTriple(Graph g, Triple t) {
+ }
+
+ @Override
+ public void notifyEvent(Graph source, Object value) {
+ }
+
+ }
+
+ /**
+ * ComeAndGoListener implementation that does no damage
+ *
+ */
+ private static final class SimpleListener extends ComeAndGoListener {
+ @Override
+ void doSomeDamage() {
+ }
+ }
+
+ /**
+ * Test adding a triple to trigger event.
+ *
+ * @param registerTo
+ * Number of listeners to register.
+ * @param allx
+ */
+ private void testAddingTriple(int registerTo, ComeAndGoListener... allx) {
+ all = allx;
+ // register addMe
+ for (int i = 0; i < registerTo; i++) {
+ all[i].register(gem);
+ }
+
+ // start them all
+ for (ComeAndGoListener l : all) {
+ l.start();
+ }
+ // send the notification.
+ gem.notifyAddTriple(mockGraph, GraphHelper.triple("make a change"));
+ // check them
+ for (ComeAndGoListener l : all) {
+ l.check();
+ }
+ }
+
+ /**
+ * Test that a listener added during event processing does not receive the
+ * event.
+ */
+ @ContractTest
+ public void testAddOne() {
+ testAddingTriple(2, new ComeAndGoListener() {
+ @Override
+ void doSomeDamage() {
+ all[2].register(gem);
+ }
+ }, new SimpleListener(), new SimpleListener());
+ }
+
+ /**
+ * Test that when a listener that has not yet been handled is removed during
+ * event processing it receive the event.
+ */
+ @ContractTest
+ public void testDelete2nd() {
+ testAddingTriple(3, new ComeAndGoListener() {
+ @Override
+ void doSomeDamage() {
+ all[1].unregister(gem);
+ }
+ }, new SimpleListener(), new SimpleListener());
+ }
+
+ /**
+ * Test that when a listener that has been handled is removed during event
+ * processing it receives the event.
+ */
+ @ContractTest
+ public void testDelete1st() {
+ testAddingTriple(3, new SimpleListener(), new ComeAndGoListener() {
+ @Override
+ void doSomeDamage() {
+ all[0].unregister(gem);
+ }
+ }, new SimpleListener());
+ }
+
+ /**
+ * Test that when a listener that removes itself during event processing it
+ * receives the event.
+ */
+ @ContractTest
+ public void testDeleteSelf() {
+ testAddingTriple(3, new ComeAndGoListener() {
+ @Override
+ void doSomeDamage() {
+ unregister(gem);
+ }
+ }, new SimpleListener(), new SimpleListener());
+ }
+
+ /**
+ * Test that when a listener that removes and adds itself during event
+ * processing it receives the event.
+ */
+ @ContractTest
+ public void testDeleteAndAddSelf() {
+ testAddingTriple(3, new ComeAndGoListener() {
+ @Override
+ void doSomeDamage() {
+ unregister(gem);
+ register(gem);
+ }
+ }, new SimpleListener(), new SimpleListener());
+ }
+
+}