Merge branch 'master' of ssh://git.eclipse.org/gitroot/virgo/org.eclipse.virgo.util into 369907-rework-dag-interface
diff --git a/org.eclipse.virgo.util.common/src/main/java/org/eclipse/virgo/util/common/DirectedAcyclicGraph.java b/org.eclipse.virgo.util.common/src/main/java/org/eclipse/virgo/util/common/DirectedAcyclicGraph.java
index 7bec6d7..bb84056 100644
--- a/org.eclipse.virgo.util.common/src/main/java/org/eclipse/virgo/util/common/DirectedAcyclicGraph.java
+++ b/org.eclipse.virgo.util.common/src/main/java/org/eclipse/virgo/util/common/DirectedAcyclicGraph.java
@@ -8,12 +8,11 @@
  * Contributors:
  *   VMware Inc. - initial contribution (Tree.java)
  *   EclipseSource - reworked from generic tree to DAG (Bug 358697)
+ *   EclipseSource - removed internal root node list (Bug 369907)
  *******************************************************************************/
 
 package org.eclipse.virgo.util.common;
 
-import java.util.List;
-
 /**
  * {@link DirectedAcyclicGraph} is a set of {@link GraphNode}s with a parent child relationship. The nodes are connected
  * to each other in a way that it is impossible to start at a node n and follow a child relationship that loops back to
@@ -31,35 +30,11 @@
 public interface DirectedAcyclicGraph<V> {
 
     /**
-     * Create a new {@link GraphNode} and add it to this {@link DirectedAcyclicGraph}'s root nodes. The value is not
-     * copied.
+     * Create a new {@link GraphNode} for this {@link DirectedAcyclicGraph}. The value is not copied.
      * 
      * @param value of the node to create
      * @return a node with the given value
      */
-    GraphNode<V> createRootNode(V value);
-
-    /**
-     * Removes the occurrence of the given {@link GraphNode} from this {@link DirectedAcyclicGraph}'s root nodes.
-     * Returns <code>true</code> if the node was found and removed, otherwise <code>false</code>.
-     * 
-     * <strong>Note</strong>: Removal is only allowed if the root node has no children.
-     * 
-     * @param node the node to remove
-     * @throws IllegalArgumentException if the given node is not a root node (the node has one or more parents)
-     * @throws IllegalArgumentException if the given node has children
-     * @throws IllegalArgumentException if the given node does not belong to the same {@link DirectedAcyclicGraph}.
-     * @return <code>true</code> if the node was removed successfully, otherwise <code>false</code>.
-     * @see java.util.List#remove
-     */
-    boolean deleteRootNode(GraphNode<V> node);
-
-    /**
-     * Returns a list of this {@link DirectedAcyclicGraph}'s root nodes (not copies of the nodes). If the graph has no
-     * root nodes (and is therefore empty), returns an empty list. Never returns <code>null</code>.
-     * 
-     * @return this graph's root nodes
-     */
-    List<GraphNode<V>> getRootNodes();
+    GraphNode<V> createNode(V value);
 
 }
diff --git a/org.eclipse.virgo.util.common/src/main/java/org/eclipse/virgo/util/common/ThreadSafeDirectedAcyclicGraph.java b/org.eclipse.virgo.util.common/src/main/java/org/eclipse/virgo/util/common/ThreadSafeDirectedAcyclicGraph.java
index 03aa4da..e149fe7 100644
--- a/org.eclipse.virgo.util.common/src/main/java/org/eclipse/virgo/util/common/ThreadSafeDirectedAcyclicGraph.java
+++ b/org.eclipse.virgo.util.common/src/main/java/org/eclipse/virgo/util/common/ThreadSafeDirectedAcyclicGraph.java
@@ -8,12 +8,11 @@
  * Contributors:
  *   VMware Inc. - initial contribution (ThreadSafeArrayListTree.java)
  *   EclipseSource - reworked from generic tree to DAG (Bug 358697)
+ *   EclipseSource - removed internal root node list (Bug 369907)
  *******************************************************************************/
 
 package org.eclipse.virgo.util.common;
 
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * {@link DirectedAcyclicGraph} is a set of {@link GraphNode}s with a parent child relationship. The nodes are connected
@@ -33,140 +32,12 @@
 
     private final Object monitor = new Object();
 
-    private static final Object tieMonitor = new Object();
-
-    private final List<ThreadSafeGraphNode<V>> nodes = new ArrayList<ThreadSafeGraphNode<V>>();
-
     /**
      * {@inheritDoc}
      */
     @Override
