SLING-4058 - more specific MappingEventsTest added
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1634552 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/MappingEventsTest.java b/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/MappingEventsTest.java
new file mode 100644
index 0000000..2784779
--- /dev/null
+++ b/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/MappingEventsTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.launchpad.testservices.serversidetests;
+
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.junit.annotations.SlingAnnotationsTestRunner;
+import org.apache.sling.junit.annotations.TestReference;
+import org.apache.sling.launchpad.testservices.events.EventsCounter;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@RunWith(SlingAnnotationsTestRunner.class)
+public class MappingEventsTest {
+
+ public static final String PROP_REDIRECT_EXTERNAL = "sling:redirect";
+
+ private static final Logger logger = LoggerFactory.getLogger(MappingEventsTest.class);
+ private static Session session;
+ private Node mapRoot;
+ private static List<String> toDelete = new ArrayList<String>();
+
+ @TestReference
+ private EventsCounter eventsCounter;
+
+ @TestReference
+ private SlingRepository repository;
+
+ private Node maybeCreateNode(Node parent, String name, String type) throws RepositoryException {
+ if(parent.hasNode(name)) {
+ return parent.getNode(name);
+ } else {
+ return parent.addNode(name, type);
+ }
+ }
+
+ @Before
+ public synchronized void setup() throws Exception {
+ // Do the mappings setup only once, and clean it up
+ // after all tests
+ session = repository.loginAdministrative(null);
+ final Node rootNode = maybeCreateNode(session.getRootNode(), "content", "nt:unstructured");
+ session.save();
+ if(toDelete.isEmpty()) {
+ final Node mapRoot = maybeCreateNode(session.getRootNode(), "etc", "nt:folder");
+ final Node map = maybeCreateNode(mapRoot, "map", "sling:Mapping");
+ final Node http = maybeCreateNode(map, "http", "sling:Mapping");
+ maybeCreateNode(http, "localhost.80", "sling:Mapping");
+ final Node https = maybeCreateNode(map, "https", "sling:Mapping");
+ maybeCreateNode(https, "localhost.443", "sling:Mapping");
+ toDelete.add(map.getPath());
+ toDelete.add(rootNode.getPath());
+ }
+
+ mapRoot = session.getNode("/etc");
+ }
+
+ @AfterClass
+ public static void deleteTestNodes() throws Exception {
+ logger.debug("{} test done, deleting test nodes", MappingEventsTest.class.getSimpleName());
+
+ try {
+ for(String path : toDelete) {
+ if(session.itemExists(path)) {
+ session.getItem(path).remove();
+ }
+ }
+ toDelete.clear();
+ session.save();
+ } finally {
+ session.logout();
+ }
+ }
+
+ /** Test SLING-4058 - unexpected timeouts in saveMappings */
+ @Test public void testSaveMappings() throws Exception {
+ final Node base = mapRoot.getNode("map/https/localhost.443");
+ final MappingsFacade f = new MappingsFacade(eventsCounter);
+ try {
+ int count = 20;
+ while(count-- > 0) {
+ base.setProperty(PROP_REDIRECT_EXTERNAL,"http://somehost." + count);
+ final String result = f.saveMappings(session);
+ if(result != null) {
+ fail(result);
+ }
+ }
+ } finally {
+ base.setProperty(PROP_REDIRECT_EXTERNAL,"");
+ session.save();
+ }
+ }
+}
diff --git a/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/MappingsFacade.java b/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/MappingsFacade.java
new file mode 100644
index 0000000..9ee3f6e
--- /dev/null
+++ b/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/MappingsFacade.java
@@ -0,0 +1,64 @@
+/*
+ * 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.launchpad.testservices.serversidetests;
+
+import javax.jcr.Session;
+
+import org.apache.sling.launchpad.testservices.events.EventsCounter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Facade for saving mappings and waiting for the corresponding events */
+public class MappingsFacade {
+
+ public static final String MAPPING_EVENT_TOPIC = "org/apache/sling/api/resource/ResourceResolverMapping/CHANGED";
+ private static final Logger logger = LoggerFactory.getLogger(MappingsFacade.class);
+ private final EventsCounter eventsCounter;
+
+ // How long to wait for mapping updates
+ public static final String MAPPING_UPDATE_TIMEOUT_MSEC = "ResourceResolverTest.mapping.update.timeout.msec";
+ private static final long updateTimeout = Long.valueOf(System.getProperty(MAPPING_UPDATE_TIMEOUT_MSEC, "10000"));
+
+ public MappingsFacade(EventsCounter c) {
+ logger.info("updateTimeout = {}, use {} system property to change", updateTimeout, MAPPING_UPDATE_TIMEOUT_MSEC);
+ eventsCounter = c;
+ }
+
+ /** Save a Session that has mapping changes, and wait for the OSGi event
+ * that signals that mappings have been updated.
+ * @return error message, null if ok
+ */
+ public String saveMappings(Session session) throws Exception {
+ final int oldEventsCount = eventsCounter.getEventsCount(MAPPING_EVENT_TOPIC);
+ logger.debug("Saving Session and waiting for event counter {} to change from current value {}", MAPPING_EVENT_TOPIC, oldEventsCount);
+ session.save();
+ final long timeout = System.currentTimeMillis() + updateTimeout;
+ while(System.currentTimeMillis() < timeout) {
+ if(eventsCounter.getEventsCount(MAPPING_EVENT_TOPIC) != oldEventsCount) {
+ // Sleeping here shouldn't be needed but it looks
+ // like mappings are not immediately updated once the event arrives
+ Thread.sleep(updateTimeout / 50);
+ return null;
+ }
+ try {
+ Thread.sleep(10);
+ } catch(InterruptedException ignore) {
+ }
+ }
+ return "Timeout waiting for " + MAPPING_EVENT_TOPIC + " event, after " + updateTimeout + " msec";
+ }
+}
diff --git a/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/ResourceResolverTest.java b/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/ResourceResolverTest.java
index b2d0f11..906573b 100644
--- a/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/ResourceResolverTest.java
+++ b/src/main/java/org/apache/sling/launchpad/testservices/serversidetests/ResourceResolverTest.java
@@ -70,7 +70,8 @@
private String [] vanity;
private static List<String> toDelete = new ArrayList<String>();
private static ResourceResolverFactory cleanupResolverFactory;
- private static String eventTimeoutTopic;
+ private MappingsFacade mappingsFacade;
+ private static String saveMappingsError;
@TestReference
private EventsCounter eventsCounter;
@@ -78,44 +79,6 @@
@TestReference
private ResourceResolverFactory resourceResolverFactory;
- // How long to wait for mapping updates
- public static final String MAPPING_UPDATE_TIMEOUT_MSEC = "ResourceResolverTest.mapping.update.timeout.msec";
- private static final long updateTimeout = Long.valueOf(System.getProperty(MAPPING_UPDATE_TIMEOUT_MSEC, "10000"));
-
- public ResourceResolverTest() throws Exception {
- logger.info("updateTimeout = {}, use {} system property to change", updateTimeout, MAPPING_UPDATE_TIMEOUT_MSEC);
- }
-
- /** Save a Session that has mapping changes, and wait for the OSGi event
- * that signals that mappings have been updated.
- */
- private void saveMappings(Session session) throws Exception {
- if(eventTimeoutTopic != null) {
- // Avoid wasting a lot of time if events are not detected in timely fashion
- fail("Event timeout (" + eventTimeoutTopic + ") detected in previous tests, failing saveMappings()");
- }
-
- final int oldEventsCount = eventsCounter.getEventsCount(MAPPING_EVENT_TOPIC);
- logger.debug("Saving Session and waiting for event counter {} to change from current value {}", MAPPING_EVENT_TOPIC, oldEventsCount);
- session.save();
- final long timeout = System.currentTimeMillis() + updateTimeout;
- while(System.currentTimeMillis() < timeout) {
- if(eventsCounter.getEventsCount(MAPPING_EVENT_TOPIC) != oldEventsCount) {
- // Sleeping here shouldn't be needed but it looks
- // like mappings are not immediately updated once the event arrives
- Thread.sleep(updateTimeout / 50);
- return;
- }
- try {
- Thread.sleep(10);
- } catch(InterruptedException ignore) {
- }
- }
- eventTimeoutTopic = MAPPING_EVENT_TOPIC;
- logger.error("Timeout waiting for event counter {} to change from current value {}", MAPPING_EVENT_TOPIC, oldEventsCount);
- fail("Timeout waiting for " + MAPPING_EVENT_TOPIC + " event, after " + updateTimeout + " msec");
- }
-
private Node maybeCreateNode(Node parent, String name, String type) throws RepositoryException {
if(parent.hasNode(name)) {
return parent.getNode(name);
@@ -123,6 +86,20 @@
return parent.addNode(name, type);
}
}
+
+ private void saveMappings(Session s) throws Exception {
+ if(mappingsFacade == null) {
+ mappingsFacade = new MappingsFacade(eventsCounter);
+ }
+ if(saveMappingsError != null) {
+ fail(saveMappingsError);
+ } else {
+ saveMappingsError = mappingsFacade.saveMappings(s);
+ if(saveMappingsError != null) {
+ fail(saveMappingsError);
+ }
+ }
+ }
@Before
public synchronized void setup() throws Exception {
@@ -173,7 +150,7 @@
@AfterClass
@BeforeClass
public static void clearTimeouts() {
- eventTimeoutTopic = null;
+ saveMappingsError = null;
}
@AfterClass
@@ -195,7 +172,7 @@
resolver.close();
}
}
-
+
@Test public void test_clone_based_on_anonymous() throws Exception {
final ResourceResolver anon0 = this.resourceResolverFactory.getResourceResolver((Map<String, Object>) null);
final Session anon0Session = anon0.adaptTo(Session.class);