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/08/27 08:01:02 UTC

svn commit: r1517755 [1/2] - in /jena/Experimental/new-test: ./ .settings/ src/ src/test/ src/test/java/ src/test/java/com/ src/test/java/com/hp/ src/test/java/com/hp/hpl/ src/test/java/com/hp/hpl/jena/ src/test/java/com/hp/hpl/jena/graph/ src/test/jav...

Author: claude
Date: Tue Aug 27 06:01:01 2013
New Revision: 1517755

URL: http://svn.apache.org/r1517755
Log:
Initial checkin of JENA-380 

Added:
    jena/Experimental/new-test/.classpath   (with props)
    jena/Experimental/new-test/.project   (with props)
    jena/Experimental/new-test/.settings/
    jena/Experimental/new-test/.settings/org.eclipse.core.resources.prefs   (with props)
    jena/Experimental/new-test/.settings/org.eclipse.jdt.core.prefs   (with props)
    jena/Experimental/new-test/.settings/org.eclipse.m2e.core.prefs   (with props)
    jena/Experimental/new-test/pom.xml   (with props)
    jena/Experimental/new-test/src/
    jena/Experimental/new-test/src/test/
    jena/Experimental/new-test/src/test/java/
    jena/Experimental/new-test/src/test/java/com/
    jena/Experimental/new-test/src/test/java/com/hp/
    jena/Experimental/new-test/src/test/java/com/hp/hpl/
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphTest.java   (with props)
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphProducerInterface.java   (with props)
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphTestUtils.java   (with props)
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/MemGraphTest.java   (with props)
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/NodeCreateUtils.java   (with props)
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/RecordingListener.java   (with props)
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/impl/
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/impl/TestCollectionGraph.java   (with props)
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/test/
    jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/test/TestUtils.java   (with props)
    jena/Experimental/new-test/src/test/resources/
    jena/Experimental/new-test/src/test/resources/com/
    jena/Experimental/new-test/src/test/resources/com/hp/
    jena/Experimental/new-test/src/test/resources/com/hp/hpl/
    jena/Experimental/new-test/src/test/resources/com/hp/hpl/jena/
    jena/Experimental/new-test/src/test/resources/com/hp/hpl/jena/graph/
    jena/Experimental/new-test/src/test/resources/regression/
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/1-1.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/1-2.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/2-1.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/2-2.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/3-1.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/3-2.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/4-1.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/4-2.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/5-1.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/5-2.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/6-1.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/6-2.rdf
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/7-1.nt
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/7-2.nt
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/8-1.nt
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/8-2.nt
    jena/Experimental/new-test/src/test/resources/regression/testModelEquals/README_LICENSE

Added: jena/Experimental/new-test/.classpath
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/.classpath?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/.classpath (added)
+++ jena/Experimental/new-test/.classpath Tue Aug 27 06:01:01 2013
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

Propchange: jena/Experimental/new-test/.classpath
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jena/Experimental/new-test/.project
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/.project?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/.project (added)
+++ jena/Experimental/new-test/.project Tue Aug 27 06:01:01 2013
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>new-test</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>

Propchange: jena/Experimental/new-test/.project
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jena/Experimental/new-test/.settings/org.eclipse.core.resources.prefs
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/.settings/org.eclipse.core.resources.prefs?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/.settings/org.eclipse.core.resources.prefs (added)
+++ jena/Experimental/new-test/.settings/org.eclipse.core.resources.prefs Tue Aug 27 06:01:01 2013
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//src/test/java=UTF-8
+encoding/<project>=UTF-8

Propchange: jena/Experimental/new-test/.settings/org.eclipse.core.resources.prefs
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jena/Experimental/new-test/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/.settings/org.eclipse.jdt.core.prefs?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/.settings/org.eclipse.jdt.core.prefs (added)
+++ jena/Experimental/new-test/.settings/org.eclipse.jdt.core.prefs Tue Aug 27 06:01:01 2013
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6

Propchange: jena/Experimental/new-test/.settings/org.eclipse.jdt.core.prefs
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jena/Experimental/new-test/.settings/org.eclipse.m2e.core.prefs
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/.settings/org.eclipse.m2e.core.prefs?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/.settings/org.eclipse.m2e.core.prefs (added)
+++ jena/Experimental/new-test/.settings/org.eclipse.m2e.core.prefs Tue Aug 27 06:01:01 2013
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1

Propchange: jena/Experimental/new-test/.settings/org.eclipse.m2e.core.prefs
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jena/Experimental/new-test/pom.xml
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/pom.xml?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/pom.xml (added)
+++ jena/Experimental/new-test/pom.xml Tue Aug 27 06:01:01 2013
@@ -0,0 +1,26 @@
+<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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.jena</groupId>
+  <artifactId>new-test</artifactId>
+  <version>2.10.2-SNAPSHOT</version>
+  <name>new Jena tests</name>
+  <description>New test suite for Jena project.   This is a complete rewrite of the existing tests</description>
+  <parent>
+  	<groupId>org.apache.jena</groupId>
+  	<artifactId>jena-parent</artifactId>
+  	<version>7-SNAPSHOT</version>
+  </parent>
+  <dependencies>
+  <dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>${ver.junit}</version>
+		</dependency>
+  <dependency>
+			<groupId>org.apache.jena</groupId>
+			<artifactId>apache-jena-libs</artifactId>
+			<version>${version}</version>
+			<type>pom</type>
+		</dependency>
+  </dependencies>
+</project>
\ No newline at end of file