-    public ThreadSafeGraphNode<V> createRootNode(V value) {
-        synchronized (this.monitor) {
-            ThreadSafeGraphNode<V> node = new ThreadSafeGraphNode<V>(value, this.monitor);
-            this.nodes.add(node);
-            return node;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean deleteRootNode(GraphNode<V> node) {
-        assertTypeAndMembership(node);
-        synchronized (this.monitor) {
-            Assert.isTrue(node.getChildren().isEmpty(), "Cannot delete node '%s'. Node has children. Please remove the children first.", node);
-            Assert.isTrue(node.getParents().isEmpty(),
-                "Cannot delete node '%s'. Node is still in use. Please remove it from the other node(s) first.", node);
-            boolean removed = this.nodes.remove(node);
-            return removed;
-        }
-    }
-
-    private ThreadSafeGraphNode<V> assertTypeAndMembership(GraphNode<V> child) {
-        Assert.isInstanceOf(ThreadSafeGraphNode.class, child, "A child must be of type %s.", this.getClass().getName());
-        ThreadSafeGraphNode<V> concreteChild = (ThreadSafeGraphNode<V>) child;
-        Assert.isTrue(concreteChild.belongsToSameGraph(this.monitor), "The node '%s' does not belong to the graph '%s'", concreteChild, this);
-        return concreteChild;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public List<GraphNode<V>> getRootNodes() {
-        List<GraphNode<V>> rootNodes = new ArrayList<GraphNode<V>>();
-        synchronized (this.monitor) {
-            for (GraphNode<V> node : this.nodes) {
-                if (node.isRootNode()) {
-                    rootNodes.add(node);
-                }
-            }
-            return rootNodes;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String toString() {
-        StringBuffer result = new StringBuffer();
-        result.append("<");
-        synchronized (this.monitor) {
-            boolean first = true;
-            for (GraphNode<V> child : getRootNodes()) {
-                if (!first) {
-                    result.append(", ");
-                }
-                result.append(child.toString());
-                first = false;
-            }
-        }
-        result.append(">");
-        return result.toString();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        synchronized (this.monitor) {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + this.nodes.hashCode();
-            return result;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @SuppressWarnings("unchecked")
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        ThreadSafeDirectedAcyclicGraph<V> other = (ThreadSafeDirectedAcyclicGraph<V>) obj;
-        int thisHash = System.identityHashCode(this);
-        int otherHash = System.identityHashCode(other);
-        if (thisHash < otherHash) {
-            synchronized (this.monitor) {
-                synchronized (other.monitor) {
-                    if (!this.nodes.equals(other.nodes)) {
-                        return false;
-                    }
-                }
-            }
-        } else if (thisHash > otherHash) {
-            synchronized (other.monitor) {
-                synchronized (this.monitor) {
-                    if (!this.nodes.equals(other.nodes)) {
-                        return false;
-                    }
-                }
-            }
-        } else {
-            synchronized (tieMonitor) {
-                synchronized (this.monitor) {
-                    synchronized (other.monitor) {
-                        if (!this.nodes.equals(other.nodes)) {
-                            return false;
-                        }
-                    }
-                }
-            }
-        }
-        return true;
+    public ThreadSafeGraphNode<V> createNode(V value) {
+        return new ThreadSafeGraphNode<V>(value, this.monitor);
     }
 
 }
diff --git a/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeAcyclicDirectedGraphTests.java b/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeAcyclicDirectedGraphTests.java
deleted file mode 100644
index f181dd2..0000000
--- a/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeAcyclicDirectedGraphTests.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 VMware Inc. and others
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *   VMware Inc. - initial contribution (ThreadSafeArrayListTreeTests.java)
- *   EclipseSource - reworked from generic tree to DAG (Bug 358697)
- *******************************************************************************/
-
-package org.eclipse.virgo.util.common;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.concurrent.CyclicBarrier;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class ThreadSafeAcyclicDirectedGraphTests {
-
-    private DirectedAcyclicGraph<String> graph;
-
-    private static DirectedAcyclicGraph<String> getDAG() {
-        return getDAG("We");
-    }
-
-    private static DirectedAcyclicGraph<String> getDAG(String rootValue) {
-        DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
-
-        // shared nodes
-        GraphNode<String> lo = graph.createRootNode("Lo");
-        GraphNode<String> fi = graph.createRootNode("Fi");
-
-        // We.add(Pa)
-        GraphNode<String> we = graph.createRootNode("We");
-        GraphNode<String> pa = graph.createRootNode("Pa");
-        we.addChild(pa);
-        // Pa.add(Cr)
-        GraphNode<String> cr = graph.createRootNode("Cr");
-        pa.addChild(cr);
-        // Cr.add(B1,Lo,Fi)
-        cr.addChild(graph.createRootNode("B1"));
-        cr.addChild(lo);
-        cr.addChild(fi);
-
-        // Pa.add(Cu)
-        GraphNode<String> cu = graph.createRootNode("Cu");
-        pa.addChild(cu);
-        cu.addChild(graph.createRootNode("B2"));
-        cu.addChild(lo);
-        cu.addChild(fi);
-
-        // Pa.add(B3)
-        pa.addChild(graph.createRootNode("B3"));
-        // Pa.add(Lo)
-        pa.addChild(lo);
-
-        return graph;
-    }
-
-    @Before
-    public void setUp() {
-        this.graph = getDAG();
-    }
-
-    @Test
-    public void testEmptyGraph() throws Exception {
-        DirectedAcyclicGraph<String> emptyGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-
-        assertNotNull(emptyGraph);
-        assertNotNull(emptyGraph.getRootNodes());
-        assertEquals("<>", emptyGraph.toString());
-        assertTrue(emptyGraph.getRootNodes().isEmpty());
-    }
-
-    @Test
-    public void testGraphWithSingleRootNode() throws Exception {
-        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-
-        GraphNode<String> rootNode = smallGraph.createRootNode("root");
-
-        assertEquals("<root<>>", smallGraph.toString());
-        assertEquals(1, smallGraph.getRootNodes().size());
-
-        smallGraph.deleteRootNode(rootNode);
-
-        assertEquals(0, smallGraph.getRootNodes().size());
-    }
-
-    @Test
-    public void testGraphWithSingleNullRootNode() throws Exception {
-        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-
-        GraphNode<String> rootNode = smallGraph.createRootNode(null);
-
-        assertEquals("<null<>>", smallGraph.toString());
-        assertEquals(1, smallGraph.getRootNodes().size());
-
-        smallGraph.deleteRootNode(rootNode);
-
-        assertEquals(0, smallGraph.getRootNodes().size());
-    }
-
-    @Test
-    public void testGraphWithOnlyChildren() throws Exception {
-        DirectedAcyclicGraph<String> onlyChildGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-
-        GraphNode<String> rootNode = onlyChildGraph.createRootNode("root");
-        assertEquals("<root<>>", onlyChildGraph.toString());
-        assertEquals(1, onlyChildGraph.getRootNodes().size());
-
-        GraphNode<String> child = onlyChildGraph.createRootNode("child");
-        rootNode.addChild(child);
-        assertEquals("<root<child<>>>", onlyChildGraph.toString());
-
-        GraphNode<String> grandchild = onlyChildGraph.createRootNode("grandchild");
-        child.addChild(grandchild);
-        assertEquals("<root<child<grandchild<>>>>", onlyChildGraph.toString());
-        assertEquals(1, onlyChildGraph.getRootNodes().size());
-
-        assertTrue(child.removeChild(grandchild));
-        onlyChildGraph.deleteRootNode(grandchild);
-        assertTrue(rootNode.removeChild(child));
-        onlyChildGraph.deleteRootNode(child);
-        onlyChildGraph.deleteRootNode(rootNode);
-        assertEquals(0, onlyChildGraph.getRootNodes().size());
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testDirectCycle() throws Exception {
-        DirectedAcyclicGraph<Integer> smallGraph = new ThreadSafeDirectedAcyclicGraph<Integer>();
-        GraphNode<Integer> root = smallGraph.createRootNode(Integer.valueOf(42));
-
-        root.addChild(root);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testParentNodeIsNotADescendantOfTheNewChild() throws Exception {
-        DirectedAcyclicGraph<String> dag = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> rootNode = dag.createRootNode("root");
-        GraphNode<String> child = dag.createRootNode("child");
-
-        rootNode.addChild(child);
-        child.addChild(rootNode);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testParentIsNotADescendantOfTheNewChildDistanceTwo() throws Exception {
-        DirectedAcyclicGraph<String> dag = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> rootNode = dag.createRootNode("root");
-
-        GraphNode<String> child = dag.createRootNode("child");
-        rootNode.addChild(child);
-        GraphNode<String> child2 = dag.createRootNode("child2");
-        rootNode.addChild(child2);
-        GraphNode<String> grandchild = dag.createRootNode("grandchild");
-        child.addChild(grandchild);
-
-        grandchild.addChild(rootNode);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testDeleteRootNodeFromOtherGraph() {
-        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> r1 = smallGraph.createRootNode("R1");
-
-        this.graph.deleteRootNode(r1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testDeleteRootNodeOfWrongType() {
-        this.graph.deleteRootNode(new ThreadSafeGraphNodeTests.NoopGraphNode());
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testDeleteRootNodeWithChildren() {
-        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> r1 = smallGraph.createRootNode("R1");
-        GraphNode<String> c1 = smallGraph.createRootNode("C1");
-        r1.addChild(c1);
-
-        this.graph.deleteRootNode(r1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testDeleteNonRootNode() {
-        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> r1 = smallGraph.createRootNode("R1");
-        GraphNode<String> c1 = smallGraph.createRootNode("C1");
-        r1.addChild(c1);
-
-        this.graph.deleteRootNode(c1);
-    }
-
-    @Test
-    public void testAddSharedChildWithMultipleThreads() throws Exception {
-
-        final DirectedAcyclicGraph<String> sharedChildGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-        final int THREAD_COUNT = 150;
-        final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
-        final GraphNode<String> sharedChild = sharedChildGraph.createRootNode("shared child");
-        assertEquals(0, sharedChild.getParents().size());
-        assertEquals(1, sharedChildGraph.getRootNodes().size());
-
-        class AddChildThread extends Thread {
-
-            private final int counter;
-
-            public AddChildThread(int counter) {
-                this.counter = counter;
-            }
-
-            @Override
-            public void run() {
-                try {
-                    barrier.await(); // 1
-                    GraphNode<String> root = sharedChildGraph.createRootNode("root" + this.counter);
-                    root.addChild(sharedChild);
-                    barrier.await(); // 2
-                    barrier.await();
-                    assertTrue(root.removeChild(sharedChild));
-                    barrier.await(); // 3
-                    barrier.await();
-                    sharedChildGraph.deleteRootNode(root);
-                    barrier.await();
-                } catch (Exception e) {
-                    fail();
-                }
-            }
-        }
-
-        for (int i = 0; i < THREAD_COUNT; i++) {
-            new AddChildThread(i).start();
-        }
-        barrier.await(); // 1 - wait for all threads to be ready
-        barrier.await(); // 2 - wait for all threads to create and add the nodes
-        assertEquals(THREAD_COUNT, sharedChild.getParents().size());
-        assertEquals(THREAD_COUNT, sharedChildGraph.getRootNodes().size());
-        barrier.await(); //
-        barrier.await(); // 3 - wait for all threads to be finish
-        assertEquals(0, sharedChild.getParents().size());
-        assertEquals(THREAD_COUNT + 1, sharedChildGraph.getRootNodes().size());
-        barrier.await(); // wait for all threads to be finish
-        assertEquals(0, sharedChild.getParents().size());
-    }
-
-    @Test
-    public void testGraphWithSharedNodes() throws Exception {
-        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-
-        GraphNode<String> r1 = smallGraph.createRootNode("R1");
-        GraphNode<String> c1 = smallGraph.createRootNode("C1");
-        GraphNode<String> c2 = smallGraph.createRootNode("C2");
-        smallGraph.createRootNode("C3");
-        assertEquals(4, smallGraph.getRootNodes().size());
-        assertEquals("<R1<>, C1<>, C2<>, C3<>>", smallGraph.toString());
-
-        r1.addChild(c1);
-        assertEquals(3, smallGraph.getRootNodes().size());
-        r1.addChild(c2);
-        assertEquals(2, smallGraph.getRootNodes().size());
-        assertEquals("<R1<C1<>, C2<>>, C3<>>", smallGraph.toString());
-
-        GraphNode<String> r2 = smallGraph.createRootNode("R2");
-        assertEquals(3, smallGraph.getRootNodes().size());
-        assertEquals("<R1<C1<>, C2<>>, C3<>, R2<>>", smallGraph.toString());
-
-        r2.addChild(c1);
-        assertEquals(3, smallGraph.getRootNodes().size());
-        assertEquals("<R1<C1<>, C2<>>, C3<>, R2<C1<>>>", smallGraph.toString());
-    }
-
-    @Test
-    public void testDisassembleGraphWithSharedNodes() throws Exception {
-        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> r1 = smallGraph.createRootNode("R1");
-        GraphNode<String> c1 = smallGraph.createRootNode("C1");
-        GraphNode<String> c2 = smallGraph.createRootNode("C2");
-        GraphNode<String> c3 = smallGraph.createRootNode("C3");
-        r1.addChild(c1);
-        r1.addChild(c2);
-        GraphNode<String> r2 = smallGraph.createRootNode("R2");
-        r2.addChild(c1);
-        assertEquals("<R1<C1<>, C2<>>, C3<>, R2<C1<>>>", smallGraph.toString());
-        assertEquals(3, smallGraph.getRootNodes().size());
-
-        // remove shared node
-        assertTrue(r2.removeChild(c1));
-        assertEquals("<R1<C1<>, C2<>>, C3<>, R2<>>", smallGraph.toString());
-        assertEquals(3, smallGraph.getRootNodes().size());
-        assertTrue(r1.removeChild(c2));
-        assertEquals(4, smallGraph.getRootNodes().size());
-        assertTrue(r1.removeChild(c1));
-        assertEquals(5, smallGraph.getRootNodes().size());
-        assertEquals("<R1<>, C1<>, C2<>, C3<>, R2<>>", smallGraph.toString());
-        assertTrue(smallGraph.deleteRootNode(r2));
-        assertEquals(4, smallGraph.getRootNodes().size());
-        assertEquals("<R1<>, C1<>, C2<>, C3<>>", smallGraph.toString());
-        assertTrue(smallGraph.deleteRootNode(r1));
-        assertEquals(3, smallGraph.getRootNodes().size());
-        assertEquals("<C1<>, C2<>, C3<>>", smallGraph.toString());
-        smallGraph.deleteRootNode(smallGraph.getRootNodes().get(0));
-        assertEquals(2, smallGraph.getRootNodes().size());
-        assertEquals("<C2<>, C3<>>", smallGraph.toString());
-        assertTrue(smallGraph.deleteRootNode(c2));
-        assertEquals(1, smallGraph.getRootNodes().size());
-        assertTrue(smallGraph.deleteRootNode(c3));
-        assertTrue(smallGraph.getRootNodes().isEmpty());
-    }
-
-    @Test
-    public void testRemovalOfAnAlreadyRemovedRootNode() throws Exception {
-        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> r1 = smallGraph.createRootNode("R1");
-
-        assertTrue(smallGraph.deleteRootNode(r1));
-
-        assertFalse(smallGraph.deleteRootNode(r1));
-    }
-
-    @Test
-    public void testHashCodeEquals() {
-        assertFalse(this.graph.equals(null));
-
-        assertFalse(this.graph.equals(new Object()));
-
-        DirectedAcyclicGraph<String> graph2 = getDAG();
-        assertEquals(this.graph.hashCode(), graph2.hashCode());
-        assertEquals(this.graph, this.graph);
-        assertEquals(graph2, this.graph);
-        assertEquals(this.graph, graph2);
-
-        DirectedAcyclicGraph<String> g1 = new ThreadSafeDirectedAcyclicGraph<String>();
-        assertFalse(this.graph.equals(g1));
-        assertFalse(g1.equals(this.graph));
-
-        assertTrue(new ThreadSafeDirectedAcyclicGraph<String>().equals(new ThreadSafeDirectedAcyclicGraph<String>()));
-    }
-
-}
diff --git a/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeDirectedAcyclicGraphTests.java b/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeDirectedAcyclicGraphTests.java
new file mode 100644
index 0000000..77ef324
--- /dev/null
+++ b/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeDirectedAcyclicGraphTests.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2011 VMware Inc. and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   VMware Inc. - initial contribution (ThreadSafeArrayListTreeTests.java)
+ *   EclipseSource - reworked from generic tree to DAG (Bug 358697)
+ *   EclipseSource - removed internal root node list from TSDAG (Bug 369907)
+ *******************************************************************************/
+
+package org.eclipse.virgo.util.common;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.concurrent.CyclicBarrier;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ThreadSafeDirectedAcyclicGraphTests {
+
+    private DirectedAcyclicGraph<String> graph;
+
+    private static DirectedAcyclicGraph<String> getDAG() {
+        return getDAG("We");
+    }
+
+    private static DirectedAcyclicGraph<String> getDAG(String rootValue) {
+        DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
+
+        // shared nodes
+        GraphNode<String> lo = graph.createNode("Lo");
+        GraphNode<String> fi = graph.createNode("Fi");
+
+        // We.add(Pa)
+        GraphNode<String> we = graph.createNode("We");
+        GraphNode<String> pa = graph.createNode("Pa");
+        we.addChild(pa);
+        // Pa.add(Cr)
+        GraphNode<String> cr = graph.createNode("Cr");
+        pa.addChild(cr);
+        // Cr.add(B1,Lo,Fi)
+        cr.addChild(graph.createNode("B1"));
+        cr.addChild(lo);
+        cr.addChild(fi);
+
+        // Pa.add(Cu)
+        GraphNode<String> cu = graph.createNode("Cu");
+        pa.addChild(cu);
+        cu.addChild(graph.createNode("B2"));
+        cu.addChild(lo);
+        cu.addChild(fi);
+
+        // Pa.add(B3)
+        pa.addChild(graph.createNode("B3"));
+        // Pa.add(Lo)
+        pa.addChild(lo);
+
+        return graph;
+    }
+
+    @Before
+    public void setUp() {
+        this.graph = getDAG();
+    }
+
+    @Test
+    public void testEmptyGraph() throws Exception {
+        DirectedAcyclicGraph<String> emptyGraph = new ThreadSafeDirectedAcyclicGraph<String>();
+
+        assertNotNull(emptyGraph);
+    }
+
+    @Test
+    public void testGraphWithSingleRootNode() throws Exception {
+        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
+
+        GraphNode<String> rootNode = smallGraph.createNode("root");
+
+        assertNotNull(rootNode);
+    }
+
+    @Test
+    public void testGraphWithSingleNullRootNode() throws Exception {
+        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
+
+        GraphNode<String> rootNode = smallGraph.createNode(null);
+
+        assertNotNull(rootNode);
+    }
+
+    @Test
+    public void testGraphWithOnlyChildren() throws Exception {
+        DirectedAcyclicGraph<String> onlyChildGraph = new ThreadSafeDirectedAcyclicGraph<String>();
+
+        GraphNode<String> rootNode = onlyChildGraph.createNode("root");
+
+        GraphNode<String> child = onlyChildGraph.createNode("child");
+        rootNode.addChild(child);
+
+        GraphNode<String> grandchild = onlyChildGraph.createNode("grandchild");
+        child.addChild(grandchild);
+
+        assertTrue(child.removeChild(grandchild));
+        assertTrue(rootNode.removeChild(child));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testDirectCycle() throws Exception {
+        DirectedAcyclicGraph<Integer> smallGraph = new ThreadSafeDirectedAcyclicGraph<Integer>();
+        GraphNode<Integer> root = smallGraph.createNode(Integer.valueOf(42));
+
+        root.addChild(root);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testParentNodeIsNotADescendantOfTheNewChild() throws Exception {
+        DirectedAcyclicGraph<String> dag = new ThreadSafeDirectedAcyclicGraph<String>();
+        GraphNode<String> rootNode = dag.createNode("root");
+        GraphNode<String> child = dag.createNode("child");
+
+        rootNode.addChild(child);
+        child.addChild(rootNode);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testParentIsNotADescendantOfTheNewChildDistanceTwo() throws Exception {
+        DirectedAcyclicGraph<String> dag = new ThreadSafeDirectedAcyclicGraph<String>();
+        GraphNode<String> rootNode = dag.createNode("root");
+
+        GraphNode<String> child = dag.createNode("child");
+        rootNode.addChild(child);
+        GraphNode<String> child2 = dag.createNode("child2");
+        rootNode.addChild(child2);
+        GraphNode<String> grandchild = dag.createNode("grandchild");
+        child.addChild(grandchild);
+
+        grandchild.addChild(rootNode);
+    }
+
+    @Test
+    public void testAddSharedChildWithMultipleThreads() throws Exception {
+
+        final DirectedAcyclicGraph<String> sharedChildGraph = new ThreadSafeDirectedAcyclicGraph<String>();
+        final int THREAD_COUNT = 150;
+        final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
+        final GraphNode<String> sharedChild = sharedChildGraph.createNode("shared child");
+        assertEquals(0, sharedChild.getParents().size());
+
+        class AddChildThread extends Thread {
+
+            private final int counter;
+
+            public AddChildThread(int counter) {
+                this.counter = counter;
+            }
+
+            @Override
+            public void run() {
+                try {
+                    barrier.await(); // 1
+                    GraphNode<String> root = sharedChildGraph.createNode("root" + this.counter);
+                    root.addChild(sharedChild);
+                    barrier.await(); // 2
+                    barrier.await();
+                    assertTrue(root.removeChild(sharedChild));
+                    barrier.await(); // 3
+                    barrier.await();
+                } catch (Exception e) {
+                    fail();
+                }
+            }
+        }
+
+        for (int i = 0; i < THREAD_COUNT; i++) {
+            new AddChildThread(i).start();
+        }
+        barrier.await(); // 1 - wait for all threads to be ready
+        barrier.await(); // 2 - wait for all threads to create and add the nodes
+        assertEquals(THREAD_COUNT, sharedChild.getParents().size());
+        barrier.await(); //
+        barrier.await(); // 3 - wait for all threads to be finish
+        assertEquals(0, sharedChild.getParents().size());
+        barrier.await(); // wait for all threads to be finish
+        assertEquals(0, sharedChild.getParents().size());
+    }
+
+    @Test
+    public void testGraphWithSharedNodes() throws Exception {
+        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
+
+        GraphNode<String> r1 = smallGraph.createNode("R1");
+        GraphNode<String> c1 = smallGraph.createNode("C1");
+        GraphNode<String> c2 = smallGraph.createNode("C2");
+        smallGraph.createNode("C3");
+
+        r1.addChild(c1);
+        r1.addChild(c2);
+        assertEquals("R1<C1<>, C2<>>", r1.toString());
+
+        GraphNode<String> r2 = smallGraph.createNode("R2");
+
+        r2.addChild(c1);
+        assertEquals("R2<C1<>>", r2.toString());
+    }
+
+    @Test
+    public void testDisassembleGraphWithSharedNodes() throws Exception {
+        DirectedAcyclicGraph<String> smallGraph = new ThreadSafeDirectedAcyclicGraph<String>();
+        GraphNode<String> r1 = smallGraph.createNode("R1");
+        GraphNode<String> c1 = smallGraph.createNode("C1");
+        GraphNode<String> c2 = smallGraph.createNode("C2");
+        r1.addChild(c1);
+        r1.addChild(c2);
+        GraphNode<String> r2 = smallGraph.createNode("R2");
+        r2.addChild(c1);
+        assertEquals("R1<C1<>, C2<>>", r1.toString());
+        assertEquals("R2<C1<>>", r2.toString());
+
+        // remove shared node
+        assertTrue(r2.removeChild(c1));
+        assertEquals("R1<C1<>, C2<>>", r1.toString());
+        assertTrue(r1.removeChild(c2));
+        assertTrue(r1.removeChild(c1));
+    }
+
+    @Test
+    public void testHashCodeEquals() {
+        assertFalse(this.graph.equals(null));
+
+        assertFalse(this.graph.equals(new Object()));
+
+        assertFalse(new ThreadSafeDirectedAcyclicGraph<String>().equals(new ThreadSafeDirectedAcyclicGraph<String>()));
+    }
+
+}
diff --git a/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeGraphNodeTests.java b/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeGraphNodeTests.java
index 6632cac..ca34167 100644
--- a/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeGraphNodeTests.java
+++ b/org.eclipse.virgo.util.common/src/test/java/org/eclipse/virgo/util/common/ThreadSafeGraphNodeTests.java
@@ -8,6 +8,7 @@
  * Contributors:
  *   VMware Inc. - initial contribution (ThreadSafeArrayListTreeTests.java)
  *   EclipseSource - reworked from generic tree to DAG (Bug 358697)
+ *   EclipseSource - removed internal root node list from TSDAG (Bug 369907)
  *******************************************************************************/
 
 package org.eclipse.virgo.util.common;
@@ -52,31 +53,31 @@
     }
 
     private GraphNode<String> buildTestGraphAndReturnRootNode(DirectedAcyclicGraph<String> graph, String rootValue) {
-        GraphNode<String> top = graph.createRootNode(rootValue);
+        GraphNode<String> top = graph.createNode(rootValue);
 
         // shared nodes
-        GraphNode<String> lo = graph.createRootNode("Lo");
-        GraphNode<String> fi = graph.createRootNode("Fi");
+        GraphNode<String> lo = graph.createNode("Lo");
+        GraphNode<String> fi = graph.createNode("Fi");
 
         // We.add(Pa)
-        top.addChild(graph.createRootNode("Pa"));
+        top.addChild(graph.createNode("Pa"));
         GraphNode<String> pa = top.getChildren().get(0);
         // Pa.add(Cr)
-        pa.addChild(graph.createRootNode("Cr"));
+        pa.addChild(graph.createNode("Cr"));
         GraphNode<String> cr = pa.getChildren().get(0);
-        cr.addChild(graph.createRootNode("B1"));
+        cr.addChild(graph.createNode("B1"));
         cr.addChild(lo);
         cr.addChild(fi);
 
         // Pa.add(Cu)
-        pa.addChild(graph.createRootNode("Cu"));
+        pa.addChild(graph.createNode("Cu"));
         GraphNode<String> cu = pa.getChildren().get(1);
-        cu.addChild(graph.createRootNode("B2"));
+        cu.addChild(graph.createNode("B2"));
         cu.addChild(lo);
         cu.addChild(fi);
 
         // Pa.add(B3)
-        pa.addChild(graph.createRootNode("B3"));
+        pa.addChild(graph.createNode("B3"));
         // Pa.add(Lo)
         pa.addChild(lo);
 
@@ -84,9 +85,9 @@
     }
 
     private GraphNode<String> addFluffyToGraph(DirectedAcyclicGraph<String> graph) {
-        GraphNode<String> body = graph.createRootNode("Fluffy's body");
+        GraphNode<String> body = graph.createNode("Fluffy's body");
         for (int i = 0; i < 3; i++) {
-            GraphNode<String> head = graph.createRootNode("head " + i);
+            GraphNode<String> head = graph.createNode("head " + i);
             head.addChild(body);
         }
         return body;
@@ -96,7 +97,7 @@
     public void testEmptyNode() throws Exception {
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
 
-        GraphNode<String> nullGraph = graph.createRootNode(null);
+        GraphNode<String> nullGraph = graph.createNode(null);
 
         assertNull(nullGraph.getValue());
         assertEquals("null<>", nullGraph.toString());
@@ -105,10 +106,10 @@
     @Test
     public void testDepthTwo() throws Exception {
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> root = graph.createRootNode("root");
+        GraphNode<String> root = graph.createNode("root");
 
-        root.addChild(graph.createRootNode("C1"));
-        root.addChild(graph.createRootNode("C2"));
+        root.addChild(graph.createNode("C1"));
+        root.addChild(graph.createNode("C2"));
 
         assertEquals("root<C1<>, C2<>>", root.toString());
     }
@@ -116,9 +117,9 @@
     @Test
     public void testDepthThree() throws Exception {
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> we = graph.createRootNode("We");
-        GraphNode<String> pa = graph.createRootNode("Pa");
-        GraphNode<String> cr = graph.createRootNode("Cr");
+        GraphNode<String> we = graph.createNode("We");
+        GraphNode<String> pa = graph.createNode("Pa");
+        GraphNode<String> cr = graph.createNode("Cr");
 
         we.addChild(pa);
         pa.addChild(cr);
@@ -130,7 +131,7 @@
     public void testToString() {
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
 
-        assertEquals("null<>", graph.createRootNode(null).toString());
+        assertEquals("null<>", graph.createNode(null).toString());
 
         GraphNode<String> top = buildTestGraphAndReturnRootNode(graph);
 
@@ -140,13 +141,13 @@
     @Test
     public void testHashCodeEquals() {
         DirectedAcyclicGraph<String> graphA = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> topA = graphA.createRootNode("root");
+        GraphNode<String> topA = graphA.createNode("root");
 
         assertFalse(topA.equals(null));
         assertFalse(topA.equals(new Object()));
 
         DirectedAcyclicGraph<String> graphB = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> topB = graphB.createRootNode("root");
+        GraphNode<String> topB = graphB.createNode("root");
 
         assertEquals(topA.hashCode(), topB.hashCode());
         assertEquals(topB.hashCode(), topA.hashCode());
@@ -154,7 +155,7 @@
         assertEquals(topA, topB);
         assertEquals(topB, topA);
 
-        GraphNode<String> t1 = graphA.createRootNode("a");
+        GraphNode<String> t1 = graphA.createNode("a");
         {
             GraphNode<String> a = t1;
             assertFalse(topA.equals(a));
@@ -162,17 +163,17 @@
         }
 
         {
-            GraphNode<String> a = graphA.createRootNode(null);
+            GraphNode<String> a = graphA.createNode(null);
             a.hashCode();
             assertFalse(topA.equals(a));
             assertFalse(a.equals(topA));
         }
 
-        assertTrue(graphA.createRootNode(null).equals(graphA.createRootNode(null)));
-        assertFalse(graphA.createRootNode(null).equals(graphA.createRootNode("a")));
-        assertFalse(graphA.createRootNode("a").equals(graphA.createRootNode(null)));
+        assertTrue(graphA.createNode(null).equals(graphA.createNode(null)));
+        assertFalse(graphA.createNode(null).equals(graphA.createNode("a")));
+        assertFalse(graphA.createNode("a").equals(graphA.createNode(null)));
 
-        GraphNode<String> t2 = graphA.createRootNode("b");
+        GraphNode<String> t2 = graphA.createNode("b");
         assertFalse(t1.equals(t2));
         assertFalse(t2.equals(t1));
     }
@@ -196,16 +197,16 @@
     public void testSizeWithNullNodes() throws Exception {
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
 
-        GraphNode<String> graphWithNullNodes = graph.createRootNode("with null values");
+        GraphNode<String> graphWithNullNodes = graph.createNode("with null values");
         assertEquals(1, graphWithNullNodes.size());
 
-        graphWithNullNodes.addChild(graph.createRootNode("first"));
+        graphWithNullNodes.addChild(graph.createNode("first"));
         assertEquals(2, graphWithNullNodes.size());
 
-        graphWithNullNodes.addChild(graph.createRootNode(null));
+        graphWithNullNodes.addChild(graph.createNode(null));
         assertEquals(3, graphWithNullNodes.size());
 
-        graphWithNullNodes.addChild(graph.createRootNode("third"));
+        graphWithNullNodes.addChild(graph.createNode("third"));
         assertEquals(4, graphWithNullNodes.size());
     }
 
@@ -229,7 +230,7 @@
 
         List<GraphNode<String>> children = top.getChildren();
         assertEquals(1, children.size());
-        GraphNode<String> newChild = graph.createRootNode("newChild");
+        GraphNode<String> newChild = graph.createNode("newChild");
 
         top.addChild(newChild);
         assertEquals(2, children.size());
@@ -240,7 +241,7 @@
     public void testDAGWithNoChilds() throws Exception {
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
 
-        GraphNode<String> solo = graph.createRootNode("solo");
+        GraphNode<String> solo = graph.createNode("solo");
 
         assertNotNull(solo.getChildren());
         assertTrue(solo.getChildren().isEmpty());
@@ -251,19 +252,18 @@
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
         GraphNode<String> child = new NoopGraphNode();
 
-        graph.createRootNode("foo").addChild(child);
+        graph.createNode("foo").addChild(child);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testDuplicateInsertionOfAChild() throws Exception {
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
-        buildTestGraphAndReturnRootNode(graph);
 
-        GraphNode<String> node = graph.getRootNodes().get(0);
-        GraphNode<String> child = graph.createRootNode("child");
+        GraphNode<String> rootNode = buildTestGraphAndReturnRootNode(graph);
+        GraphNode<String> child = graph.createNode("child");
 
-        node.addChild(child);
-        node.addChild(child);
+        rootNode.addChild(child);
+        rootNode.addChild(child);
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -272,7 +272,7 @@
         GraphNode<String> top = buildTestGraphAndReturnRootNode(graph);
 
         DirectedAcyclicGraph<String> secondGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> alienNode = secondGraph.createRootNode("alien");
+        GraphNode<String> alienNode = secondGraph.createNode("alien");
 
         top.addChild(alienNode);
     }
@@ -280,9 +280,9 @@
     @Test
     public void testAddSharedChild() {
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> cr = graph.createRootNode("cr");
-        GraphNode<String> cu = graph.createRootNode("cu");
-        GraphNode<String> lo = graph.createRootNode("lo");
+        GraphNode<String> cr = graph.createNode("cr");
+        GraphNode<String> cu = graph.createNode("cu");
+        GraphNode<String> lo = graph.createNode("lo");
 
         cr.addChild(lo);
         cu.addChild(lo);
@@ -302,7 +302,7 @@
         final int THREAD_COUNT = 150;
         final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
         final DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
-        final GraphNode<String> sharedChild = graph.createRootNode("shared child");
+        final GraphNode<String> sharedChild = graph.createNode("shared child");
 
         class AddChildThread extends Thread {
 
@@ -316,7 +316,7 @@
             public void run() {
                 try {
                     barrier.await();
-                    GraphNode<String> root = graph.createRootNode("root" + this.counter);
+                    GraphNode<String> root = graph.createNode("root" + this.counter);
                     root.addChild(sharedChild);
                     barrier.await();
                 } catch (Exception e) {
@@ -383,7 +383,7 @@
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
         GraphNode<String> child = new NoopGraphNode();
 
-        graph.createRootNode("foo").removeChild(child);
+        graph.createNode("foo").removeChild(child);
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -392,7 +392,7 @@
         GraphNode<String> top = buildTestGraphAndReturnRootNode(graph);
 
         DirectedAcyclicGraph<String> secondGraph = new ThreadSafeDirectedAcyclicGraph<String>();
-        GraphNode<String> alienNode = secondGraph.createRootNode("alien");
+        GraphNode<String> alienNode = secondGraph.createNode("alien");
 
         top.removeChild(alienNode);
     }
@@ -430,7 +430,7 @@
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
 
         TestDirectedAcyclicGraphVisitor visitor = new TestDirectedAcyclicGraphVisitor();
-        GraphNode<String> t = graph.createRootNode("-");
+        GraphNode<String> t = graph.createNode("-");
         t.visit(visitor);
         List<String> visited = visitor.getVisited();
 
@@ -444,10 +444,10 @@
         GraphNode<String> top = buildTestGraphAndReturnRootNode(graph);
 
         TestDirectedAcyclicGraphVisitor visitor = new TestDirectedAcyclicGraphVisitor();
-        top.addChild(graph.createRootNode("-"));
+        top.addChild(graph.createNode("-"));
         GraphNode<String> t = top.getChildren().get(1);
-        t.addChild(graph.createRootNode("foo"));
-        t.addChild(graph.createRootNode("bar"));
+        t.addChild(graph.createNode("foo"));
+        t.addChild(graph.createNode("bar"));
         assertEquals(12, top.size());
 
         top.visit(visitor);
@@ -471,7 +471,7 @@
         DirectedAcyclicGraph<String> graph = new ThreadSafeDirectedAcyclicGraph<String>();
 
         TestExceptionThrowingDirectedAcyclicGraphVisitor visitor = new TestExceptionThrowingDirectedAcyclicGraphVisitor();
-        GraphNode<String> t = graph.createRootNode("-");
+        GraphNode<String> t = graph.createNode("-");
         t.visit(visitor);
 
         List<String> visited = visitor.getVisited();
@@ -485,10 +485,10 @@
         GraphNode<String> top = buildTestGraphAndReturnRootNode(graph);
 
         TestExceptionThrowingDirectedAcyclicGraphVisitor visitor = new TestExceptionThrowingDirectedAcyclicGraphVisitor();
-        top.addChild(graph.createRootNode("-"));
+        top.addChild(graph.createNode("-"));
         GraphNode<String> t = top.getChildren().get(1);
-        t.addChild(graph.createRootNode("foo"));
-        t.addChild(graph.createRootNode("bar"));
+        t.addChild(graph.createNode("foo"));
+        t.addChild(graph.createNode("bar"));
         assertEquals(12, top.size());
 
         top.visit(visitor);
@@ -502,10 +502,10 @@
         GraphNode<String> top = buildTestGraphAndReturnRootNode(graph);
 
         TestExceptionThrowingDirectedAcyclicGraphVisitor visitor = new TestExceptionThrowingDirectedAcyclicGraphVisitor();
-        top.addChild(graph.createRootNode("*"));
+        top.addChild(graph.createNode("*"));
         GraphNode<String> t = top.getChildren().get(1);
-        t.addChild(graph.createRootNode("foo"));
-        t.addChild(graph.createRootNode("bar"));
+        t.addChild(graph.createNode("foo"));
+        t.addChild(graph.createNode("bar"));
 
         assertEquals(12, top.size());
         try {