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-resourceresolver.git
The following commit(s) were added to refs/heads/master by this push: new a19995d SLING-12160 Prevent ConcurrentModificationException in readAliasesOptimized(...) (#107) a19995d is described below commit a19995d2ec700f1b444adc52c783cdbceae5a7ce Author: Konrad Windszus <k...@apache.org> AuthorDate: Mon Nov 27 09:00:50 2023 +0100 SLING-12160 Prevent ConcurrentModificationException in readAliasesOptimized(...) (#107) Refactor to use nested ConcurrentHashMap with Collection<String> for alias map --- .../impl/ResourceResolverImpl.java | 25 ++- .../resourceresolver/impl/mapping/MapEntries.java | 85 ++++---- .../impl/mapping/MapEntriesHandler.java | 8 +- .../impl/mapping/PathGenerator.java | 3 +- .../impl/mapping/ResourceMapperImpl.java | 18 +- .../mapping/AbstractMappingMapEntriesTest.java | 2 +- .../impl/mapping/MapEntriesTest.java | 240 ++++++++++----------- 7 files changed, 176 insertions(+), 205 deletions(-) diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java index 0a528d2..7b32c4d 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverImpl.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; @@ -839,20 +840,18 @@ public class ResourceResolverImpl extends SlingAdaptable implements ResourceReso if (factory.getMapEntries().isOptimizeAliasResolutionEnabled()){ logger.debug("getChildInternal: Optimize Alias Resolution is Enabled"); //optimization made in SLING-2521 - final Map<String, String> aliases = factory.getMapEntries().getAliasMap(parent.getPath()); - if (aliases != null) { - final String aliasName = aliases.get(childName); - if (aliasName != null ) { - final String aliasPath; - if ( aliasName.startsWith("/") ) { - aliasPath = aliasName; - } else { - aliasPath = parent.getPath() + '/' + aliasName; - } - final Resource aliasedChild = getAbsoluteResourceInternal(parent, ResourceUtil.normalize(aliasPath), EMPTY_PARAMETERS, true ); - logger.debug("getChildInternal: Found Resource {} with alias {} to use", aliasedChild, childName); - return aliasedChild; + final Optional<String> aliasedResourceName = factory.getMapEntries().getAliasMap(parent.getPath()).entrySet() + .stream().filter(e -> e.getValue().contains(childName)).findFirst().map(Map.Entry::getKey); + if (aliasedResourceName.isPresent()) { + final String aliasPath; + if ( aliasedResourceName.get().startsWith("/") ) { + aliasPath = aliasedResourceName.get(); + } else { + aliasPath = parent.getPath() + '/' + aliasedResourceName.get(); } + final Resource aliasedChild = getAbsoluteResourceInternal(parent, ResourceUtil.normalize(aliasPath), EMPTY_PARAMETERS, true ); + logger.debug("getChildInternal: Found Resource {} with alias {} to use", aliasedChild, childName); + return aliasedChild; } } else { if ( this.factory.isOptimizeAliasResolutionEnabled() ) { diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java index 84b64fd..1c89504 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java @@ -34,6 +34,7 @@ import org.apache.sling.api.resource.path.Path; import org.apache.sling.resourceresolver.impl.ResourceResolverImpl; import org.apache.sling.resourceresolver.impl.ResourceResolverMetrics; import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig; +import org.jetbrains.annotations.NotNull; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceRegistration; @@ -56,7 +57,6 @@ import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -68,6 +68,7 @@ import java.util.SortedMap; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -140,7 +141,10 @@ public class MapEntries implements private Map <String,List <String>> vanityTargets; - private Map<String, Map<String, String>> aliasMap; + /** + * The key of the map is the parent path, while the value is a map with the the resource name as key and the actual aliases as values) + */ + private Map<String, Map<String, Collection<String>>> aliasMapsMap; private final AtomicLong aliasResourcesOnStartup; @@ -159,7 +163,6 @@ public class MapEntries implements private final StringInterpolationProvider stringInterpolationProvider; private final boolean useOptimizeAliasResolution; - public MapEntries(final MapConfigurationProvider factory, final BundleContext bundleContext, final EventAdmin eventAdmin, @@ -174,7 +177,7 @@ public class MapEntries implements this.resolveMapsMap = Collections.singletonMap(GLOBAL_LIST_KEY, Collections.emptyList()); this.mapMaps = Collections.<MapEntry> emptyList(); this.vanityTargets = Collections.<String,List <String>>emptyMap(); - this.aliasMap = Collections.<String, Map<String, String>>emptyMap(); + this.aliasMapsMap = new ConcurrentHashMap<>(); this.stringInterpolationProvider = stringInterpolationProvider; this.aliasResourcesOnStartup = new AtomicLong(0); @@ -197,7 +200,7 @@ public class MapEntries implements this.metrics.get().setNumberOfVanityPathLookupsSupplier(vanityPathLookups::get); this.metrics.get().setNumberOfVanityPathBloomNegativeSupplier(vanityPathBloomNegative::get); this.metrics.get().setNumberOfVanityPathBloomFalsePositiveSupplier(vanityPathBloomFalsePositive::get); - this.metrics.get().setNumberOfResourcesWithAliasedChildrenSupplier(() -> (long) aliasMap.size()); + this.metrics.get().setNumberOfResourcesWithAliasedChildrenSupplier(() -> (long) aliasMapsMap.size()); this.metrics.get().setNumberOfResourcesWithAliasesOnStartupSupplier(aliasResourcesOnStartup::get); } } @@ -237,8 +240,8 @@ public class MapEntries implements //optimization made in SLING-2521 if (isOptimizeAliasResolutionEnabled) { try { - final Map<String, Map<String, String>> loadedMap = this.loadAliases(resolver); - this.aliasMap = loadedMap; + final Map<String, Map<String, Collection<String>>> loadedMap = this.loadAliases(resolver); + this.aliasMapsMap = loadedMap; } catch (final Exception e) { @@ -430,7 +433,7 @@ public class MapEntries implements } if (this.useOptimizeAliasResolution) { final String pathPrefix = path + "/"; - for (final String contentPath : this.aliasMap.keySet()) { + for (final String contentPath : this.aliasMapsMap.keySet()) { if (path.startsWith(contentPath + "/") || path.equals(contentPath) || contentPath.startsWith(pathPrefix)) { changed |= removeAlias(contentPath, path, resolverRefreshed); @@ -451,7 +454,7 @@ public class MapEntries implements // a direct child of vanity path but not jcr:content, or a jcr:content child of a direct child // otherwise we can discard the event boolean handle = true; - String resourcePath = null; + final String resourcePath; if ( path != null && path.length() > contentPath.length()) { final String subPath = path.substring(contentPath.length() + 1); final int firstSlash = subPath.indexOf('/'); @@ -467,6 +470,7 @@ public class MapEntries implements resourcePath = ResourceUtil.getParent(path); } else { handle = false; + resourcePath = null; } } else { @@ -478,20 +482,13 @@ public class MapEntries implements this.initializing.lock(); try { - final Map<String, String> aliasMapEntry = aliasMap.get(contentPath); + final Map<String, Collection<String>> aliasMapEntry = aliasMapsMap.get(contentPath); if (aliasMapEntry != null) { this.refreshResolverIfNecessary(resolverRefreshed); - for (Iterator<Map.Entry<String, String>> iterator = aliasMapEntry.entrySet().iterator(); iterator.hasNext(); ) { - final Map.Entry<String, String> entry = iterator.next(); - String prefix = contentPath.endsWith("/") ? contentPath : contentPath + "/"; - if ((prefix + entry.getValue()).startsWith(resourcePath)){ - iterator.remove(); - } - } - - if (aliasMapEntry.isEmpty()) { - this.aliasMap.remove(contentPath); + String prefix = contentPath.endsWith("/") ? contentPath : contentPath + "/"; + if (aliasMapEntry.entrySet().removeIf(e -> (prefix + e.getKey()).startsWith(resourcePath)) && (aliasMapEntry.isEmpty())) { + this.aliasMapsMap.remove(contentPath); } Resource containingResource = this.resolver != null ? this.resolver.getResource(resourcePath) : null; @@ -575,7 +572,7 @@ public class MapEntries implements } private boolean doAddAlias(final Resource resource) { - return loadAlias(resource, this.aliasMap); + return loadAlias(resource, this.aliasMapsMap); } /** @@ -595,20 +592,14 @@ public class MapEntries implements final String containingResourceName = containingResource.getName(); final String parentPath = ResourceUtil.getParent(containingResource.getPath()); - final Map<String, String> aliasMapEntry = parentPath == null ? null : aliasMap.get(parentPath); + final Map<String, Collection<String>> aliasMapEntry = parentPath == null ? null : aliasMapsMap.get(parentPath); if (aliasMapEntry != null) { - for (Iterator<Map.Entry<String, String>> iterator = aliasMapEntry.entrySet().iterator(); iterator.hasNext(); ) { - final Map.Entry<String, String> entry = iterator.next(); - if (containingResourceName.equals(entry.getValue())){ - iterator.remove(); - } + aliasMapEntry.remove(containingResourceName); + if (aliasMapEntry.isEmpty()) { + this.aliasMapsMap.remove(parentPath); } } - if (aliasMapEntry != null && aliasMapEntry.isEmpty()) { - this.aliasMap.remove(parentPath); - } - boolean changed = aliasMapEntry != null; if ( containingResource.getValueMap().containsKey(ResourceResolverImpl.PROP_ALIAS) ) { @@ -710,8 +701,9 @@ public class MapEntries implements } @Override - public Map<String, String> getAliasMap(final String parentPath) { - return aliasMap.get(parentPath); + public @NotNull Map<String, Collection<String>> getAliasMap(final String parentPath) { + Map<String, Collection<String>> aliasMapForParent = aliasMapsMap.get(parentPath); + return aliasMapForParent != null ? aliasMapForParent : Collections.emptyMap(); } @Override @@ -1156,8 +1148,8 @@ public class MapEntries implements * Load aliases - Search for all nodes (except under /jcr:system) below * configured alias locations having the sling:alias property */ - private Map<String, Map<String, String>> loadAliases(final ResourceResolver resolver) { - final Map<String, Map<String, String>> map = new ConcurrentHashMap<>(); + private Map<String, Map<String, Collection<String>>> loadAliases(final ResourceResolver resolver) { + final Map<String, Map<String, Collection<String>>> map = new ConcurrentHashMap<>(); final String queryString = generateAliasQuery(); log.debug("start alias query: {}", queryString); @@ -1211,7 +1203,7 @@ public class MapEntries implements /** * Load alias given a resource */ - private boolean loadAlias(final Resource resource, Map<String, Map<String, String>> map) { + private boolean loadAlias(final Resource resource, Map<String, Map<String, Collection<String>>> map) { // resource containing the alias final Resource containingResource; @@ -1243,24 +1235,23 @@ public class MapEntries implements if (aliasArray != null) { log.debug("Found alias, total size {}", aliasArray.length); + // the order matters here, the first alias in the array must come first for (final String alias : aliasArray) { if (isAliasValid(alias)) { log.warn("Encountered invalid alias {} under parent path {}. Refusing to use it.", alias, parentPath); } else { - Map<String, String> parentMap = map.get(parentPath); - - if (parentMap == null) { - parentMap = new LinkedHashMap<>(); - map.put(parentPath, parentMap); - } - - String current = parentMap.get(alias); - if (current != null) { + Map<String, Collection<String>> parentMap = map.computeIfAbsent(parentPath, key -> new ConcurrentHashMap<>()); + Optional<String> siblingResourceNameWithDuplicateAlias = parentMap.entrySet().stream() + .filter(entry -> !entry.getKey().equals(resourceName)) // ignore entry for the current resource + .filter(entry -> entry.getValue().contains(alias)) + .findFirst().map(Map.Entry::getKey); + if (siblingResourceNameWithDuplicateAlias.isPresent()) { log.warn( "Encountered duplicate alias {} under parent path {}. Refusing to replace current target {} with {}.", - alias, parentPath, current, resourceName); + alias, parentPath, siblingResourceNameWithDuplicateAlias.get(), resourceName); } else { - parentMap.put(alias, resourceName); + Collection<String> existingAliases = parentMap.computeIfAbsent(resourceName, name -> new CopyOnWriteArrayList<>()); + existingAliases.add(alias); hasAlias = true; } } diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesHandler.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesHandler.java index a32a457..78e3024 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesHandler.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesHandler.java @@ -57,7 +57,7 @@ public interface MapEntriesHandler { } @Override - public Map<String, String> getAliasMap(String parentPath) { + public Map<String, Collection<String>> getAliasMap(String parentPath) { return Collections.emptyMap(); } @@ -89,14 +89,14 @@ public interface MapEntriesHandler { void logDisableAliasOptimization(); /** - * Returns all alias entries that for children of the specified <code>parentPath</code> + * Returns all alias entries for children of the specified <code>parentPath</code> * - * <p>The returned map has resource names as keys and aliases as values.</p> + * <p>The returned map has resource names as keys and the assigned aliases as values.</p> * * @param parentPath the parent path * @return a map of all child alias entries, possibly empty */ - @NotNull Map<String, String> getAliasMap(@NotNull String parentPath); + @NotNull Map<String, Collection<String>> getAliasMap(@NotNull String parentPath); /** * Creates an iterator over the possibly applicable mapping entries for resolving a resource diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PathGenerator.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PathGenerator.java index 0d61e1a..a3bcd3d 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PathGenerator.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PathGenerator.java @@ -19,6 +19,7 @@ package org.apache.sling.resourceresolver.impl.mapping; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -74,7 +75,7 @@ public class PathGenerator { * @param alias the list of aliases * @param name the name */ - public void insertSegment(@NotNull List<String> alias, @NotNull String name) { + public void insertSegment(@NotNull Collection<String> alias, @NotNull String name) { List<String> filtered = Stream.concat(alias.stream(), Stream.of(name) ) .filter( e -> e != null && ! e.isEmpty() ) diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/ResourceMapperImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/ResourceMapperImpl.java index f1e3dcb..4a1da82 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/ResourceMapperImpl.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/ResourceMapperImpl.java @@ -24,10 +24,7 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.function.UnaryOperator; -import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; @@ -223,7 +220,7 @@ public class ResourceMapperImpl implements ResourceMapper { if (this.mapEntries.isOptimizeAliasResolutionEnabled()) { // this code path avoids any creation of Sling Resource objects while (path != null) { - List<String> aliases = Collections.emptyList(); + Collection<String> aliases = Collections.emptyList(); // read alias only if we can read the resources and it's not a jcr:content leaf if (!path.endsWith(ResourceResolverImpl.JCR_CONTENT_LEAF)) { aliases = readAliasesOptimized(path); @@ -278,7 +275,7 @@ public class ResourceMapperImpl implements ResourceMapper { * @param path * @return */ - private List<String> readAliasesOptimized(String path) { + private Collection<String> readAliasesOptimized(String path) { logger.debug("map: Optimize Alias Resolution is Enabled"); String parentPath = ResourceUtil.getParent(path); if ( parentPath == null ) { @@ -286,16 +283,7 @@ public class ResourceMapperImpl implements ResourceMapper { } String name = ResourceUtil.getName(path); - final Map<String, String> aliases = mapEntries.getAliasMap(parentPath); - - if ( aliases == null || !aliases.containsValue(name) ) - return Collections.emptyList(); - - return aliases.entrySet().stream() - .filter( e -> name.contentEquals(e.getValue()) ) - .map( Entry::getKey ) - .collect(Collectors.toList()); - + return mapEntries.getAliasMap(parentPath).getOrDefault(name, Collections.emptyList()); } private void populateMappingsFromMapEntries(List<String> mappings, List<String> mappedPathList, diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AbstractMappingMapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AbstractMappingMapEntriesTest.java index fd66d0e..ce65917 100644 --- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AbstractMappingMapEntriesTest.java +++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AbstractMappingMapEntriesTest.java @@ -120,7 +120,7 @@ public abstract class AbstractMappingMapEntriesTest { setupStringInterpolationProvider(stringInterpolationProvider, stringInterpolationProviderConfiguration, new String[] {}); mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider, metrics); - final Field aliasMapField = MapEntries.class.getDeclaredField("aliasMap"); + final Field aliasMapField = MapEntries.class.getDeclaredField("aliasMapsMap"); aliasMapField.setAccessible(true); this.aliasMap = ( Map<String, Map<String, String>>) aliasMapField.get(mapEntries); } diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java index fc8ec76..f5d842a 100644 --- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java +++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java @@ -161,8 +161,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { Optional<ResourceResolverMetrics> metrics = Optional.empty(); - mapEntries = Mockito.spy(new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider, metrics)); - final Field aliasMapField = MapEntries.class.getDeclaredField("aliasMap"); + mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider, metrics); + final Field aliasMapField = MapEntries.class.getDeclaredField("aliasMapsMap"); aliasMapField.setAccessible(true); this.aliasMap = ( Map<String, Map<String, String>>) aliasMapField.get(mapEntries); @@ -201,10 +201,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { mapEntries.doInit(); - Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); + Map<String, Collection<String>> aliasMap = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMap); - assertTrue(aliasMap.containsKey("alias")); - assertEquals("child", aliasMap.get("alias")); + assertTrue(aliasMap.containsKey("child")); + assertEquals(Collections.singletonList("alias"), aliasMap.get("child")); } @Test @@ -238,10 +238,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { mapEntries.doInit(); - Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); + Map<String, Collection<String>> aliasMap = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMap); - assertTrue(aliasMap.containsKey("alias")); - assertEquals("child", aliasMap.get("alias")); + assertTrue(aliasMap.containsKey("child")); + assertEquals(Collections.singletonList("alias"), aliasMap.get("child")); } @Test @@ -936,8 +936,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); - Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); - assertNull(aliasMap); + Map<String, Collection<String>> aliasMap = mapEntries.getAliasMap("/parent"); + assertNotNull(aliasMap); } //SLING-3727 @@ -961,8 +961,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); - Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); - assertNull(aliasMap); + Map<String, Collection<String>> aliasMap = mapEntries.getAliasMap("/parent"); + assertEquals(Collections.emptyMap(), aliasMap); } //SLING-3727 @@ -986,8 +986,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); - Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); - assertNull(aliasMap); + Map<String, Collection<String>> aliasMap = mapEntries.getAliasMap("/parent"); + assertEquals(Collections.emptyMap(), aliasMap); } @Test @@ -1009,10 +1009,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("child", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(Collections.singletonList("alias"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1028,8 +1028,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("child", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(Collections.singletonList("alias"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1045,9 +1045,9 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertEquals(2, aliasMapEntry.size()); - assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); + assertEquals(1, aliasMapEntry.size()); // only 2 aliases for 1 child resource + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("alias","aliasJcrContent"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); } @@ -1071,10 +1071,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, "/parent", new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("parent", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("parent")); + assertEquals(Collections.singletonList("alias"), aliasMapEntry.get("parent")); assertEquals(1, aliasMap.size()); @@ -1090,8 +1090,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("parent", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("parent")); + assertEquals(Collections.singletonList("alias"), aliasMapEntry.get("parent")); assertEquals(1, aliasMap.size()); @@ -1107,9 +1107,9 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/"); assertNotNull(aliasMapEntry); - assertEquals(2, aliasMapEntry.size()); - assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); - assertEquals("parent", aliasMapEntry.get("aliasJcrContent")); + assertEquals(1, aliasMapEntry.size()); + assertTrue(aliasMapEntry.containsKey("parent")); + assertEquals(List.of("alias","aliasJcrContent"), aliasMapEntry.get("parent")); assertEquals(1, aliasMap.size()); @@ -1125,8 +1125,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("parent", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("parent")); + assertEquals(List.of("alias", "aliasJcrContent"), aliasMapEntry.get("parent")); assertEquals(1, aliasMap.size()); } @@ -1150,11 +1150,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { updateResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertFalse(aliasMapEntry.containsKey("aliasUpdated")); - assertEquals("child", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("alias"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1164,9 +1163,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertFalse(aliasMapEntry.containsKey("alias")); - assertTrue(aliasMapEntry.containsKey("aliasUpdated")); - assertEquals("child", aliasMapEntry.get("aliasUpdated")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasUpdated"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1183,10 +1181,9 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertEquals(2, aliasMapEntry.size()); - assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); - assertFalse(aliasMapEntry.containsKey("aliasJcrContentUpdated")); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); + assertEquals(1, aliasMapEntry.size()); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasUpdated","aliasJcrContent"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1195,10 +1192,9 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertEquals(2, aliasMapEntry.size()); - assertFalse(aliasMapEntry.containsKey("aliasJcrContent")); - assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated")); - assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated")); + assertEquals(1, aliasMapEntry.size()); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasUpdated", "aliasJcrContentUpdated"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1207,10 +1203,9 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertEquals(2, aliasMapEntry.size()); - assertFalse(aliasMapEntry.containsKey("alias")); - assertTrue(aliasMapEntry.containsKey("aliasUpdated")); - assertEquals("child", aliasMapEntry.get("aliasUpdated")); + assertEquals(1, aliasMapEntry.size()); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasUpdated","aliasJcrContentUpdated"), aliasMapEntry.get("child")); //add another node with different alias and check that the update doesn't break anything (see also SLING-3728) final Resource secondResult = mock(Resource.class); @@ -1225,17 +1220,16 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertEquals(3, aliasMapEntry.size()); + assertEquals(2, aliasMapEntry.size()); when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContentUpdated")); updateResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertEquals(3, aliasMapEntry.size()); - assertFalse(aliasMapEntry.containsKey("aliasJcrContent")); - assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated")); - assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated")); + assertEquals(2, aliasMapEntry.size()); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasUpdated","aliasJcrContentUpdated"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1247,9 +1241,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); assertEquals(2, aliasMapEntry.size()); - assertFalse(aliasMapEntry.containsKey("aliasJcrContent")); - assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated")); - assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasJcrContentUpdated"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1278,10 +1271,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("child", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("alias"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1289,7 +1282,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/parent"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); assertEquals(0, aliasMap.size()); @@ -1299,8 +1292,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("child", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("alias"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1308,7 +1301,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/parent"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); assertEquals(0, aliasMap.size()); } @@ -1344,10 +1337,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasJcrContent"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); @@ -1356,7 +1349,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/parent"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); assertEquals(0, aliasMap.size()); @@ -1367,8 +1360,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasJcrContent"), aliasMapEntry.get("child")); assertEquals(1, aliasMap.size()); when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null); @@ -1376,11 +1369,12 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/parent"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); assertEquals(0, aliasMap.size()); } + @Test public void test_doRemoveAlias3() throws Exception { final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); @@ -1415,11 +1409,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { // test with two nodes assertEquals(1, aliasMap.size()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertEquals(2, aliasMapEntry.size()); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); - assertEquals("child", aliasMapEntry.get("alias")); + assertEquals(1, aliasMapEntry.size()); + assertEquals(List.of("alias", "aliasJcrContent"), aliasMapEntry.get("child")); // remove child jcr:content node when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null); @@ -1431,7 +1424,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); assertEquals(1, aliasMapEntry.size()); - assertEquals("child", aliasMapEntry.get("alias")); + assertEquals(List.of("alias"), aliasMapEntry.get("child")); // re-add the node and test /parent/child when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult); @@ -1441,9 +1434,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { // STOP aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertEquals(2, aliasMapEntry.size()); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); - assertEquals("child", aliasMapEntry.get("alias")); + assertEquals(1, aliasMapEntry.size()); + assertEquals(List.of("alias", "aliasJcrContent"), aliasMapEntry.get("child")); when(resourceResolver.getResource("/parent/child")).thenReturn(null); removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); @@ -1454,16 +1446,16 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); assertEquals(1, aliasMapEntry.size()); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); + assertEquals(List.of("aliasJcrContent"), aliasMapEntry.get("child")); // re-add the node and test node removal addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); - assertEquals(2, aliasMapEntry.size()); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("aliasJcrContent", "alias"), aliasMapEntry.get("child")); + assertEquals(1, aliasMapEntry.size()); when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null); when(childRsrc.getChild("jcr:content")).thenReturn(null); @@ -1482,16 +1474,16 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); - assertEquals("child", aliasMapEntry.get("aliasJcrContent")); - assertEquals(2, aliasMapEntry.size()); + assertTrue(aliasMapEntry.containsKey("child")); + assertEquals(List.of("alias","aliasJcrContent"), aliasMapEntry.get("child")); + assertEquals(1, aliasMapEntry.size()); when(resourceResolver.getResource("/parent/child")).thenReturn( null); removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); assertEquals(0, aliasMap.size()); aliasMapEntry = mapEntries.getAliasMap("/parent"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); } @Test @@ -1516,10 +1508,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, "/parent", new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("parent", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("parent")); + assertEquals(List.of("alias"), aliasMapEntry.get("parent")); assertEquals(1, aliasMap.size()); @@ -1527,7 +1519,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeAlias.invoke(mapEntries, "/", "/parent", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); assertEquals(0, aliasMap.size()); @@ -1537,8 +1529,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("alias")); - assertEquals("parent", aliasMapEntry.get("alias")); + assertTrue(aliasMapEntry.containsKey("parent")); + assertEquals(List.of("alias"), aliasMapEntry.get("parent")); assertEquals(1, aliasMap.size()); @@ -1546,7 +1538,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeAlias.invoke(mapEntries, "/", "/parent", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); assertEquals(0, aliasMap.size()); } @@ -1582,10 +1574,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, "/parent/jcr:content", new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); - assertEquals("parent", aliasMapEntry.get("aliasJcrContent")); + assertTrue(aliasMapEntry.containsKey("parent")); + assertEquals(List.of("aliasJcrContent"), aliasMapEntry.get("parent")); assertEquals(1, aliasMap.size()); @@ -1594,7 +1586,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeAlias.invoke(mapEntries, "/", "/parent/jcr:content", new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); assertEquals(0, aliasMap.size()); } @@ -1659,11 +1651,11 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, grandChildJcrContent.getPath(), new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent/container/childContainer"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/parent/container/childContainer"); assertNotNull(aliasMapEntry); assertEquals(1, aliasMapEntry.size()); - assertTrue(aliasMapEntry.containsKey("gc")); - assertEquals("grandChild", aliasMapEntry.get("gc")); + assertTrue(aliasMapEntry.containsKey("grandChild")); + assertEquals(List.of("gc"), aliasMapEntry.get("grandChild")); // delete the jcr:content present in a parent path @@ -1674,8 +1666,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent/container/childContainer"); assertNotNull(aliasMapEntry); assertEquals(1, aliasMapEntry.size()); - assertTrue(aliasMapEntry.containsKey("gc")); - assertEquals("grandChild", aliasMapEntry.get("gc")); + assertTrue(aliasMapEntry.containsKey("grandChild")); + assertEquals(List.of("gc"), aliasMapEntry.get("grandChild")); } @@ -1717,10 +1709,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { addResource.invoke(mapEntries, child1JcrContent.getPath(), new AtomicBoolean()); - Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); + Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("test1")); - assertEquals("child1", aliasMapEntry.get("test1")); + assertTrue(aliasMapEntry.containsKey("child1")); + assertEquals(List.of("test1"), aliasMapEntry.get("child1")); assertEquals(1, aliasMap.size()); @@ -1745,10 +1737,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("test1")); - assertTrue(aliasMapEntry.containsKey("test2")); - assertEquals("child1", aliasMapEntry.get("test1")); - assertEquals("child2", aliasMapEntry.get("test2")); + assertTrue(aliasMapEntry.containsKey("child1")); + assertTrue(aliasMapEntry.containsKey("child2")); + assertEquals(List.of("test1"), aliasMapEntry.get("child1")); + assertEquals(List.of("test2"), aliasMapEntry.get("child2")); assertEquals(1, aliasMap.size()); @@ -1765,10 +1757,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("test1")); - assertTrue(aliasMapEntry.containsKey("test2")); - assertEquals("child1", aliasMapEntry.get("test1")); - assertEquals("child2", aliasMapEntry.get("test2")); + assertTrue(aliasMapEntry.containsKey("child1")); + assertTrue(aliasMapEntry.containsKey("child2")); + assertEquals(List.of("test1"), aliasMapEntry.get("child1")); + assertEquals(List.of("test2"), aliasMapEntry.get("child2")); assertEquals(1, aliasMap.size()); @@ -1780,8 +1772,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("test1")); - assertEquals("child1", aliasMapEntry.get("test1")); + assertTrue(aliasMapEntry.containsKey("child1")); + assertEquals(List.of("test1"), aliasMapEntry.get("child1")); assertEquals(1, aliasMap.size()); @@ -1792,7 +1784,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { removeResource.invoke(mapEntries, child1JcrContent.getPath(), new AtomicBoolean()); aliasMapEntry = mapEntries.getAliasMap("/parent"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); when(child1.getChild("jcr:content")).thenReturn(child1JcrContent); addResource.invoke(mapEntries, child1JcrContent.getPath(), new AtomicBoolean()); @@ -1801,10 +1793,10 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); assertNotNull(aliasMapEntry); - assertTrue(aliasMapEntry.containsKey("test1")); - assertTrue(aliasMapEntry.containsKey("test2")); - assertEquals("child1", aliasMapEntry.get("test1")); - assertEquals("child2", aliasMapEntry.get("test2")); + assertTrue(aliasMapEntry.containsKey("child1")); + assertTrue(aliasMapEntry.containsKey("child2")); + assertEquals(List.of("test1"), aliasMapEntry.get("child1")); + assertEquals(List.of("test2"), aliasMapEntry.get("child2")); assertEquals(1, aliasMap.size()); @@ -1814,7 +1806,7 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest { aliasMapEntry = mapEntries.getAliasMap("/parent"); - assertNull(aliasMapEntry); + assertEquals(Collections.emptyMap(), aliasMapEntry); } @Test