Propchange: jena/Experimental/new-test/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: 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/AbstractGraphTest.java?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphTest.java (added)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/AbstractGraphTest.java Tue Aug 27 06:01:01 2013
@@ -0,0 +1,1092 @@
+/*
+ * 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 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.Test;
+
+import com.hp.hpl.jena.graph.Capabilities;
+import com.hp.hpl.jena.graph.Factory;
+import com.hp.hpl.jena.graph.Graph;
+import com.hp.hpl.jena.graph.GraphEventManager;
+import com.hp.hpl.jena.graph.GraphEvents;
+import com.hp.hpl.jena.graph.GraphListener;
+import com.hp.hpl.jena.graph.GraphStatisticsHandler;
+import com.hp.hpl.jena.graph.GraphUtil;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.TransactionHandler;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.mem.TrackingTripleIterator ;
+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.Command ;
+import com.hp.hpl.jena.shared.JenaException ;
+import com.hp.hpl.jena.util.CollectionFactory ;
+import com.hp.hpl.jena.util.iterator.ClosableIterator ;
+import com.hp.hpl.jena.util.iterator.ExtendedIterator ;
+import static com.hp.hpl.jena.graph.GraphTestUtils.*;
+import static org.junit.Assert.*;
+
+/**
+    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. 
+ */
+public abstract class AbstractGraphTest 
+{
+	private GraphProducerInterface graphProducer;
+	
+	protected AbstractGraphTest( GraphProducerInterface graphProducer )
+	{
+		this.graphProducer = graphProducer;
+	}
+	
+	protected Graph getGraph()
+	{
+		return graphProducer.newGraph();
+	}
+	
+    public Graph getGraphWith( String facts )
+    {
+        Graph g = getGraph();
+        graphAdd( g, facts );
+        return g;    
+    }
+
+    @Test
+    public void testCloseSetsIsClosed()
+    {
+        Graph g = getGraph();
+        assertFalse( "unclosed Graph shouild not be isClosed()", g.isClosed() );
+        g.close();
+        assertTrue( "closed Graph should be isClosed()", g.isClosed() );
+    }
+
+    /**
+        This test case was generated by Ian and was caused by GraphMem
+        not keeping up with changes to the find interface. 
+     */
+    @Test
+    public void testFindAndContains()
+    {
+        Graph g = getGraph();
+        Node r = NodeCreateUtils.create( "r" ), s = NodeCreateUtils.create( "s" ), p = NodeCreateUtils.create( "P" );
+        g.add( Triple.create( r, p, s ) );
+        assertTrue( g.contains( r, p, Node.ANY ) );
+        assertEquals( 1, g.find( r, p, Node.ANY ).toList().size() );
+    }
+
+    @Test
+    public void testRepeatedSubjectDoesNotConceal()
+    {
+        Graph g = getGraphWith( "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 ??" ) ) );
+    }
+
+    @Test
+    public void testFindByFluidTriple()
+    {
+        Graph g = getGraphWith( "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 testContainsConcrete()
+    {
+        Graph g = getGraphWith( "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" ) ) );
+    }
+
+    @Test
+    public void testContainsFluid()
+    {
+        Graph g = getGraphWith( "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 ??" ) ) );
+    }
+
+    /**
+        Check that contains respects by-value semantics.
+     */
+    @Test
+    public void testContainsByValue()
+    {
+        if (getGraph().getCapabilities().handlesLiteralTyping())
+        {
+            Graph g1 = getGraphWith( "x P '1'xsd:integer" );
+            assertTrue( g1.contains( triple( "x P '01'xsd:int" ) ) );
+            //
+            Graph g2 = getGraphWith( "x P '1'xsd:int" );
+            assertTrue( g2.contains( triple( "x P '1'xsd:integer" ) ) );
+            //
+            Graph g3 = getGraphWith( "x P '123'xsd:string" );
+            assertTrue( g3.contains( triple( "x P '123'" ) ) );
+        }
+    }
+
+    @Test
+    public void testMatchLanguagedLiteralCaseInsensitive()
+    {
+        Graph m = graphWith( "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() );
+        }
+    }
+
+    @Test
+    public void testMatchBothLanguagedLiteralsCaseInsensitive()
+    {
+        Graph m = graphWith( "a p 'chat'en; 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( 2, m.find( Node.ANY, Node.ANY, chaten ).toList().size() );
+            assertEquals( 2, m.find( Node.ANY, Node.ANY, chatEN ).toList().size() );
+        }
+    }
+
+    @Test
+    public void testNoMatchAgainstUnlanguagesLiteral()
+    {
+        Graph m = graphWith( "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() );        
+        }
+    }
+
+    /**
+        test  isEmpty - moved from the QueryHandler code.
+     */
+    @Test
+    public void testIsEmpty()
+    {
+        Graph g = getGraph();
+        if (canBeEmpty( g ))
+        {
+            assertTrue( g.isEmpty() );
+            g.add( NodeCreateUtils.createTriple( "S P O" ) );
+            assertFalse( g.isEmpty() );
+            g.add( NodeCreateUtils.createTriple( "A B C" ) );
+            assertFalse( g.isEmpty() );
+            g.add( NodeCreateUtils.createTriple( "S P O" ) );
+            assertFalse( g.isEmpty() );
+            g.delete( NodeCreateUtils.createTriple( "S P O" ) );
+            assertFalse( g.isEmpty() );
+            g.delete( NodeCreateUtils.createTriple( "A B C" ) );
+            assertTrue( g.isEmpty() );
+        }
+    }
+
+
+    @Test
+     public void testAGraph()
+    {
+        String title = this.getClass().getName();
+        Graph g = getGraph();
+        int baseSize = g.size();
+        graphAdd( 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() );
+        graphAdd( g, "spindizzies lift cities; Diracs communicate instantaneously" );
+        assertEquals( title + ": size after adding", baseSize + 5, g.size() );
+        g.delete( triple( "x R y" ) );
+        g.delete( triple( "a T b" ) );
+        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.
+     */
+    @Test
+    public void testHasTransactions()
+    {
+        Graph g = getGraph();
+        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 = getGraph();
+    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) {}
+    }
+    }
+
+    static final Triple [] tripleArray = tripleArray( "S P O; A R B; X Q Y" );
+
+    static final List<Triple> tripleList = Arrays.asList( tripleArray( "i lt j; p equals q" ) );
+
+    static final Triple [] setTriples = tripleArray
+        ( "scissors cut paper; paper wraps stone; stone breaks scissors" );
+
+    static final Set<Triple> tripleSet = CollectionFactory.createHashedSet( Arrays.asList( setTriples ) );
+
+    @Test
+    public void testBulkUpdate()
+    {
+        Graph g = getGraph();
+        Graph items = graphWith( "pigs might fly; dead can dance" );
+        int initialSize = g.size();
+        /* */
+        GraphUtil.add( g,  tripleArray );
+        testContains( g, tripleArray );
+        testOmits( g, tripleList );
+        /* */
+        GraphUtil.add( g,  tripleList );
+        testContains( g, tripleList );
+        testContains( g, tripleArray );
+        /* */
+        GraphUtil.add( g, tripleSet.iterator() );
+        testContains( g, tripleSet.iterator() );
+        testContains( g, tripleList );
+        testContains( g, tripleArray );
+        /* */
+        GraphUtil.addInto( g, items );
+        testContains( g, items );
+        testContains( g, tripleSet.iterator() );
+        testContains( g, tripleArray );
+        testContains( g, tripleList );
+        /* */
+        GraphUtil.delete( g, tripleArray );
+        testOmits( g, tripleArray );
+        testContains( g, tripleList );
+        testContains( g, tripleSet.iterator() );
+        testContains( g, items );
+        /* */
+        GraphUtil.delete( g, tripleSet.iterator() );
+        testOmits( g, tripleSet.iterator() );
+        testOmits( g, tripleArray );
+        testContains( g, tripleList );
+        testContains( g, items );
+        /* */
+        GraphUtil.deleteFrom( g, items );
+        testOmits( g, tripleSet.iterator() );
+        testOmits( g, tripleArray );
+        testContains( g, tripleList );
+        testOmits( g, items ); 
+        /* */
+        GraphUtil.delete( g, tripleList );
+        assertEquals( "graph has original size", initialSize, g.size() );
+    }
+
+    @Test
+    public void testAddWithReificationPreamble()
+    {
+        Graph g = getGraph();
+        xSPO( 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( "A B C" ) ); }
+
+    protected void xSPO( Graph g )
+    { ReifierStd.reifyAs( g , NodeCreateUtils.create( "x" ), NodeCreateUtils.createTriple( "S P O" ) ); }
+
+    @Test
+    public void testRemove()
+    { 
+        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" );
+    }
+
+    protected void testRemove( String findRemove, String findCheck )
+    {
+        Graph g = getGraphWith( "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( g.getCapabilities().iteratorRemoveAllowed() ); 
+        }
+        it.close();
+    }
+
+    @Test
+    public void testHasCapabilities()
+    {
+        Graph g = getGraph();
+        Capabilities c = g.getCapabilities();
+        boolean sa = c.sizeAccurate();
+        boolean aaSome = c.addAllowed();
+        boolean aaAll = c.addAllowed( true );
+        boolean daSome = c.deleteAllowed();
+        boolean daAll = c.deleteAllowed( true );
+        boolean cbe = c.canBeEmpty();
+    }
+
+    @Test
+    public void testFind()
+    {
+        Graph g = getGraph();
+        graphAdd( g, "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(); }
+
+    public void testEventRegister()
+    {
+        Graph g = getGraph();
+        GraphEventManager gem = g.getEventManager();
+        assertSame( gem, gem.register( new RecordingListener() ) );
+    }
+
+    /**
+        Test that we can safely unregister a listener that isn't registered.
+     */
+    @Test
+    public void testEventUnregister()
+    {
+        getGraph().getEventManager().unregister( L );
+    }
+
+    /**
+        Handy triple for test purposes.
+     */
+    protected Triple SPO = NodeCreateUtils.createTriple( "S P O" );
+    protected RecordingListener L = new RecordingListener();
+
+    /**
+        Utility: get a graph, register L with its manager, return the graph.
+     */
+    protected Graph getAndRegister( GraphListener gl )
+    {
+        Graph g = getGraph();
+        g.getEventManager().register( gl );
+        return g;
+    }
+
+    @Test
+    public void testAddTriple()
+    {
+        Graph g = getAndRegister( L );
+        g.add( SPO );
+        L.assertHas( new Object[] {"add", g, SPO} );
+    }
+
+    @Test
+    public void testDeleteTriple()
+    {        
+        Graph g = getAndRegister( L );
+        g.delete( SPO );
+        L.assertHas( new Object[] { "delete", g, SPO} );
+    }
+
+    @Test
+    public void testListSubjects()
+    {
+        Set<Node> emptySubjects = listSubjects( getGraphWith( "" ) );
+        Graph g = getGraphWith( "x P y; y Q z" );
+        assertEquals( nodeSet( "x y" ), remove( listSubjects( g ), emptySubjects ) );
+        g.delete( triple( "x P y" ) );
+        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( getGraphWith( "" ) );
+        Graph g = getGraphWith( "x P y; y Q z" );
+        assertEquals( nodeSet( "P Q" ), remove( listPredicates( g ), emptyPredicates ) );
+        g.delete( triple( "x P y" ) );
+        assertEquals( nodeSet( "Q" ), remove( listPredicates( g ), emptyPredicates ) );
+    }
+
+    protected Set<Node> listPredicates( Graph g )
+    {
+        return GraphUtil.listPredicates( g, Node.ANY, Node.ANY ).toSet();
+    }    
+
+    @Test
+    public void testListObjects()
+    {
+        Set<Node> emptyObjects = listObjects( getGraphWith( "" ) );
+        Graph g = getGraphWith( "x P y; y Q z" );
+        assertEquals( nodeSet( "y z" ), remove( listObjects( g ), emptyObjects ) );
+        g.delete( triple( "x P y" ) );
+        assertEquals( nodeSet( "z" ), remove( listObjects( g ), emptyObjects ) );
+    }
+
+    protected Set<Node> listObjects( Graph g )
+    {
+        return GraphUtil.listObjects( g, Node.ANY, Node.ANY ).toSet();
+    }
+
+    /**
+        Answer a set with all the elements of <code>A</code> except those
+        in <code>B</code>.
+     */
+    private <T> Set<T> remove( Set<T> A, Set<T> B )
+    {
+        Set<T> result = new HashSet<T>( A );
+        result.removeAll(  B  );        
+        return result;
+    }
+
+    /**
+         Ensure that triples removed by calling .remove() on the iterator returned by
+         a find() will generate deletion notifications.
+     */
+    @Test
+    public void testEventDeleteByFind()
+    {
+        Graph g = getAndRegister( L );
+        if (g.getCapabilities().iteratorRemoveAllowed())
+        {
+            Triple toRemove = triple( "remove this triple" );
+            g.add( toRemove );
+            ExtendedIterator<Triple> rtr = g.find( toRemove );
+            assertTrue( "ensure a(t least) one triple", rtr.hasNext() );
+            rtr.next(); rtr.remove(); rtr.close();
+            L.assertHas( new Object[] { "add", g, toRemove, "delete", g, toRemove} );
+        }
+    }
+
+    @Test
+    public void testTwoListeners()
+    {
+        RecordingListener L1 = new RecordingListener();
+        RecordingListener L2 = new RecordingListener();
+        Graph g = getGraph();
+        GraphEventManager gem = g.getEventManager();
+        gem.register( L1 ).register( L2 );
+        g.add( SPO );
+        L2.assertHas( new Object[] {"add", g, SPO} );
+        L1.assertHas( new Object[] {"add", g, SPO} );
+    }
+
+    @Test
+    public void testUnregisterWorks()
+    {
+        Graph g = getGraph();
+        GraphEventManager gem = g.getEventManager();
+        gem.register( L ).unregister( L );
+        g.add( SPO );
+        L.assertHas( new Object[] {} );
+    }
+
+    @Test
+    public void testRegisterTwice()
+    {
+        Graph g = getAndRegister( L );
+        g.getEventManager().register( L );
+        g.add( SPO );
+        L.assertHas( new Object[] {"add", g, SPO, "add", g, SPO} );
+    }
+
+    @Test
+    public void testUnregisterOnce()
+    {
+        Graph g = getAndRegister( L );
+        g.getEventManager().register( L ).unregister( L );
+        g.delete( SPO );
+        L.assertHas( new Object[] {"delete", g, SPO} );
+    }
+
+    @Test
+    public void testBulkAddArrayEvent()
+    {
+        Graph g = getAndRegister( L );
+        Triple [] triples = tripleArray( "x R y; a P b" );
+        GraphUtil.add(g, triples );
+        L.assertHas( new Object[] {"add[]", g, triples} );
+    }
+
+    @Test
+    public void testBulkAddList()
+    {
+        Graph g = getAndRegister( L );
+        List<Triple> elems = Arrays.asList( tripleArray( "bells ring loudly; pigs might fly" ) );
+        GraphUtil.add(g, elems) ;
+        L.assertHas( new Object[] {"addList", g, elems} );
+    }
+
+    @Test
+    public void testBulkDeleteArray()
+    {
+        Graph g = getAndRegister( L );
+        Triple [] triples = tripleArray( "x R y; a P b" );
+        GraphUtil.delete( g, triples );
+        L.assertHas( new Object[] {"delete[]", g, triples} );
+    }
+
+    @Test
+    public void testBulkDeleteList()
+    {
+        Graph g = getAndRegister( L );
+        List<Triple> elems = Arrays.asList( tripleArray( "bells ring loudly; pigs might fly" ) );
+        GraphUtil.delete( g, elems );
+        L.assertHas( new Object[] {"deleteList", g, elems} );
+    }
+
+    @Test
+    public void testBulkAddIterator()
+    {
+        Graph g = getAndRegister( L ); 
+        Triple [] triples = tripleArray( "I wrote this; you read that; I wrote this" );
+        GraphUtil.add(g, asIterator( triples ) );
+        L.assertHas( new Object[] {"addIterator", g, Arrays.asList( triples )} );
+    }
+
+    @Test
+    public void testBulkDeleteIterator()
+    {
+        Graph g = getAndRegister( L );
+        Triple [] triples = tripleArray( "I wrote this; you read that; I wrote this" );
+        GraphUtil.delete( g, asIterator( triples ) );
+        L.assertHas( new Object[] {"deleteIterator", g, Arrays.asList( triples )} );
+    }
+
+    public Iterator<Triple> asIterator( Triple [] triples )
+    { return Arrays.asList( triples ).iterator(); }
+
+    @Test
+    public void testBulkAddGraph()
+    {
+        Graph g = getAndRegister( L );
+        Graph triples = graphWith( "this type graph; I type slowly" );
+        GraphUtil.addInto( g, triples );
+        L.assertHas( new Object[] {"addGraph", g, triples} );
+    }
+
+    @Test
+    public void testBulkDeleteGraph()
+    {        
+        Graph g = getAndRegister( L );
+        Graph triples = graphWith( "this type graph; I type slowly" );
+        GraphUtil.deleteFrom( g, triples );
+        L.assertHas( new Object[] {"deleteGraph", g, triples} );
+    }
+
+    @Test
+    public void testGeneralEvent()
+    {
+        Graph g = getAndRegister( L );
+        Object value = new int[]{};
+        g.getEventManager().notifyEvent( g, value );
+        L.assertHas( new Object[] { "someEvent", g, value } );
+    }
+
+    @Test
+    public void testRemoveAllEvent()
+    {
+        Graph g = getAndRegister( L );
+        g.clear();
+        L.assertHas( new Object[] { "someEvent", g, GraphEvents.removeAll } );        
+    }
+
+    @Test
+    public void testRemoveSomeEvent()
+    {
+        Graph g = getAndRegister( L );
+        Node S = node( "S" ), P = node( "??" ), O = node( "??" );
+        g.remove( S, P, O );
+        Object event = GraphEvents.remove( S, P, O );
+        L.assertHas( new Object[] { "someEvent", g, event } );        
+    }
+
+    /**
+     * 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 = getGraph();
+        graphAdd( g, "a P b; _c _Q _d; a 11 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( "_Q" ) ) );
+        assertTrue( containsNode( g, node( "_d" ) ) );
+        //        assertTrue( qh.containsNode( node( "10" ) ) );
+        assertTrue( containsNode( g, node( "11" ) ) );
+        assertTrue( containsNode( g, node( "12" ) ) );
+        /* */
+        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 = getGraphWith( "" );
+        Set<Node> B = GraphUtil.listSubjects( b, Node.ANY, Node.ANY ).toSet();
+        
+        Graph g = getGraphWith( "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 = getGraphWith( "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 = getGraphWith( "" );
+        Set<Node> B = GraphUtil.listObjects( b, Node.ANY, Node.ANY ).toSet();
+
+        Graph g = getGraphWith( "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" ));
+    }    
+
+    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) ;
+    }
+
+    @Test
+    public void testPredicatesFor()
+    {
+        // First get the answer from the empty graph (not empty for an inf graph)
+        Graph b = getGraphWith( "" );
+        Set<Node> B = GraphUtil.listPredicates( b, Node.ANY, Node.ANY ).toSet();
+
+        Graph g = getGraphWith( "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" ));
+    }    
+
+    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
+    public void testListObjectsNoRemove()
+    {
+        Graph g = getGraphWith( "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
+        	}
+    }
+
+    @Test
+    public void testListPredicatesNoRemove()
+    {
+        Graph g = getGraphWith( "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
+        	}
+    }
+
+    @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 testRemoveAll( String triples )
+    {
+        Graph g = getGraph();
+        graphAdd( g, triples );
+        g.clear();
+        assertTrue( g.isEmpty() );
+    }
+
+    @Test
+    public void failingTestDoubleRemoveAll() {
+        final Graph g = getGraph();
+        if (g.getCapabilities().iteratorRemoveAllowed() ) {
+            graphAdd(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() );
+        }
+    }
+
+    @Test
+    public void testGetStatisticsHandler()
+    {
+        Graph g = getGraph();
+        GraphStatisticsHandler h = g.getStatisticsHandler();
+        assertSame( h, g.getStatisticsHandler() );
+    }
+
+    /**
+     	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 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 = getGraph();
+                Graph baseContent = copy( content );
+                graphAdd( content, cases[i][0] );
+                Triple remove = triple( cases[i][1] );
+                Graph expected = graphWith( cases[i][2] );
+                content.remove( remove.getSubject(), remove.getPredicate(), remove.getObject() );
+                Graph finalContent = remove( copy( content ), baseContent );
+                assertIsomorphic( cases[i][1], expected, finalContent );
+            }
+    }
+
+    /** testIsomorphism from file data 
+     * @throws FileNotFoundException */
+    @Test
+     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 AbstractGraphTest.class.getClassLoader().getResourceAsStream(  urlStr );
+    }
+    
+    private void testIsomorphismFile(int n, String lang, String suffix, boolean result) throws URISyntaxException, MalformedURLException {
+
+        Graph g1 = getGraph();
+        Graph g2 = getGraph();
+        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 void add( Graph toUpdate, Graph toAdd )
+    {
+        GraphUtil.addInto( toUpdate, toAdd) ;
+    }
+
+    protected Graph remove( Graph toUpdate, Graph toRemove )
+    {
+        GraphUtil.deleteFrom(toUpdate, toRemove) ;
+        return toUpdate;
+    }
+
+
+    protected Graph copy( Graph g )
+    {
+        Graph result = Factory.createDefaultGraph();
+        GraphUtil.addInto(result, g) ;
+        return result;
+    }
+
+    protected Graph getClosed()
+    {
+        Graph result = getGraph();
+        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 */ }
+    //        }
+
+}

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

Added: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphProducerInterface.java
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphProducerInterface.java?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphProducerInterface.java (added)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphProducerInterface.java Tue Aug 27 06:01:01 2013
@@ -0,0 +1,14 @@
+package com.hp.hpl.jena.graph;
+
+/**
+ * Creates the graph for testing
+ *
+ */
+public interface GraphProducerInterface {
+
+	/**
+	 * Returns a Graph to take part in the test. Must be overridden in a subclass.
+	 * @return The graph implementation to test.
+	 */
+	public abstract Graph newGraph();
+}

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

Added: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphTestUtils.java
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphTestUtils.java?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphTestUtils.java (added)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/GraphTestUtils.java Tue Aug 27 06:01:01 2013
@@ -0,0 +1,431 @@
+/*
+ * 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 com.hp.hpl.jena.graph;
+
+/**
+    An extension of JenaTestBase (which see) with Graph-specific methods.
+*/
+
+import static org.junit.Assert.*;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Constructor ;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import com.hp.hpl.jena.graph.Factory;
+import com.hp.hpl.jena.graph.Graph;
+import com.hp.hpl.jena.graph.GraphUtil;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.ontology.impl.TestListSyntaxCategories;
+import com.hp.hpl.jena.shared.JenaException ;
+import com.hp.hpl.jena.shared.PrefixMapping ;
+import com.hp.hpl.jena.test.TestUtils;
+import com.hp.hpl.jena.util.CollectionFactory ;
+import com.hp.hpl.jena.util.IteratorCollection ;
+import com.hp.hpl.jena.util.iterator.ExtendedIterator ;
+
+public class GraphTestUtils extends TestUtils
+    {
+	protected static String getFileName( String fn )
+   	{
+   		URL u = TestListSyntaxCategories.class.getClassLoader().getResource( fn );
+   		if (u == null)
+   		{
+   			throw new RuntimeException( new FileNotFoundException( fn ));
+   		}
+   		try {
+   			return u.toURI().toString();
+   		} catch (URISyntaxException e) {
+   			throw new RuntimeException( e );
+   		}
+   	}
+  	
+    /**
+        Answer a Node as described by <code>x</code>; a shorthand for
+        <code>Node.create(x)</code>, which see.
+    */
+    public static Node node( String x )
+        { return NodeCreateUtils.create( x ); }
+        
+    /**
+        Answer a set containing the elements from the iterator <code>it</code>;
+        a shorthand for <code>IteratorCollection.iteratorToSet(it)</code>,
+        which see.
+    */
+    public static <T> Set<T> iteratorToSet( Iterator<? extends T> it )
+        { return IteratorCollection.iteratorToSet( it ); }
+    
+    /**
+        Answer a list containing the elements from the iterator <code>it</code>,
+        in order; a shorthand for <code>IteratorCollection.iteratorToList(it)</code>,
+        which see.
+    */
+    public static <T> List<T> iteratorToList( Iterator<? extends T> it )
+        { return IteratorCollection.iteratorToList( it ); }
+                
+    /**
+        Answer a set of the nodes described (as per <code>node()</code>) by
+        the space-separated substrings of <code>nodes</code>.
+    */
+    public static Set<Node> nodeSet( String nodes )
+        {
+        Set<Node> result = CollectionFactory.createHashedSet();
+        StringTokenizer st = new StringTokenizer( nodes );
+        while (st.hasMoreTokens()) result.add( node( st.nextToken() ) );
+        return result;
+        }
+    
+    /**
+        Answer a set of the elements of <code>A</code>.
+    */
+    public static <T> Set<T> arrayToSet( T [] A )
+        { return CollectionFactory.createHashedSet( Arrays.asList( A ) ); }
+    
+    /**
+        Answer a triple described by the three space-separated node descriptions
+        in <code>fact</code>; a shorthand for <code>Triple.create(fact)</code>,
+        which see.
+    */
+    public static Triple triple( String fact )
+        { return NodeCreateUtils.createTriple( fact ); }
+    
+    /**
+        Answer a triple described by the three space-separated node descriptions
+        in <code>fact</code>, using prefix-mappings from <code>pm</code>; a 
+        shorthand for <code>Triple.create(pm, fact)</code>, which see.
+    */
+    public static Triple triple( PrefixMapping pm, String fact )
+        { return NodeCreateUtils.createTriple( pm, fact ); }
+        
+    /**
+        Answer an array of triples; each triple is described by one of the
+        semi-separated substrings of <code>facts</code>, as per 
+        <code>triple</code> with prefix-mapping <code>Extended</code>.
+    */
+    public static Triple [] tripleArray( String facts )
+        {
+        ArrayList<Triple> al = new ArrayList<Triple>();
+        StringTokenizer semis = new StringTokenizer( facts, ";" );
+        while (semis.hasMoreTokens()) al.add( triple( PrefixMapping.Extended, semis.nextToken() ) );   
+        return al.toArray( new Triple [al.size()] );
+        }
+    
+    /**
+        Answer a set of triples where the elements are described by the
+        semi-separated substrings of <code>facts</code>, as per 
+        <code>triple</code>.
+    */
+    public static Set<Triple> tripleSet( String facts )
+        {
+        Set<Triple> result = new HashSet<Triple>();
+        StringTokenizer semis = new StringTokenizer( facts, ";" );
+        while (semis.hasMoreTokens()) result.add( triple( semis.nextToken() ) );   
+        return result;
+        }
+       
+    /**
+        Answer a list of nodes, where the nodes are described by the 
+        space-separated substrings of <code>items</code> as per
+        <code>node()</code>.
+    */
+    public static List<Node> nodeList( String items )
+        {
+        ArrayList<Node> nl = new ArrayList<Node>();
+        StringTokenizer nodes = new StringTokenizer( items );
+        while (nodes.hasMoreTokens()) nl.add( node( nodes.nextToken() ) );   
+        return nl;
+        }   
+    
+    /**
+        Answer an array of nodes, where the nodes are described by the 
+        space-separated substrings of <code>items</code> as per
+    */
+    public static Node [] nodeArray( String items )
+        {
+        List<Node> nl = nodeList( items );  
+        return nl.toArray( new Node [nl.size()] );
+        } 
+    
+    /**
+        Answer the graph <code>g</code> after adding to it every triple
+        encoded in <code>s</code> in the fashion of <code>tripleArray</code>,
+        a semi-separated sequence of space-separated node descriptions.
+    */
+    public static Graph graphAdd( Graph g, String s )
+        {
+        StringTokenizer semis = new StringTokenizer( s, ";" );
+        while (semis.hasMoreTokens()) g.add( triple( PrefixMapping.Extended, semis.nextToken() ) );     
+        return g;
+        }
+    
+    /**
+        Answer a new memory-based graph with Extended prefixes.
+    */
+    public static Graph newGraph()
+        {
+        Graph result = Factory.createGraphMem();
+        result.getPrefixMapping().setNsPrefixes( PrefixMapping.Extended );
+        return result;
+        }
+    
+    /**
+        Answer a new memory-based graph with initial contents as described
+        by <code>s</code> in the fashion of <code>graphAdd()</code>.
+        Not over-ridable; do not use for abstraction.
+    */
+    public static Graph graphWith( String s )
+        { return graphAdd( newGraph(), s ); }
+    
+    /**
+        Assert that the graph <code>g</code> is isomorphic to the graph 
+        described by <code>template</code> in the fashion of 
+        <code>graphWith</code>.
+    */
+    public static void assertEqualsTemplate( String title, Graph g, String template )
+        { assertIsomorphic( title, graphWith( template ), g ); }
+                
+    /**
+        Assert that the supplied graph <code>got</code> is isomorphic with the
+        the desired graph <code>expected</code>; if not, display a readable
+        description of both graphs.
+    */
+    public static void assertIsomorphic( String title, Graph expected, Graph got )
+        {
+        if (!expected.isIsomorphicWith( got ))
+            {
+            Map<Node, Object> map = CollectionFactory.createHashedMap();
+            fail( title + ": wanted " + nice( expected, map ) + "\nbut got " + nice( got, map ) );
+            }
+        }
+    
+    /**
+        Answer a string which is a newline-separated list of triples (as
+        produced by niceTriple) in the graph <code>g</code>. The map 
+        <code>bnodes</code> maps already-seen bnodes to their "nice" strings. 
+    */
+    public static String nice( Graph g, Map<Node, Object> bnodes )
+        {
+        StringBuffer b = new StringBuffer( g.size() * 100 );
+        ExtendedIterator<Triple> it = GraphUtil.findAll( g );
+        while (it.hasNext()) niceTriple( b, bnodes, it.next() );
+        return b.toString();
+        }
+    
+    /**
+        Append to the string buffer <code>b</code> a "nice" representation 
+        of the triple <code>t</code> on a new line, using (and updating)
+        <code>bnodes</code> to supply "nice" strings for any blank nodes.
+    */
+    protected static void niceTriple( StringBuffer b, Map<Node, Object> bnodes, Triple t )
+        {
+        b.append( "\n    " );
+        appendNode( b, bnodes, t.getSubject() );
+        appendNode( b, bnodes, t.getPredicate() );
+        appendNode( b, bnodes, t.getObject() );
+        }
+
+    /**
+        A counter for new bnode strings; it starts at 1000 so as to make
+        the bnode strings more uniform (at least for the first 9000 bnodes).
+    */
+    protected static int bnc = 1000;
+    
+    /**
+        Append to the string buffer <code>b</code> a space followed by the
+        "nice" representation of the node <code>n</code>. If <code>n</code>
+        is a bnode, re-use any existing string for it from <code>bnodes</code>
+        or make a new one of the form <i>_bNNNN</i> with NNNN a new integer.
+    */
+    protected static void appendNode( StringBuffer b, Map<Node, Object> bnodes, Node n )
+        {
+        b.append( ' ' );
+        if (n.isBlank())
+            {
+            Object already = bnodes.get( n );
+            if (already == null) bnodes.put( n, already = "_b" + bnc++ );
+            b.append( already );
+            }
+        else
+            b.append( nice( n ) );
+        }
+    
+    /**
+        Answer the "nice" representation of this node, the string returned by
+        <code>n.toString(PrefixMapping.Extended,true)</code>.
+    */
+    protected static String nice( Node n )
+        { return n.toString( PrefixMapping.Extended, true ); }
+            
+    /**
+        Assert that the computed graph <code>got</code> is isomorphic with the
+        desired graph <code>expected</code>; if not, fail with a default
+        message (and pretty output of the graphs).
+    */
+    public static void assertIsomorphic( Graph expected, Graph got )
+        { assertIsomorphic( "graphs must be isomorphic", expected, got ); }
+
+    /**
+        Assert that the graph <code>g</code> must contain the triple described
+        by <code>s</code>; if not, fail with pretty output of both graphs
+        and a message containing <code>name</code>.
+    */
+    public static void assertContains( String name, String s, Graph g )
+        {
+        assertTrue( name + " must contain " + s, g.contains( triple( s ) ) );
+        }
+    
+    /**
+        Assert that the graph <code>g</code> contains all the triples described
+        by the string <code>s</code; if not, fail with a message containing
+        <code>name</code>.
+    */
+    public static void assertContainsAll( String name, Graph g, String s )
+        {
+        StringTokenizer semis = new StringTokenizer( s, ";" );
+        while (semis.hasMoreTokens()) assertContains( name, semis.nextToken(), g );       
+        }
+    
+    /**
+        Assert that the graph <code>g</code> does not contain the triple
+        described by <code>s<code>; if it does, fail with a message containing
+        <code>name</code>.
+    */
+    public static void assertOmits( String name, Graph g, String s )
+        {
+        assertFalse( name + " must not contain " + s, g.contains( triple( s ) ) );
+        }
+    
+    /**
+        Assert that the graph <code>g</code> contains none of the triples
+        described by <code>s</code> in the usual way; otherwise, fail with
+        a message containing <code>name</code>.
+    */
+    public static void assertOmitsAll( String name, Graph g, String s )
+        {
+        StringTokenizer semis = new StringTokenizer( s, ";" );
+        while (semis.hasMoreTokens()) assertOmits( name, g, semis.nextToken() );     
+        }
+        
+    /**
+        Assert that <code>g</code> contains the triple described by 
+        <code>fact</code> in the usual way.
+    */
+    public static boolean contains( Graph g, String fact )
+        { return g.contains( triple( fact ) ); }
+    
+    /**
+        Assert that <code>g</code> contains every triple in <code>triples</code>.
+    */
+    public static void testContains( Graph g, Triple [] triples )
+        { 
+        for (int i = 0; i < triples.length; i += 1) 
+            assertTrue( "contains " + triples[i], g.contains( triples[i] ) ); 
+        }
+
+    /**
+        Assert that <code>g</code> contains every triple in <code>triples</code>.
+    */
+    public static void testContains( Graph g, List<Triple> triples )
+        {
+        for (int i = 0; i < triples.size(); i += 1)
+             assertTrue( g.contains( triples.get(i) ) );
+        }
+
+    /**
+        Assert that <code>g</code> contains every triple in <code>it</code>.
+    */
+    public static void testContains( Graph g, Iterator<Triple> it )
+        { while (it.hasNext()) assertTrue( g.contains( it.next() ) ); }
+
+    /**
+        Assert that <code>g</code> contains every triple in <code>other</code>.
+    */
+    public static void testContains( Graph g, Graph other )
+        { testContains( g, GraphUtil.findAll( other ) ); }
+    
+    /**
+        Assert that <code>g</code> contains none of the triples in 
+        <code>triples</code>.
+    */
+    public static void testOmits( Graph g, Triple [] triples )
+        { for (int i = 0; i < triples.length; i += 1) assertFalse( "", g.contains( triples[i] ) ); }
+    
+    /**
+        Assert that <code>g</code> contains none of the triples in 
+        <code>triples</code>.
+    */
+    public static void testOmits( Graph g, List<Triple> triples )
+        {
+        for (int i = 0; i < triples.size(); i += 1)
+             assertFalse( "", g.contains( triples.get(i) ) );
+        }
+    
+    /**
+        Assert that <code>g</code> contains none of the triples in 
+        <code>it</code>.
+    */
+    public static void testOmits( Graph g, Iterator<Triple> it )
+        { while (it.hasNext()) assertFalse( "", g.contains( it.next() ) ); }
+    
+    /**
+        Assert that <code>g</code> contains none of the triples in 
+        <code>other</code>.
+    */
+    public static void testOmits( Graph g, Graph other )
+        { testOmits( g, GraphUtil.findAll( other ) ); }
+
+    /**
+        Answer an instance of <code>graphClass</code>. If <code>graphClass</code> has
+        a constructor that takes a <code>ReificationStyle</code> argument, then that
+        constructor is run on <code>style</code> to get the instance. Otherwise, if it has a #
+        constructor that takes an argument of <code>wrap</code>'s class before the
+        <code>ReificationStyle</code>, that constructor is used; this allows non-static inner
+        classes to be used for <code>graphClass</code>, with <code>wrap</code> being
+        the outer class instance. If no suitable constructor exists, a JenaException is thrown.
+        
+        @param wrap the outer class instance if graphClass is an inner class
+        @param graphClass a class implementing Graph
+        @return an instance of graphClass with the given style
+        @throws RuntimeException or JenaException if construction fails
+     */
+    public static Graph getGraph( Object wrap, Class<? extends Graph> graphClass) 
+        {
+        try
+            {
+            Constructor<?> cons = getConstructor( graphClass, new Class[] {} );
+            if (cons != null) return (Graph) cons.newInstance( new Object[] { } );
+            Constructor<?> cons2 = getConstructor( graphClass, new Class [] {wrap.getClass()} );
+            if (cons2 != null) return (Graph) cons2.newInstance( new Object[] { wrap} );
+            throw new JenaException( "no suitable graph constructor found for " + graphClass );
+            }
+        catch (RuntimeException e)
+            { throw e; }
+        catch (Exception e)
+            { throw new JenaException( e ); }
+        }
+    }

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

