Return-Path: X-Original-To: apmail-jackrabbit-commits-archive@www.apache.org Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E91657B0B for ; Tue, 27 Dec 2011 18:18:03 +0000 (UTC) Received: (qmail 27764 invoked by uid 500); 27 Dec 2011 18:18:03 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 27728 invoked by uid 500); 27 Dec 2011 18:18:03 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 27721 invoked by uid 99); 27 Dec 2011 18:18:03 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Dec 2011 18:18:03 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Dec 2011 18:18:01 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 12B072388993; Tue, 27 Dec 2011 18:17:41 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1224964 [2/2] - in /jackrabbit/sandbox/jackrabbit-microkernel/src: main/java/org/apache/jackrabbit/ main/java/org/apache/jackrabbit/state/ main/java/org/apache/jackrabbit/utils/ test/java/org/apache/jackrabbit/ test/java/org/apache/jackrab... Date: Tue, 27 Dec 2011 18:17:40 -0000 To: commits@jackrabbit.apache.org From: mduerig@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111227181741.12B072388993@eris.apache.org> Added: jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java?rev=1224964&view=auto ============================================================================== --- jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java (added) +++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/state/TransientSpaceTest.java Tue Dec 27 18:17:39 2011 @@ -0,0 +1,837 @@ +package org.apache.jackrabbit.state; + +import org.apache.jackrabbit.Path; +import org.apache.jackrabbit.json.FullJsonParser; +import org.apache.jackrabbit.json.JsonValue; +import org.apache.jackrabbit.json.JsonValue.JsonAtom; +import org.apache.jackrabbit.json.JsonValue.JsonObject; +import org.apache.jackrabbit.json.JsonValue.Type; +import org.apache.jackrabbit.json.UnescapingJsonTokenizer; +import org.apache.jackrabbit.mk.MicroKernelFactory; +import org.apache.jackrabbit.mk.api.MicroKernel; +import org.apache.jackrabbit.mk.api.MicroKernelException; +import org.apache.jackrabbit.mk.store.NotFoundException; +import org.apache.jackrabbit.state.ChangeTree.NodeDelta; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.internal.matchers.TypeSafeMatcher; + +import javax.jcr.ItemExistsException; +import javax.jcr.ItemNotFoundException; +import javax.jcr.RepositoryException; + +import static org.apache.jackrabbit.state.TransientSpaceTest.MicrokernelMatcher.propertyExists; +import static org.apache.jackrabbit.state.TransientSpaceTest.MicrokernelMatcher.propertyHasValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class TransientSpaceTest { + private static final Path ROOT = Path.create("root"); + + private MicroKernel mk; + private TransientSpace transientSpace; + + @Before + public void setup() { + mk = MicroKernelFactory.getInstance("fs:target/transient-space-test;clean"); + mk.commit("", "+\"/root\":{}", mk.getHeadRevision(), ""); + + transientSpace = new TransientSpace("root", mk, mk.getHeadRevision()); + } + + @After + public void tearDown() { + mk.dispose(); + } + + @Test(expected = ItemNotFoundException.class) + public void getNotExistingNode() throws ItemNotFoundException { + transientSpace.getNode(ROOT.concat("any")); + } + + @Test + public void addNode() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("added"); + + Path addedPath = ROOT.concat("added"); + NodeDelta added = transientSpace.getNode(addedPath); + assertEquals(addedPath, added.getPath()); + + transientSpace.save(); + added = transientSpace.getNode(addedPath); + assertEquals(addedPath, added.getPath()); + } + + @Test + public void addNodes() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("a").addNode("b").addNode("c"); + transientSpace.save(); + + NodeDelta c = transientSpace.getNode(ROOT.concat("a/b/c")); + c.addNode("d").addNode("e"); + c.addNode("f"); + + assertTrue(transientSpace.nodeExists(ROOT.concat("a/b/c/d/e"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("a/b/c/f"))); + + transientSpace.save(); + + assertTrue(transientSpace.nodeExists(ROOT.concat("a/b/c/d/e"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("a/b/c/f"))); + } + + @Test(expected = ItemNotFoundException.class) + public void removeNotExistingNode() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.removeNode("remove"); + transientSpace.save(); + } + + @Test + public void removeExistingNode() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("added"); + transientSpace.save(); + + Path addedPath = ROOT.concat("added"); + assertTrue(transientSpace.nodeExists(addedPath)); + + root = transientSpace.getNode(ROOT); + root.removeNode("added"); + assertFalse(transientSpace.nodeExists(addedPath)); + transientSpace.save(); + assertFalse(transientSpace.nodeExists(addedPath)); + } + + @Test + public void removeTransientNode() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("added"); + + Path addedPath = ROOT.concat("added"); + assertTrue(transientSpace.nodeExists(addedPath)); + + root.removeNode("added"); + assertFalse(transientSpace.nodeExists(addedPath)); + transientSpace.save(); + assertFalse(transientSpace.nodeExists(addedPath)); + } + + @Test(expected = ItemNotFoundException.class) + public void removeRemovedNode() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("added"); + transientSpace.save(); + + Path addedPath = ROOT.concat("added"); + NodeDelta added = transientSpace.getNode(addedPath); + added.addNode("added2"); + + assertTrue(added.hasNode("added2")); + added.removeNode("added2"); + assertFalse(added.hasNode("added2")); + added.removeNode("added2"); + } + + @Test + public void moveTransient() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target"); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test + public void moveExisting() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test(expected = ItemNotFoundException.class) + public void moveNotExistingSource() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source"); + root.addNode("target"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + } + + @Test(expected = ItemNotFoundException.class) + public void moveToNotExistingTarget() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + } + + @Test(expected = ItemExistsException.class) + public void moveToExistingTarget() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target").addNode("moved"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + } + + @Test + public void rename() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("source/moved")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source/moved"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source/moved"))); + } + + @Test + public void moveSubTree() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + NodeDelta b = root.addNode("a").addNode("b"); + b.addNode("c").addNode("d"); + NodeDelta y = root.addNode("v").addNode("w"); + y.addNode("x").addNode("y"); + transientSpace.save(); + + b = transientSpace.getNode(ROOT.concat("a/b")); + b.moveNode("c", y.getPath().concat("c-moved")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("a/b/c"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("a/b"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("v/w/x/y"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("v/w/c-moved/d"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("a/b/c"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("a/b"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("v/w/x/y"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("v/w/c-moved/d"))); + } + + @Test + public void modifyThenMove() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node").addNode("c"); + root.addNode("target"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + NodeDelta moveNode = sourceNode.getNode("node"); + moveNode.addNode("a").addNode("b"); + moveNode.removeNode("c"); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved/c"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved/a/b"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved/c"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved/a/b"))); + } + + @Test + public void moveThenModify() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node").addNode("c"); + root.addNode("target"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + NodeDelta movedNode = transientSpace.getNode(ROOT.concat("target/moved")); + movedNode.addNode("a").addNode("b"); + movedNode.removeNode("c"); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved/c"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved/a/b"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved/c"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved/a/b"))); + } + + @Test + public void modifyThenMoveThenModify() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node").addNode("c1"); + root.getNode("source").getNode("node").addNode("c2"); + root.addNode("target"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + NodeDelta moveNode = sourceNode.getNode("node"); + moveNode.addNode("a1").addNode("b1"); + moveNode.removeNode("c1"); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + + NodeDelta movedNode = transientSpace.getNode(ROOT.concat("target/moved")); + movedNode.addNode("a2").addNode("b2"); + movedNode.removeNode("c2"); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved/c1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved/a1/b1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved/c2"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved/a2/b2"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved/c1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved/a1/b1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved/c2"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved/a2/b2"))); + } + + @Test + public void moveThenDelete() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + root.getNode("target").removeNode("moved"); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test + public void moveFromAddedThenDelete() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source"); + root.addNode("target"); + transientSpace.save(); + + root.getNode("source").addNode("node"); + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + root.getNode("target").removeNode("moved"); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test + public void moveToAddedThenDelete() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + transientSpace.save(); + + root.addNode("target"); + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + root.getNode("target").removeNode("moved"); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test + public void moveFromAddedToAddedThenDelete() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source"); + transientSpace.save(); + + root.getNode("source").addNode("node"); + root.addNode("target"); + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + root.getNode("target").removeNode("moved"); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test + public void moveMoved() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target1"); + root.addNode("target2"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target1/moved1")); + NodeDelta target1 = root.getNode("target1"); + target1.moveNode("moved1", ROOT.concat("target2/moved2")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + } + + @Test + public void moveMovedThenDelete() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target1"); + root.addNode("target2"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target1/moved1")); + NodeDelta target1 = root.getNode("target1"); + target1.moveNode("moved1", ROOT.concat("target2/moved2")); + root.getNode("target2").removeNode("moved2"); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + } + + @Test + public void moveMovedThenDeleteTransient() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source"); + transientSpace.save(); + root.getNode("source").addNode("node"); + root.addNode("target1"); + root.addNode("target2"); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target1/moved1")); + NodeDelta target1 = root.getNode("target1"); + target1.moveNode("moved1", ROOT.concat("target2/moved2")); + root.getNode("target2").removeNode("moved2"); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + } + + @Test + public void moveForthAndBack() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target"); + transientSpace.save(); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + NodeDelta target = root.getNode("target"); + target.moveNode("moved", ROOT.concat("source/node")); + + assertTrue(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertTrue(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test + public void moveForthAndBackTransient() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source"); + root.getNode("source").addNode("node"); + transientSpace.save(); + root.addNode("target"); + + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + NodeDelta target = root.getNode("target"); + target.moveNode("moved", ROOT.concat("source/node")); + + assertTrue(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertTrue(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test + public void moveFromTransient() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("target"); + transientSpace.save(); + + root.addNode("source1").addNode("node"); + NodeDelta sourceNode = transientSpace.getNode(ROOT.concat("source1")); + sourceNode.moveNode("node", ROOT.concat("target/moved")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved"))); + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved"))); + } + + @Test + public void moveIntoMove() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node1").addNode("child"); + root.getNode("source").addNode("node2"); + root.addNode("target"); + transientSpace.save(); + + root.getNode("source").moveNode("node1", ROOT.concat("target/moved1")); + root.getNode("source").moveNode("node2", ROOT.concat("target/moved1/child/moved2")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node2"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved1/child/moved2"))); + + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node2"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved1/child/moved2"))); + } + + @Test + public void moveIntoMoveTransient() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node1").addNode("child"); + root.getNode("source").addNode("node2"); + root.addNode("target"); + + root.getNode("source").moveNode("node1", ROOT.concat("target/moved1")); + root.getNode("source").moveNode("node2", ROOT.concat("target/moved1/child/moved2")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node2"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved1/child/moved2"))); + + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node2"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target/moved1/child/moved2"))); + } + + @Test + public void moveOutOfMove() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node1").addNode("child"); + root.addNode("target1"); + root.addNode("target2"); + transientSpace.save(); + + root.getNode("source").moveNode("node1", ROOT.concat("target1/moved1")); + root.getNode("target1").getNode("moved1").moveNode("child", ROOT.concat("target2/moved2")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1/child"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1/child"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + } + + @Test + public void moveOutOfMoveTransient() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node1").addNode("child"); + root.addNode("target1"); + root.addNode("target2"); + + root.getNode("source").moveNode("node1", ROOT.concat("target1/moved1")); + root.getNode("target1").getNode("moved1").moveNode("child", ROOT.concat("target2/moved2")); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1/child"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + + transientSpace.save(); + + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target1/moved1"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1/moved1/child"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved2"))); + } + + @Test + public void moveMovedParent() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target1"); + root.addNode("target2"); + transientSpace.save(); + + root.getNode("source").moveNode("node", ROOT.concat("target1/moved")); + root.moveNode("target1", ROOT.concat("target2/moved-target1")); + + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved-target1/moved"))); + + transientSpace.save(); + + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved-target1/moved"))); + } + + @Test + public void moveMovedParentTransient() throws RepositoryException { + NodeDelta root = transientSpace.getNode(ROOT); + root.addNode("source").addNode("node"); + root.addNode("target1"); + root.addNode("target2"); + + root.getNode("source").moveNode("node", ROOT.concat("target1/moved")); + root.moveNode("target1", ROOT.concat("target2/moved-target1")); + + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1"))); + assertTrue(transientSpace.nodeExists(ROOT.concat("target2/moved-target1/moved"))); + + transientSpace.save(); + + assertTrue(transientSpace.nodeExists(ROOT.concat("source"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("source/node"))); + assertFalse(transientSpace.nodeExists(ROOT.concat("target1"))); + } + + @Test + public void setPropertyTest() throws RepositoryException { + // Set property + NodeDelta root = transientSpace.getNode(ROOT); + root.setValue("prop", JsonAtom.number(42)); + transientSpace.save(); + assertThat(mk, propertyHasValue(ROOT.concat("prop"), 42)); + + // Remove property + root.setValue("prop", null); + transientSpace.save(); + assertThat(mk, CoreMatchers.not(propertyExists(ROOT.concat("prop")))); + + // Transiently remove property + root.setValue("prop", JsonAtom.number(42)); + root.setValue("prop", null); + transientSpace.save(); + assertThat(mk, CoreMatchers.not(propertyExists(ROOT.concat("prop")))); + + // Set property on transiently added parent + root.addNode("node1").addNode("node2").setValue("prop", JsonAtom.string("value")); + transientSpace.save(); + assertThat(mk, propertyHasValue(ROOT.concat("node1/node2/prop"), "value")); + + // Set property and move parent + root.addNode("source").addNode("node").setValue("prop1", JsonAtom.number(42)); + root.getNode("source").getNode("node").setValue("prop2", JsonAtom.number(43)); + root.addNode("target"); + transientSpace.save(); + assertThat(mk, propertyHasValue(ROOT.concat("source/node/prop1"), 42)); + assertThat(mk, propertyHasValue(ROOT.concat("source/node/prop2"), 43)); + + root.getNode("source").moveNode("node", ROOT.concat("target/moved")); + root.getNode("target").getNode("moved").setValue("prop2", null); + transientSpace.save(); + assertThat(mk, CoreMatchers.not(propertyExists(ROOT.concat("source/node/prop1")))); + assertThat(mk, propertyHasValue(ROOT.concat("target/moved/prop1"), 42)); + assertThat(mk, CoreMatchers.not(propertyExists(ROOT.concat("source/node/prop2")))); + assertThat(mk, CoreMatchers.not(propertyExists(ROOT.concat("target/moved/prop2")))); + } + + public static class MicrokernelMatcher { + private MicrokernelMatcher() { } + + public static Matcher propertyHasValue(final Path path, final int value) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(MicroKernel mk) { + JsonObject node = parseJson(mk.getNodes(path.getParent().getMkPath(), mk.getHeadRevision())); + JsonValue prop = node.get(path.getName()); + return prop != null && prop.type() == Type.NUMBER + && Integer.parseInt(prop.asAtom().value()) == value; + } + + @Override + public void describeTo(Description description) { + description.appendText(path + " = ").appendValue(value); + } + }; + } + + public static Matcher propertyHasValue(final Path path, final String value) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(MicroKernel mk) { + JsonObject node = parseJson(mk.getNodes(path.getParent().getMkPath(), mk.getHeadRevision())); + JsonValue prop = node.get(path.getName()); + return prop != null && prop.type() == Type.STRING + && prop.asAtom().value().equals(value); + } + + @Override + public void describeTo(Description description) { + description.appendText(path + " = ").appendValue(value); + } + }; + } + + public static Matcher propertyExists(final Path path) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(MicroKernel mk) { + try { + JsonObject node = parseJson(mk.getNodes(path.getParent().getMkPath(), mk.getHeadRevision())); + JsonValue prop = node.get(path.getName()); + return prop != null; + } + catch (MicroKernelException e) { + if (e.getCause() instanceof NotFoundException) { + return false; + } + else { + throw e; + } + } + } + + @Override + public void describeTo(Description description) { + description.appendText("Property exists").appendValue(path); + } + }; + } + + //------------------------------------------< private >--- + + private static JsonObject parseJson(String json) { + return FullJsonParser.parseObject(new UnescapingJsonTokenizer(json)); + } + } + +}