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

joerghoh pushed a commit to branch SLING-12471
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly.git

commit 6141d6aca20f07adadc3eae2489eb512d87dffc1
Author: Joerg Hoh <[email protected]>
AuthorDate: Tue Nov 5 17:39:16 2024 +0100

    SLING-12471 add test case to provoke the situation
---
 .../ScriptDependencyResolverConcurrentTest.java    | 131 +++++++++++++++++++++
 1 file changed, 131 insertions(+)

diff --git 
a/src/test/java/org/apache/sling/scripting/sightly/impl/utils/ScriptDependencyResolverConcurrentTest.java
 
b/src/test/java/org/apache/sling/scripting/sightly/impl/utils/ScriptDependencyResolverConcurrentTest.java
new file mode 100644
index 0000000..01345d6
--- /dev/null
+++ 
b/src/test/java/org/apache/sling/scripting/sightly/impl/utils/ScriptDependencyResolverConcurrentTest.java
@@ -0,0 +1,131 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements.  See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership.  The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License.  You may obtain a copy of the License at
+ ~
+ ~   http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied.  See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.scripting.sightly.impl.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import javax.script.Bindings;
+
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.scripting.SlingBindings;
+import 
org.apache.sling.scripting.api.resource.ScriptingResourceResolverProvider;
+import 
org.apache.sling.scripting.sightly.impl.engine.SightlyEngineConfiguration;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+
+@RunWith(Parameterized.class)
+public class ScriptDependencyResolverConcurrentTest {
+    
+    @Parameterized.Parameters
+    public static Object[] data() {
+        return new Object[20][0];
+    }
+    
+    
+
+    @Rule
+    public SlingContext context = new SlingContext();
+
+    @Before
+    public void before() throws PersistenceException {
+        // resource hierarchy
+        ResourceUtil.getOrCreateResource(context.resourceResolver(), 
"/apps/base/partial.html", "nt:file", "sling:Folder", true);
+        ResourceUtil.getOrCreateResource(context.resourceResolver(), 
"/apps/inherit/inherit.html", "nt:file", "sling:Folder", true);
+        Resource inherit = 
context.resourceResolver().getResource("/apps/inherit");
+        assertNotNull(inherit);
+        ModifiableValueMap inheritProperties = 
inherit.adaptTo(ModifiableValueMap.class);
+        assertNotNull(inheritProperties);
+        inheritProperties.put("sling:resourceSuperType", "base");
+        context.resourceResolver().commit();
+
+        Map<String, Object> testResourceProperties = new HashMap<>();
+        testResourceProperties.put("sling:resourceType", "inherit");
+        ResourceUtil.getOrCreateResource(context.resourceResolver(), 
"/content/test", testResourceProperties, "sling:Folder", true);
+        
context.request().setResource(context.resourceResolver().getResource("/content/test"));
+    }
+
+    @Test
+    public void 
testDependenciesResolvingCacheEnabledConcurren_neverReturnsNull() throws 
InterruptedException, ExecutionException  {
+        SightlyEngineConfiguration configuration = 
mock(SightlyEngineConfiguration.class);
+        when(configuration.getScriptResolutionCacheSize()).thenReturn(1024);
+        context.registerService(configuration);
+
+        ResourceResolver scriptingResolver = spy(context.resourceResolver());
+
+        ScriptingResourceResolverProvider scriptingResourceResolverProvider =
+                mock(ScriptingResourceResolverProvider.class);
+        
when(scriptingResourceResolverProvider.getRequestScopedResourceResolver()).thenReturn(scriptingResolver);
+        context.registerService(ScriptingResourceResolverProvider.class, 
scriptingResourceResolverProvider);
+
+        ScriptDependencyResolver scriptDependencyResolver = 
spy(context.registerInjectActivateService(new ScriptDependencyResolver()));
+
+        RenderContext renderContext = mock(RenderContext.class);
+        Bindings bindings = mock(Bindings.class);
+        when(renderContext.getBindings()).thenReturn(bindings);
+        
when(bindings.get(SlingBindings.REQUEST)).thenReturn(context.request());
+        
+        // invoke resolveScript with the same identifier
+        int size = 100;
+        ExecutorService executor = Executors.newFixedThreadPool(size);
+
+        try {
+            List<Future<Resource>> resolutionValues = new ArrayList<>();
+            for (int i = 0; i < size; i++) {
+                resolutionValues.add(executor.submit(() -> {
+                    return 
scriptDependencyResolver.resolveScript(renderContext, "partial.html");
+                }));
+            }
+            int nullValues = 0;
+            for (Future<Resource> v : resolutionValues) {
+                Resource r = v.get();
+                if (r == null) {
+                    nullValues++;
+                }
+            }
+            assertEquals("resolveScript must never return null here",0, 
nullValues);
+        } finally { 
+            executor.shutdown();
+        }
+
+    }
+
+}

Reply via email to