Added: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/MemGraphTest.java
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/MemGraphTest.java?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/MemGraphTest.java (added)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/MemGraphTest.java Tue Aug 27 06:01:01 2013
@@ -0,0 +1,19 @@
+package com.hp.hpl.jena.graph;
+
+import com.hp.hpl.jena.sparql.graph.GraphFactory;
+
+public class MemGraphTest extends AbstractGraphTest  {
+
+	public MemGraphTest() {
+		super( new GraphProducer() );
+	}
+
+	private static class GraphProducer implements GraphProducerInterface
+	{
+		@Override
+		public Graph newGraph() {
+			return GraphFactory.createGraphMem();
+		}
+	}
+
+}

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

Added: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/NodeCreateUtils.java
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/NodeCreateUtils.java?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/NodeCreateUtils.java (added)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/NodeCreateUtils.java Tue Aug 27 06:01:01 2013
@@ -0,0 +1,170 @@
+/*
+ * 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 com.hp.hpl.jena.graph;
+
+import java.util.StringTokenizer;
+
+import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory ;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.graph.impl.LiteralLabel;
+import com.hp.hpl.jena.graph.impl.LiteralLabelFactory;
+import com.hp.hpl.jena.rdf.model.AnonId;
+import com.hp.hpl.jena.shared.*;
+
+/**
+    Creating nodes from string specifications.
+*/
+public class NodeCreateUtils
+    {
+    /**
+        Returns a Node described by the string, primarily for testing purposes.
+        The string represents a URI, a numeric literal, a string literal, a bnode label,
+        or a variable.        
+        <ul>
+        <li> 'some text' :: a string literal with that text
+        <li> 'some text'someLanguage:: a string literal with that text and language
+        <li> 'some text'someURI:: a typed literal with that text and datatype
+        <li> digits :: a literal [OF WHAT TYPE] with that [numeric] value
+        <li> _XXX :: a bnode with an AnonId built from _XXX
+        <li> ?VVV :: a variable with name VVV
+        <li> &PPP :: to be done
+        <li> name:stuff :: the URI; name may be expanded using the Extended map
+        </ul>
+        @param x the string describing the node
+        @return a node of the appropriate type with the appropriate label
+    */
+    public static Node create( String x )
+        { return create( PrefixMapping.Extended, x ); }
+    
+    /**
+    Returns a Node described by the string, primarily for testing purposes.
+    The string represents a URI, a numeric literal, a string literal, a bnode label,
+    or a variable.        
+    <ul>
+    <li> 'some text' :: a string literal with that text
+    <li> 'some text'someLanguage:: a string literal with that text and language
+    <li> 'some text'someURI:: a typed literal with that text and datatype
+    <li> digits :: a literal [OF WHAT TYPE] with that [numeric] value
+    <li> _XXX :: a bnode with an AnonId built from _XXX
+    <li> ?VVV :: a variable with name VVV
+    <li> &PPP :: to be done
+    <li> name:stuff :: the URI; name may be expanded using the Extended map
+    </ul>
+    
+    @param pm the PrefixMapping for translating pre:X strings
+    @param x the string encoding the node to create
+    @return a node with the appropriate type and label
+    */
+    public static Node create( PrefixMapping pm, String x )
+        {
+        if (x.equals( "" ))
+            throw new JenaException( "Node.create does not accept an empty string as argument" );
+        char first = x.charAt( 0 );
+        if (first == '\'' || first == '\"')
+            return NodeFactory.createLiteral( newString( pm, first, x ) );
+        if (Character.isDigit( first )) 
+            return NodeFactory.createLiteral( x, "", XSDDatatype.XSDinteger );
+        if (first == '_')
+            return NodeFactory.createAnon( new AnonId( x ) );
+        if (x.equals( "??" ))
+            return Node.ANY;
+        if (first == '?')
+            return NodeFactory.createVariable( x.substring( 1 ) );
+        if (first == '&')
+            return NodeFactory.createURI( "q:" + x.substring( 1 ) );        
+        int colon = x.indexOf( ':' );
+        String d = pm.getNsPrefixURI( "" );
+        return colon < 0 
+            ? NodeFactory.createURI( (d == null ? "eh:/" : d) + x )
+            : NodeFactory.createURI( pm.expandPrefix( x ) )
+            ;
+        }
+
+    public static String unEscape( String spelling )
+        {
+        if (spelling.indexOf( '\\' ) < 0) return spelling;
+        StringBuffer result = new StringBuffer( spelling.length() );
+        int start = 0;
+        while (true)
+            {
+            int b = spelling.indexOf( '\\', start );
+            if (b < 0) break;
+            result.append( spelling.substring( start, b ) );
+            result.append( unEscape( spelling.charAt( b + 1 ) ) );
+            start = b + 2;
+            }
+        result.append( spelling.substring( start ) );
+        return result.toString();
+        }
+    
+    public static char unEscape( char ch )
+        {
+        switch (ch)
+        	{
+            case '\\':
+            case '\"':
+            case '\'': return ch;
+            case 'n': return '\n';
+            case 's': return ' ';
+            case 't': return '\t';
+            default: return 'Z';
+        	}
+        }
+
+    public static LiteralLabel literal( PrefixMapping pm, String spelling, String langOrType )
+        {
+        String content = unEscape( spelling );
+        int colon = langOrType.indexOf( ':' );
+        return colon < 0 
+            ? LiteralLabelFactory.create( content, langOrType, false )
+            : LiteralLabelFactory.createLiteralLabel( content, "", NodeFactory.getType( pm.expandPrefix( langOrType ) ) )
+            ;
+        }
+
+    public static LiteralLabel newString( PrefixMapping pm, char quote, String nodeString )
+        {
+        int close = nodeString.lastIndexOf( quote );
+        return literal( pm, nodeString.substring( 1, close ), nodeString.substring( close + 1 ) );
+        }
+
+	/**
+	    Utility factory as for create(String), but allowing the PrefixMapping to
+	    be specified explicitly.
+	*/
+	public static Triple createTriple( PrefixMapping pm, String fact )
+	    {
+	    StringTokenizer st = new StringTokenizer( fact );
+	    Node sub = create( pm, st.nextToken() );
+	    Node pred = create( pm, st.nextToken() );
+	    Node obj = create( pm, st.nextToken() );
+	    return Triple.create( sub, pred, obj );
+	    }
+
+	/**
+	    Utility factory method for creating a triple based on the content of an
+	    "S P O" string. The S, P, O are processed by Node.create, see which for
+	    details of the supported syntax. This method exists to support test code.
+	    Nodes are interpreted using the Standard prefix mapping.
+	*/
+	
+	public static Triple createTriple( String fact )
+	    { return createTriple( PrefixMapping.Standard, fact ); }
+    }

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

