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 2013/10/09 19:16:18 UTC

svn commit: r1530718 [2/10] - in /jena/Experimental/new-test: ./ src/test/java/com/hp/hpl/jena/graph/ src/test/java/com/hp/hpl/jena/graph/compose/ src/test/java/com/hp/hpl/jena/graph/impl/ src/test/java/com/hp/hpl/jena/mem/ src/test/java/com/hp/hpl/jen...

Copied: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphContractTest.java (from r1523135, jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphTest.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphContractTest.java?p2=jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphContractTest.java&p1=jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphTest.java&r1=1523135&r2=1530718&rev=1530718&view=diff
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphTest.java (original)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphContractTest.java Wed Oct  9 17:16:15 2013
@@ -21,15 +21,16 @@ package com.hp.hpl.jena.graph;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
-
+import org.junit.After;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xenei.junit.contract.Contract;
+
 import static org.junit.Assert.*;
 
 import com.hp.hpl.jena.graph.Capabilities;
@@ -43,12 +44,15 @@ import com.hp.hpl.jena.mem.TrackingTripl
 import com.hp.hpl.jena.rdf.model.Model;
 import com.hp.hpl.jena.rdf.model.ModelFactory;
 import com.hp.hpl.jena.rdf.model.impl.ReifierStd;
+import com.hp.hpl.jena.shared.PrefixMappingContractTest;
 import com.hp.hpl.jena.shared.ClosedException;
-import com.hp.hpl.jena.testing_framework.AbstractGraphProducerUser;
+import com.hp.hpl.jena.shared.DeleteDeniedException;
+import com.hp.hpl.jena.shared.PrefixMapping;
+import org.xenei.junit.contract.IProducer;
 import com.hp.hpl.jena.testing_framework.NodeCreateUtils;
-import com.hp.hpl.jena.util.CollectionFactory;
 import com.hp.hpl.jena.util.iterator.ClosableIterator;
 import com.hp.hpl.jena.util.iterator.ExtendedIterator;
+import com.hp.hpl.jena.util.iterator.Map1;
 
 import static com.hp.hpl.jena.testing_framework.GraphHelper.*;
 
@@ -57,55 +61,319 @@ import static com.hp.hpl.jena.testing_fr
  * to be a Graph. The abstract method getGraph must be overridden in subclasses
  * to deliver a Graph of interest.
  */
+@Contract(Graph.class)
+public abstract class GraphContractTest {
 
-public abstract class AbstractGraphTest extends AbstractGraphProducerUser {
+	private static final Logger LOG = LoggerFactory
+			.getLogger(GraphContractTest.class);
 
-	protected Graph graphWithTxn(String s) {
-		Graph g = getGraphProducer().newGraph();
-		txnBegin(g);
-		try {
-			graphAdd(g, s);
-			txnCommit(g);
-		} catch (Exception e) {
-			txnRollback(g);
-			fail(e.getMessage());
-		}
-		return g;
+	@Contract.Inject( "org.xenei.junit.contract.IProducer<%s>" )
+	public abstract IProducer<? extends Graph> getGraphProducer();
+
+	protected RecordingGraphListener GL = new RecordingGraphListener();
+
+	@After
+	public final void afterAbstractGraphTest() {
+		getGraphProducer().cleanUp();
+		GL.clear();
 	}
 
 	@Test
-	public void testCloseSetsIsClosed() {
-		Graph g = getGraphProducer().newGraph();
-		assertFalse("unclosed Graph shouild not be isClosed()", g.isClosed());
-		g.close();
-		assertTrue("closed Graph should be isClosed()", g.isClosed());
+	public void testAdd_Triple() {
+		Graph graph = getGraphProducer().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")));
 	}
 
 	/**
-	 * This test case was generated by Ian and was caused by GraphMem not
-	 * keeping up with changes to the find interface.
+	 * Infrence graphs can not be truely 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 truely 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.
 	 */
 	@Test
-	public void testFindAndContains() {
-		Graph g = getGraphProducer().newGraph();
-		Node r = NodeCreateUtils.create("r"), s = NodeCreateUtils.create("s"), p = NodeCreateUtils
-				.create("P");
-		txnBegin(g);
+	public void testClear() {
+		Graph graph = getGraphProducer().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(getGraphProducer().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();
+
+	}
+
+	@Test
+	public void testClose() {
+		Graph graph = graphWith(getGraphProducer().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());
+
+		txnBegin(graph);
 		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());
+			graph.add(triple("S P O"));
+		} catch (Exception expected) {
+			// expected
+		} finally {
+			txnRollback(graph);
+		}
+
+		txnBegin(graph);
+		try {
+			graph.delete(triple("x R y"));
+			fail("delete when closed");
+		} catch (ClosedException c) {
+			// Expected
+		} finally {
+			txnRollback(graph);
+			GL.assertEmpty();
+		}
+
+		txnBegin(graph);
+		try {
+			graph.add(triple("x R y"));
+			fail("add when closed");
+		} catch (ClosedException c) { /* as required */
+		} finally {
+			txnRollback(graph);
+			GL.assertEmpty();
+		}
+
+		txnBegin(graph);
+		try {
+			graph.contains(triple("x R y"));
+			fail("contains[triple] when closed");
+		} catch (ClosedException c) { /* as required */
+		} finally {
+			txnRollback(graph);
+			GL.assertEmpty();
+		}
+
+		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();
+		}
+
+		txnBegin(graph);
+		try {
+			graph.find(triple("x R y"));
+			fail("find [triple] when closed");
+		} catch (ClosedException c) { /* as required */
+		} finally {
+			txnRollback(graph);
+			GL.assertEmpty();
+		}
+
+		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();
+		}
+
+		txnBegin(graph);
+		try {
+			graph.size();
+			fail("size when closed (" + this.getClass() + ")");
+		} catch (ClosedException c) { /* as required */
+		} finally {
+			txnRollback(graph);
+			GL.assertEmpty();
+		}
+	}
+
+	@Test
+	public void testContains_Node_Node_Node() {
+		Graph graph = graphWith(getGraphProducer().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));
+	}
+
+	@Test
+	public void testContains_Node_Node_Node_RepeatedSubjectDoesNotConceal() {
+
+		Graph g = graphWith(getGraphProducer().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));
+	}
+
+	@Test
+	public void testContains_Node_Node_Node_ByValue() {
+		Node x = node("x");
+		Node P = node("P");
+		if (getGraphProducer().newInstance().getCapabilities()
+				.handlesLiteralTyping()) {
+			Graph g1 = graphWith(getGraphProducer().newInstance(),
+					"x P '1'xsd:integer");
+			assertTrue(g1.contains(x, P, node("'01'xsd:int")));
+			//
+			Graph g2 = graphWith(getGraphProducer().newInstance(),
+					"x P '1'xsd:int");
+			assertTrue(g2.contains(x, P, node("'1'xsd:integer")));
+			//
+			Graph g3 = graphWith(getGraphProducer().newInstance(),
+					"x P '123'xsd:string");
+			assertTrue(g3.contains(x, P, node("'123'")));
 		}
 	}
 
 	@Test
-	public void testRepeatedSubjectDoesNotConceal() {
+	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(getGraphProducer().newInstance(),
+				"s P o; _x _R _y; x S 0");
+		assertTrue(g.contains(s, P, o));
+		assertTrue(g.contains(_x, _R, _y));
+		assertTrue(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")));
+	}
+
+	@Test
+	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(getGraphProducer().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));
+	}
+
+	@Test
+	public void testContains_Triple() {
+		Graph graph = graphWith(getGraphProducer().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)));
+
+	}
+
+	@Test
+	public void testContains_Triple_RepeatedSubjectDoesNotConceal() {
 
-		Graph g = graphWithTxn("s P o; s Q r");
+		Graph g = graphWith(getGraphProducer().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")));
@@ -115,17 +383,28 @@ public abstract class AbstractGraphTest 
 	}
 
 	@Test
-	public void testFindByFluidTriple() {
-		Graph g = graphWithTxn("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());
+	public void testContains_Triple_ByValue() {
+
+		if (getGraphProducer().newInstance().getCapabilities()
+				.handlesLiteralTyping()) {
+			Graph g1 = graphWith(getGraphProducer().newInstance(),
+					"x P '1'xsd:integer");
+			assertTrue(g1.contains(triple("x P '01'xsd:int")));
+			//
+			Graph g2 = graphWith(getGraphProducer().newInstance(),
+					"x P '1'xsd:int");
+			assertTrue(g2.contains(triple("x P '1'xsd:integer")));
+			//
+			Graph g3 = graphWith(getGraphProducer().newInstance(),
+					"x P '123'xsd:string");
+			assertTrue(g3.contains(triple("x P '123'")));
+		}
 	}
 
 	@Test
-	public void testContainsConcrete() {
-		Graph g = graphWithTxn("s P o; _x _R _y; x S 0");
+	public void testContains_Triple_Concrete() {
+		Graph g = graphWith(getGraphProducer().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")));
@@ -138,8 +417,8 @@ public abstract class AbstractGraphTest 
 	}
 
 	@Test
-	public void testContainsFluid() {
-		Graph g = graphWithTxn("x R y; a P b");
+	public void testContains_Triple_Fluid() {
+		Graph g = graphWith(getGraphProducer().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 ??")));
@@ -157,26 +436,112 @@ public abstract class AbstractGraphTest 
 	}
 
 	/**
-	 * Check that contains respects by-value semantics.
+	 * Inference graphs can not be empty
 	 */
 	@Test
-	public void testContainsByValue() {
-		if (getGraphProducer().newGraph().getCapabilities()
-				.handlesLiteralTyping()) {
-			Graph g1 = graphWithTxn("x P '1'xsd:integer");
-			assertTrue(g1.contains(triple("x P '01'xsd:int")));
-			//
-			Graph g2 = graphWithTxn("x P '1'xsd:int");
-			assertTrue(g2.contains(triple("x P '1'xsd:integer")));
-			//
-			Graph g3 = graphWithTxn("x P '123'xsd:string");
-			assertTrue(g3.contains(triple("x P '123'")));
-		}
+	public void testDelete_Triple() {
+		Graph graph = graphWith(getGraphProducer().newInstance(),
+				"S P O; S2 P2 O2; S3 P3 O3");
+		Graph base = getGraphProducer().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")));
+	}
+
+	@Test
+	public void testDelete_Triple_FromNothing() {
+		Graph g = getGraphProducer().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"));
+	}
+
+	@Test
+	public void testDependsOn() {
+		LOG.warn("testDependsOn should be overridden");
+	}
+
+	@Test
+	public void testFind_Node_Node_Node() {
+		Graph graph = graphWith(getGraphProducer().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());
+
 	}
 
 	@Test
-	public void testProgrammaticValues() {
-		Graph g = getGraphProducer().newGraph();
+	public void testFind_Node_Node_Node_ByFluidTriple() {
+		Node x = node("x");
+		Node y = node("y");
+		Node z = node("z");
+		Graph g = graphWith(getGraphProducer().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());
+	}
+
+	@Test
+	public void testFind_Node_Node_Node_ProgrammaticValues() {
+		Graph g = getGraphProducer().newInstance();
 		if (g.getCapabilities().handlesLiteralTyping()) {
 			Node ab = NodeFactory.createLiteral(LiteralLabelFactory
 					.create(new Byte((byte) 42)));
@@ -213,8 +578,8 @@ public abstract class AbstractGraphTest 
 	}
 
 	@Test
-	public void testMatchLanguagedLiteralCaseInsensitive() {
-		Graph m = graphWithTxn("a p 'chat'en");
+	public void testFind_Node_Node_Node_MatchLanguagedLiteralCaseInsensitive() {
+		Graph m = graphWith(getGraphProducer().newInstance(), "a p 'chat'en");
 		if (m.getCapabilities().handlesLiteralTyping()) {
 			Node chaten = node("'chat'en"), chatEN = node("'chat'EN");
 			assertDiffer(chaten, chatEN);
@@ -226,245 +591,338 @@ public abstract class AbstractGraphTest 
 	}
 
 	@Test
-	public void testMatchBothLanguagedLiteralsCaseInsensitive() {
-		Graph m = graphWithTxn("a p 'chat'en; a p 'chat'EN");
+	public void testFind_Node_Node_Node_NoMatchAgainstUnlanguagesLiteral() {
+		Graph m = graphWith(getGraphProducer().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(2, m.find(Node.ANY, Node.ANY, chaten).toList().size());
-			assertEquals(2, m.find(Node.ANY, Node.ANY, chatEN).toList().size());
+			assertEquals(1, m.find(Node.ANY, Node.ANY, chaten).toList().size());
+			assertEquals(1, m.find(Node.ANY, Node.ANY, chatEN).toList().size());
+		}
+	}
+
+	@Test
+	public void testFind_Triple() {
+		Graph graph = graphWith(getGraphProducer().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());
+
+	}
+
+	@Test
+	public void testFind_Triple_ByFluidTriple() {
+		Graph g = graphWith(getGraphProducer().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());
+	}
+
+	@Test
+	public void testFind_Triple_ProgrammaticValues() {
+		Graph g = getGraphProducer().newInstance();
+		if (g.getCapabilities().handlesLiteralTyping()) {
+			Node ab = NodeFactory.createLiteral(LiteralLabelFactory
+					.create(new Byte((byte) 42)));
+			Node as = NodeFactory.createLiteral(LiteralLabelFactory
+					.create(new Short((short) 42)));
+			Node ai = NodeFactory.createLiteral(LiteralLabelFactory
+					.create(new Integer(42)));
+			Node al = NodeFactory.createLiteral(LiteralLabelFactory
+					.create(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(
+					4,
+					iteratorToSet(
+							g.find(new Triple(Node.ANY, P, NodeCreateUtils
+									.create("42")))).size());
 		}
 	}
 
 	@Test
-	public void testNoMatchAgainstUnlanguagesLiteral() {
-		Graph m = graphWithTxn("a p 'chat'en; a p 'chat'");
+	public void testFind_Triple_MatchLanguagedLiteralCaseInsensitive() {
+		Graph m = graphWith(getGraphProducer().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());
+			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());
 		}
 	}
 
-	/**
-	 * test isEmpty - moved from the QueryHandler code.
-	 */
 	@Test
-	public void testIsEmpty() {
-		Graph g = getGraphProducer().newGraph();
-		if (canBeEmpty(g)) {
-			assertTrue(g.isEmpty());
-			txnBegin(g);
-			g.add(NodeCreateUtils.createTriple("S P O"));
-			txnCommit(g);
-			assertFalse(g.isEmpty());
-			txnBegin(g);
-			g.add(NodeCreateUtils.createTriple("A B C"));
-			txnCommit(g);
-			assertFalse(g.isEmpty());
-			txnBegin(g);
-			g.add(NodeCreateUtils.createTriple("S P O"));
-			txnCommit(g);
-			assertFalse(g.isEmpty());
-			txnBegin(g);
-			g.delete(NodeCreateUtils.createTriple("S P O"));
-			txnCommit(g);
-			assertFalse(g.isEmpty());
-			txnBegin(g);
-			g.delete(NodeCreateUtils.createTriple("A B C"));
-			txnCommit(g);
-			assertTrue(g.isEmpty());
+	public void testFind_Triple_NoMatchAgainstUnlanguagesLiteral() {
+		Graph m = graphWith(getGraphProducer().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());
 		}
 	}
 
 	@Test
-	public void testAGraph() {
-		String title = this.getClass().getName();
-		Graph g = getGraphProducer().newGraph();
-		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 testGetCapabilities() {
+		Graph g = getGraphProducer().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());
+		}
 	}
 
-	// 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
+	public void testGetEventManager() {
+		assertNotNull("Must return an EventManager", getGraphProducer()
+				.newInstance().getEventManager());
+	}
 
-	// /**
-	// Test that Graphs have transaction support methods, and that if they fail
-	// on some g they fail because they do not support the operation.
-	// */
-	// @Test
-	// public void testHasTransactions()
-	// {
-	// Graph g = getGraphProducer().newGraph();
-	// 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) {}
-	// }
-	//
-	// @Test
-	// public void testExecuteInTransactionCatchesThrowable()
-	// {Graph g = getGraphProducer().newGraph();
-	// 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) {}
-	// }
-	// }
+	@Test
+	public void testGetPrefixMapping() {
+		Graph g = getGraphProducer().newInstance();
+		PrefixMapping pm = g.getPrefixMapping();
+		assertNotNull("Must return prefix mapping", pm);
+		assertSame("getPrefixMapping must always return the same object", pm,
+				g.getPrefixMapping());
 
-	protected static final Triple[] tripleArray = tripleArray("S P O; A R B; X Q Y");
+		pm.setNsPrefix("pfx1", PrefixMappingContractTest.httpURI);
+		pm.setNsPrefix("pfx2", PrefixMappingContractTest.urnURI);
 
-	protected static final List<Triple> tripleList = Arrays
-			.asList(tripleArray("i lt j; p equals q"));
+		// assert same after adding to other mapl
+		assertSame("getPrefixMapping must always return the same object", pm,
+				g.getPrefixMapping());
 
-	protected static final Triple[] setTriples = tripleArray("scissors cut paper; paper wraps stone; stone breaks scissors");
+	}
 
-	protected static final Set<Triple> tripleSet = CollectionFactory
-			.createHashedSet(Arrays.asList(setTriples));
+	@Test
+	public void testGetStatisticsHandler() {
+		Graph g = getGraphProducer().newInstance();
+		GraphStatisticsHandler sh = g.getStatisticsHandler();
+		if (sh != null) {
+			assertSame(
+					"getStatisticsHandler must always return the same object",
+					sh, g.getStatisticsHandler());
+		}
+	}
 
 	@Test
-	public void testBulkUpdate() {
-		Graph g = getGraphProducer().newGraph();
-		Graph items = graphWithTxn("pigs might fly; dead can dance");
-		int initialSize = g.size();
-		/* */
-		txnBegin(g);
-		GraphUtil.add(g, tripleArray);
-		txnCommit(g);
-		testContains(g, tripleArray);
-		testOmits(g, tripleList);
-		/* */
-		txnBegin(g);
-		GraphUtil.add(g, tripleList);
-		txnCommit(g);
-		testContains(g, tripleList);
-		testContains(g, tripleArray);
-		/* */
-		txnBegin(g);
-		GraphUtil.add(g, tripleSet.iterator());
-		txnCommit(g);
-		testContains(g, tripleSet.iterator());
-		testContains(g, tripleList);
-		testContains(g, tripleArray);
-		/* */
-		txnBegin(g);
-		GraphUtil.addInto(g, items);
-		txnCommit(g);
-		testContains(g, items);
-		testContains(g, tripleSet.iterator());
-		testContains(g, tripleArray);
-		testContains(g, tripleList);
-		/* */
-		txnBegin(g);
-		GraphUtil.delete(g, tripleArray);
-		txnCommit(g);
-		testOmits(g, tripleArray);
-		testContains(g, tripleList);
-		testContains(g, tripleSet.iterator());
-		testContains(g, items);
-		/* */
-		txnBegin(g);
-		GraphUtil.delete(g, tripleSet.iterator());
-		txnCommit(g);
-		testOmits(g, tripleSet.iterator());
-		testOmits(g, tripleArray);
-		testContains(g, tripleList);
-		testContains(g, items);
-		/* */
-		txnBegin(g);
-		GraphUtil.deleteFrom(g, items);
-		txnCommit(g);
-		testOmits(g, tripleSet.iterator());
-		testOmits(g, tripleArray);
-		testContains(g, tripleList);
-		testOmits(g, items);
-		/* */
-		txnBegin(g);
-		GraphUtil.delete(g, tripleList);
-		txnCommit(g);
-		assertEquals("graph has original size", initialSize, g.size());
+	public void testGetTransactionHandler() {
+		Graph g = getGraphProducer().newInstance();
+		assertNotNull("Must return a Transaction handler",
+				g.getTransactionHandler());
 	}
 
 	@Test
-	public void testAddWithReificationPreamble() {
-		Graph g = getGraphProducer().newGraph();
-		txnBegin(g);
-		xSPO(g);
-		txnCommit(g);
-		assertFalse(g.isEmpty());
+	public void testIsClosed() {
+		Graph g = getGraphProducer().newInstance();
+		assertFalse("Graph created in closed state", g.isClosed());
+		g.close();
+		assertTrue("Graph does not report closed state after close called",
+				g.isClosed());
 	}
 
-	protected void xSPOyXYZ(Graph g) {
-		xSPO(g);
-		ReifierStd.reifyAs(g, NodeCreateUtils.create("y"),
-				NodeCreateUtils.createTriple("X Y Z"));
+	@Test
+	public void testIsEmpty() {
+		Graph g = getGraphProducer().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("A B C"));
+			g.delete(NodeCreateUtils.createTriple("S P O"));
+			txnCommit(g);
+			assertFalse("Should not report empty", g.isEmpty());
+			txnBegin(g);
+			g.delete(NodeCreateUtils.createTriple("A B C"));
+			txnCommit(g);
+			assertTrue("Should report empty after all entries deleted",
+					g.isEmpty());
+		}
 	}
 
-	protected void aABC(Graph g) {
-		ReifierStd.reifyAs(g, NodeCreateUtils.create("a"),
-				NodeCreateUtils.createTriple("A B C"));
+	@Test
+	public void testIsIsomorphicWith_Graph() {
+		Graph graph = getGraphProducer().newInstance();
+		Graph g2 = memGraph();
+		assertTrue("Empty graphs should be isomorphic",
+				graph.isIsomorphicWith(g2));
+
+		graph = graphWith(getGraphProducer().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));
 	}
 
-	protected void xSPO(Graph g) {
-		ReifierStd.reifyAs(g, NodeCreateUtils.create("x"),
-				NodeCreateUtils.createTriple("S P O"));
+	private Graph copy(Graph g) {
+		Graph result = getGraphProducer().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.
+	 */
 	@Test
-	public void testRemove() {
+	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 = getGraphProducer().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);
+			}
+	}
+
+	@Test
+	public void testRemove_ByIterator() {
 		testRemove("?? ?? ??", "?? ?? ??");
 		testRemove("S ?? ??", "S ?? ??");
 		testRemove("S ?? ??", "?? P ??");
@@ -477,8 +935,8 @@ public abstract class AbstractGraphTest 
 		testRemove("?? ?? O", "?? ?? O");
 	}
 
-	protected void testRemove(String findRemove, String findCheck) {
-		Graph g = graphWithTxn("S P O");
+	private void testRemove(String findRemove, String findCheck) {
+		Graph g = graphWith(getGraphProducer().newInstance(), "S P O");
 		ExtendedIterator<Triple> it = g.find(NodeCreateUtils
 				.createTriple(findRemove));
 		try {
@@ -489,284 +947,170 @@ public abstract class AbstractGraphTest 
 			assertFalse(g.contains(NodeCreateUtils.createTriple(findCheck)));
 		} catch (UnsupportedOperationException e) {
 			it.close();
-			assertFalse(g.getCapabilities().iteratorRemoveAllowed());
+			assertFalse(
+					"delete failed but capailities indicates it should work", g
+							.getCapabilities().iteratorRemoveAllowed());
 		}
-		it.close();
-	}
-
-	@Test
-	public void testFind() {
-		Graph g = graphWithTxn("S P O");
-		assertDiffer(new HashSet<Triple>(), g
-				.find(Node.ANY, Node.ANY, Node.ANY).toSet());
-		assertDiffer(new HashSet<Triple>(), g.find(Triple.ANY).toSet());
-	}
-
-	protected boolean canBeEmpty(Graph g) {
-		return g.isEmpty();
-	}
-
-	@Test
-	public void testListSubjects() {
-		Set<Node> emptySubjects = listSubjects(graphWithTxn(""));
-		Graph g = graphWithTxn("x P y; y Q z");
-		assertEquals(nodeSet("x y"), remove(listSubjects(g), emptySubjects));
-		txnBegin(g);
-		g.delete(triple("x P y"));
-		txnCommit(g);
-		assertEquals(nodeSet("y"), remove(listSubjects(g), emptySubjects));
-	}
-
-	protected Set<Node> listSubjects(Graph g) {
-		return GraphUtil.listSubjects(g, Node.ANY, Node.ANY).toSet();
-	}
-
-	@Test
-	public void testListPredicates() {
-		Set<Node> emptyPredicates = listPredicates(graphWithTxn(""));
-		Graph g = graphWithTxn("x P y; y Q z");
-		assertEquals(nodeSet("P Q"), remove(listPredicates(g), emptyPredicates));
-		txnBegin(g);
-		g.delete(triple("x P y"));
-		txnCommit(g);
-		assertEquals(nodeSet("Q"), remove(listPredicates(g), emptyPredicates));
-	}
-
-	protected Set<Node> listPredicates(Graph g) {
-		return GraphUtil.listPredicates(g, Node.ANY, Node.ANY).toSet();
 	}
 
+	/**
+	 * This test case was generated by Ian and was caused by GraphMem not
+	 * keeping up with changes to the find interface.
+	 */
 	@Test
-	public void testListObjects() {
-		Set<Node> emptyObjects = listObjects(graphWithTxn(""));
-		Graph g = graphWithTxn("x P y; y Q z");
-		assertEquals(nodeSet("y z"), remove(listObjects(g), emptyObjects));
+	public void testFindAndContains() {
+		Graph g = getGraphProducer().newInstance();
+		Node r = NodeCreateUtils.create("r"), s = NodeCreateUtils.create("s"), p = NodeCreateUtils
+				.create("P");
 		txnBegin(g);
-		g.delete(triple("x P y"));
-		txnCommit(g);
-		assertEquals(nodeSet("z"), remove(listObjects(g), emptyObjects));
-	}
-
-	protected Set<Node> listObjects(Graph g) {
-		return GraphUtil.listObjects(g, Node.ANY, Node.ANY).toSet();
+		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());
+		}
 	}
 
 	/**
-	 * Answer a set with all the elements of <code>A</code> except those in
-	 * <code>B</code>.
+	 * Check that contains respects by-value semantics.
 	 */
-	private <T> Set<T> remove(Set<T> A, Set<T> B) {
-		Set<T> result = new HashSet<T>(A);
-		result.removeAll(B);
-		return result;
-	}
 
-	/**
-	 * Test that nodes can be found in all triple positions. However, testing
-	 * for literals in subject positions is suppressed at present to avoid
-	 * problems with InfGraphs which try to prevent such constructs leaking out
-	 * to the RDF layer.
-	 */
 	@Test
-	public void testContainsNode() {
-		Graph g = graphWithTxn("a P b; _c p1 _D; a P2 12");
-		assertTrue(containsNode(g, node("a")));
-		assertTrue(containsNode(g, node("P")));
-		assertTrue(containsNode(g, node("b")));
-		assertTrue(containsNode(g, node("_c")));
-		assertTrue(containsNode(g, node("p1")));
-		assertTrue(containsNode(g, node("_D")));
-		// assertTrue( qh.containsNode( node( "10" ) ) );
-		// assertTrue(containsNode(g, node("11")));
-		assertTrue(containsNode(g, node("12")));
+	public void testAGraph() {
+		String title = this.getClass().getName();
+		Graph g = getGraphProducer().newInstance();
+		int baseSize = g.size();
+		graphAddTxn(g, "x R y; p S q; a T b");
 		/* */
-		assertFalse(containsNode(g, node("x")));
-		assertFalse(containsNode(g, node("_y")));
-		assertFalse(containsNode(g, node("99")));
-	}
-
-	private boolean containsNode(Graph g, Node node) {
-		return GraphUtil.containsNode(g, node);
-	}
-
-	@Test
-	public void testSubjectsFor() {
-		// First get the answer from the empty graph (not empty for an inf
-		// graph)
-		Graph b = graphWithTxn("");
-		Set<Node> B = GraphUtil.listSubjects(b, Node.ANY, Node.ANY).toSet();
-
-		Graph g = graphWithTxn("a P b; a Q c; a P d; b P x; c Q y");
-
-		testSubjects(g, B, Node.ANY, Node.ANY, node("a"), node("b"), node("c"));
-		testSubjects(g, B, node("P"), Node.ANY, node("a"), node("b"));
-		testSubjects(g, B, node("Q"), node("c"), node("a"));
-		testSubjects(g, B, node("Q"), node("y"), node("c"));
-		testSubjects(g, B, node("Q"), node("a"));
-		testSubjects(g, B, node("Q"), node("z"));
-	}
-
-	protected void testSubjects(Graph g, Collection<Node> exclude, Node p,
-			Node o, Node... expected) {
-		List<Node> R = GraphUtil.listSubjects(g, p, o).toList();
-		R.removeAll(exclude);
-		assertSameUnordered(R, exclude, expected);
-	}
-
-	// Same - except for order
-	private void assertSameUnordered(List<Node> x1, Collection<Node> exclude,
-			Node[] expected) {
-		List<Node> x = new ArrayList<Node>();
-		x.addAll(x1);
-		x.removeAll(exclude);
-
-		assertEquals(expected.length, x.size());
-		Set<Node> X = new HashSet<Node>();
-		X.addAll(x);
-
-		Set<Node> R = new HashSet<Node>();
-		R.addAll(Arrays.asList(expected));
-
-		assertEquals(R, X);
-
-	}
-
-	@Test
-	public void testListSubjectsNoRemove() {
-		Graph g = graphWithTxn("a P b; b Q c; c R a");
-		Iterator<Node> it = GraphUtil.listSubjects(g, Node.ANY, Node.ANY);
-		it.next();
-		try {
-			it.remove();
-			fail("listSubjects for " + g.getClass()
-					+ " should not support .remove()");
-		} catch (UnsupportedOperationException expected) {
-			// expected result
-		}
-	}
-
-	@Test
-	public void testObjectsFor() {
-		// First get the answer from the empty graph (not empty for an inf
-		// graph)
-		Graph b = graphWithTxn("");
-		Set<Node> B = GraphUtil.listObjects(b, Node.ANY, Node.ANY).toSet();
-
-		Graph g = graphWithTxn("b P a; c Q a; d P a; x P b; y Q c");
-		testObjects(g, B, Node.ANY, Node.ANY, node("a"), node("b"), node("c"));
-		testObjects(g, B, Node.ANY, node("P"), node("a"), node("b"));
-		testObjects(g, B, node("c"), node("Q"), node("a"));
-		testObjects(g, B, node("y"), node("Q"), node("c"));
-		testObjects(g, B, node("a"), node("Q"));
-		testObjects(g, B, node("z"), node("Q"));
-	}
+		assertContainsAll(title + ": simple graph", g, "x R y; p S q; a T b");
+		assertEquals(title + ": size", baseSize + 3, g.size());
 
-	protected void testObjects(Graph g, Collection<Node> exclude, Node s,
-			Node p, Node... expected) {
-		List<Node> X = GraphUtil.listObjects(g, s, p).toList();
-		assertSameUnordered(X, exclude, expected);
+		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();
 	}
 
-	@Test
-	public void testPredicatesFor() {
-		// First get the answer from the empty graph (not empty for an inf
-		// graph)
-		Graph b = graphWithTxn("");
-		Set<Node> B = GraphUtil.listPredicates(b, Node.ANY, Node.ANY).toSet();
-
-		Graph g = graphWithTxn("a P b; z P b; c Q d; e R f; g P b; h Q i");
-		testPredicates(g, B, Node.ANY, Node.ANY, node("P"), node("Q"),
-				node("R"));
-		testPredicates(g, B, Node.ANY, node("b"), node("P"));
-		testPredicates(g, B, node("g"), Node.ANY, node("P"));
-		testPredicates(g, B, node("c"), node("d"), node("Q"));
-		testPredicates(g, B, node("e"), node("f"), node("R"));
-		testPredicates(g, B, node("e"), node("a"));
-		testPredicates(g, B, node("z"), node("y"));
-	}
+	// 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" );
+	// }
 
-	protected void testPredicates(Graph g, Collection<Node> exclude, Node s,
-			Node o, Node... expected) {
-		List<Node> X = GraphUtil.listPredicates(g, s, o).toList();
-		assertSameUnordered(X, exclude, expected);
-	}
+	// /**
+	// Test that Graphs have transaction support methods, and that if they fail
+	// on some g they fail because they do not support the operation.
+	// */
+	// @Test
+	// public void testHasTransactions()
+	// {
+	// Graph g = getGraphProducer().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) {}
+	// }
+	//
+	// @Test
+	// public void testExecuteInTransactionCatchesThrowable()
+	// {Graph g = getGraphProducer().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) {}
+	// }
+	// }
 
 	@Test
-	public void testListObjectsNoRemove() {
-		Graph g = graphWithTxn("a P b; b Q c; c R a");
-		Iterator<Node> it = GraphUtil.listObjects(g, Node.ANY, Node.ANY);
-		it.next();
-		try {
-			it.remove();
-			fail("listObjects for " + g.getClass()
-					+ " should not support .remove()");
-		} catch (UnsupportedOperationException e) {
-			// expected
-		}
+	public void testAddWithReificationPreamble() {
+		Graph g = getGraphProducer().newInstance();
+		txnBegin(g);
+		xSPO(g);
+		txnCommit(g);
+		assertFalse(g.isEmpty());
 	}
 
-	@Test
-	public void testListPredicatesNoRemove() {
-		Graph g = graphWithTxn("a P b; b Q c; c R a");
-		Iterator<Node> it = GraphUtil.listPredicates(g, Node.ANY, Node.ANY);
-		it.next();
-		try {
-			it.remove();
-			fail("listPredicates for " + g.getClass()
-					+ " should not support .remove()");
-		} catch (UnsupportedOperationException e) {
-			// expected
-		}
+	protected void xSPOyXYZ(Graph g) {
+		xSPO(g);
+		ReifierStd.reifyAs(g, NodeCreateUtils.create("y"),
+				NodeCreateUtils.createTriple("X Y Z"));
 	}
 
-	@Test
-	public void testRemoveAll() {
-		testRemoveAll("");
-		testRemoveAll("a R b");
-		testRemoveAll("c S d; e:ff GGG hhhh; _i J 27; Ell Em 'en'");
+	protected void aABC(Graph g) {
+		ReifierStd.reifyAs(g, NodeCreateUtils.create("a"),
+				NodeCreateUtils.createTriple("A B C"));
 	}
 
-	protected void testRemoveAll(String triples) {
-		Graph g = graphWithTxn(triples);
-		txnBegin(g);
-		g.clear();
-		txnCommit(g);
-		assertTrue(g.isEmpty());
+	protected void xSPO(Graph g) {
+		ReifierStd.reifyAs(g, NodeCreateUtils.create("x"),
+				NodeCreateUtils.createTriple("S P O"));
 	}
 
 	@Test
 	public void failingTestDoubleRemoveAll() {
-		final Graph g = getGraphProducer().newGraph();
+		final Graph g = getGraphProducer().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.
+				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();
 				}
-			};
-			while (it.hasNext()) {
-				it.next();
-				it.remove();
-			}
-			assertTrue(g.isEmpty());
-			}
-			catch (UnsupportedOperationException e)
-			{
-				fail( "Error attempting to remove nodes"+e.getMessage() );
+				assertTrue(g.isEmpty());
+			} catch (UnsupportedOperationException e) {
+				fail("Error attempting to remove nodes" + e.getMessage());
 			}
 		}
 	}
 
-	@Test
-	public void testGetStatisticsHandler() {
-		Graph g = getGraphProducer().newGraph();
-		GraphStatisticsHandler h = g.getStatisticsHandler();
-		assertSame(h, g.getStatisticsHandler());
-	}
-
 	/**
 	 * Test cases for RemoveSPO(); each entry is a triple (add, remove, result).
 	 * <ul>
@@ -775,38 +1119,14 @@ public abstract class AbstractGraphTest 
 	 * <li>result - the triples that should remain in the graph
 	 * </ul>
 	 */
-	protected static String[][] cases = { { "x R y", "x R y", "" },
-			{ "x R y; a P b", "x R y", "a P b" },
-			{ "x R y; a P b", "?? R y", "a P b" },
-			{ "x R y; a P b", "x R ??", "a P b" },
-			{ "x R y; a P b", "x ?? y", "a P b" },
-			{ "x R y; a P b", "?? ?? ??", "" },
-			{ "x R y; a P b; c P d", "?? P ??", "x R y" },
-			{ "x R y; a P b; x S y", "x ?? ??", "a P b" }, };
-
-	/**
-	 * 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.
-	 */
-	@Test
-	public void testRemoveSPO() {
-		for (int i = 0; i < cases.length; i += 1)
-			for (int j = 0; j < 3; j += 1) {
-				Graph content = getGraphProducer().newGraph();
-				Graph baseContent = copy(content);
-				graphAddTxn(content, cases[i][0]);
-				Triple remove = triple(cases[i][1]);
-				Graph expected = graphWithTxn(cases[i][2]);
-				txnBegin(content);
-				content.remove(remove.getSubject(), remove.getPredicate(),
-						remove.getObject());
-				txnCommit(content);
-				Graph finalContent = remove(copy(content), baseContent);
-				assertIsomorphic(cases[i][1], expected, finalContent);
-			}
-	}
+	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
@@ -842,15 +1162,15 @@ public abstract class AbstractGraphTest 
 			throws URISyntaxException, MalformedURLException {
 		String urlStr = String.format("regression/testModelEquals/%s-%s.%s", n,
 				n2, suffix);
-		return AbstractGraphTest.class.getClassLoader().getResourceAsStream(
+		return GraphContractTest.class.getClassLoader().getResourceAsStream(
 				urlStr);
 	}
 
 	private void testIsomorphismFile(int n, String lang, String suffix,
 			boolean result) throws URISyntaxException, MalformedURLException {
 
-		Graph g1 = getGraphProducer().newGraph();
-		Graph g2 = getGraphProducer().newGraph();
+		Graph g1 = getGraphProducer().newInstance();
+		Graph g2 = getGraphProducer().newInstance();
 		Model m1 = ModelFactory.createModelForGraph(g1);
 		Model m2 = ModelFactory.createModelForGraph(g2);
 
@@ -868,133 +1188,16 @@ public abstract class AbstractGraphTest 
 		assertTrue("Isomorphism test failed", rslt);
 	}
 
-	protected void add(Graph toUpdate, Graph toAdd) {
-		txnBegin(toUpdate);
-		GraphUtil.addInto(toUpdate, toAdd);
-		txnCommit(toUpdate);
-	}
-
-	protected Graph remove(Graph toUpdate, Graph toRemove) {
-		txnBegin(toUpdate);
-		GraphUtil.deleteFrom(toUpdate, toRemove);
-		txnCommit(toUpdate);
-		return toUpdate;
-	}
-
-	protected Graph copy(Graph g) {
-		Graph result = getGraphProducer().newGraph();
-		txnBegin(result);
-		GraphUtil.addInto(result, g);
-		txnCommit(result);
-		return result;
-	}
-
 	protected Graph getClosed() {
-		Graph result = getGraphProducer().newGraph();
+		Graph result = getGraphProducer().newInstance();
 		result.close();
 		return result;
 	}
 
-	public void testClosedDelete() {
-		try {
-			getClosed().delete(triple("x R y"));
-			fail("delete when closed");
-		} catch (ClosedException c) { /* as required */
-		}
-	}
-
-	public void testClosedAdd() {
-		try {
-			getClosed().add(triple("x R y"));
-			fail("add when closed");
-		} catch (ClosedException c) { /* as required */
-		}
-	}
-
-	public void testClosedContainsTriple() {
-		try {
-			getClosed().contains(triple("x R y"));
-			fail("contains[triple] when closed");
-		} catch (ClosedException c) { /* as required */
-		}
-	}
-
-	public void testClosedContainsSPO() {
-		Node a = Node.ANY;
-		try {
-			getClosed().contains(a, a, a);
-			fail("contains[SPO] when closed");
-		} catch (ClosedException c) { /* as required */
-		}
-	}
-
-	public void testClosedFindTriple() {
-		try {
-			getClosed().find(triple("x R y"));
-			fail("find [triple] when closed");
-		} catch (ClosedException c) { /* as required */
-		}
-	}
-
-	public void testClosedFindSPO() {
-		Node a = Node.ANY;
-		try {
-			getClosed().find(a, a, a);
-			fail("find[SPO] when closed");
-		} catch (ClosedException c) { /* as required */
-		}
-	}
-
-	public void testClosedSize() {
-		try {
-			getClosed().size();
-			fail("size when closed (" + this.getClass() + ")");
-		} catch (ClosedException c) { /* as required */
-		}
-	}
-
-	@Test
-	public void testCapabilitiesAvailable() {
-		Graph g = getGraphProducer().newGraph();
-		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());
-		}
-
-	}
-
 	// @Test
 	// public void testTransactionCommit()
 	// {
-	// Graph g = getGraphProducer().newGraph();
+	// Graph g = getGraphProducer().newInstance();
 	// if (g.getTransactionHandler().transactionsSupported())
 	// {
 	// Graph initial = graphWithTxn( "initial hasValue 42; also hasURI hello" );
@@ -1020,7 +1223,7 @@ public abstract class AbstractGraphTest 
 	// @Test
 	// public void testTransactionAbort()
 	// {
-	// Graph g = getGraphProducer().newGraph();
+	// Graph g = getGraphProducer().newInstance();
 	// if (g.getTransactionHandler().transactionsSupported())
 	// {
 	// Graph initial = graphWithTxn( "initial hasValue 42; also hasURI hello" );
@@ -1038,12 +1241,12 @@ public abstract class AbstractGraphTest 
 	// @Test
 	// public void testTransactionCommitThenAbort()
 	// {
-	// Graph g = getGraphProducer().newGraph();
+	// Graph g = getGraphProducer().newInstance();
 	// if (g.getTransactionHandler().transactionsSupported())
 	// {
 	// Graph initial = graphWithTxn( "A pings B; B pings C" );
 	// Graph extra = graphWithTxn( "C pingedBy B; fileGraph rdf:type Graph" );
-	// //Graph g = getGraphProducer().newGraph();
+	// //Graph g = getGraphProducer().newInstance();
 	// //File foo = FileUtils.tempFileName( "fileGraph", ".nt" );
 	// //Graph g = new FileGraph( foo, true, true );
 	// g.getTransactionHandler().begin();
@@ -1058,18 +1261,219 @@ public abstract class AbstractGraphTest 
 	// //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.
+	 */
+	@Test
+	public void testPartialUpdate() {
+		Graph source = graphWith(getGraphProducer().newInstance(),
+				"a R b; b S e");
+		Graph dest = graphWith(getGraphProducer().newInstance(), "b R d");
+		GraphExtract e = new GraphExtract(TripleBoundary.stopNowhere);
+		e.extractInto(dest, node("a"), source);
+		assertIsomorphic(
+				graphWith(getGraphProducer().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.
+	 */
+	@Test
+	public void testIterator_Remove() {
+		Graph graph = graphWith(getGraphProducer().newInstance(),
+				"a R b; b S e");
+		if (graph.getCapabilities().iteratorRemoveAllowed()) {
+
+			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);
+		}
+	}
+
+	@Test
+	public void testTransactionHandler_Commit() {
+		Graph g = getGraphProducer().newInstance();
+		if (g.getTransactionHandler().transactionsSupported()) {
+			Graph initial = graphWith(getGraphProducer().newInstance(),
+					"initial hasValue 42; also hasURI hello");
+			Graph extra = graphWith(getGraphProducer().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() );
+		}
+	}
+
+	@Test
+	public void testTransactionHandler_Abort() {
+		Graph g = getGraphProducer().newInstance();
+		if (g.getTransactionHandler().transactionsSupported()) {
+			Graph initial = graphWith(getGraphProducer().newInstance(),
+					"initial hasValue 42; also hasURI hello");
+			Graph extra = graphWith(getGraphProducer().newInstance(),
+					"extra hasValue 17; also hasURI world");
+			GraphUtil.addInto(g, initial);
+			g.getTransactionHandler().begin();
+			GraphUtil.addInto(g, extra);
+			g.getTransactionHandler().abort();
+			assertIsomorphic(initial, g);
+		}
+	}
+
+	@Test
+	public void testTransactionHandler_CommitThenAbort() {
+		Graph g = getGraphProducer().newInstance();
+		if (g.getTransactionHandler().transactionsSupported()) {
+			Graph initial = graphWith(getGraphProducer().newInstance(),
+					"A pings B; B pings C");
+			Graph extra = graphWith(getGraphProducer().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) {
+		String fmt = "TestFindLiterals: graph '{'{%s}'}' size {%s} search {%s} expecting '{'{%s}'}'";
+
+		Graph g = getGraphProducer().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);
+		}
+	}
+
+	@Test
+	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 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);
+	}
+
+	@Test
+	public void testQuadRemove() {
+		Graph g = getGraphProducer().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());
+	}
+
 	@Test
 	public void testSizeAfterRemove() {
-		Graph g = graphWithTxn("x p y");
+		Graph g = graphWith(getGraphProducer().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() );
+				ExtendedIterator<Triple> it = g.find(triple("x ?? ??"));
+				it.removeNext();
+				assertEquals(0, g.size());
+			} catch (UnsupportedOperationException e) {
+				fail("Error attempting to remove nodes" + e.getMessage());
 			}
 		}
 	}
@@ -1077,7 +1481,7 @@ public abstract class AbstractGraphTest 
 	@Test
 	public void testSingletonStatisticsWithSingleTriple() {
 
-		Graph g = graphWithTxn("a P b");
+		Graph g = graphWith(getGraphProducer().newInstance(), "a P b");
 		GraphStatisticsHandler h = g.getStatisticsHandler();
 		if (h != null) {
 			assertEquals(1L, h.getStatistic(node("a"), Node.ANY, Node.ANY));
@@ -1094,7 +1498,8 @@ public abstract class AbstractGraphTest 
 	@Test
 	public void testSingletonStatisticsWithSeveralTriples() {
 
-		Graph g = graphWithTxn("a P b; a P c; a Q b; x S y");
+		Graph g = graphWith(getGraphProducer().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));
@@ -1114,7 +1519,8 @@ public abstract class AbstractGraphTest 
 	@Test
 	public void testDoubletonStatisticsWithTriples() {
 
-		Graph g = graphWithTxn("a P b; a P c; a Q b; x S y");
+		Graph g = graphWith(getGraphProducer().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));
@@ -1134,7 +1540,7 @@ public abstract class AbstractGraphTest 
 	}
 
 	private void testStatsWithAllVariables(String triples) {
-		Graph g = graphWithTxn(triples);
+		Graph g = graphWith(getGraphProducer().newInstance(), triples);
 		GraphStatisticsHandler h = g.getStatisticsHandler();
 		if (h != null) {
 			assertEquals(g.size(), h.getStatistic(Node.ANY, Node.ANY, Node.ANY));
@@ -1148,7 +1554,7 @@ public abstract class AbstractGraphTest 
 
 	private void testStatsWithConcreteTriple(int expect, String triple,
 			String graph) {
-		Graph g = graphWithTxn(graph);
+		Graph g = graphWith(getGraphProducer().newInstance(), graph);
 		GraphStatisticsHandler h = g.getStatisticsHandler();
 		if (h != null) {
 			Triple t = triple(triple);
@@ -1161,71 +1567,69 @@ public abstract class AbstractGraphTest 
 
 	@Test
 	public void testBrokenIndexes() {
-		Graph g = graphWithTxn("x R y; x S z");
+		Graph g = graphWith(getGraphProducer().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() );
+				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());
 			}
 		}
 	}
 
 	@Test
 	public void testBrokenSubject() {
-		Graph g = graphWithTxn("x brokenSubject y");
+		Graph g = graphWith(getGraphProducer().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() );
+				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());
 			}
 		}
 	}
 
 	@Test
 	public void testBrokenPredicate() {
-		Graph g = graphWithTxn("x brokenPredicate y");
+		Graph g = graphWith(getGraphProducer().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() );
+				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());
 			}
 		}
 	}
 
 	@Test
 	public void testBrokenObject() {
-		Graph g = graphWithTxn("x brokenObject y");
+		Graph g = graphWith(getGraphProducer().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() );
+				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());
+			}
 		}
 	}
-	}
 
 }

Copied: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphEventManagerContractTest.java (from r1523135, jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractEventManagerTest.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphEventManagerContractTest.java?p2=jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphEventManagerContractTest.java&p1=jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractEventManagerTest.java&r1=1523135&r2=1530718&rev=1530718&view=diff
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractEventManagerTest.java (original)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphEventManagerContractTest.java Wed Oct  9 17:16:15 2013
@@ -19,17 +19,22 @@
 package com.hp.hpl.jena.graph;
 
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
+
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.xenei.junit.contract.Contract;
 
 import static org.junit.Assert.*;
 
 import com.hp.hpl.jena.graph.Graph;
 import com.hp.hpl.jena.graph.GraphEventManager;
 import com.hp.hpl.jena.graph.Triple;
-import com.hp.hpl.jena.testing_framework.GraphEventManagerProducerInterface;
+import com.hp.hpl.jena.testing_framework.GraphHelper;
+import org.xenei.junit.contract.IProducer;
 import com.hp.hpl.jena.testing_framework.NodeCreateUtils;
 
 import static com.hp.hpl.jena.testing_framework.GraphHelper.*;
@@ -41,10 +46,11 @@ import static com.hp.hpl.jena.testing_fr
  * Subclasses of this class must implement the getEventManagerProducer() method
  * to create a new instance of the EventManager for testing.
  */
+@Contract(GraphEventManager.class)
+public abstract class GraphEventManagerContractTest {
 
-public abstract class AbstractEventManagerTest {
-
-	protected abstract GraphEventManagerProducerInterface getEventManagerProducer();
+	@Contract.Inject( "org.xenei.junit.contract.IProducer<%s>" )
+	protected abstract IProducer<GraphEventManager> getEventManagerProducer();
 
 	protected static final Triple[] tripleArray = tripleArray("S P O; A R B; X Q Y");
 
@@ -54,10 +60,15 @@ public abstract class AbstractEventManag
 	private GraphEventManager gem;
 
 	@Before
-	public void startup() {
+	public final void beforeAbstractEventManagerTest() {
 		mockGraph = Mockito.mock(Graph.class);
-		gem = getEventManagerProducer().newEventManager();
-		L = new RecordingListener();
+		gem = getEventManagerProducer().newInstance();
+		L = new RecordingGraphListener();
+	}
+
+	@After
+	public final void afterAbstractEventManagerTest() {
+		getEventManagerProducer().cleanUp();
 	}
 
 	/**
@@ -66,7 +77,7 @@ public abstract class AbstractEventManag
 	 */
 	@Test
 	public void testEventRegister() {
-		assertSame(gem, gem.register(new RecordingListener()));
+		assertSame(gem, gem.register(new RecordingGraphListener()));
 	}
 
 	/**
@@ -74,7 +85,7 @@ public abstract class AbstractEventManag
 	 */
 	@Test
 	public void testEventUnregister() {
-		gem.unregister(L);
+		assertSame(gem, gem.unregister(L));
 	}
 
 	/**
@@ -86,7 +97,7 @@ public abstract class AbstractEventManag
 	 * The RecordingListener that reports all the events sent from the
 	 * EventManager.
 	 */
-	protected RecordingListener L;
+	protected RecordingGraphListener L;
 
 	/**
 	 * Test that adding a triple is reported.
@@ -113,8 +124,8 @@ public abstract class AbstractEventManag
 	 */
 	@Test
 	public void testTwoListeners() {
-		RecordingListener L1 = new RecordingListener();
-		RecordingListener L2 = new RecordingListener();
+		RecordingGraphListener L1 = new RecordingGraphListener();
+		RecordingGraphListener L2 = new RecordingGraphListener();
 		gem.register(L1).register(L2);
 		gem.notifyAddTriple(mockGraph, SPO);
 		L2.assertHas(new Object[] { "add", mockGraph, SPO });
@@ -275,4 +286,206 @@ public abstract class AbstractEventManag
 		L.assertHas(new Object[] { "someEvent", mockGraph, value });
 	}
 
+	@Test
+	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());
+	}
+
+	//
+	// A 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.
+	 */
+	@Test
+	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.
+	 */
+	@Test
+	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.
+	 */
+	@Test
+	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.
+	 */
+	@Test
+	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.
+	 */
+	@Test
+	public void testDeleteAndAddSelf() {
+		testAddingTriple(3, new ComeAndGoListener() {
+			@Override
+			void doSomeDamage() {
+				unregister(gem);
+				register(gem);
+			}
+		}, new SimpleListener(), new SimpleListener());
+	}
+
 }

Copied: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphExtractTest.java (from r1523135, jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphExtractTest.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphExtractTest.java?p2=jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphExtractTest.java&p1=jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphExtractTest.java&r1=1523135&r2=1530718&rev=1530718&view=diff
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphExtractTest.java (original)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphExtractTest.java Wed Oct  9 17:16:15 2013
@@ -23,13 +23,22 @@ import static org.junit.Assert.*;
 
 import org.junit.Test;
 
-import com.hp.hpl.jena.testing_framework.AbstractGraphProducerUser;
+import com.hp.hpl.jena.mem.GraphMem;
+import com.hp.hpl.jena.testing_framework.AbstractGraphProducer;
 
 /**
  * Tests for recursive sub-graph extraction.
  */
-public abstract class AbstractGraphExtractTest extends
-		AbstractGraphProducerUser {
+
+public class GraphExtractTest {
+
+	protected AbstractGraphProducer graphProducer = new AbstractGraphProducer() {
+
+		@Override
+		protected Graph createNewGraph() {
+			return new GraphMem();
+		}
+	};
 
 	@Test
 	public void testExtractNothing() {
@@ -87,23 +96,6 @@ public abstract class AbstractGraphExtra
 				TripleBoundary.stopAtAnonObject);
 	}
 
-	/**
-	 * 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.
-	 */
-	@Test
-	public void testPartialUpdate() {
-		Graph source = graphWith(getGraphProducer().newGraph(), "a R b; b S e");
-		Graph dest = graphWith(getGraphProducer().newGraph(), "b R d");
-		GraphExtract e = new GraphExtract(TripleBoundary.stopNowhere);
-		e.extractInto(dest, node("a"), source);
-		assertIsomorphic(
-				graphWith(getGraphProducer().newGraph(), "a R b; b S e; b R d"),
-				dest);
-	}
-
 	private void testExtract(String wanted, String node, String source) {
 		testExtract(wanted, node, source, TripleBoundary.stopNowhere);
 	}
@@ -112,10 +104,14 @@ public abstract class AbstractGraphExtra
     */
 	private void testExtract(String wanted, String node, String source,
 			TripleBoundary b) {
-		assertIsomorphic(
-				graphWith(getGraphProducer().newGraph(), wanted),
-				extract(node(node), b,
-						graphWith(getGraphProducer().newGraph(), source)));
+		Graph g1 = graphWith(graphProducer.newInstance(), wanted);
+		Graph g2 = graphWith(graphProducer.newInstance(), source);
+		try {
+			assertIsomorphic(g1, extract(node(node), b, graphWith(g2, source)));
+		} finally {
+			g1.close();
+			g2.close();
+		}
 	}
 
 	private Graph extract(Node node, TripleBoundary b, Graph graph) {

Copied: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphMakerContractTest.java (from r1523135, jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphMakerTest.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphMakerContractTest.java?p2=jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphMakerContractTest.java&p1=jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphMakerTest.java&r1=1523135&r2=1530718&rev=1530718&view=diff
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphMakerTest.java (original)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphMakerContractTest.java Wed Oct  9 17:16:15 2013
@@ -24,6 +24,7 @@ import java.util.Set;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.xenei.junit.contract.Contract;
 
 import com.hp.hpl.jena.graph.Graph;
 import com.hp.hpl.jena.graph.GraphMaker;
@@ -32,6 +33,7 @@ import com.hp.hpl.jena.graph.Triple;
 import com.hp.hpl.jena.shared.AlreadyExistsException;
 import com.hp.hpl.jena.shared.DoesNotExistException;
 import com.hp.hpl.jena.testing_framework.GraphHelper;
+import org.xenei.junit.contract.IProducer;
 import com.hp.hpl.jena.testing_framework.TestUtils;
 
 /**
@@ -44,21 +46,23 @@ import com.hp.hpl.jena.testing_framework
  * the development of the first full graph factory. (Although at the time it
  * wasn't abstract.)
  */
+@Contract(GraphMaker.class)
+public abstract class GraphMakerContractTest {
 
-public abstract class AbstractGraphMakerTest {
-
-	public abstract GraphMaker getGraphMaker();
+	@Contract.Inject( "org.xenei.junit.contract.IProducer<%s>" )
+	public abstract IProducer<GraphMaker> getGraphMakerProducer();
 
 	private GraphMaker graphMaker;
 
 	@Before
 	public void setUp() {
-		graphMaker = getGraphMaker();
+		graphMaker = getGraphMakerProducer().newInstance();
 	}
 
 	@After
 	public void tearDown() {
 		graphMaker.close();
+		getGraphMakerProducer().cleanUp();
 	}
 
 	/**
@@ -254,8 +258,7 @@ public abstract class AbstractGraphMaker
 		Graph Y = graphMaker.createGraph(y);
 		Graph Z = graphMaker.createGraph(z);
 		Set<String> wanted = TestUtils.setOfStrings(x + " " + y + " " + z);
-		assertEquals(wanted,
-				GraphHelper.iteratorToSet(graphMaker.listGraphs()));
+		assertEquals(wanted, GraphHelper.iteratorToSet(graphMaker.listGraphs()));
 		X.close();
 		Y.close();
 		Z.close();

Added: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphWithPerformContractTest.java
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphWithPerformContractTest.java?rev=1530718&view=auto
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphWithPerformContractTest.java (added)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphWithPerformContractTest.java Wed Oct  9 17:16:15 2013
@@ -0,0 +1,58 @@
+package com.hp.hpl.jena.graph;
+
+import static com.hp.hpl.jena.testing_framework.GraphHelper.graphWith;
+import static com.hp.hpl.jena.testing_framework.GraphHelper.triple;
+import static com.hp.hpl.jena.testing_framework.GraphHelper.txnBegin;
+import static com.hp.hpl.jena.testing_framework.GraphHelper.txnCommit;
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xenei.junit.contract.Contract;
+
+import com.hp.hpl.jena.graph.impl.GraphWithPerform;
+import org.xenei.junit.contract.IProducer;
+
+/**
+ * GraphWithPerform is an implementation interface that extends Graph with the
+ * performAdd and performDelete methods used by GraphBase to invoke
+ * non-notifying versions of add and delete.
+ */
+@Contract(GraphWithPerform.class)
+public abstract class GraphWithPerformContractTest {
+	protected RecordingGraphListener GL = new RecordingGraphListener();
+
+	private static final Logger LOG = LoggerFactory
+			.getLogger(GraphWithPerformContractTest.class);
+
+	@Contract.Inject( "org.xenei.junit.contract.IProducer<%s>" )
+	abstract public IProducer<? extends GraphWithPerform> getGraphProducer();
+
+	@Test
+	public void testPerformAdd_Triple() {
+		GraphWithPerform g = (GraphWithPerform) graphWith(getGraphProducer()
+				.newInstance(), "S P O; S2 P2 O2");
+		g.getEventManager().register(GL);
+		txnBegin(g);
+		g.performAdd(triple("S3 P3 O3"));
+		txnCommit(g);
+		GL.assertEmpty();
+		assertTrue(g.contains(triple("S3 P3 O3")));
+
+	}
+
+	@Test
+	public void testPerformDelete_Triple() {
+		GraphWithPerform g = (GraphWithPerform) graphWith(getGraphProducer()
+				.newInstance(), "S P O; S2 P2 O2");
+		g.getEventManager().register(GL);
+		txnBegin(g);
+		g.performDelete(triple("S2 P2 O2"));
+		txnCommit(g);
+		GL.assertEmpty();
+		assertFalse(g.contains(triple("S2 P2 O2")));
+
+	}
+
+}

Propchange: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphWithPerformContractTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain