You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2012/09/26 11:48:58 UTC

svn commit: r1390356 - in /jackrabbit/oak/trunk/oak-mongomk/src: main/java/org/apache/jackrabbit/mongomk/model/ test/java/org/apache/jackrabbit/mongomk/command/ test/java/org/apache/jackrabbit/mongomk/query/

Author: jukka
Date: Wed Sep 26 09:48:57 2012
New Revision: 1390356

URL: http://svn.apache.org/viewvc?rev=1390356&view=rev
Log:
OAK-338: [MongoMK] Adding duplicate children should throw an error

Patch by Mete Atamel

Modified:
    jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/model/CommitCommandInstructionVisitor.java
    jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/command/CommitCommandMongoTest.java
    jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesByPathAndDepthQueryTest.java
    jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesForRevisionQueryTest.java

Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/model/CommitCommandInstructionVisitor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/model/CommitCommandInstructionVisitor.java?rev=1390356&r1=1390355&r2=1390356&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/model/CommitCommandInstructionVisitor.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/model/CommitCommandInstructionVisitor.java Wed Sep 26 09:48:57 2012
@@ -65,10 +65,9 @@ public class CommitCommandInstructionVis
             if (parent == null) {
                 throw new RuntimeException("No such parent: " + PathUtils.getName(parentNodePath));
             }
-            // FIXME [Mete] Add once tests are fixed.
-            //if (parent.childExists(nodeName)) {
-            //    throw new RuntimeException("There's already a child node with name '" + nodeName + "'");
-            //}
+            if (parent.childExists(nodeName)) {
+                throw new RuntimeException("There's already a child node with name '" + nodeName + "'");
+            }
         } else {
             parent = getStagedNode(parentNodePath);
         }

Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/command/CommitCommandMongoTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/command/CommitCommandMongoTest.java?rev=1390356&r1=1390355&r2=1390356&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/command/CommitCommandMongoTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/command/CommitCommandMongoTest.java Wed Sep 26 09:48:57 2012
@@ -78,7 +78,7 @@ public class CommitCommandMongoTest exte
     }
 
     @Test
-    public void commitAddNodes() throws Exception {
+    public void addNodes() throws Exception {
         List<Instruction> instructions = new LinkedList<Instruction>();
         instructions.add(new AddNodeInstructionImpl("/", "a"));
         instructions.add(new AddNodeInstructionImpl("/a", "b"));
@@ -100,7 +100,29 @@ public class CommitCommandMongoTest exte
     }
 
     @Test
-    public void commitAddNodesAndPropertiesOutOfOrder() throws Exception {
+    public void addDuplicateNode() throws Exception {
+        // Add /a and /a/b
+        List<Instruction> instructions = new LinkedList<Instruction>();
+        instructions.add(new AddNodeInstructionImpl("/", "a"));
+        instructions.add(new AddNodeInstructionImpl("/a", "b"));
+        Commit commit = new CommitImpl("/", "+a : { \"b\" : {} }", "Add /a, /a/b", instructions);
+        CommitCommandMongo command = new CommitCommandMongo(mongoConnection, commit);
+        command.execute();
+
+        // Add /a/b again
+        instructions = new LinkedList<Instruction>();
+        instructions.add(new AddNodeInstructionImpl("/a", "b"));
+        commit = new CommitImpl("/a", "+b", "Add /a/b", instructions);
+        command = new CommitCommandMongo(mongoConnection, commit);
+        try {
+            command.execute();
+            fail("Exception expected");
+        } catch (Exception expected) {
+        }
+    }
+
+    @Test
+    public void addNodesAndPropertiesOutOfOrder() throws Exception {
         List<Instruction> instructions = new LinkedList<Instruction>();
         instructions.add(new AddPropertyInstructionImpl("/a", "key1", "value1"));
         instructions.add(new AddNodeInstructionImpl("/", "a"));
@@ -130,7 +152,7 @@ public class CommitCommandMongoTest exte
     }
 
     @Test
-    public void commitAddNodesWhichAlreadyExist() throws Exception {
+    public void addNodesWhichAlreadyExist() throws Exception {
         SimpleNodeScenario scenario1 = new SimpleNodeScenario(mongoConnection);
         scenario1.create();
 

Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesByPathAndDepthQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesByPathAndDepthQueryTest.java?rev=1390356&r1=1390355&r2=1390356&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesByPathAndDepthQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesByPathAndDepthQueryTest.java Wed Sep 26 09:48:57 2012
@@ -16,19 +16,23 @@
  */
 package org.apache.jackrabbit.mongomk.query;
 
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.jackrabbit.mongomk.BaseMongoTest;
+import org.apache.jackrabbit.mongomk.api.model.Commit;
+import org.apache.jackrabbit.mongomk.api.model.Instruction;
 import org.apache.jackrabbit.mongomk.api.model.Node;
+import org.apache.jackrabbit.mongomk.command.CommitCommandMongo;
 import org.apache.jackrabbit.mongomk.impl.NodeAssert;
 import org.apache.jackrabbit.mongomk.impl.builder.NodeBuilder;
+import org.apache.jackrabbit.mongomk.impl.model.AddNodeInstructionImpl;
+import org.apache.jackrabbit.mongomk.impl.model.CommitImpl;
 import org.apache.jackrabbit.mongomk.model.CommitMongo;
 import org.apache.jackrabbit.mongomk.model.NodeMongo;
-import org.apache.jackrabbit.mongomk.query.FetchNodesByPathAndDepthQuery;
 import org.apache.jackrabbit.mongomk.scenario.SimpleNodeScenario;
 import org.apache.jackrabbit.mongomk.util.MongoUtil;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import com.mongodb.BasicDBObject;
@@ -36,109 +40,65 @@ import com.mongodb.DBCollection;
 import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
 
-/**
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
- */
-@SuppressWarnings("all")
 public class FetchNodesByPathAndDepthQueryTest extends BaseMongoTest {
 
     @Test
-    @Ignore
-    public void testFetchWithInvalidFirstRevision() throws Exception {
-        SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
-        String firstRevisionId = scenario.create();
-        String secondRevisionId = scenario.update_A_and_add_D_and_E();
-        SimpleNodeScenario scenario2 = new SimpleNodeScenario(mongoConnection);
-        String thirdRevisionId = scenario.update_A_and_add_D_and_E();
-
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
-                .is(MongoUtil.toMongoRepresentation(firstRevisionId)).get();
-        DBObject u = new BasicDBObject("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
-        commitCollection.update(q, u);
-
-        q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID).is(MongoUtil.toMongoRepresentation(secondRevisionId))
-                .get();
-        u = new BasicDBObject("$set", new BasicDBObject(CommitMongo.KEY_BASE_REVISION_ID, 0L));
-        commitCollection.update(q, u);
-
-        FetchNodesByPathAndDepthQuery query = new FetchNodesByPathAndDepthQuery(mongoConnection, "/", thirdRevisionId,
-                -1);
-        List<NodeMongo> result = query.execute();
-        List<Node> actuals = NodeMongo.toNode(result);
-        Node expected = NodeBuilder
-                .build(String
-                        .format("{ \"/#%0$s\" : { \"a#%3$s\" : { \"int\" : 1 , \"double\" : 0.123 , \"b#%3$s\" : { \"string\" : \"foo\" , \"e#%3$s\" : { \"array\" : [ 123, null, 123.456, \"for:bar\", true ] } } , \"d#%3$s\" : { \"null\" : null } } } }",
-                                firstRevisionId, secondRevisionId,
-                                thirdRevisionId));
-        Set<Node> expecteds = expected.getDescendants(true);
+    public void fetchWithInvalidFirstRevision() throws Exception {
+        String revisionId1 = addNode("a");
+        String revisionId2 = addNode("b");
+        String revisionId3 = addNode("c");
+
+        invalidateCommit(revisionId1);
+        updateBaseRevisionId(revisionId2, "0");
+
+        FetchNodesByPathAndDepthQuery query = new FetchNodesByPathAndDepthQuery(mongoConnection,
+                "/", revisionId3, -1);
+        List<Node> actuals = NodeMongo.toNode(query.execute());
+
+        //String json = String.format("{\"/#%1$s\" : { \"a#%2$s\" : {}, \"b#%3$s\" : {}, \"c#%1$s\" : {} }}", revisionId3, revisionId1, revisionId2);
+        String json = String.format("{\"/#%2$s\" : { \"b#%1$s\" : {}, \"c#%2$s\" : {} }}", revisionId2, revisionId3);
+        Set<Node> expecteds = NodeBuilder.build(json).getDescendants(true);
         NodeAssert.assertEquals(expecteds, actuals);
     }
 
     @Test
-    public void testFetchWithInvalidLastRevision() throws Exception {
-        SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
-        String firstRevisionId = scenario.create();
-        String secondRevisionId = scenario.update_A_and_add_D_and_E();
-        SimpleNodeScenario scenario2 = new SimpleNodeScenario(mongoConnection);
-        String thirdRevisionId = scenario.update_A_and_add_D_and_E();
-
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
-                .is(MongoUtil.toMongoRepresentation(thirdRevisionId)).get();
-        DBObject u = new BasicDBObject();
-        u.put("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
-        commitCollection.update(q, u);
-
-        FetchNodesByPathAndDepthQuery query = new FetchNodesByPathAndDepthQuery(mongoConnection, "/", thirdRevisionId,
-                -1);
-        List<NodeMongo> result = query.execute();
-        List<Node> actuals = NodeMongo.toNode(result);
-        Node expected = NodeBuilder
-                .build(String
-                        .format("{ \"/#%1$s\" : { \"a#%2$s\" : { \"int\" : 1 , \"double\" : 0.123 , \"b#%2$s\" : { \"string\" : \"foo\" , \"e#%2$s\" : { \"array\" : [ 123, null, 123.456, \"for:bar\", true ] } } , \"c#%1$s\" : { \"bool\" : true }, \"d#%2$s\" : { \"null\" : null } } } }",
-                                firstRevisionId, secondRevisionId));
-        Set<Node> expecteds = expected.getDescendants(true);
+    public void fetchWithInvalidLastRevision() throws Exception {
+        String revisionId1 = addNode("a");
+        String revisionId2 = addNode("b");
+        String revisionId3 = addNode("c");
+
+        invalidateCommit(revisionId3);
+
+        FetchNodesByPathAndDepthQuery query = new FetchNodesByPathAndDepthQuery(mongoConnection,
+                "/", revisionId3, -1);
+        List<Node> actuals = NodeMongo.toNode(query.execute());
+
+        //String json = String.format("{\"/#%1$s\" : { \"a#%2$s\" : {}, \"b#%3$s\" : {}, \"c#%1$s\" : {} }}", revisionId3, revisionId1, revisionId2);
+        String json = String.format("{\"/#%2$s\" : { \"a#%1$s\" : {}, \"b#%2$s\" : {} }}", revisionId1, revisionId2);
+        Set<Node> expecteds = NodeBuilder.build(json).getDescendants(true);
         NodeAssert.assertEquals(expecteds, actuals);
     }
 
     @Test
-    public void testFetchWithInvalidMiddleRevision() throws Exception {
-        SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
-        String firstRevisionId = scenario.create();
-        String secondRevisionId = scenario.update_A_and_add_D_and_E();
-        SimpleNodeScenario scenario2 = new SimpleNodeScenario(mongoConnection);
-        String thirdRevisionId = scenario.update_A_and_add_D_and_E();
+    public void fetchWithInvalidMiddleRevision() throws Exception {
+        String revisionId1 = addNode("a");
+        String revisionId2 = addNode("b");
+        String revisionId3 = addNode("c");
+
+        invalidateCommit(revisionId2);
+        updateBaseRevisionId(revisionId3, revisionId1);
+
+        FetchNodesByPathAndDepthQuery query = new FetchNodesByPathAndDepthQuery(mongoConnection,
+                "/", revisionId3, -1);
+        List<Node> actuals = NodeMongo.toNode(query.execute());
 
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
-                .is(MongoUtil.toMongoRepresentation(secondRevisionId)).get();
-        DBObject u = new BasicDBObject("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
-        commitCollection.update(q, u);
-
-        q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID).is(MongoUtil.toMongoRepresentation(thirdRevisionId))
-                .get();
-        u = new BasicDBObject();
-        u.put("$set",
-                new BasicDBObject(CommitMongo.KEY_BASE_REVISION_ID, MongoUtil
-                        .toMongoRepresentation(firstRevisionId)));
-        commitCollection.update(q, u);
-
-        FetchNodesByPathAndDepthQuery query = new FetchNodesByPathAndDepthQuery(mongoConnection, "/", thirdRevisionId,
-                -1);
-        List<NodeMongo> result = query.execute();
-        List<Node> actuals = NodeMongo.toNode(result);
-        Node expected = NodeBuilder
-                .build(String
-                        .format("{ \"/#%1$s\" : { \"a#%3$s\" : { \"int\" : 1 , \"double\" : 0.123 , \"b#%3$s\" : { \"string\" : \"foo\" , \"e#%3$s\" : { \"array\" : [ 123, null, 123.456, \"for:bar\", true ] } } , \"c#%1$s\" : { \"bool\" : true }, \"d#%3$s\" : { \"null\" : null } } } }",
-                                firstRevisionId, secondRevisionId,
-                                thirdRevisionId));
-        Set<Node> expecteds = expected.getDescendants(true);
+        String json = String.format("{\"/#%2$s\" : { \"a#%1$s\" : {}, \"c#%2$s\" : {} }}", revisionId1, revisionId3);
+        Set<Node> expecteds = NodeBuilder.build(json).getDescendants(true);
         NodeAssert.assertEquals(expecteds, actuals);
     }
 
     @Test
-    public void testSimpleFetchRootAndAllDepths() throws Exception {
+    public void simpleFetchRootAndAllDepths() throws Exception {
         SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
         String firstRevisionId = scenario.create();
         String secondRevisionId = scenario.update_A_and_add_D_and_E();
@@ -215,4 +175,33 @@ public class FetchNodesByPathAndDepthQue
         expecteds = expected.getDescendants(true);
         NodeAssert.assertEquals(expecteds, actuals);
     }
+
+    private String addNode(String nodeName) throws Exception {
+        List<Instruction> instructions = new LinkedList<Instruction>();
+        instructions.add(new AddNodeInstructionImpl("/", nodeName));
+        Commit commit = new CommitImpl("/", "+" + nodeName, "Add /" + nodeName, instructions);
+        CommitCommandMongo command = new CommitCommandMongo(mongoConnection, commit);
+        String revisionId = command.execute();
+        return revisionId;
+    }
+
+    private void invalidateCommit(String revisionId) {
+        DBCollection commitCollection = mongoConnection.getCommitCollection();
+        DBObject query = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
+                .is(MongoUtil.toMongoRepresentation(revisionId)).get();
+        DBObject update = new BasicDBObject();
+        update.put("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
+        commitCollection.update(query, update);
+    }
+
+    private void updateBaseRevisionId(String revisionId2, String baseRevisionId) {
+        DBCollection commitCollection = mongoConnection.getCommitCollection();
+        DBObject query = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
+                .is(MongoUtil.toMongoRepresentation(revisionId2))
+                .get();
+        DBObject update = new BasicDBObject("$set",
+                new BasicDBObject(CommitMongo.KEY_BASE_REVISION_ID,
+                        MongoUtil.toMongoRepresentation(baseRevisionId)));
+        commitCollection.update(query, update);
+    }
 }

Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesForRevisionQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesForRevisionQueryTest.java?rev=1390356&r1=1390355&r2=1390356&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesForRevisionQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/query/FetchNodesForRevisionQueryTest.java Wed Sep 26 09:48:57 2012
@@ -16,13 +16,19 @@
  */
 package org.apache.jackrabbit.mongomk.query;
 
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.jackrabbit.mongomk.BaseMongoTest;
+import org.apache.jackrabbit.mongomk.api.model.Commit;
+import org.apache.jackrabbit.mongomk.api.model.Instruction;
 import org.apache.jackrabbit.mongomk.api.model.Node;
+import org.apache.jackrabbit.mongomk.command.CommitCommandMongo;
 import org.apache.jackrabbit.mongomk.impl.NodeAssert;
 import org.apache.jackrabbit.mongomk.impl.builder.NodeBuilder;
+import org.apache.jackrabbit.mongomk.impl.model.AddNodeInstructionImpl;
+import org.apache.jackrabbit.mongomk.impl.model.CommitImpl;
 import org.apache.jackrabbit.mongomk.model.CommitMongo;
 import org.apache.jackrabbit.mongomk.model.NodeMongo;
 import org.apache.jackrabbit.mongomk.scenario.SimpleNodeScenario;
@@ -42,98 +48,61 @@ import com.mongodb.QueryBuilder;
 public class FetchNodesForRevisionQueryTest extends BaseMongoTest {
 
     @Test
-    @Ignore
-    public void testFetchWithInvalidFirstRevision() throws Exception {
-        SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
-        String firstRevisionId = scenario.create();
-        String secondRevisionId = scenario.update_A_and_add_D_and_E();
-        SimpleNodeScenario scenario2 = new SimpleNodeScenario(mongoConnection);
-        String thirdRevisionId = scenario.update_A_and_add_D_and_E();
-
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
-                .is(MongoUtil.toMongoRepresentation(secondRevisionId)).get();
-        DBObject u = new BasicDBObject();
-        u.put("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
-        commitCollection.update(q, u);
-
-        FetchNodesForRevisionQuery query = new FetchNodesForRevisionQuery(mongoConnection, new String[] { "/", "/a",
-                "/a/b", "/a/c", "/a/d", "/a/b/e", "not_existing" }, thirdRevisionId);
-        List<NodeMongo> nodeMongos = query.execute();
-        List<Node> actuals = NodeMongo.toNode(nodeMongos);
-        Node expected = NodeBuilder
-                .build(String
-                        .format("{ \"/#%1$s\" : { \"a#%3$s\" : { \"int\" : 1 , \"double\" : 0.123 , \"b#%3$s\" : { \"string\" : \"foo\" , \"e#%3$s\" : { \"array\" : [ 123, null, 123.456, \"for:bar\", true ] } } , \"c#%1$s\" : { \"bool\" : true }, \"d#%3$s\" : { \"null\" : null } } } }",
-                                firstRevisionId, secondRevisionId,
-                                thirdRevisionId));
-        Set<Node> expecteds = expected.getDescendants(true);
+    public void fetchWithInvalidFirstRevision() throws Exception {
+        String revisionId1 = addNode("a");
+        String revisionId2 = addNode("b");
+        String revisionId3 = addNode("c");
+
+        invalidateCommit(revisionId1);
+        updateBaseRevisionId(revisionId2, "0");
+
+        FetchNodesForRevisionQuery query = new FetchNodesForRevisionQuery(mongoConnection,
+                new String[] { "/", "/a", "/b", "/c", "not_existing" }, revisionId3);
+        List<Node> actuals = NodeMongo.toNode(query.execute());
+
+        //String json = String.format("{\"/#%1$s\" : { \"a#%2$s\" : {}, \"b#%3$s\" : {}, \"c#%1$s\" : {} }}", revisionId3, revisionId1, revisionId2);
+        String json = String.format("{\"/#%2$s\" : { \"b#%1$s\" : {}, \"c#%2$s\" : {} }}", revisionId2, revisionId3);
+        Set<Node> expecteds = NodeBuilder.build(json).getDescendants(true);
         NodeAssert.assertEquals(expecteds, actuals);
     }
 
     @Test
-    public void testFetchWithInvalidLastRevision() throws Exception {
-        SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
-        String firstRevisionId = scenario.create();
-        String secondRevisionId = scenario.update_A_and_add_D_and_E();
-        SimpleNodeScenario scenario2 = new SimpleNodeScenario(mongoConnection);
-        String thirdRevisionId = scenario.update_A_and_add_D_and_E();
+    public void fetchWithInvalidLastRevision() throws Exception {
+        String revisionId1 = addNode("a");
+        String revisionId2 = addNode("b");
+        String revisionId3 = addNode("c");
+
+        invalidateCommit(revisionId3);
+
+        FetchNodesForRevisionQuery query = new FetchNodesForRevisionQuery(mongoConnection,
+                new String[] { "/", "/a", "/b", "/c", "not_existing" }, revisionId3);
+        List<Node> actuals = NodeMongo.toNode(query.execute());
 
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
-                .is(MongoUtil.toMongoRepresentation(thirdRevisionId)).get();
-        DBObject u = new BasicDBObject();
-        u.put("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
-        commitCollection.update(q, u);
-
-        FetchNodesForRevisionQuery query = new FetchNodesForRevisionQuery(mongoConnection, new String[] { "/", "/a",
-                "/a/b", "/a/c", "/a/d", "/a/b/e", "not_existing" }, thirdRevisionId);
-        List<NodeMongo> nodeMongos = query.execute();
-        List<Node> actuals = NodeMongo.toNode(nodeMongos);
-        Node expected = NodeBuilder
-                .build(String
-                        .format("{ \"/#%1$s\" : { \"a#%2$s\" : { \"int\" : 1 , \"double\" : 0.123 , \"b#%2$s\" : { \"string\" : \"foo\" , \"e#%2$s\" : { \"array\" : [ 123, null, 123.456, \"for:bar\", true ] } } , \"c#%1$s\" : { \"bool\" : true }, \"d#%2$s\" : { \"null\" : null } } } }",
-                                firstRevisionId, secondRevisionId));
-        Set<Node> expecteds = expected.getDescendants(true);
+        String json = String.format("{\"/#%2$s\" : { \"a#%1$s\" : {}, \"b#%2$s\" : {} }}", revisionId1, revisionId2);
+        Set<Node> expecteds = NodeBuilder.build(json).getDescendants(true);
         NodeAssert.assertEquals(expecteds, actuals);
     }
 
     @Test
-    public void testFetchWithInvalidMiddleRevision() throws Exception {
-        SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
-        String firstRevisionId = scenario.create();
-        String secondRevisionId = scenario.update_A_and_add_D_and_E();
-        SimpleNodeScenario scenario2 = new SimpleNodeScenario(mongoConnection);
-        String thirdRevisionId = scenario.update_A_and_add_D_and_E();
-
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
-                .is(MongoUtil.toMongoRepresentation(secondRevisionId)).get();
-        DBObject u = new BasicDBObject("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
-        commitCollection.update(q, u);
+    public void fetchWithInvalidMiddleRevision() throws Exception {
+        String revisionId1 = addNode("a");
+        String revisionId2 = addNode("b");
+        String revisionId3 = addNode("c");
+
+        invalidateCommit(revisionId2);
+        updateBaseRevisionId(revisionId3, revisionId1);
+
+        FetchNodesForRevisionQuery query = new FetchNodesForRevisionQuery(mongoConnection,
+                new String[] { "/", "/a", "/b", "/c", "not_existing" }, revisionId3);
+        List<Node> actuals = NodeMongo.toNode(query.execute());
 
-        q = QueryBuilder.start(CommitMongo.KEY_REVISION_ID).is(MongoUtil.toMongoRepresentation(thirdRevisionId))
-                .get();
-        u = new BasicDBObject();
-        u.put("$set",
-                new BasicDBObject(CommitMongo.KEY_BASE_REVISION_ID, MongoUtil
-                        .toMongoRepresentation(firstRevisionId)));
-        commitCollection.update(q, u);
-
-        FetchNodesForRevisionQuery query = new FetchNodesForRevisionQuery(mongoConnection, new String[] { "/", "/a",
-                "/a/b", "/a/c", "/a/d", "/a/b/e", "not_existing" }, thirdRevisionId);
-        List<NodeMongo> nodeMongos = query.execute();
-        List<Node> actuals = NodeMongo.toNode(nodeMongos);
-        Node expected = NodeBuilder
-                .build(String
-                        .format("{ \"/#%1$s\" : { \"a#%3$s\" : { \"int\" : 1 , \"double\" : 0.123 , \"b#%3$s\" : { \"string\" : \"foo\" , \"e#%3$s\" : { \"array\" : [ 123, null, 123.456, \"for:bar\", true ] } } , \"c#%1$s\" : { \"bool\" : true }, \"d#%3$s\" : { \"null\" : null } } } }",
-                                firstRevisionId, secondRevisionId,
-                                thirdRevisionId));
-        Set<Node> expecteds = expected.getDescendants(true);
+        String json = String.format("{\"/#%2$s\" : { \"a#%1$s\" : {}, \"c#%2$s\" : {} }}", revisionId1, revisionId3);
+        Set<Node> expecteds = NodeBuilder.build(json).getDescendants(true);
         NodeAssert.assertEquals(expecteds, actuals);
     }
 
     @Test
-    public void testFetchWithOneRevision() throws Exception {
+    public void fetchWithOneRevision() throws Exception {
         SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
         String revisionId = scenario.create();
 
@@ -158,7 +127,7 @@ public class FetchNodesForRevisionQueryT
     }
 
     @Test
-    public void testFetchWithTwoRevisions() throws Exception {
+    public void fetchWithTwoRevisions() throws Exception {
         SimpleNodeScenario scenario = new SimpleNodeScenario(mongoConnection);
         String firstRevisionId = scenario.create();
         String secondRevisionId = scenario.update_A_and_add_D_and_E();
@@ -185,4 +154,33 @@ public class FetchNodesForRevisionQueryT
         expecteds = expected.getDescendants(true);
         NodeAssert.assertEquals(expecteds, actuals);
     }
+
+    private String addNode(String nodeName) throws Exception {
+        List<Instruction> instructions = new LinkedList<Instruction>();
+        instructions.add(new AddNodeInstructionImpl("/", nodeName));
+        Commit commit = new CommitImpl("/", "+" + nodeName, "Add /" + nodeName, instructions);
+        CommitCommandMongo command = new CommitCommandMongo(mongoConnection, commit);
+        String revisionId = command.execute();
+        return revisionId;
+    }
+
+    private void invalidateCommit(String revisionId) {
+        DBCollection commitCollection = mongoConnection.getCommitCollection();
+        DBObject query = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
+                .is(MongoUtil.toMongoRepresentation(revisionId)).get();
+        DBObject update = new BasicDBObject();
+        update.put("$set", new BasicDBObject(CommitMongo.KEY_FAILED, Boolean.TRUE));
+        commitCollection.update(query, update);
+    }
+
+    private void updateBaseRevisionId(String revisionId2, String baseRevisionId) {
+        DBCollection commitCollection = mongoConnection.getCommitCollection();
+        DBObject query = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
+                .is(MongoUtil.toMongoRepresentation(revisionId2))
+                .get();
+        DBObject update = new BasicDBObject("$set",
+                new BasicDBObject(CommitMongo.KEY_BASE_REVISION_ID,
+                        MongoUtil.toMongoRepresentation(baseRevisionId)));
+        commitCollection.update(query, update);
+    }
 }