This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-resource.git


The following commit(s) were added to refs/heads/master by this push:
     new 7660582  SLING-12246 Add tests for move and orderBefore operations 
(#41)
7660582 is described below

commit 7660582019bc8b4b0fdda73bdddbde77262159e6
Author: Konrad Windszus <k...@apache.org>
AuthorDate: Fri Mar 1 12:17:55 2024 +0100

    SLING-12246 Add tests for move and orderBefore operations (#41)
    
    The move operations are tested with observers on different levels
---
 .../resource/internal/JcrResourceListenerTest.java | 153 ++++++++++++++++++++-
 1 file changed, 147 insertions(+), 6 deletions(-)

diff --git 
a/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
 
b/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
index 9389a69..e487b10 100644
--- 
a/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
+++ 
b/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
@@ -18,6 +18,7 @@ package org.apache.sling.jcr.resource.internal;
 
 import static java.util.Collections.synchronizedList;
 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;
@@ -29,12 +30,17 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import javax.jcr.AccessDeniedException;
 import javax.jcr.Credentials;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Value;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.version.VersionException;
 
+import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.sling.api.resource.observation.ResourceChange;
 import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
 import org.apache.sling.api.resource.path.PathSet;
@@ -61,6 +67,8 @@ public class JcrResourceListenerTest {
 
     private final String createdPath = "/test" + System.currentTimeMillis() + 
"-create";
 
+    private final String movedPath = "/test" + System.currentTimeMillis() + 
"-moved";
+
     private final String pathToDelete = "/test" + System.currentTimeMillis() + 
"-delete";
 
     private final String pathToModify = "/test" + System.currentTimeMillis() + 
"-modify";
@@ -74,7 +82,13 @@ public class JcrResourceListenerTest {
     public void setUp() throws Exception {
         repository = SlingRepositoryProvider.getRepository();
         this.adminSession = repository.loginAdministrative(null);
-        ObservationReporter observationReporter = getObservationReporter();
+        registerListener("/");
+    }
+
+    private void registerListener(String paths) throws RepositoryException {
+        unregisterListener();
+        events.clear();
+        ObservationReporter observationReporter = 
getObservationReporter(paths);
         this.config = new JcrListenerBaseConfig(observationReporter,
                 new SlingRepository() {
 
@@ -140,7 +154,6 @@ public class JcrResourceListenerTest {
 
                     @Override
                     public String getDefaultWorkspace() {
-                        // TODO Auto-generated method stub
                         return repository.getDefaultWorkspace();
                     }
                 });
@@ -149,11 +162,22 @@ public class JcrResourceListenerTest {
     }
 
     @After
-    public void tearDown() {
+    public void tearDown() throws AccessDeniedException, VersionException, 
LockException, ConstraintViolationException, RepositoryException {
+        unregisterListener();
+        if (adminSession.itemExists("/apps")) {
+            adminSession.removeItem("/apps");
+        }
+        if (adminSession.itemExists("/apps2")) {
+            adminSession.removeItem("/apps2");
+        }
         if (adminSession != null) {
+            adminSession.save();
             adminSession.logout();
             adminSession = null;
         }
+    }
+
+    private void unregisterListener() {
         if (listener != null) {
             listener.close();
             listener = null;
@@ -200,6 +224,115 @@ public class JcrResourceListenerTest {
         assertTrue("Removed set should contain " + pathToDelete, 
removePaths.contains(pathToDelete));
     }
 
+    @Test
+    public void testMoveOperationsInsideObservedPathOnLeafNode() throws 
RepositoryException, InterruptedException {
+        createNode(adminSession, createdPath);
+        adminSession.move(createdPath, movedPath);
+        adminSession.save();
+        Thread.sleep(3500);
+
+        assertTrue("Events must contain \"added\" for path \"" + movedPath + 
"\"",
+                events.stream().anyMatch(e -> e.getPath().equals(movedPath) && 
e.getType() == ChangeType.ADDED));
+        assertTrue("Events must contain \"removed\" for path \"" + createdPath 
+ "\"",
+                events.stream().anyMatch(e -> e.getPath().equals(createdPath) 
&& e.getType() == ChangeType.REMOVED));
+    }
+
+    @Test
+    public void testMoveOperationsInsideObservedPath() throws 
RepositoryException, InterruptedException {
+        createNode(adminSession, "/apps/test" + createdPath);
+        // clear events for node creation
+        Thread.sleep(2000);
+        registerListener("/");
+        adminSession.move("/apps", "/apps2");
+        adminSession.save();
+        Thread.sleep(3500);
+
+        // 1 added + 1 removed event for roots
+        assertEquals("Events must only contain 2 events but has " + 
events.toString(), 2, events.size());
+        assertTrue("Events must contain \"added\" for path \"/apps2\"",
+                events.stream().anyMatch(e -> e.getPath().equals("/apps2") && 
e.getType() == ChangeType.ADDED));
+        assertTrue("Events must contain \"removed\" for path \"/apps\"",
+                events.stream().anyMatch(e -> e.getPath().equals("/apps") && 
e.getType() == ChangeType.REMOVED));
+    }
+
+    @Test
+    public void testMoveOperationsIntoObservedPath() throws 
RepositoryException, InterruptedException {
+        registerListener("/apps");
+        createNode(adminSession, "/apps2/test" + createdPath);
+        adminSession.move("/apps2", "/apps");
+        adminSession.save();
+        Thread.sleep(3500);
+        String expectedAddedPath = "/apps/test" + createdPath;
+        assertTrue("Events must contain \"added\" for path \"" + 
expectedAddedPath + "\"",
+                events.stream().anyMatch(e -> 
e.getPath().equals(expectedAddedPath) && e.getType() == ChangeType.ADDED));
+        assertFalse("Events must not contain any \"removed\" events",
+                events.stream().anyMatch(e -> e.getType() == 
ChangeType.REMOVED));
+    }
+
+    @Test
+    public void testMoveOperationsOutOfObservedPath() throws 
RepositoryException, InterruptedException {
+        createNode(adminSession, "/apps/test" + createdPath);
+        Thread.sleep(2000);
+        registerListener("/apps");
+        adminSession.move("/apps", "/apps2");
+        adminSession.save();
+        Thread.sleep(3500);
+        String expectedPath = "/apps";
+        // 1 removed events for the moved root only
+        assertEquals("Events must only contain 1 events but has " + 
events.toString(), 1, events.size());
+        assertTrue("Events must contain \"removed\" for path \"" + 
expectedPath + "\"",
+                events.stream().anyMatch(e -> e.getPath().equals(expectedPath) 
&& e.getType() == ChangeType.REMOVED));
+    }
+
+    @Test
+    public void testMoveOperationsIntoObservedPathWithGlobs() throws 
RepositoryException, InterruptedException {
+        registerListener("glob:/*/test/**");
+        createNode(adminSession, "/apps/test2" + createdPath);
+        adminSession.move("/apps/test2", "/apps/test"); // move happens above 
observed path
+        adminSession.save();
+        Thread.sleep(3500);
+
+        // only an added event for the root is received
+        assertEquals("Events must only contain 1 event but has " + 
events.toString(), 1, events.size());
+        assertTrue("Events must contain \"added\" for root path 
\"/apps/test\"",
+                events.stream().anyMatch(e -> e.getPath().equals("/apps/test") 
&& e.getType() == ChangeType.ADDED));
+    }
+
+    @Test
+    public void testMoveOperationsOutOfObservedPathWithGlobs() throws 
RepositoryException, InterruptedException {
+        createNode(adminSession, "/apps/test" + createdPath);
+        Thread.sleep(2000);
+        registerListener("glob:/*/test/**");
+        adminSession.save();
+        adminSession.move("/apps/test", "/apps/test2"); // move happens above 
observed path
+        adminSession.save();
+        Thread.sleep(3500);
+
+        // 2 removed events for the whole subgraph below the observed path is 
received
+        assertEquals("Events must only contain 2 events but has " + 
events.toString(), 2, events.size());
+        assertTrue("Events must contain \"added\" for root path 
\"/apps/test\"",
+                events.stream().anyMatch(e -> e.getPath().equals("/apps/test" 
+ createdPath) && e.getType() == ChangeType.REMOVED));
+    }
+
+    @Test
+    public void testOrderBeforeOperations() throws RepositoryException, 
InterruptedException {
+        Node node = createNode(adminSession, createdPath);
+        node.addNode("child1");
+        node.addNode("child2");
+
+        adminSession.save();
+        Thread.sleep(2000);
+        events.clear();
+        // reorder child1 to appear after child2
+        node.orderBefore("child1", null);
+
+        adminSession.save();
+        Thread.sleep(2000);
+
+        // TODO: send events here
+        assertEquals("Received: " + events, 0, events.size());
+    }
+
     @Test
     public void testMultiplePaths() throws Exception {
         ObserverConfiguration observerConfig = new ObserverConfiguration() {
@@ -304,7 +437,7 @@ public class JcrResourceListenerTest {
     }
 
     private static Node createNode(final Session session, final String path) 
throws RepositoryException {
-        final Node n = session.getRootNode().addNode(path.substring(1), 
"nt:unstructured");
+        Node n = JcrUtils.getOrCreateByPath(path, "nt:unstructured", session);
         session.save();
         return n;
     }
@@ -332,11 +465,19 @@ public class JcrResourceListenerTest {
     }
 
     protected ObservationReporter getObservationReporter() {
-        return new SimpleObservationReporter();
+        return new SimpleObservationReporter("/");
+    }
+
+    protected ObservationReporter getObservationReporter(String... paths) {
+        return new SimpleObservationReporter(paths);
     }
 
     private class SimpleObservationReporter implements ObservationReporter {
 
+        private final String[] paths;
+        public SimpleObservationReporter(String... paths) {
+            this.paths = paths;
+        }
         @Override
         public void reportChanges(Iterable<ResourceChange> changes, boolean 
distribute) {
             for (ResourceChange c : changes) {
@@ -355,7 +496,7 @@ public class JcrResourceListenerTest {
 
                 @Override
                 public PathSet getPaths() {
-                    return PathSet.fromStrings("/");
+                    return PathSet.fromStrings(paths);
                 }
 
                 @Override

Reply via email to