Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/AbstractTopologyEventTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/AbstractTopologyEventTest.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/AbstractTopologyEventTest.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/AbstractTopologyEventTest.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,252 @@ +/* + * 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.discovery.base.its; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.sling.discovery.TopologyEvent; +import org.apache.sling.discovery.TopologyEvent.Type; +import org.apache.sling.discovery.TopologyView; +import org.apache.sling.discovery.base.its.setup.VirtualInstance; +import org.apache.sling.discovery.base.its.setup.VirtualInstanceBuilder; +import org.apache.sling.discovery.base.its.setup.mock.AssertingTopologyEventListener; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Test class covering correct sending of TopologyEvents + * in various scenarios (which are not covered in other tests already). + */ +public abstract class AbstractTopologyEventTest { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private VirtualInstance instance1; + private VirtualInstance instance2; + + private Level logLevel; + + @Before + public void setup() throws Exception { + final org.apache.log4j.Logger discoveryLogger = LogManager.getRootLogger().getLogger("org.apache.sling.discovery"); + logLevel = discoveryLogger.getLevel(); + discoveryLogger.setLevel(Level.DEBUG); + } + + @After + public void tearDown() throws Throwable { + if (instance1!=null) { + instance1.stopViewChecker(); + instance1.stop(); + instance1 = null; + } + if (instance2!=null) { + instance2.stopViewChecker(); + instance2.stop(); + instance2 = null; + } + final org.apache.log4j.Logger discoveryLogger = LogManager.getRootLogger().getLogger("org.apache.sling.discovery"); + discoveryLogger.setLevel(logLevel); + } + + public abstract VirtualInstanceBuilder newBuilder(); + + /** + * Tests the fact that the INIT event is delayed until voting has succeeded + * (which is the default with SLIGN-5030 and SLING-4959 + * @throws Throwable + */ + @Test + public void testDelayedInitEvent() throws Throwable { + logger.info("testDelayedInitEvent: start"); + instance1 = newBuilder().setDebugName("firstInstanceA") + .newRepository("/var/discovery/impl/", true) + .setConnectorPingTimeout(3 /* heartbeat-timeout */) + .setMinEventDelay(3 /*min event delay*/).build(); + AssertingTopologyEventListener l1 = new AssertingTopologyEventListener("instance1.l1"); + instance1.bindTopologyEventListener(l1); + logger.info("testDelayedInitEvent: instance1 created, no events expected yet. slingId="+instance1.slingId); + + // should not have received any events yet + assertEquals(0, l1.getEvents().size()); + assertEquals(0, l1.getUnexpectedCount()); + + // one heartbeat doesn't make a day yet - and is 2sec too early for the init + instance1.heartbeatsAndCheckView(); + Thread.sleep(1200); + logger.info("testDelayedInitEvent: even after 500ms no events expected, as it needs more than 1 heartbeat"); + // should not have received any events yet + assertEquals(0, l1.getEvents().size()); + assertEquals(0, l1.getUnexpectedCount()); + + // but two are a good start + l1.addExpected(Type.TOPOLOGY_INIT); + instance1.heartbeatsAndCheckView(); + Thread.sleep(1200); + instance1.heartbeatsAndCheckView(); + Thread.sleep(1200); + logger.info("testDelayedInitEvent: 2nd/3rd heartbeat sent - now expecting a TOPOLOGY_INIT"); + instance1.dumpRepo(); + assertEquals(1, l1.getEvents().size()); // one event + assertEquals(0, l1.getRemainingExpectedCount()); // the expected one + assertEquals(0, l1.getUnexpectedCount()); + + logger.info("testDelayedInitEvent: creating instance2"); + instance2 = newBuilder().setDebugName("secondInstanceB") + .useRepositoryOf(instance1) + .setConnectorPingTimeout(20) + .setMinEventDelay(3).build(); + logger.info("testDelayedInitEvent: instance2 created with slingId="+instance2.slingId); + AssertingTopologyEventListener l2 = new AssertingTopologyEventListener("instance2.l2"); + instance2.bindTopologyEventListener(l2); + logger.info("testDelayedInitEvent: listener instance2.l2 added - it should not get any events though"); + AssertingTopologyEventListener l1Two = new AssertingTopologyEventListener("instance1.l1Two"); + l1Two.addExpected(Type.TOPOLOGY_INIT); + logger.info("testDelayedInitEvent: listener instance1.l1Two added - it expects an INIT now"); + instance1.bindTopologyEventListener(l1Two); + + Thread.sleep(500); // SLING-4755: async event sending requires some minimal wait time nowadays + + // just because instance2 is started doesn't kick off any events yet + // since instance2 didn't send heartbeats yet + assertEquals(1, l1.getEvents().size()); // one event + assertEquals(0, l1.getRemainingExpectedCount()); // the expected one + assertEquals(0, l1.getUnexpectedCount()); + assertEquals(0, l2.getEvents().size()); + assertEquals(0, l2.getUnexpectedCount()); + assertEquals(1, l1Two.getEvents().size()); + assertEquals(0, l1Two.getRemainingExpectedCount()); // the expected one + assertEquals(0, l1Two.getUnexpectedCount()); + + + // the second & third heartbeat though triggers the voting etc + logger.info("testDelayedInitEvent: two more heartbeats should trigger events"); + l1.addExpected(Type.TOPOLOGY_CHANGING); + l1Two.addExpected(Type.TOPOLOGY_CHANGING); + Thread.sleep(500); + l2.addExpected(Type.TOPOLOGY_INIT); + instance1.heartbeatsAndCheckView(); + instance2.heartbeatsAndCheckView(); + Thread.sleep(500); + instance1.heartbeatsAndCheckView(); + instance2.heartbeatsAndCheckView(); + Thread.sleep(500); + instance1.heartbeatsAndCheckView(); + instance2.heartbeatsAndCheckView(); + logger.info("testDelayedInitEvent: instance1: "+instance1.slingId); + logger.info("testDelayedInitEvent: instance2: "+instance2.slingId); + instance1.dumpRepo(); + assertEquals(0, l1.getUnexpectedCount()); + assertEquals(2, l1.getEvents().size()); + assertEquals(0, l2.getUnexpectedCount()); + assertEquals(1, l2.getEvents().size()); + assertEquals(0, l1Two.getUnexpectedCount()); + assertEquals(2, l1Two.getEvents().size()); + + // wait until CHANGED is sent - which is 3 sec after CHANGING + l1.addExpected(Type.TOPOLOGY_CHANGED); + l1Two.addExpected(Type.TOPOLOGY_CHANGED); + Thread.sleep(4000); + assertEquals(0, l1.getUnexpectedCount()); + assertEquals(3, l1.getEvents().size()); // one event + assertEquals(0, l2.getUnexpectedCount()); + assertEquals(1, l2.getEvents().size()); + assertEquals(0, l1Two.getUnexpectedCount()); + assertEquals(3, l1Two.getEvents().size()); + logger.info("testDelayedInitEvent: end"); + } + + @Test + public void testGetDuringDelay() throws Throwable { + instance1 = newBuilder().setDebugName("firstInstanceA") + .newRepository("/var/discovery/impl/", true) + .setConnectorPingTimeout(20 /* heartbeat-timeout */) + .setMinEventDelay(6 /* min event delay */).build(); + AssertingTopologyEventListener l1 = new AssertingTopologyEventListener("instance1.l1"); + l1.addExpected(TopologyEvent.Type.TOPOLOGY_INIT); + instance1.bindTopologyEventListener(l1); + + TopologyView earlyTopo = instance1.getDiscoveryService().getTopology(); + assertNotNull(earlyTopo); + assertFalse(earlyTopo.isCurrent()); + assertEquals(1, earlyTopo.getInstances().size()); + + for(int i=0; i<4; i++) { + instance1.heartbeatsAndCheckView(); + Thread.sleep(125); + } + TopologyView secondTopo = instance1.getDiscoveryService().getTopology(); + assertEquals(1, secondTopo.getInstances().size()); + assertEquals(instance1.getSlingId(), secondTopo.getInstances().iterator().next().getSlingId()); + assertTrue(secondTopo.isCurrent()); + instance1.dumpRepo(); + + assertEarlyAndFirstClusterViewIdMatches(earlyTopo, secondTopo); + + Thread.sleep(500); + // should have gotten the INIT, hence 0 remaining expected events + assertEquals(0, l1.getRemainingExpectedCount()); + assertEquals(0, l1.getUnexpectedCount()); + + l1.addExpected(TopologyEvent.Type.TOPOLOGY_CHANGING); + instance2 = newBuilder().setDebugName("secondInstanceB") + .useRepositoryOf(instance1) + .setConnectorPingTimeout(20) + .setMinEventDelay(1).build(); + AssertingTopologyEventListener l2 = new AssertingTopologyEventListener("instance2.l1"); + l2.addExpected(TopologyEvent.Type.TOPOLOGY_INIT); + instance2.bindTopologyEventListener(l2); + + for(int i=0; i<4; i++) { + instance2.heartbeatsAndCheckView(); + instance1.heartbeatsAndCheckView(); + Thread.sleep(750); + } + + assertEquals(0, l1.getUnexpectedCount()); + TopologyView topo2 = instance2.getDiscoveryService().getTopology(); + assertTrue(topo2.isCurrent()); + assertEquals(2, topo2.getInstances().size()); + TopologyView topo1 = instance1.getDiscoveryService().getTopology(); + assertTrue(topo1.isCurrent()); + assertEquals(2, topo1.getInstances().size()); + + l1.addExpected(TopologyEvent.Type.TOPOLOGY_CHANGED); + Thread.sleep(5000); + assertEquals(0, l1.getRemainingExpectedCount()); + assertEquals(0, l1.getUnexpectedCount()); + assertEquals(0, l2.getRemainingExpectedCount()); + assertEquals(0, l2.getUnexpectedCount()); + assertTrue(instance2.getDiscoveryService().getTopology().isCurrent()); + assertEquals(2, instance2.getDiscoveryService().getTopology().getInstances().size()); + assertTrue(instance1.getDiscoveryService().getTopology().isCurrent()); + assertEquals(2, instance1.getDiscoveryService().getTopology().getInstances().size()); + } + + public abstract void assertEarlyAndFirstClusterViewIdMatches(TopologyView earlyTopo, TopologyView secondTopo); + +} \ No newline at end of file
Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/AbstractTopologyEventTest.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/TopologyTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/TopologyTest.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/TopologyTest.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/TopologyTest.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,150 @@ +/* + * 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.discovery.base.its; + +import static org.junit.Assert.assertEquals; + +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.apache.sling.discovery.InstanceDescription; +import org.apache.sling.discovery.base.connectors.DummyVirtualInstanceBuilder; +import org.apache.sling.discovery.base.connectors.announcement.Announcement; +import org.apache.sling.discovery.base.its.setup.TopologyHelper; +import org.apache.sling.discovery.base.its.setup.VirtualConnector; +import org.apache.sling.discovery.base.its.setup.VirtualInstance; +import org.apache.sling.discovery.base.its.setup.VirtualInstanceBuilder; +import org.junit.After; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TopologyTest { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final List<VirtualInstance> instances = new LinkedList<VirtualInstance>(); + + private VirtualInstanceBuilder newBuilder() { + return new DummyVirtualInstanceBuilder(); + } + + @After + public void tearDown() throws Exception { + for (Iterator<VirtualInstance> it = instances.iterator(); it.hasNext();) { + final VirtualInstance instance = it.next(); + instance.stop(); + } + } + + @Test + public void testTwoNodes() throws Throwable { + VirtualInstanceBuilder builder1 = newBuilder() + .newRepository("/var/discovery/impl/", true) + .setDebugName("instance1") + .setConnectorPingInterval(20) + .setConnectorPingTimeout(200); + VirtualInstance instance1 = builder1.build(); + instances.add(instance1); + VirtualInstanceBuilder builder2 = newBuilder() + .useRepositoryOf(builder1) + .setDebugName("instance2") + .setConnectorPingInterval(20) + .setConnectorPingTimeout(200); + VirtualInstance instance2 = builder2.build(); + instances.add(instance2); + instance1.getConfig().setViewCheckTimeout(8); + instance1.getConfig().setViewCheckInterval(1); + instance2.getConfig().setViewCheckTimeout(2); + instance2.getConfig().setViewCheckInterval(1); + + for(int i=0; i<5; i++) { + instance1.heartbeatsAndCheckView(); + instance2.heartbeatsAndCheckView(); + Thread.sleep(500); + } + + Set<InstanceDescription> instances1 = instance1.getDiscoveryService().getTopology().getInstances(); + Set<InstanceDescription> instances2 = instance2.getDiscoveryService().getTopology().getInstances(); + + assertEquals(1, instances1.size()); + assertEquals(1, instances2.size()); + assertEquals(instance1.getSlingId(), instances1.iterator().next().getSlingId()); + assertEquals(instance2.getSlingId(), instances2.iterator().next().getSlingId()); + + new VirtualConnector(instance1, instance2); + + // check instance 1's announcements + Collection<Announcement> instance1LocalAnnouncements = + instance1.getAnnouncementRegistry().listLocalAnnouncements(); + assertEquals(1, instance1LocalAnnouncements.size()); + Announcement instance1LocalAnnouncement = instance1LocalAnnouncements.iterator().next(); + assertEquals(instance2.getSlingId(), instance1LocalAnnouncement.getOwnerId()); + assertEquals(true, instance1LocalAnnouncement.isInherited()); + + // check instance 2's announcements + Collection<Announcement> instance2LocalAnnouncements = + instance2.getAnnouncementRegistry().listLocalAnnouncements(); + assertEquals(1, instance2LocalAnnouncements.size()); + Announcement instance2LocalAnnouncement = instance2LocalAnnouncements.iterator().next(); + assertEquals(instance1.getSlingId(), instance2LocalAnnouncement.getOwnerId()); + assertEquals(false, instance2LocalAnnouncement.isInherited()); + + // check topology + TopologyHelper.assertTopologyConsistsOf(instance1.getDiscoveryService().getTopology(), instance1.getSlingId(), instance2.getSlingId()); + TopologyHelper.assertTopologyConsistsOf(instance2.getDiscoveryService().getTopology(), instance1.getSlingId(), instance2.getSlingId()); + + instance1LocalAnnouncements = + instance1.getAnnouncementRegistry().listLocalAnnouncements(); + assertEquals(1, instance1LocalAnnouncements.size()); + instance2LocalAnnouncements = + instance2.getAnnouncementRegistry().listLocalAnnouncements(); + assertEquals(1, instance2LocalAnnouncements.size()); + + Thread.sleep(2200); // sleep of 2.2sec ensures instance2's heartbeat timeout (which is 2sec) hits + + instance1LocalAnnouncements = + instance1.getAnnouncementRegistry().listLocalAnnouncements(); + assertEquals(1, instance1LocalAnnouncements.size()); + instance2LocalAnnouncements = + instance2.getAnnouncementRegistry().listLocalAnnouncements(); + assertEquals(0, instance2LocalAnnouncements.size()); + + logger.info("testTwoNodes: instance1: "+instance1.getSlingId()); + instance1.dumpRepo(); + logger.info("testTwoNodes: instance2: "+instance2.getSlingId()); + instance2.dumpRepo(); + TopologyHelper.assertTopologyConsistsOf(instance1.getDiscoveryService().getTopology(), instance1.getSlingId(), instance2.getSlingId()); + TopologyHelper.assertTopologyConsistsOf(instance2.getDiscoveryService().getTopology(), instance2.getSlingId()); + + Thread.sleep(6000); // another sleep 6s (2.2+6 = 8.2sec) ensures instance1's heartbeat timeout (which is 8sec) hits as well + instance1LocalAnnouncements = + instance1.getAnnouncementRegistry().listLocalAnnouncements(); + assertEquals(0, instance1LocalAnnouncements.size()); + instance2LocalAnnouncements = + instance2.getAnnouncementRegistry().listLocalAnnouncements(); + assertEquals(0, instance2LocalAnnouncements.size()); + + TopologyHelper.assertTopologyConsistsOf(instance1.getDiscoveryService().getTopology(), instance1.getSlingId()); + TopologyHelper.assertTopologyConsistsOf(instance2.getDiscoveryService().getTopology(), instance2.getSlingId()); + } +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/TopologyTest.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/ModifiableTestBaseConfig.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/ModifiableTestBaseConfig.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/ModifiableTestBaseConfig.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/ModifiableTestBaseConfig.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,37 @@ +/* + * 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.discovery.base.its.setup; + +import org.apache.sling.discovery.base.connectors.BaseConfig; + +/** + * test extension of the BaseConfig that allows setting some + * parameters in test classes + */ +public interface ModifiableTestBaseConfig extends BaseConfig { + + void addTopologyConnectorWhitelistEntry(String string); + + void setMinEventDelay(int minEventDelay); + + void setViewCheckTimeout(int viewCheckTimeout); + + void setViewCheckInterval(int viewCheckInterval); + +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/ModifiableTestBaseConfig.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/OSGiMock.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/OSGiMock.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/OSGiMock.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/OSGiMock.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,124 @@ +/* + * 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.discovery.base.its.setup; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.sling.discovery.base.its.setup.mock.MockFactory; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OSGiMock { + + private static final Logger logger = LoggerFactory.getLogger(OSGiMock.class); + + private final List<Object> services = new LinkedList<Object>(); + + public void addService(Object service) { + if (service==null) { + throw new IllegalArgumentException("service must not be null"); + } + services.add(service); + } + + public void activateAll() throws Exception { + for (@SuppressWarnings("rawtypes") + Iterator it = services.iterator(); it.hasNext();) { + Object aService = it.next(); + + activate(aService); + } + } + + public static void activate(Object aService) throws IllegalAccessException, + InvocationTargetException { + Class<?> clazz = aService.getClass(); + while (clazz != null) { + Method[] methods = clazz.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (method.getName().equals("activate")) { + method.setAccessible(true); + if ( method.getParameterTypes().length == 0 ) { + logger.info("activate: activating "+aService+"..."); + method.invoke(aService, null); + logger.info("activate: activating "+aService+" done."); + } else if (method.getParameterTypes().length==1 && (method.getParameterTypes()[0]==ComponentContext.class)){ + logger.info("activate: activating "+aService+"..."); + method.invoke(aService, MockFactory.mockComponentContext()); + logger.info("activate: activating "+aService+" done."); + } else if (method.getParameterTypes().length==1 && (method.getParameterTypes()[0]==BundleContext.class)){ + logger.info("activate: activating "+aService+"..."); + method.invoke(aService, MockFactory.mockBundleContext()); + logger.info("activate: activating "+aService+" done."); + } else { + throw new IllegalStateException("unsupported activate variant: "+method); + } + return; + } + } + clazz = clazz.getSuperclass(); + } + } + + public void deactivateAll() throws Exception { + for (@SuppressWarnings("rawtypes") + Iterator it = services.iterator(); it.hasNext();) { + Object aService = it.next(); + + deactivate(aService); + } + } + + public static void deactivate(Object aService) throws IllegalAccessException, + InvocationTargetException { + Class<?> clazz = aService.getClass(); + while (clazz != null) { + Method[] methods = clazz.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (method.getName().equals("deactivate")) { + method.setAccessible(true); + if ( method.getParameterTypes().length == 0 ) { + method.invoke(aService, null); + } else { + method.invoke(aService, MockFactory.mockComponentContext()); + } + return; + } + } + clazz = clazz.getSuperclass(); + } + } + + public void addServices(Object[] additionalServices) { + if (additionalServices==null) { + return; + } + for (Object additionalService : additionalServices) { + addService(additionalService); + } + } +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/OSGiMock.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/TopologyHelper.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/TopologyHelper.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/TopologyHelper.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/TopologyHelper.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,145 @@ +/* + * 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.discovery.base.its.setup; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Set; +import java.util.UUID; + +import org.apache.sling.discovery.ClusterView; +import org.apache.sling.discovery.InstanceDescription; +import org.apache.sling.discovery.TopologyView; +import org.apache.sling.discovery.base.commons.DefaultTopologyView; +import org.apache.sling.discovery.commons.providers.DefaultClusterView; +import org.apache.sling.discovery.commons.providers.DefaultInstanceDescription; + +import junitx.util.PrivateAccessor; + +public class TopologyHelper { + + public static DefaultInstanceDescription createInstanceDescription( + ClusterView clusterView) { + return createInstanceDescription(UUID.randomUUID().toString(), false, clusterView); + } + + public static DefaultInstanceDescription createInstanceDescription( + String instanceId, boolean isLocal, ClusterView clusterView) { + if (!(clusterView instanceof DefaultClusterView)) { + throw new IllegalArgumentException( + "Must pass a clusterView of type " + + DefaultClusterView.class); + } + DefaultInstanceDescription i = new DefaultInstanceDescription( + (DefaultClusterView) clusterView, false, isLocal, instanceId, new HashMap<String, String>()); + return i; + } + + public static DefaultTopologyView createTopologyView(String clusterViewId, + String slingId) { + DefaultTopologyView t = new DefaultTopologyView(); + DefaultClusterView c = new DefaultClusterView(clusterViewId); + DefaultInstanceDescription i = new DefaultInstanceDescription( + c, true, false, slingId, new HashMap<String, String>()); + Collection<InstanceDescription> instances = new LinkedList<InstanceDescription>(); + instances.add(i); + t.addInstances(instances); + return t; + } + + public static DefaultTopologyView cloneTopologyView(DefaultTopologyView original) { + DefaultTopologyView t = new DefaultTopologyView(); + Iterator<ClusterView> it = original.getClusterViews().iterator(); + while (it.hasNext()) { + DefaultClusterView c = (DefaultClusterView) it.next(); + t.addInstances(clone(c).getInstances()); + } + return t; + } + + public static DefaultClusterView clone(DefaultClusterView original) { + DefaultClusterView c = new DefaultClusterView(original.getId()); + Iterator<InstanceDescription> it = original.getInstances().iterator(); + while (it.hasNext()) { + DefaultInstanceDescription id = (DefaultInstanceDescription) it + .next(); + c.addInstanceDescription(cloneWOClusterView(id)); + } + return c; + } + + public static DefaultInstanceDescription cloneWOClusterView( + DefaultInstanceDescription original) { + DefaultInstanceDescription id = new DefaultInstanceDescription( + null, original.isLeader(), original.isLocal(), + original.getSlingId(), new HashMap<String, String>( + original.getProperties())); + return id; + } + + public static DefaultInstanceDescription createAndAddInstanceDescription( + DefaultTopologyView newView, ClusterView clusterView) { + DefaultInstanceDescription i = createInstanceDescription(clusterView); + return addInstanceDescription(newView, i); + } + + public static DefaultInstanceDescription addInstanceDescription( + DefaultTopologyView newView, DefaultInstanceDescription i) { + Collection<InstanceDescription> instances = new LinkedList<InstanceDescription>(); + instances.add(i); + newView.addInstances(instances); + return i; + } + + public static DefaultTopologyView cloneTopologyView(DefaultTopologyView view, + String newLeader) throws NoSuchFieldException { + final DefaultTopologyView clone = cloneTopologyView(view); + final DefaultClusterView cluster = (DefaultClusterView) clone.getClusterViews().iterator().next(); + for (Iterator it = cluster.getInstances().iterator(); it.hasNext();) { + DefaultInstanceDescription id = (DefaultInstanceDescription) it.next(); + PrivateAccessor.setField(id, "isLeader", id.getSlingId().equals(newLeader)); + } + return clone; + } + + public static void assertTopologyConsistsOf(TopologyView topology, String... slingIds) { + assertNotNull(topology); + assertEquals(slingIds.length, topology.getInstances().size()); + for(int i=0; i<slingIds.length; i++) { + final String aSlingId = slingIds[i]; + final Set<?> instances = topology.getInstances(); + boolean found = false; + for (Iterator<?> it = instances.iterator(); it.hasNext();) { + InstanceDescription anInstance = (InstanceDescription) it.next(); + if (anInstance.getSlingId().equals(aSlingId)) { + found = true; + break; + } + } + assertTrue(found); + } + } + +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/TopologyHelper.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualConnector.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualConnector.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualConnector.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualConnector.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,39 @@ +/* + * 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.discovery.base.its.setup; + +import org.apache.sling.discovery.base.connectors.ping.TopologyConnectorClientInformation; + +public class VirtualConnector { + @SuppressWarnings("unused") + private final VirtualInstance from; + @SuppressWarnings("unused") + private final VirtualInstance to; + private final int jettyPort; + @SuppressWarnings("unused") + private final TopologyConnectorClientInformation connectorInfo; + + public VirtualConnector(VirtualInstance from, VirtualInstance to) throws Throwable { + this.from = from; + this.to = to; + to.startJetty(); + this.jettyPort = to.getJettyPort(); + this.connectorInfo = from.connectTo("http://localhost:"+jettyPort+"/system/console/topology/connector"); + } +} \ No newline at end of file Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualConnector.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstance.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstance.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstance.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstance.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,374 @@ +/* + * 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.discovery.base.its.setup; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Date; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.jcr.Session; +import javax.servlet.Servlet; + +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceResolverFactory; +import org.apache.sling.commons.testing.jcr.RepositoryProvider; +import org.apache.sling.discovery.InstanceDescription; +import org.apache.sling.discovery.PropertyProvider; +import org.apache.sling.discovery.TopologyEventListener; +import org.apache.sling.discovery.base.commons.BaseDiscoveryService; +import org.apache.sling.discovery.base.commons.ClusterViewService; +import org.apache.sling.discovery.base.commons.ViewChecker; +import org.apache.sling.discovery.base.commons.UndefinedClusterViewException; +import org.apache.sling.discovery.base.connectors.announcement.AnnouncementRegistry; +import org.apache.sling.discovery.base.connectors.ping.ConnectorRegistry; +import org.apache.sling.discovery.base.connectors.ping.TopologyConnectorClientInformation; +import org.apache.sling.discovery.base.connectors.ping.TopologyConnectorServlet; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.osgi.framework.Constants; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.http.HttpContext; +import org.osgi.service.http.HttpService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import junitx.util.PrivateAccessor; + +public class VirtualInstance { + + protected final static Logger logger = LoggerFactory.getLogger(VirtualInstance.class); + + public final String slingId; + + ClusterViewService clusterViewService; + + private final ResourceResolverFactory resourceResolverFactory; + + private final OSGiMock osgiMock; + + private final BaseDiscoveryService discoveryService; + + private final AnnouncementRegistry announcementRegistry; + + private final ConnectorRegistry connectorRegistry; + + protected final String debugName; + + private ResourceResolver resourceResolver; + + private int serviceId = 999; + + private ViewCheckerRunner viewCheckerRunner = null; + + private ServletContextHandler servletContext; + + private Server jettyServer; + + private ModifiableTestBaseConfig config; + + private ViewChecker viewChecker; + + private final VirtualInstanceBuilder builder; + + private class ViewCheckerRunner implements Runnable { + + private final int intervalInSeconds; + + private boolean stopped_ = false; + + public ViewCheckerRunner(int intervalInSeconds) { + this.intervalInSeconds = intervalInSeconds; + } + + public synchronized void stop() { + logger.info("Stopping Instance ["+slingId+"]"); + stopped_ = true; + } + + public void run() { + while(true) { + synchronized(this) { + if (stopped_) { + logger.info("Instance ["+slingId+"] stopps."); + return; + } + } + try{ + heartbeatsAndCheckView(); + } catch(Exception e) { + logger.error("run: ping connector for slingId="+slingId+" threw exception: "+e, e); + } + try { + Thread.sleep(intervalInSeconds*1000); + } catch (InterruptedException e) { + e.printStackTrace(); + return; + } + } + } + + } + + public VirtualInstance(VirtualInstanceBuilder builder) throws Exception { + this.builder = builder; + this.slingId = builder.getSlingId(); + this.debugName = builder.getDebugName(); + logger.info("<init>: starting slingId="+slingId+", debugName="+debugName); + + osgiMock = new OSGiMock(); + + this.resourceResolverFactory = builder.getResourceResolverFactory(); + + config = builder.getConnectorConfig(); + config.addTopologyConnectorWhitelistEntry("127.0.0.1"); + config.setMinEventDelay(builder.getMinEventDelay()); + + clusterViewService = builder.getClusterViewService(); + announcementRegistry = builder.getAnnouncementRegistry(); + connectorRegistry = builder.getConnectorRegistry(); + viewChecker = builder.getViewChecker(); + discoveryService = builder.getDiscoverService(); + + osgiMock.addService(clusterViewService); + osgiMock.addService(announcementRegistry); + osgiMock.addService(connectorRegistry); + osgiMock.addService(viewChecker); + osgiMock.addService(discoveryService); + osgiMock.addServices(builder.getAdditionalServices(this)); + + resourceResolver = resourceResolverFactory + .getAdministrativeResourceResolver(null); + + if (builder.isResetRepo()) { + //SLING-4587 : do resetRepo before creating the observationListener + // otherwise it will get tons of events from the deletion of /var + // which the previous test could have left over. + // Doing it before addEventListener should prevent that. + builder.resetRepo(); + } + + osgiMock.activateAll(); + } + + @Override + public String toString() { + return "a [Test]Instance[slingId="+slingId+", debugName="+debugName+"]"; + } + + public void bindPropertyProvider(PropertyProvider propertyProvider, + String... propertyNames) throws Throwable { + Map<String, Object> props = new HashMap<String, Object>(); + props.put(Constants.SERVICE_ID, (long) serviceId++); + props.put(PropertyProvider.PROPERTY_PROPERTIES, propertyNames); + + PrivateAccessor.invoke(discoveryService, "bindPropertyProvider", + new Class[] { PropertyProvider.class, Map.class }, + new Object[] { propertyProvider, props }); + } + + public String getSlingId() { + return slingId; + } + + public ClusterViewService getClusterViewService() { + return clusterViewService; + } + + public BaseDiscoveryService getDiscoveryService() { + return discoveryService; + } + + public AnnouncementRegistry getAnnouncementRegistry() { + return announcementRegistry; + } + + public synchronized void startJetty() throws Throwable { + if (jettyServer!=null) { + return; + } + servletContext = new ServletContextHandler(ServletContextHandler.NO_SECURITY); + servletContext.setContextPath("/"); + + TopologyConnectorServlet servlet = new TopologyConnectorServlet(); + PrivateAccessor.setField(servlet, "config", config); + PrivateAccessor.setField(servlet, "clusterViewService", clusterViewService); + PrivateAccessor.setField(servlet, "announcementRegistry", announcementRegistry); + + Mockery context = new JUnit4Mockery(); + final HttpService httpService = context.mock(HttpService.class); + context.checking(new Expectations() { + { + allowing(httpService).registerServlet(with(any(String.class)), + with(any(Servlet.class)), + with(any(Dictionary.class)), + with(any(HttpContext.class))); + } + }); + PrivateAccessor.setField(servlet, "httpService", httpService); + ComponentContext cc = null; + PrivateAccessor.invoke(servlet, "activate", new Class[] {ComponentContext.class}, new Object[] {cc}); + + ServletHolder holder = + new ServletHolder(servlet); + + servletContext.addServlet(holder, "/system/console/topology/*"); + + jettyServer = new Server(); + jettyServer.setHandler(servletContext); + Connector connector=new SelectChannelConnector(); + jettyServer.setConnectors(new Connector[]{connector}); + jettyServer.start(); + } + + public synchronized int getJettyPort() { + if (jettyServer==null) { + throw new IllegalStateException("jettyServer not started"); + } + final Connector[] connectors = jettyServer.getConnectors(); + return connectors[0].getLocalPort(); + } + + public TopologyConnectorClientInformation connectTo(String url) throws MalformedURLException { + return connectorRegistry.registerOutgoingConnector(clusterViewService, new URL(url)); + } + + public InstanceDescription getLocalInstanceDescription() throws UndefinedClusterViewException { + final Iterator<InstanceDescription> it = getClusterViewService().getLocalClusterView().getInstances().iterator(); + while(it.hasNext()) { + final InstanceDescription id = it.next(); + if (slingId.equals(id.getSlingId())) { + return id; + } + } + fail("no local instanceDescription found"); + // never called: + return null; + } + + public void heartbeatsAndCheckView() { + logger.info("Instance ["+slingId+"] issues a pulse now "+new Date()); + viewChecker.heartbeatAndCheckView(); + } + + public void startViewChecker(int intervalInSeconds) throws IllegalAccessException, InvocationTargetException { + logger.info("startViewChecker: intervalInSeconds="+intervalInSeconds); + if (viewCheckerRunner!=null) { + logger.info("startViewChecker: stopping first..."); + viewCheckerRunner.stop(); + logger.info("startViewChecker: stopped."); + } + logger.info("startViewChecker: activating..."); + try{ + OSGiMock.activate(viewChecker); + } catch(Error er) { + er.printStackTrace(System.out); + throw er; + } catch(RuntimeException re) { + re.printStackTrace(System.out); + } + logger.info("startViewChecker: initializing..."); + viewCheckerRunner = new ViewCheckerRunner(intervalInSeconds); + Thread th = new Thread(viewCheckerRunner, "Test-ViewCheckerRunner ["+debugName+"]"); + th.setDaemon(true); + logger.info("startViewChecker: starting thread..."); + th.start(); + logger.info("startViewChecker: done."); + } + + public boolean isViewCheckerRunning() { + return (viewCheckerRunner!=null); + } + + public void stopViewChecker() throws Throwable { + if (viewCheckerRunner!=null) { + viewCheckerRunner.stop(); + viewCheckerRunner = null; + } + try{ + OSGiMock.deactivate(viewChecker); + } catch(Error er) { + er.printStackTrace(System.out); + throw er; + } catch(RuntimeException re) { + re.printStackTrace(System.out); + throw re; + } + } + + public void dumpRepo() throws Exception { + VirtualInstanceHelper.dumpRepo(resourceResolverFactory); + } + + public ResourceResolverFactory getResourceResolverFactory() { + return resourceResolverFactory; + } + + public void stop() throws Exception { + logger.info("stop: stopping slingId="+slingId+", debugName="+debugName); + try { + stopViewChecker(); + } catch (Throwable e) { + throw new Exception("Caught Throwable in stopConnectorPinger: "+e, e); + } + + if (resourceResolver != null) { + resourceResolver.close(); + } + osgiMock.deactivateAll(); + logger.info("stop: stopped slingId="+slingId+", debugName="+debugName); + } + + public void bindTopologyEventListener(TopologyEventListener eventListener) + throws Throwable { + PrivateAccessor.invoke(discoveryService, "bindTopologyEventListener", + new Class[] { TopologyEventListener.class }, + new Object[] { eventListener }); + } + + public ModifiableTestBaseConfig getConfig() { + return config; + } + + public ViewChecker getViewChecker() { + return viewChecker; + } + + public void assertEstablishedView() { + assertTrue(getDiscoveryService().getTopology().isCurrent()); + } + + public VirtualInstanceBuilder getBuilder() { + return builder; + } + +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstance.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceBuilder.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceBuilder.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceBuilder.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceBuilder.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,238 @@ +/* + * 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.discovery.base.its.setup; + +import java.util.UUID; + +import org.apache.sling.api.resource.ResourceResolverFactory; +import org.apache.sling.commons.scheduler.Scheduler; +import org.apache.sling.commons.scheduler.impl.QuartzScheduler; +import org.apache.sling.commons.threads.ThreadPoolManager; +import org.apache.sling.commons.threads.impl.DefaultThreadPoolManager; +import org.apache.sling.discovery.base.commons.BaseDiscoveryService; +import org.apache.sling.discovery.base.commons.ClusterViewService; +import org.apache.sling.discovery.base.commons.ViewChecker; +import org.apache.sling.discovery.base.connectors.announcement.AnnouncementRegistry; +import org.apache.sling.discovery.base.connectors.announcement.AnnouncementRegistryImpl; +import org.apache.sling.discovery.base.connectors.ping.ConnectorRegistry; +import org.apache.sling.discovery.base.connectors.ping.ConnectorRegistryImpl; +import org.apache.sling.discovery.base.its.setup.mock.FailingScheduler; +import org.apache.sling.discovery.commons.providers.spi.impl.DummySlingSettingsService; +import org.apache.sling.settings.SlingSettingsService; + +import junitx.util.PrivateAccessor; + +public abstract class VirtualInstanceBuilder { + + private static Scheduler singletonScheduler = null; + + public static Scheduler getSingletonScheduler() throws Exception { + if (singletonScheduler!=null) { + return singletonScheduler; + } + final Scheduler newscheduler = new QuartzScheduler(); + final ThreadPoolManager tpm = new DefaultThreadPoolManager(null, null); + try { + PrivateAccessor.invoke(newscheduler, "bindThreadPoolManager", + new Class[] { ThreadPoolManager.class }, + new Object[] { tpm }); + } catch (Throwable e1) { + org.junit.Assert.fail(e1.toString()); + } + OSGiMock.activate(newscheduler); + singletonScheduler = newscheduler; + return singletonScheduler; + } + + private String debugName; + protected ResourceResolverFactory factory; + private boolean resetRepo; + private String slingId = UUID.randomUUID().toString(); + private ClusterViewService clusterViewService; + protected ViewChecker viewChecker; + private AnnouncementRegistry announcementRegistry; + private ConnectorRegistry connectorRegistry; + private Scheduler scheduler; + private BaseDiscoveryService discoveryService; + private SlingSettingsService slingSettingsService; + protected boolean ownRepository; + private int minEventDelay = 1; + protected VirtualInstanceBuilder hookedToBuilder; + + public VirtualInstanceBuilder() { + } + + public VirtualInstanceBuilder newRepository(String path, boolean resetRepo) throws Exception { + createNewRepository(); + ownRepository = true; + this.resetRepo = resetRepo; + setPath(path); + return this; + } + + public abstract VirtualInstanceBuilder createNewRepository() throws Exception; + + public VirtualInstanceBuilder useRepositoryOf(VirtualInstance other) throws Exception { + return useRepositoryOf(other.getBuilder()); + } + + public VirtualInstanceBuilder useRepositoryOf(VirtualInstanceBuilder other) throws Exception { + factory = other.factory; + hookedToBuilder = other; + ownRepository = false; + return this; + } + + public VirtualInstanceBuilder setConnectorPingTimeout(int connectorPingTimeout) { + getConnectorConfig().setViewCheckTimeout(connectorPingTimeout); + return this; + } + + public VirtualInstanceBuilder setConnectorPingInterval(int connectorPingInterval) { + getConnectorConfig().setViewCheckInterval(connectorPingInterval); + return this; + } + + public boolean isResetRepo() { + return resetRepo; + } + + public String getSlingId() { + return slingId; + } + + public String getDebugName() { + return debugName; + } + + public ResourceResolverFactory getResourceResolverFactory() { + return factory; + } + + public ClusterViewService getClusterViewService() { + if (clusterViewService==null) { + clusterViewService = createClusterViewService(); + } + return clusterViewService; + } + + protected abstract ClusterViewService createClusterViewService(); + + public ViewChecker getViewChecker() throws Exception { + if (viewChecker==null) { + viewChecker = createViewChecker(); + } + return viewChecker; + } + + public AnnouncementRegistry getAnnouncementRegistry() { + if (announcementRegistry==null) { + announcementRegistry = createAnnouncementRegistry(); + } + return announcementRegistry; + } + + protected AnnouncementRegistry createAnnouncementRegistry() { + return AnnouncementRegistryImpl.testConstructor( + getResourceResolverFactory(), getSlingSettingsService(), getConnectorConfig()); + } + + public ConnectorRegistry getConnectorRegistry() { + if (connectorRegistry==null) { + connectorRegistry = createConnectorRegistry(); + } + return connectorRegistry; + } + + protected ConnectorRegistry createConnectorRegistry() { + return ConnectorRegistryImpl.testConstructor(announcementRegistry, getConnectorConfig()); + } + + protected abstract ViewChecker createViewChecker() throws Exception; + + protected abstract VirtualInstanceBuilder setPath(String string); + + public VirtualInstanceBuilder setDebugName(String debugName) { + this.debugName = debugName; + return this; + } + + public abstract ModifiableTestBaseConfig getConnectorConfig(); + + public void setScheduler(Scheduler singletonScheduler) { + this.scheduler = singletonScheduler; + } + + public Scheduler getScheduler() throws Exception { + if (scheduler == null) { + scheduler = getSingletonScheduler(); + } + return scheduler; + } + + public BaseDiscoveryService getDiscoverService() throws Exception { + if (discoveryService==null) { + discoveryService = createDiscoveryService(); + } + return discoveryService; + } + + protected abstract BaseDiscoveryService createDiscoveryService() throws Exception; + + protected SlingSettingsService getSlingSettingsService() { + if (slingSettingsService==null) { + slingSettingsService = createSlingSettingsService(); + } + return slingSettingsService; + } + + protected SlingSettingsService createSlingSettingsService() { + return new DummySlingSettingsService(getSlingId()); + } + + public abstract Object[] getAdditionalServices(VirtualInstance instance) throws Exception; + + public VirtualInstanceBuilder setMinEventDelay(int minEventDelay) { + this.minEventDelay = minEventDelay; + return this; + } + + public int getMinEventDelay() { + return minEventDelay; + } + + public VirtualInstance build() throws Exception { + return new VirtualInstance(this); + } + + public VirtualInstanceBuilder setSlingId(String slingId) { + this.slingId = slingId; + return this; + } + + public VirtualInstanceBuilder withFailingScheduler(boolean useFailingScheduler) { + if (useFailingScheduler) { + this.scheduler = new FailingScheduler(); + } + return this; + } + + protected abstract void resetRepo() throws Exception; + +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceBuilder.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceHelper.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceHelper.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceHelper.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceHelper.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,88 @@ +/* + * 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.discovery.base.its.setup; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.sling.api.resource.ResourceResolverFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VirtualInstanceHelper { + + private final static Logger logger = LoggerFactory.getLogger(VirtualInstanceHelper.class); + + public static void dumpRepo(ResourceResolverFactory resourceResolverFactory) throws Exception { + Session session = resourceResolverFactory + .getAdministrativeResourceResolver(null).adaptTo(Session.class); + logger.info("dumpRepo: ====== START ====="); + logger.info("dumpRepo: repo = " + session.getRepository()); + + dump(session.getRootNode()); + + // session.logout(); + logger.info("dumpRepo: ====== END ====="); + + session.logout(); + } + + public static void dump(Node node) throws RepositoryException { + if (node.getPath().equals("/jcr:system") + || node.getPath().equals("/rep:policy")) { + // ignore that one + return; + } + + PropertyIterator pi = node.getProperties(); + StringBuilder sb = new StringBuilder(); + while (pi.hasNext()) { + Property p = pi.nextProperty(); + sb.append(" "); + sb.append(p.getName()); + sb.append("="); + if (p.getType() == PropertyType.BOOLEAN) { + sb.append(p.getBoolean()); + } else if (p.getType() == PropertyType.STRING) { + sb.append(p.getString()); + } else if (p.getType() == PropertyType.DATE) { + sb.append(p.getDate().getTime()); + } else { + sb.append("<unknown type=" + p.getType() + "/>"); + } + } + + StringBuffer depth = new StringBuffer(); + for(int i=0; i<node.getDepth(); i++) { + depth.append(" "); + } + logger.info(depth + "/" + node.getName() + " -- " + sb); + NodeIterator it = node.getNodes(); + while (it.hasNext()) { + Node child = it.nextNode(); + dump(child); + } + } + +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualInstanceHelper.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualRepository.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualRepository.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualRepository.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualRepository.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,27 @@ +/* + * 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.discovery.base.its.setup; + +import org.apache.sling.api.resource.ResourceResolverFactory; + +public interface VirtualRepository { + + ResourceResolverFactory getResourceResolverFactory(); + +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/VirtualRepository.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/WithholdingAppender.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/WithholdingAppender.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/WithholdingAppender.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/WithholdingAppender.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,82 @@ +/* + * 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 SF 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.discovery.base.its.setup; + +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.net.URL; + +import org.apache.log4j.Layout; +import org.apache.log4j.LogManager; +import org.apache.log4j.PatternLayout; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.WriterAppender; + +public class WithholdingAppender extends WriterAppender { + + private final ByteArrayOutputStream baos; + private final Writer writer; + + /** + * Install the WithholdingAppender, essentially muting all logging + * and withholding it until release() is called + * @return the WithholdingAppender that can be used to get the + * withheld log output + */ + public static WithholdingAppender install() { + LogManager.getRootLogger().removeAllAppenders(); + final WithholdingAppender withholdingAppender = new WithholdingAppender( + new PatternLayout("%d{dd.MM.yyyy HH:mm:ss} *%-5p* [%t] %c{1}: %m\n")); + LogManager.getRootLogger().addAppender(withholdingAppender); + return withholdingAppender; + } + + /** + * Release this WithholdingAppender and optionally dump what was + * withheld (eg in case of an exception) + * @param dumpToSysout + */ + public void release(boolean dumpToSysout) { + LogManager.resetConfiguration(); + URL log4jPropertiesFile = getClass().getResource("/log4j.properties"); + PropertyConfigurator.configure(log4jPropertiesFile); + if (dumpToSysout) { + String withheldLogoutput = getBuffer(); + System.out.println(withheldLogoutput); + } + } + + public WithholdingAppender(Layout layout) { + this.layout = layout; + this.baos = new ByteArrayOutputStream(); + this.writer = new BufferedWriter(new OutputStreamWriter(baos)); + this.setWriter(writer); + } + + public String getBuffer() { + try{ + writer.flush(); + } catch(IOException e) { + // ignore + } + return baos.toString(); + } +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/WithholdingAppender.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsMultiple.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsMultiple.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsMultiple.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsMultiple.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,65 @@ +/* + * 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.discovery.base.its.setup.mock; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.sling.discovery.TopologyEvent; +import org.apache.sling.discovery.TopologyEvent.Type; + +public class AcceptsMultiple implements TopologyEventAsserter { + + private final Type[] acceptedTypes; + + private final Map<Type, Integer> counts = new HashMap<Type, Integer>(); + + public AcceptsMultiple(Type... acceptedTypes) { + this.acceptedTypes = acceptedTypes; + } + + public synchronized void assertOk(TopologyEvent event) { + for (int i = 0; i < acceptedTypes.length; i++) { + Type aType = acceptedTypes[i]; + if (aType == event.getType()) { + // perfect + Integer c = counts.remove(aType); + if (c == null) { + counts.put(aType, new Integer(1)); + } else { + counts.put(aType, new Integer(c + 1)); + } + return; + } + } + + throw new IllegalStateException("Got an Event which I did not expect: " + + event.getType()); + } + + public synchronized int getEventCnt(Type type) { + Integer i = counts.get(type); + if (i!=null) { + return i; + } else { + return 0; + } + } + +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsMultiple.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsParticularTopologyEvent.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsParticularTopologyEvent.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsParticularTopologyEvent.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsParticularTopologyEvent.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,50 @@ +/* + * 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.discovery.base.its.setup.mock; + +import org.apache.sling.discovery.TopologyEvent; +import org.apache.sling.discovery.TopologyEvent.Type; + +public class AcceptsParticularTopologyEvent implements TopologyEventAsserter { + + private final Type particularType; + + private int eventCnt = 0; + + /** + * @param singleInstanceTest + */ + public AcceptsParticularTopologyEvent(Type particularType) { + this.particularType = particularType; + } + + public void assertOk(TopologyEvent event) { + if (event.getType() == particularType) { + // fine + eventCnt++; + } else { + throw new IllegalStateException("expected " + particularType + + ", got " + event.getType()); + } + } + + public int getEventCnt() { + return eventCnt; + } +} \ No newline at end of file Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AcceptsParticularTopologyEvent.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AssertingTopologyEventListener.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AssertingTopologyEventListener.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AssertingTopologyEventListener.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AssertingTopologyEventListener.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,160 @@ +/* + * 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.discovery.base.its.setup.mock; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.sling.discovery.TopologyEvent; +import org.apache.sling.discovery.TopologyEvent.Type; +import org.apache.sling.discovery.TopologyEventListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AssertingTopologyEventListener implements TopologyEventListener { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final List<TopologyEventAsserter> expectedEvents = new LinkedList<TopologyEventAsserter>(); + + private String debugInfo = null; + + private String errorMsg = null; + + public AssertingTopologyEventListener() { + } + + public AssertingTopologyEventListener(String debugInfo) { + this.debugInfo = debugInfo; + } + + @Override + public String toString() { + return super.toString()+"-[debugInfo="+debugInfo+"]"; + } + + private List<TopologyEvent> events_ = new LinkedList<TopologyEvent>(); + + private List<TopologyEvent> unexpectedEvents_ = new LinkedList<TopologyEvent>(); + + public void handleTopologyEvent(TopologyEvent event) { + final String logPrefix = "handleTopologyEvent["+(debugInfo!=null ? debugInfo : "this="+this) +"] "; + logger.info(logPrefix + "got event=" + event); + TopologyEventAsserter asserter = null; + synchronized (expectedEvents) { + if (expectedEvents.size() == 0) { + unexpectedEvents_.add(event); + throw new IllegalStateException( + "no expected events anymore. But got: " + event); + } + asserter = expectedEvents.remove(0); + } + if (asserter == null) { + throw new IllegalStateException("this should not occur"); + } + try{ + asserter.assertOk(event); + logger.info(logPrefix + "event matched expectations (" + event+")"); + } catch(RuntimeException re) { + synchronized(expectedEvents) { + unexpectedEvents_.add(event); + } + throw re; + } catch(Error er) { + synchronized(expectedEvents) { + unexpectedEvents_.add(event); + } + throw er; + } + try{ + switch(event.getType()) { + case PROPERTIES_CHANGED: { + assertNotNull(event.getOldView()); + assertNotNull(event.getNewView()); + assertTrue(event.getNewView().isCurrent()); + assertFalse(event.getOldView().isCurrent()); + break; + } + case TOPOLOGY_CHANGED: { + assertNotNull(event.getOldView()); + assertNotNull(event.getNewView()); + assertTrue(event.getNewView().isCurrent()); + assertFalse(event.getOldView().isCurrent()); + break; + } + case TOPOLOGY_CHANGING: { + assertNotNull(event.getOldView()); + assertNull(event.getNewView()); + assertFalse(event.getOldView().isCurrent()); + break; + } + case TOPOLOGY_INIT: { + assertNull(event.getOldView()); + assertNotNull(event.getNewView()); + // cannot make any assertions on event.getNewView().isCurrent() + // as that can be true or false + break; + } + } + } catch(RuntimeException re) { + logger.error("RuntimeException: "+re, re); + throw re; + } catch(AssertionError e) { + logger.error("AssertionError: "+e, e); + throw e; + } + events_.add(event); + } + + public List<TopologyEvent> getEvents() { + return events_; + } + + public void addExpected(Type expectedType) { + addExpected(new AcceptsParticularTopologyEvent(expectedType)); + } + + public void addExpected(TopologyEventAsserter topologyEventAsserter) { + expectedEvents.add(topologyEventAsserter); + } + + public int getRemainingExpectedCount() { + return expectedEvents.size(); + } + + public int getUnexpectedCount() { + return unexpectedEvents_.size(); + } + + public void dump() { + StringBuffer ue = new StringBuffer(); + if (unexpectedEvents_.size()>0) { + for (Iterator<TopologyEvent> it = unexpectedEvents_.iterator(); it.hasNext();) { + TopologyEvent topologyEvent = it.next(); + ue.append(topologyEvent+", "); + } + unexpectedEvents_.iterator(); + } + logger.info("dump: got "+events_.size()+" events, "+unexpectedEvents_.size()+" (details: "+ue+") thereof unexpected. My list of expected events contains "+expectedEvents.size()); + } +} \ No newline at end of file Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/AssertingTopologyEventListener.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/DummyViewChecker.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/DummyViewChecker.java?rev=1709601&view=auto ============================================================================== --- sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/DummyViewChecker.java (added) +++ sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/DummyViewChecker.java Tue Oct 20 14:12:31 2015 @@ -0,0 +1,48 @@ +/* + * 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.discovery.base.its.setup.mock; + +import org.apache.sling.api.resource.ResourceResolverFactory; +import org.apache.sling.commons.scheduler.Scheduler; +import org.apache.sling.discovery.base.commons.BaseViewChecker; +import org.apache.sling.discovery.base.connectors.BaseConfig; +import org.apache.sling.discovery.base.connectors.announcement.AnnouncementRegistry; +import org.apache.sling.discovery.base.connectors.ping.ConnectorRegistry; +import org.apache.sling.settings.SlingSettingsService; + +public class DummyViewChecker extends BaseViewChecker { + + public static DummyViewChecker testConstructor( + SlingSettingsService slingSettingsService, + ResourceResolverFactory resourceResolverFactory, + ConnectorRegistry connectorRegistry, + AnnouncementRegistry announcementRegistry, + Scheduler scheduler, + BaseConfig connectorConfig) { + DummyViewChecker pinger = new DummyViewChecker(); + pinger.slingSettingsService = slingSettingsService; + pinger.resourceResolverFactory = resourceResolverFactory; + pinger.connectorRegistry = connectorRegistry; + pinger.announcementRegistry = announcementRegistry; + pinger.scheduler = scheduler; + pinger.connectorConfig = connectorConfig; + return pinger; + } + +} Propchange: sling/trunk/bundles/extensions/discovery/base/src/test/java/org/apache/sling/discovery/base/its/setup/mock/DummyViewChecker.java ------------------------------------------------------------------------------ svn:eol-style = native