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

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


The following commit(s) were added to refs/heads/master by this push:
     new ea08010  SLING-11869 MockUserManager should load and save home folder 
items (#21)
ea08010 is described below

commit ea08010516b8827430487adf3010976f3d1ac5cd
Author: Eric Norman <[email protected]>
AuthorDate: Thu May 11 19:33:03 2023 -0700

    SLING-11869 MockUserManager should load and save home folder items (#21)
---
 pom.xml                                            |   6 +
 .../sling/testing/mock/jcr/MockAuthorizable.java   | 113 +++++++++++-------
 .../apache/sling/testing/mock/jcr/MockGroup.java   |   6 +-
 .../testing/mock/jcr/MockPrincipalManager.java     |   3 +-
 .../apache/sling/testing/mock/jcr/MockSession.java |   3 +-
 .../apache/sling/testing/mock/jcr/MockUser.java    |   5 +-
 .../sling/testing/mock/jcr/MockUserManager.java    | 130 ++++++++++++++++++++-
 .../sling/testing/mock/jcr/package-info.java       |   2 +-
 .../testing/mock/jcr/MockAuthorizableTest.java     |  33 ++++--
 .../sling/testing/mock/jcr/MockGroupTest.java      |   6 +
 .../testing/mock/jcr/MockPrincipalManagerTest.java |   5 +-
 .../testing/mock/jcr/MockUserManagerTest.java      |  37 +++++-
 .../sling/testing/mock/jcr/MockUserTest.java       |   6 +
 13 files changed, 293 insertions(+), 62 deletions(-)

diff --git a/pom.xml b/pom.xml
index 46cbd97..e96af82 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,12 @@
             <version>1.22.5</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>oak-security-spi</artifactId>
+            <version>1.22.5</version>
+            <scope>compile</scope>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.commons</groupId>
diff --git 
a/src/main/java/org/apache/sling/testing/mock/jcr/MockAuthorizable.java 
b/src/main/java/org/apache/sling/testing/mock/jcr/MockAuthorizable.java
index e8be563..c58490d 100644
--- a/src/main/java/org/apache/sling/testing/mock/jcr/MockAuthorizable.java
+++ b/src/main/java/org/apache/sling/testing/mock/jcr/MockAuthorizable.java
@@ -16,21 +16,23 @@
  */
 package org.apache.sling.testing.mock.jcr;
 
-import java.nio.file.Paths;
 import java.security.Principal;
-import java.util.HashMap;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.Map;
 import java.util.Set;
-import java.util.stream.Collectors;
 
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
-import org.apache.jackrabbit.value.ValueFactoryImpl;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -38,16 +40,19 @@ import org.jetbrains.annotations.Nullable;
  * Mock {@link Authorizable} implementation.
  */
 abstract class MockAuthorizable implements Authorizable {
-    static final String REP_PRINCIPAL_NAME = "rep:principalName";
+    // internal property names to filter out of the authorizable properties
+    protected Set<String> notAuthorizablePropNames = new 
HashSet<>(Arrays.asList(
+            JcrConstants.JCR_PRIMARYTYPE,
+            UserConstants.REP_AUTHORIZABLE_ID,
+            UserConstants.REP_PRINCIPAL_NAME));
+
     protected String id;
     protected Principal principal;
-    protected String path;
     protected MockUserManager mockUserMgr;
-    protected Map<String, Value[]> propsMap = new HashMap<>();
-    protected Set<Group> declaredMemberOf = new HashSet<>();
+    protected Node homeNode;
 
     MockAuthorizable(@Nullable String id, @Nullable Principal principal,
-            @Nullable String intermediatePath,
+            @NotNull Node homeNode,
             @NotNull MockUserManager mockUserMgr) {
         this.principal = principal;
         if (id == null && principal != null) {
@@ -59,19 +64,8 @@ abstract class MockAuthorizable implements Authorizable {
             this.principal = () -> this.id;
         }
 
-        if (intermediatePath == null) {
-            // use a default intermediate path when none supplied
-            if (isGroup()) {
-                intermediatePath = "/home/groups"; // NOSONAR
-            } else {
-                intermediatePath = "/home/users"; // NOSONAR
-            }
-        }
-        this.path = Paths.get(intermediatePath, this.id).toString();
+        this.homeNode = homeNode;
         this.mockUserMgr = mockUserMgr;
-
-        // pre-populate the principalName property that is needed by 
MockPrincipalManager#findPrincipals
-        propsMap.put(REP_PRINCIPAL_NAME, new Value[] 
{ValueFactoryImpl.getInstance().createValue(this.id)});
     }
 
     @Override
@@ -91,6 +85,14 @@ abstract class MockAuthorizable implements Authorizable {
 
     @Override
     public @NotNull Iterator<Group> declaredMemberOf() throws 
RepositoryException {
+        Set<Group> declaredMemberOf = new HashSet<>();
+        Set<Authorizable> all = 
mockUserMgr.all(PrincipalManager.SEARCH_TYPE_GROUP);
+        for (Authorizable authorizable : all) {
+            Group group = (Group)authorizable;
+            if (group.isDeclaredMember(this)) {
+                declaredMemberOf.add(group);
+            }
+        }
         return declaredMemberOf.iterator();
     }
 
@@ -131,52 +133,85 @@ abstract class MockAuthorizable implements Authorizable {
 
     @Override
     public @NotNull Iterator<String> getPropertyNames() throws 
RepositoryException {
-        Set<String> propNames = propsMap.keySet().stream()
-                .filter(key -> key.indexOf('/') == -1)
-                .collect(Collectors.toSet());
-            return propNames.iterator();
+        Set<String> propNames = new HashSet<>();
+        PropertyIterator properties = homeNode.getProperties();
+        while (properties.hasNext()) {
+            Property nextProperty = properties.nextProperty();
+            if (!notAuthorizablePropNames.contains(nextProperty.getName())) {
+                propNames.add(nextProperty.getName());
+            }
+        }
+        return propNames.iterator();
     }
 
     @Override
     public @NotNull Iterator<String> getPropertyNames(@NotNull String relPath) 
throws RepositoryException {
-        Set<String> propNames = propsMap.keySet().stream()
-            .filter(key -> key.startsWith(relPath))
-            .collect(Collectors.toSet());
+        Set<String> propNames = new HashSet<>();
+        if (homeNode.hasNode(relPath)) {
+            PropertyIterator properties = 
homeNode.getNode(relPath).getProperties();
+            while (properties.hasNext()) {
+                Property nextProperty = properties.nextProperty();
+                if 
(!notAuthorizablePropNames.contains(nextProperty.getName())) {
+                    propNames.add(nextProperty.getName());
+                }
+            }
+        }
         return propNames.iterator();
     }
 
     @Override
     public boolean hasProperty(@NotNull String relPath) throws 
RepositoryException {
-        return propsMap.containsKey(relPath);
+        return homeNode.hasProperty(relPath);
     }
 
     @Override
     public void setProperty(@NotNull String relPath, @Nullable Value value) 
throws RepositoryException {
-        propsMap.put(relPath, new Value[] {value});
+        String[] segments = relPath.split("/");
+        Node node = homeNode;
+        for (int i = 0; i < segments.length - 1; i++) {
+            String segment = segments[i];
+            if (node.hasNode(segment)) {
+                node = node.getNode(segment);
+            } else {
+                node = node.addNode(segment, 
UserConstants.NT_REP_AUTHORIZABLE_FOLDER);
+            }
+        }
+        String propName = segments[segments.length - 1];
+        node.setProperty(propName, value);
     }
 
     @Override
     public void setProperty(@NotNull String relPath, @Nullable Value[] value) 
throws RepositoryException {
-        propsMap.put(relPath, value);
+        homeNode.setProperty(relPath, value);
     }
 
     @Override
     public @Nullable Value[] getProperty(@NotNull String relPath) throws 
RepositoryException {
-        return propsMap.get(relPath);
+        if (homeNode.hasProperty(relPath)) {
+            Property property = homeNode.getProperty(relPath);
+            if (property.isMultiple()) {
+                return property.getValues();
+            } else {
+                return new Value[] {property.getValue()};
+            }
+        } else {
+            return null;
+        }
     }
 
     @Override
     public boolean removeProperty(@NotNull String relPath) throws 
RepositoryException {
-        return propsMap.remove(relPath) != null;
+        boolean removed = false;
+        if (homeNode.hasProperty(relPath)) {
+            homeNode.getProperty(relPath).remove();
+            removed = true;
+        }
+        return removed;
     }
 
     @Override
     public @NotNull String getPath() throws RepositoryException {
-        return path;
-    }
-
-    public void addDeclaredMemberOf(Group group) {
-        declaredMemberOf.add(group);
+        return homeNode.getPath();
     }
 
 }
diff --git a/src/main/java/org/apache/sling/testing/mock/jcr/MockGroup.java 
b/src/main/java/org/apache/sling/testing/mock/jcr/MockGroup.java
index 27ff95b..dd75d54 100644
--- a/src/main/java/org/apache/sling/testing/mock/jcr/MockGroup.java
+++ b/src/main/java/org/apache/sling/testing/mock/jcr/MockGroup.java
@@ -23,6 +23,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
+import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.api.security.user.Authorizable;
@@ -37,9 +38,9 @@ class MockGroup extends MockAuthorizable implements Group {
     private Map<String, Authorizable> declaredMembers = new HashMap<>();
 
     public MockGroup(@Nullable String id, @Nullable Principal principal,
-            @Nullable String intermediatePath,
+            @NotNull Node homeNode,
             @NotNull MockUserManager mockUserMgr) {
-        super(id, principal, intermediatePath, mockUserMgr);
+        super(id, principal, homeNode, mockUserMgr);
     }
 
     @Override
@@ -107,7 +108,6 @@ class MockGroup extends MockAuthorizable implements Group {
         boolean added = false;
         if (!isMember(authorizable)) {
             declaredMembers.put(authorizable.getID(), authorizable);
-            ((MockAuthorizable)authorizable).addDeclaredMemberOf(this);
             added = true;
         }
         return added;
diff --git 
a/src/main/java/org/apache/sling/testing/mock/jcr/MockPrincipalManager.java 
b/src/main/java/org/apache/sling/testing/mock/jcr/MockPrincipalManager.java
index ba32cd5..49ad0e5 100644
--- a/src/main/java/org/apache/sling/testing/mock/jcr/MockPrincipalManager.java
+++ b/src/main/java/org/apache/sling/testing/mock/jcr/MockPrincipalManager.java
@@ -30,6 +30,7 @@ import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
@@ -57,7 +58,7 @@ public class MockPrincipalManager implements PrincipalManager 
{
         Set<Principal> principals = new HashSet<>();
         try {
             @NotNull Iterator<Authorizable> authorizables = 
mockUserManager.findAuthorizables(
-                    MockAuthorizable.REP_PRINCIPAL_NAME, simpleFilter, 
searchType);
+                    UserConstants.REP_PRINCIPAL_NAME, simpleFilter, 
searchType);
             while (authorizables.hasNext()) {
                 Authorizable next = authorizables.next();
                 principals.add(next.getPrincipal());
diff --git a/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java 
b/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java
index 05a110c..b461638 100644
--- a/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java
+++ b/src/main/java/org/apache/sling/testing/mock/jcr/MockSession.java
@@ -75,11 +75,12 @@ class MockSession implements Session, JackrabbitSession {
             String userId, String workspaceName) throws RepositoryException {
         this.repository = repository;
         this.workspace = new MockWorkspace(repository, this, workspaceName);
-        this.userManager = new MockUserManager();
+        this.userManager = new MockUserManager(this);
         this.principalManager = new MockPrincipalManager(this.userManager);
         this.items = items;
         this.userId = userId;
         isLive = true;
+        this.userManager.loadAlreadyExistingAuthorizables();
         hasKnownChanges = false;
         this.save();
     }
diff --git a/src/main/java/org/apache/sling/testing/mock/jcr/MockUser.java 
b/src/main/java/org/apache/sling/testing/mock/jcr/MockUser.java
index a4ae6b2..faa1b83 100644
--- a/src/main/java/org/apache/sling/testing/mock/jcr/MockUser.java
+++ b/src/main/java/org/apache/sling/testing/mock/jcr/MockUser.java
@@ -20,6 +20,7 @@ import java.security.Principal;
 import java.util.Arrays;
 
 import javax.jcr.Credentials;
+import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.SimpleCredentials;
 
@@ -40,9 +41,9 @@ class MockUser extends MockAuthorizable implements User {
     private String disabledReason;
 
     public MockUser(@Nullable String id, @Nullable Principal principal,
-            @Nullable String intermediatePath,
+            @NotNull Node homeNode,
             @NotNull MockUserManager mockUserMgr) {
-        super(id, principal, intermediatePath, mockUserMgr);
+        super(id, principal, homeNode, mockUserMgr);
     }
 
     @Override
diff --git 
a/src/main/java/org/apache/sling/testing/mock/jcr/MockUserManager.java 
b/src/main/java/org/apache/sling/testing/mock/jcr/MockUserManager.java
index ed1b0e5..e69d4a8 100644
--- a/src/main/java/org/apache/sling/testing/mock/jcr/MockUserManager.java
+++ b/src/main/java/org/apache/sling/testing/mock/jcr/MockUserManager.java
@@ -24,7 +24,10 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import javax.jcr.Node;
+import javax.jcr.Property;
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.Value;
 
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
@@ -35,6 +38,8 @@ import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.Query;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.commons.visitor.FilteringItemVisitor;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
@@ -45,9 +50,68 @@ import org.slf4j.LoggerFactory;
  */
 public class MockUserManager implements UserManager {
     private Logger logger = LoggerFactory.getLogger(getClass());
+    protected Session session = null;
     protected Map<String, Authorizable> authorizables = new HashMap<>();
     private boolean autoSave;
 
+    /**
+     * @deprecated use {@link #MockUserManager(Session)} instead
+     */
+    @Deprecated
+    public MockUserManager() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param session the jcr session where the people state is stored
+     */
+    public MockUserManager(Session session) {
+        this.session = session;
+    }
+
+    /**
+     * Scans the repository to populate any already existing users/groups
+     */
+    void loadAlreadyExistingAuthorizables() {
+        try {
+            Node rootNode = session.getRootNode();
+            if (rootNode.hasNode("home")) {
+                FilteringItemVisitor visitor = new FilteringItemVisitor() {
+                    @Override
+                    protected void entering(Node node, int level) throws 
RepositoryException {
+                        if (node.isNodeType(UserConstants.NT_REP_USER)) {
+                            String userID = 
node.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString();
+                            authorizables.computeIfAbsent(userID, id -> new 
MockUser(id, null, node, MockUserManager.this));
+                        } else if 
(node.isNodeType(UserConstants.NT_REP_GROUP)) {
+                            String userID = 
node.getProperty(UserConstants.REP_AUTHORIZABLE_ID).getString();
+                            authorizables.computeIfAbsent(userID, id -> new 
MockGroup(id, null, node, MockUserManager.this));
+                        }
+                    }
+
+                    @Override
+                    protected void entering(Property property, int level) 
throws RepositoryException {
+                        // no-op
+                    }
+
+                    @Override
+                    protected void leaving(Property property, int level) 
throws RepositoryException {
+                        // no-op
+                    }
+
+                    @Override
+                    protected void leaving(Node node, int level) throws 
RepositoryException {
+                        // no-op
+                    }
+                };
+                visitor.setWalkProperties(false);
+
+                rootNode.getNode("home").accept(visitor);
+            }
+        } catch (RepositoryException e) {
+            logger.error("Failed to load already existing authorizables", e);
+        }
+    }
+
     /**
      * Callback function for {@link MockUser#remove()} and {@link 
MockGroup#remove()} to
      * invoke.
@@ -57,7 +121,14 @@ public class MockUserManager implements UserManager {
      * @return true if removed, false otherwise
      */
     boolean removeAuthorizable(Authorizable a) throws RepositoryException {
-        return authorizables.remove(a.getID(), a);
+        boolean removed = authorizables.remove(a.getID(), a);
+        if (removed) {
+            @NotNull String path = a.getPath();
+            if (session.nodeExists(path)) {
+                session.getNode(path).remove();
+            }
+        }
+        return removed;
     }
 
     Set<Authorizable> all(int searchType) throws RepositoryException { // 
NOSONAR
@@ -115,7 +186,58 @@ public class MockUserManager implements UserManager {
         if (authorizables.containsKey(groupID)) {
             throw new AuthorizableExistsException("Group already exists");
         }
-        return (Group)authorizables.computeIfAbsent(groupID, id -> new 
MockGroup(id, principal, intermediatePath, this));
+        String principalName = toPrincipalName(groupID, principal);
+        Node node = ensureAuthorizablePathExists(intermediatePath, 
principalName, true);
+        return (Group)authorizables.computeIfAbsent(groupID, id -> new 
MockGroup(id, principal, node, this));
+    }
+
+    /**
+     * Calculates the principal name, preferring the supplied id or
+     * fallback to the {@link Principal#getName()} value
+     * 
+     * @param id the user or group id 
+     * @param principal the principal
+     * @return the principal name
+     */
+    protected @Nullable String toPrincipalName(@Nullable String id, @Nullable 
Principal principal) {
+        String principalName = id;
+        if (principalName == null && principal != null) {
+            principalName = principal.getName();
+        }
+        return principalName;
+    }
+
+    /**
+     * Creates the user/group home folder if they don't exist yet
+     * 
+     * @param intermediatePath the parent path
+     */
+    protected Node ensureAuthorizablePathExists(String intermediatePath, 
String principalName, boolean isGroup) throws RepositoryException {
+        if (intermediatePath == null) {
+            if (isGroup) {
+                intermediatePath = "/home/groups"; // NOSONAR
+            } else {
+                intermediatePath = "/home/users"; // NOSONAR
+            }
+        }
+        // ensure the resource at the path exists
+        String[] segments = intermediatePath.split("/");
+        Node node = session.getRootNode();
+        for (int i = 0; i < segments.length; i++) {
+            String segment = segments[i];
+            if (node.hasNode(segment)) {
+                node = node.getNode(segment);
+            } else {
+                node = node.addNode(segment, 
UserConstants.NT_REP_AUTHORIZABLE_FOLDER);
+            }
+        }
+        if (!node.hasNode(principalName)) {
+            node = node.addNode(principalName, isGroup ? 
UserConstants.NT_REP_GROUP : UserConstants.NT_REP_USER);
+            node.setProperty(UserConstants.REP_PRINCIPAL_NAME, principalName);
+            node.setProperty(UserConstants.REP_AUTHORIZABLE_ID, principalName);
+        }
+
+        return node;
     }
 
     @Override
@@ -141,7 +263,9 @@ public class MockUserManager implements UserManager {
         if (authorizables.containsKey(userID)) {
             throw new AuthorizableExistsException("User already exists");
         }
-        return (User)authorizables.computeIfAbsent(userID, id -> new 
MockUser(id, principal, intermediatePath, this));
+        String principalName = toPrincipalName(userID, principal);
+        Node node = ensureAuthorizablePathExists(intermediatePath, 
principalName, false);
+        return (User)authorizables.computeIfAbsent(userID, id -> new 
MockUser(id, principal, node, this));
     }
 
     @Override
diff --git a/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java 
b/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java
index b14419d..78c894c 100644
--- a/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java
+++ b/src/main/java/org/apache/sling/testing/mock/jcr/package-info.java
@@ -19,5 +19,5 @@
 /**
  * Mock implementation of selected JCR APIs.
  */
[email protected]("1.2.0")
[email protected]("1.3.0")
 package org.apache.sling.testing.mock.jcr;
diff --git 
a/src/test/java/org/apache/sling/testing/mock/jcr/MockAuthorizableTest.java 
b/src/test/java/org/apache/sling/testing/mock/jcr/MockAuthorizableTest.java
index e0474ae..1f1d032 100644
--- a/src/test/java/org/apache/sling/testing/mock/jcr/MockAuthorizableTest.java
+++ b/src/test/java/org/apache/sling/testing/mock/jcr/MockAuthorizableTest.java
@@ -28,6 +28,7 @@ import java.util.Iterator;
 import java.util.Set;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
@@ -45,13 +46,15 @@ import org.junit.Test;
  *
  */
 public abstract class MockAuthorizableTest<T extends Authorizable> {
+    protected Session session;
     protected UserManager userManager;
     protected T authorizable;
     protected ValueFactory vf = ValueFactoryImpl.getInstance();
 
     @Before
     public void before() throws RepositoryException {
-        userManager = new MockUserManager();
+        session = MockJcr.newSession();
+        userManager = new MockUserManager(session);
         authorizable = createAuthorizable();
     }
 
@@ -131,13 +134,9 @@ public abstract class MockAuthorizableTest<T extends 
Authorizable> {
      */
     @Test
     public void testGetPropertyNames() throws RepositoryException {
-        // only rep:principalName property
+        // no properties
         @NotNull Iterator<String> propertyNames = 
authorizable.getPropertyNames();
-        assertTrue(propertyNames.hasNext());
-        Set<String> propertyNamesSet = new HashSet<>();
-        propertyNames.forEachRemaining(propertyNamesSet::add);
-        assertEquals(1, propertyNamesSet.size());
-        
assertTrue(propertyNamesSet.contains(MockAuthorizable.REP_PRINCIPAL_NAME));
+        assertFalse(propertyNames.hasNext());
 
         // set some props
         authorizable.setProperty("prop1", vf.createValue("value1"));
@@ -145,9 +144,9 @@ public abstract class MockAuthorizableTest<T extends 
Authorizable> {
 
         propertyNames = authorizable.getPropertyNames();
         assertTrue(propertyNames.hasNext());
-        propertyNamesSet.clear();
+        Set<String> propertyNamesSet = new HashSet<>();
         propertyNames.forEachRemaining(propertyNamesSet::add);
-        assertEquals(2, propertyNamesSet.size());
+        assertEquals(1, propertyNamesSet.size());
         assertTrue(propertyNamesSet.contains("prop1"));
     }
 
@@ -169,7 +168,7 @@ public abstract class MockAuthorizableTest<T extends 
Authorizable> {
         Set<String> propertyNamesSet = new HashSet<>();
         propertyNames.forEachRemaining(propertyNamesSet::add);
         assertEquals(1, propertyNamesSet.size());
-        assertTrue(propertyNamesSet.contains("relPath/prop2"));
+        assertTrue(propertyNamesSet.contains("prop2"));
     }
 
     /**
@@ -192,6 +191,20 @@ public abstract class MockAuthorizableTest<T extends 
Authorizable> {
         assertNotNull(property);
         assertEquals(1, property.length);
         assertEquals("value1", property[0].getString());
+
+        // nested prop
+        authorizable.setProperty("relPath2/prop2", vf.createValue("value2"));
+        property = authorizable.getProperty("relPath2/prop2");
+        assertNotNull(property);
+        assertEquals(1, property.length);
+        assertEquals("value2", property[0].getString());
+
+        // second nested prop where intermediate subnode already exists
+        authorizable.setProperty("relPath2/prop3", vf.createValue("value3"));
+        property = authorizable.getProperty("relPath2/prop3");
+        assertNotNull(property);
+        assertEquals(1, property.length);
+        assertEquals("value3", property[0].getString());
     }
 
     /**
diff --git a/src/test/java/org/apache/sling/testing/mock/jcr/MockGroupTest.java 
b/src/test/java/org/apache/sling/testing/mock/jcr/MockGroupTest.java
index 28aaa12..57ae042 100644
--- a/src/test/java/org/apache/sling/testing/mock/jcr/MockGroupTest.java
+++ b/src/test/java/org/apache/sling/testing/mock/jcr/MockGroupTest.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
 
+import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
 
@@ -31,6 +32,7 @@ import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.AuthorizableExistsException;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
 
@@ -240,6 +242,10 @@ public class MockGroupTest extends 
MockAuthorizableTest<Group> {
     @Override
     public void testGetPath() throws UnsupportedRepositoryOperationException, 
RepositoryException {
         assertEquals("/home/groups/group1", authorizable.getPath());
+        assertTrue(session.nodeExists(authorizable.getPath()));
+        Node node = session.getNode(authorizable.getPath());
+        assertEquals(authorizable.getID(), 
+                
node.getProperty(UserConstants.REP_PRINCIPAL_NAME).getString());
     }
 
 }
diff --git 
a/src/test/java/org/apache/sling/testing/mock/jcr/MockPrincipalManagerTest.java 
b/src/test/java/org/apache/sling/testing/mock/jcr/MockPrincipalManagerTest.java
index eaa1a39..a2a5961 100644
--- 
a/src/test/java/org/apache/sling/testing/mock/jcr/MockPrincipalManagerTest.java
+++ 
b/src/test/java/org/apache/sling/testing/mock/jcr/MockPrincipalManagerTest.java
@@ -30,6 +30,7 @@ import java.util.HashSet;
 import java.util.Set;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 
 import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
@@ -48,12 +49,14 @@ import ch.qos.logback.classic.Level;
  *
  */
 public class MockPrincipalManagerTest {
+    protected Session session;
     protected UserManager userManager;
     protected MockPrincipalManager principalManager;
 
     @Before
     public void before() throws RepositoryException {
-        userManager = new MockUserManager();
+        session = MockJcr.newSession();
+        userManager = new MockUserManager(session);
         principalManager = new 
MockPrincipalManager((MockUserManager)userManager);
     }
 
diff --git 
a/src/test/java/org/apache/sling/testing/mock/jcr/MockUserManagerTest.java 
b/src/test/java/org/apache/sling/testing/mock/jcr/MockUserManagerTest.java
index 057791b..95ddd5d 100644
--- a/src/test/java/org/apache/sling/testing/mock/jcr/MockUserManagerTest.java
+++ b/src/test/java/org/apache/sling/testing/mock/jcr/MockUserManagerTest.java
@@ -26,7 +26,9 @@ import static org.junit.Assert.assertTrue;
 import java.util.Iterator;
 import java.util.Set;
 
+import javax.jcr.Node;
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.jcr.ValueFactory;
 
@@ -37,6 +39,7 @@ import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.Query;
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.apache.jackrabbit.value.ValueFactoryImpl;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -50,12 +53,24 @@ import ch.qos.logback.classic.Level;
  *
  */
 public class MockUserManagerTest {
+    protected Session session;
     protected MockUserManager userManager;
     protected ValueFactory vf = ValueFactoryImpl.getInstance();
 
     @Before
     public void before() throws RepositoryException {
-        userManager = new MockUserManager();
+        session = MockJcr.newSession();
+        userManager = new MockUserManager(session);
+    }
+
+    /**
+     * Verify deprecated constructor now throws exception
+     */
+    @SuppressWarnings("deprecation")
+    @Deprecated
+    @Test
+    public void testDeprecatedConstructor() {
+        assertThrows(UnsupportedOperationException.class, () -> new 
MockUserManager());
     }
 
     /**
@@ -71,6 +86,26 @@ public class MockUserManagerTest {
         assertFalse(userManager.removeAuthorizable(user1));
     }
 
+    @Test
+    public void testLoadAlreadyExistingAuthorizables() throws 
RepositoryException {
+        Node homeNode = session.getRootNode()
+            .addNode("home", UserConstants.NT_REP_AUTHORIZABLE_FOLDER);
+        Node usersNode = homeNode.addNode("users", 
UserConstants.NT_REP_AUTHORIZABLE_FOLDER);
+        Node testuser1 = usersNode.addNode("testuser1", 
UserConstants.NT_REP_USER);
+        testuser1.setProperty(UserConstants.REP_AUTHORIZABLE_ID, "testuser1");
+        testuser1.setProperty(UserConstants.REP_PRINCIPAL_NAME, "testuser1");
+
+        Node groupsNode = homeNode.addNode("groups", 
UserConstants.NT_REP_AUTHORIZABLE_FOLDER);
+        Node testgroup1 = groupsNode.addNode("testgroup1", 
UserConstants.NT_REP_GROUP);
+        testgroup1.setProperty(UserConstants.REP_AUTHORIZABLE_ID, 
"testgroup1");
+        testgroup1.setProperty(UserConstants.REP_PRINCIPAL_NAME, "testgroup1");
+
+        userManager.loadAlreadyExistingAuthorizables();
+
+        assertNotNull(userManager.getAuthorizable("testuser1"));
+        assertNotNull(userManager.getAuthorizable("testgroup1"));
+    }
+
     /**
      * Test method for {@link 
org.apache.sling.testing.mock.jcr.MockUserManager#all(int)}.
      */
diff --git a/src/test/java/org/apache/sling/testing/mock/jcr/MockUserTest.java 
b/src/test/java/org/apache/sling/testing/mock/jcr/MockUserTest.java
index 11e44e8..519d5fc 100644
--- a/src/test/java/org/apache/sling/testing/mock/jcr/MockUserTest.java
+++ b/src/test/java/org/apache/sling/testing/mock/jcr/MockUserTest.java
@@ -24,11 +24,13 @@ import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
 import javax.jcr.Credentials;
+import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.SimpleCredentials;
 import javax.jcr.UnsupportedRepositoryOperationException;
 
 import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.jetbrains.annotations.NotNull;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -186,6 +188,10 @@ public class MockUserTest extends 
MockAuthorizableTest<User> {
     @Override
     public void testGetPath() throws UnsupportedRepositoryOperationException, 
RepositoryException {
         assertEquals("/home/users/user1", authorizable.getPath());
+        assertTrue(session.nodeExists(authorizable.getPath()));
+        Node node = session.getNode(authorizable.getPath());
+        assertEquals(authorizable.getID(), 
+                
node.getProperty(UserConstants.REP_PRINCIPAL_NAME).getString());
     }
 
 }

Reply via email to