Added: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/RecordingListener.java
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/RecordingListener.java?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/RecordingListener.java (added)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/RecordingListener.java Tue Aug 27 06:01:01 2013
@@ -0,0 +1,121 @@
+/*
+ * 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 com.hp.hpl.jena.graph;
+
+import java.util.ArrayList ;
+import java.util.Arrays ;
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.junit.Assert ;
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.GraphListener ;
+import com.hp.hpl.jena.graph.Triple ;
+
+/**
+    This testing listener records the event names and data, and provides
+    a method for comparing the actual with the expected history. 
+*/    
+public class RecordingListener implements GraphListener
+    {
+    public List<Object> history = new ArrayList<Object>();
+    
+    @Override
+    public void notifyAddTriple( Graph g, Triple t )
+        { record( "add", g, t ); }
+        
+    @Override
+    public void notifyAddArray( Graph g, Triple [] triples )
+        { record( "add[]", g, triples ); }
+        
+    @Override
+    public void notifyAddList( Graph g, List<Triple> triples )
+        { record( "addList", g, triples ); }
+        
+    @Override
+    public void notifyAddIterator( Graph g, Iterator<Triple> it )
+        { record( "addIterator", g, GraphTestUtils.iteratorToList( it ) ); }
+        
+    @Override
+    public void notifyAddGraph( Graph g, Graph added )
+        { record( "addGraph", g, added ); }
+        
+    @Override
+    public void notifyDeleteTriple( Graph g, Triple t )
+        { record( "delete", g, t ); }
+        
+    @Override
+    public void notifyDeleteArray( Graph g, Triple [] triples )
+        { record( "delete[]", g, triples ); }
+        
+    @Override
+    public void notifyDeleteList( Graph g, List<Triple> triples )
+        { record( "deleteList", g, triples ); }
+        
+    @Override
+    public void notifyDeleteIterator( Graph g, Iterator<Triple> it )
+        { record( "deleteIterator", g, GraphTestUtils.iteratorToList( it ) ); }
+        
+    @Override
+    public void notifyDeleteGraph( Graph g, Graph removed )
+        { record( "deleteGraph", g, removed ); }
+    
+    @Override
+    public void notifyEvent( Graph source, Object event )
+        { record( "someEvent", source, event ); }
+        
+    protected void record( String tag, Object x, Object y )
+        { history.add( tag ); history.add( x ); history.add( y ); }
+    
+    protected void record( String tag, Object info )
+        { history.add( tag ); history.add( info ); }
+        
+    public void clear()
+        { history.clear(); }
+
+    public boolean has( List<Object> things )
+        { return Arrays.deepEquals(history.toArray(), things.toArray() ); } 
+    
+    public boolean hasStart( List<Object> L )
+        { return L.size() <= history.size() && L.equals( history.subList( 0, L.size() ) ); }
+    
+    public boolean hasEnd( List<Object> L )
+        { return L.size() <= history.size() && L.equals( history.subList( history.size() - L.size(), history.size() ) ); }
+    
+    public boolean has( Object [] things )
+        { return Arrays.deepEquals(history.toArray(), things ); } 
+        
+    public void assertHas( List<Object> things )
+        { if (has( things ) == false) Assert.fail( "expected " + things + " but got " + history ); }  
+    
+    public void assertHas( Object [] things )
+        { assertHas( Arrays.asList( things ) ); }
+    
+    public void assertHasStart( Object [] start )
+        { 
+        List<Object> L = Arrays.asList( start );
+        if (hasStart( L ) == false) Assert.fail( "expected " + L + " at the beginning of " + history );
+        }
+    
+    public void assertHasEnd( Object [] end )
+        {
+        List<Object> L = Arrays.asList( end );
+        if (hasEnd( L ) == false) Assert.fail( "expected " + L + " at the end of " + history );        
+        }
+    }

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

Added: jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/impl/TestCollectionGraph.java
URL: http://svn.apache.org/viewvc/jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/impl/TestCollectionGraph.java?rev=1517755&view=auto
==============================================================================
--- jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/impl/TestCollectionGraph.java (added)
+++ jena/Experimental/new-test/src/test/java/com/hp/hpl/jena/graph/impl/TestCollectionGraph.java Tue Aug 27 06:01:01 2013
@@ -0,0 +1,43 @@
+/*
+ * 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 com.hp.hpl.jena.graph.impl;
+
+import java.util.HashSet;
+
+import com.hp.hpl.jena.graph.GraphProducerInterface;
+import com.hp.hpl.jena.graph.AbstractGraphTest;
+import com.hp.hpl.jena.graph.Graph;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.graph.impl.CollectionGraph;
+
+public class TestCollectionGraph extends AbstractGraphTest {
+	 
+	public TestCollectionGraph() {
+		super( new GraphProducer() );
+	}
+
+	public static class GraphProducer implements GraphProducerInterface
+	{
+	@Override
+	public Graph newGraph() {
+		return new CollectionGraph( new HashSet<Triple>() );
+	}
+	}
+
+}

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