You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by st...@apache.org on 2015/10/08 16:31:46 UTC
svn commit: r1707548 [3/4] - in
/sling/trunk/bundles/extensions/discovery/commons: ./
src/main/java/org/apache/sling/discovery/commons/providers/
src/main/java/org/apache/sling/discovery/commons/providers/impl/
src/main/java/org/apache/sling/discovery/...
Copied: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/impl/TestViewStateManager.java (from r1706814, sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/TestViewStateManager.java)
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/impl/TestViewStateManager.java?p2=sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/impl/TestViewStateManager.java&p1=sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/TestViewStateManager.java&r1=1706814&r2=1707548&rev=1707548&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/TestViewStateManager.java (original)
+++ sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/impl/TestViewStateManager.java Thu Oct 8 14:31:45 2015
@@ -16,146 +16,72 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.sling.discovery.commons.providers;
+package org.apache.sling.discovery.commons.providers.impl;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Random;
-import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
-import org.apache.sling.discovery.ClusterView;
-import org.apache.sling.discovery.InstanceDescription;
-import org.apache.sling.discovery.InstanceFilter;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
import org.apache.sling.discovery.TopologyEvent;
-import org.apache.sling.discovery.TopologyEventListener;
import org.apache.sling.discovery.commons.providers.BaseTopologyView;
-import org.apache.sling.discovery.commons.providers.ViewStateManager;
+import org.apache.sling.discovery.commons.providers.EventFactory;
+import org.apache.sling.discovery.commons.providers.spi.ConsistencyService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class TestViewStateManager {
- private class Listener implements TopologyEventListener {
-
- private List<TopologyEvent> events = new LinkedList<TopologyEvent>();
- private TopologyEvent lastEvent;
-
- public synchronized void handleTopologyEvent(TopologyEvent event) {
- events.add(event);
- lastEvent = event;
- }
-
- public synchronized List<TopologyEvent> getEvents() {
- return Collections.unmodifiableList(events);
- }
-
- public synchronized int countEvents() {
- return events.size();
- }
-
- public synchronized TopologyEvent getLastEvent() {
- return lastEvent;
- }
+ private static final Logger logger = LoggerFactory.getLogger(TestViewStateManager.class);
- public synchronized void clearEvents() {
- events.clear();
- }
+ private class ConsistencyServiceWithSemaphore implements ConsistencyService {
- public BaseTopologyView getLastView() {
- if (lastEvent==null) {
- return null;
- } else {
- switch(lastEvent.getType()) {
- case TOPOLOGY_INIT:
- case PROPERTIES_CHANGED:
- case TOPOLOGY_CHANGED: {
- return (BaseTopologyView) lastEvent.getNewView();
- }
- case TOPOLOGY_CHANGING:{
- return (BaseTopologyView) lastEvent.getOldView();
- }
- default: {
- fail("no other types supported yet");
- }
- }
- }
- return null;
- }
-
- }
-
- private class View extends BaseTopologyView {
-
- private final BaseTopologyView clonedView;
+ private final Semaphore semaphore;
+ private final Lock lock;
- public View() {
- clonedView = null;
+ public ConsistencyServiceWithSemaphore(Lock lock, Semaphore semaphore) {
+ this.lock = lock;
+ this.semaphore = semaphore;
}
- public View(BaseTopologyView clonedView) {
- this.clonedView = clonedView;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof View)) {
- return false;
- }
- final View other = (View) obj;
- if (clonedView!=null) {
- if (obj==clonedView) {
- return true;
+ public void sync(BaseTopologyView view, Runnable callback) {
+ try {
+ lock.unlock();
+ try{
+ semaphore.acquire();
+ } finally {
+ lock.lock();
}
- } else if (other.clonedView==this) {
- return true;
+ callback.run();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
}
- return super.equals(obj);
}
- @Override
- public int hashCode() {
- if (clonedView!=null) {
- return clonedView.hashCode();
- }
- return super.hashCode();
- }
-
- public View addInstance() {
- return this;
- }
-
- public InstanceDescription getLocalInstance() {
- throw new IllegalStateException("not yet implemented");
- }
-
- public Set<InstanceDescription> getInstances() {
- throw new IllegalStateException("not yet implemented");
- }
-
- public Set<InstanceDescription> findInstances(InstanceFilter filter) {
- throw new IllegalStateException("not yet implemented");
- }
-
- public Set<ClusterView> getClusterViews() {
- throw new IllegalStateException("not yet implemented");
- }
}
- private ViewStateManager mgr;
+ private ViewStateManagerImpl mgr;
private Random defaultRandom;
@Before
public void setup() throws Exception {
- mgr = new ViewStateManager();
+ mgr = new ViewStateManagerImpl(new ReentrantLock(), new ConsistencyService() {
+
+ public void sync(BaseTopologyView view, Runnable callback) {
+ callback.run();
+ }
+ });
defaultRandom = new Random(1234123412); // I want randomness yes, but deterministic, for some methods at least
}
@@ -165,73 +91,15 @@ public class TestViewStateManager {
defaultRandom= null;
}
- private void assertNoEvents(Listener listener) {
- assertEquals(0, listener.countEvents());
+ void assertEvents(Listener listener, TopologyEvent... events) {
+ TestHelper.assertEvents(mgr, listener, events);
}
- private void assertEvents(Listener listener, TopologyEvent... events) {
- assertEquals(events.length, listener.countEvents());
- for (int i = 0; i < events.length; i++) {
- TopologyEvent e = events[i];
- assertEquals(e.getType(), listener.getEvents().get(i).getType());
- switch(e.getType()) {
- case TOPOLOGY_INIT: {
- assertNull(listener.getEvents().get(i).getOldView());
- assertEquals(e.getNewView(), listener.getEvents().get(i).getNewView());
- break;
- }
- case TOPOLOGY_CHANGING: {
- assertEquals(e.getOldView(), listener.getEvents().get(i).getOldView());
- assertNull(listener.getEvents().get(i).getNewView());
- break;
- }
- case PROPERTIES_CHANGED:
- case TOPOLOGY_CHANGED: {
- assertEquals(e.getOldView(), listener.getEvents().get(i).getOldView());
- assertEquals(e.getNewView(), listener.getEvents().get(i).getNewView());
- break;
- }
- default: {
- fail("no other type supported yet");
- }
- }
- }
- listener.clearEvents();
- }
-
/** does couple loops randomly calling handleChanging() (or not) and then handleNewView().
- * Note: random is passed to allow customizing and not hardcoding this method to a particular random **/
- private void randomEventLoop(final Random random, Listener... listeners) {
- for(int i=0; i<100; i++) {
- final boolean shouldCallChanging = random.nextBoolean();
- if (shouldCallChanging) {
- // dont always do a changing
- mgr.handleChanging();
- for(int j=0; j<listeners.length; j++) {
- assertEvents(listeners[j], ViewStateManager.newChangingEvent(listeners[j].getLastView()));
- }
- } else {
- for(int j=0; j<listeners.length; j++) {
- assertNoEvents(listeners[j]);
- }
- }
- final BaseTopologyView view = new View().addInstance();
- BaseTopologyView[] lastViews = new BaseTopologyView[listeners.length];
- for(int j=0; j<listeners.length; j++) {
- lastViews[j] = listeners[j].getLastView();
- }
- mgr.handleNewView(view);
- if (!shouldCallChanging) {
- // in that case I should still get a CHANGING - by contract
- for(int j=0; j<listeners.length; j++) {
- assertEvents(listeners[j], ViewStateManager.newChangingEvent(lastViews[j]), ViewStateManager.newChangedEvent(lastViews[j], view));
- }
- } else {
- for(int j=0; j<listeners.length; j++) {
- assertEvents(listeners[j], ViewStateManager.newChangedEvent(lastViews[j], view));
- }
- }
- }
+ * Note: random is passed to allow customizing and not hardcoding this method to a particular random
+ * @throws InterruptedException **/
+ private void randomEventLoop(final Random random, Listener... listeners) throws InterruptedException {
+ TestHelper.randomEventLoop(mgr, null, 100, -1, random, listeners);
}
@Test
@@ -254,14 +122,14 @@ public class TestViewStateManager {
public void testBindActivateChangingChanged() throws Exception {
final Listener listener = new Listener();
mgr.bind(listener);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleActivated();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertEvents(listener, ViewStateManager.newInitEvent(view));
+ assertEvents(listener, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener);
}
@@ -269,14 +137,14 @@ public class TestViewStateManager {
public void testBindChangingActivateChanged() throws Exception {
final Listener listener = new Listener();
mgr.bind(listener);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleActivated();
- assertNoEvents(listener);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertEvents(listener, ViewStateManager.newInitEvent(view));
+ assertEvents(listener, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener);
}
@@ -284,14 +152,14 @@ public class TestViewStateManager {
public void testBindChangingChangedActivate() throws Exception {
final Listener listener = new Listener();
mgr.bind(listener);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleActivated();
- assertEvents(listener, ViewStateManager.newInitEvent(view));
+ assertEvents(listener, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener);
}
@@ -299,19 +167,19 @@ public class TestViewStateManager {
public void testBindChangingChangedChangingActivate() throws Exception {
final Listener listener = new Listener();
mgr.bind(listener);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleActivated();
- assertNoEvents(listener);
- final BaseTopologyView view2 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view2 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view2);
- assertEvents(listener, ViewStateManager.newInitEvent(view2));
+ assertEvents(listener, EventFactory.newInitEvent(view2));
randomEventLoop(defaultRandom, listener);
}
@@ -319,17 +187,17 @@ public class TestViewStateManager {
public void testBindChangedChangingActivate() throws Exception {
final Listener listener = new Listener();
mgr.bind(listener);
- assertNoEvents(listener);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleActivated();
- assertNoEvents(listener);
- final BaseTopologyView view2 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view2 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view2);
- assertEvents(listener, ViewStateManager.newInitEvent(view2));
+ assertEvents(listener, EventFactory.newInitEvent(view2));
randomEventLoop(defaultRandom, listener);
}
@@ -338,15 +206,15 @@ public class TestViewStateManager {
final Listener listener = new Listener();
// first activate
mgr.handleActivated();
- assertNoEvents(listener); // paranoia
+ TestHelper.assertNoEvents(listener); // paranoia
// then bind
mgr.bind(listener);
- assertNoEvents(listener); // there was no changing or changed yet
+ TestHelper.assertNoEvents(listener); // there was no changing or changed yet
mgr.handleChanging();
- assertNoEvents(listener);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertEvents(listener, ViewStateManager.newInitEvent(view));
+ assertEvents(listener, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener);
}
@@ -355,15 +223,15 @@ public class TestViewStateManager {
final Listener listener = new Listener();
// first activate
mgr.handleActivated();
- assertNoEvents(listener); // paranoia
+ TestHelper.assertNoEvents(listener); // paranoia
mgr.handleChanging();
- assertNoEvents(listener); // no listener yet
+ TestHelper.assertNoEvents(listener); // no listener yet
// then bind
mgr.bind(listener);
- assertNoEvents(listener); // no changed event yet
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener); // no changed event yet
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertEvents(listener, ViewStateManager.newInitEvent(view));
+ assertEvents(listener, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener);
}
@@ -372,15 +240,15 @@ public class TestViewStateManager {
final Listener listener = new Listener();
// first activate
mgr.handleActivated();
- assertNoEvents(listener); // paranoia
+ TestHelper.assertNoEvents(listener); // paranoia
mgr.handleChanging();
- assertNoEvents(listener); // no listener yet
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener); // no listener yet
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertNoEvents(listener); // no listener yet
+ TestHelper.assertNoEvents(listener); // no listener yet
// then bind
mgr.bind(listener);
- assertEvents(listener, ViewStateManager.newInitEvent(view));
+ assertEvents(listener, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener);
}
@@ -390,19 +258,19 @@ public class TestViewStateManager {
final Listener listener2 = new Listener();
mgr.bind(listener1);
- assertNoEvents(listener1);
+ TestHelper.assertNoEvents(listener1);
mgr.handleActivated();
- assertNoEvents(listener1);
+ TestHelper.assertNoEvents(listener1);
mgr.bind(listener2);
- assertNoEvents(listener1);
- assertNoEvents(listener2);
+ TestHelper.assertNoEvents(listener1);
+ TestHelper.assertNoEvents(listener2);
mgr.handleChanging();
- assertNoEvents(listener1);
- assertNoEvents(listener2);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener1);
+ TestHelper.assertNoEvents(listener2);
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertEvents(listener1, ViewStateManager.newInitEvent(view));
- assertEvents(listener2, ViewStateManager.newInitEvent(view));
+ assertEvents(listener1, EventFactory.newInitEvent(view));
+ assertEvents(listener2, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener1, listener2);
}
@@ -413,18 +281,18 @@ public class TestViewStateManager {
final Listener listener2 = new Listener();
mgr.bind(listener1);
- assertNoEvents(listener1);
+ TestHelper.assertNoEvents(listener1);
mgr.handleActivated();
- assertNoEvents(listener1);
+ TestHelper.assertNoEvents(listener1);
mgr.handleChanging();
- assertNoEvents(listener1);
+ TestHelper.assertNoEvents(listener1);
mgr.bind(listener2);
- assertNoEvents(listener1);
- assertNoEvents(listener2);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener1);
+ TestHelper.assertNoEvents(listener2);
+ final BaseTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertEvents(listener1, ViewStateManager.newInitEvent(view));
- assertEvents(listener2, ViewStateManager.newInitEvent(view));
+ assertEvents(listener1, EventFactory.newInitEvent(view));
+ assertEvents(listener2, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener1, listener2);
}
@@ -435,11 +303,11 @@ public class TestViewStateManager {
mgr.handleActivated();
mgr.bind(listener);
mgr.handleChanging();
- final BaseTopologyView view = new View().addInstance();
+ final SimpleTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertEvents(listener, ViewStateManager.newInitEvent(view));
- mgr.handleNewView(clone(view));
- assertNoEvents(listener);
+ assertEvents(listener, EventFactory.newInitEvent(view));
+ mgr.handleNewView(SimpleTopologyView.clone(view));
+ TestHelper.assertNoEvents(listener);
randomEventLoop(defaultRandom, listener);
}
@@ -449,15 +317,15 @@ public class TestViewStateManager {
mgr.handleActivated();
mgr.bind(listener1);
mgr.handleChanging();
- final BaseTopologyView view = new View().addInstance();
+ final SimpleTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertEvents(listener1, ViewStateManager.newInitEvent(view));
+ assertEvents(listener1, EventFactory.newInitEvent(view));
final Listener listener2 = new Listener();
mgr.bind(listener2);
- mgr.handleNewView(clone(view));
- assertNoEvents(listener1);
- assertEvents(listener2, ViewStateManager.newInitEvent(view));
+ mgr.handleNewView(SimpleTopologyView.clone(view));
+ TestHelper.assertNoEvents(listener1);
+ assertEvents(listener2, EventFactory.newInitEvent(view));
randomEventLoop(defaultRandom, listener1, listener2);
}
@@ -465,14 +333,14 @@ public class TestViewStateManager {
public void testActivateChangedBindDuplicateHandleNewView() throws Exception {
final Listener listener = new Listener();
mgr.handleActivated();
- assertNoEvents(listener);
- final BaseTopologyView view = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final SimpleTopologyView view = new SimpleTopologyView().addInstance();
mgr.handleNewView(view);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.bind(listener);
- assertEvents(listener, ViewStateManager.newInitEvent(view));
- mgr.handleNewView(clone(view));
- assertNoEvents(listener);
+ assertEvents(listener, EventFactory.newInitEvent(view));
+ mgr.handleNewView(SimpleTopologyView.clone(view));
+ TestHelper.assertNoEvents(listener);
randomEventLoop(defaultRandom, listener);
}
@@ -480,17 +348,17 @@ public class TestViewStateManager {
public void testBindActivateChangedChanged() throws Exception {
final Listener listener = new Listener();
mgr.handleActivated();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.bind(listener);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
- final BaseTopologyView view1 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view1 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view1);
- assertEvents(listener, ViewStateManager.newInitEvent(view1));
- final BaseTopologyView view2 = new View().addInstance();
+ assertEvents(listener, EventFactory.newInitEvent(view1));
+ final BaseTopologyView view2 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view2);
- assertEvents(listener, ViewStateManager.newChangingEvent(view1), ViewStateManager.newChangedEvent(view1, view2));
+ assertEvents(listener, EventFactory.newChangingEvent(view1), EventFactory.newChangedEvent(view1, view2));
randomEventLoop(defaultRandom, listener);
}
@@ -498,72 +366,225 @@ public class TestViewStateManager {
public void testBindActivateChangedDeactivateChangingActivateChanged() throws Exception {
final Listener listener = new Listener();
mgr.bind(listener);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleActivated();
- assertNoEvents(listener);
- final BaseTopologyView view1 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view1 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view1);
- assertEvents(listener, ViewStateManager.newInitEvent(view1));
+ assertEvents(listener, EventFactory.newInitEvent(view1));
mgr.handleDeactivated();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.bind(listener); // need to bind again after deactivate
mgr.handleActivated();
- assertNoEvents(listener);
- final BaseTopologyView view2 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view2 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view2);
- assertEvents(listener, ViewStateManager.newInitEvent(view2));
+ assertEvents(listener, EventFactory.newInitEvent(view2));
}
@Test
public void testBindActivateChangedDeactivateChangedActivateChanged() throws Exception {
final Listener listener = new Listener();
mgr.bind(listener);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleActivated();
- assertNoEvents(listener);
- final BaseTopologyView view1 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view1 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view1);
- assertEvents(listener, ViewStateManager.newInitEvent(view1));
+ assertEvents(listener, EventFactory.newInitEvent(view1));
mgr.handleDeactivated();
- assertNoEvents(listener);
- final BaseTopologyView view2 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view2 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view2);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.bind(listener); // need to bind again after deactivate
mgr.handleActivated();
- assertEvents(listener, ViewStateManager.newInitEvent(view2));
- final BaseTopologyView view3 = new View().addInstance();
+ assertEvents(listener, EventFactory.newInitEvent(view2));
+ final BaseTopologyView view3 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view3);
- assertEvents(listener, ViewStateManager.newChangingEvent(view2), ViewStateManager.newChangedEvent(view2, view3));
+ assertEvents(listener, EventFactory.newChangingEvent(view2), EventFactory.newChangedEvent(view2, view3));
}
@Test
public void testBindActivateChangedChangingDeactivateActivateChangingChanged() throws Exception {
final Listener listener = new Listener();
mgr.bind(listener);
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleActivated();
- assertNoEvents(listener);
- final BaseTopologyView view1 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view1 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view1);
- assertEvents(listener, ViewStateManager.newInitEvent(view1));
+ assertEvents(listener, EventFactory.newInitEvent(view1));
mgr.handleChanging();
- assertEvents(listener, ViewStateManager.newChangingEvent(view1));
+ assertEvents(listener, EventFactory.newChangingEvent(view1));
mgr.handleDeactivated();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.bind(listener); // need to bind again after deactivate
mgr.handleActivated();
- assertNoEvents(listener);
+ TestHelper.assertNoEvents(listener);
mgr.handleChanging();
- assertNoEvents(listener);
- final BaseTopologyView view2 = new View().addInstance();
+ TestHelper.assertNoEvents(listener);
+ final BaseTopologyView view2 = new SimpleTopologyView().addInstance();
mgr.handleNewView(view2);
- assertEvents(listener, ViewStateManager.newInitEvent(view2));
+ assertEvents(listener, EventFactory.newInitEvent(view2));
}
+
+ @Test
+ public void testConsistencyService_noConcurrency() throws Exception {
+ final org.apache.log4j.Logger commonsLogger = LogManager.getRootLogger().getLogger("org.apache.sling.discovery.commons.providers");
+ final org.apache.log4j.Level logLevel = commonsLogger.getLevel();
+ commonsLogger.setLevel(Level.INFO); // change here to DEBUG in case of issues with this test
+ final Semaphore serviceSemaphore = new Semaphore(0);
+ final ReentrantLock lock = new ReentrantLock();
+ final ConsistencyServiceWithSemaphore cs = new ConsistencyServiceWithSemaphore(lock, serviceSemaphore );
+ mgr = new ViewStateManagerImpl(lock, cs);
+ final Listener listener = new Listener();
+ mgr.bind(listener);
+ TestHelper.assertNoEvents(listener);
+ mgr.handleActivated();
+ TestHelper.assertNoEvents(listener);
+ final String slingId1 = UUID.randomUUID().toString();
+ final String slingId2 = UUID.randomUUID().toString();
+ final String clusterId = UUID.randomUUID().toString();
+ final SimpleClusterView cluster = new SimpleClusterView(clusterId);
+ final SimpleTopologyView view1 = new SimpleTopologyView()
+ .addInstance(slingId1, cluster, true, true)
+ .addInstance(slingId2, cluster, false, false);
+ async(new Runnable() {
+
+ public void run() {
+ mgr.handleNewView(view1);
+ }
+
+ });
+ Thread.sleep(1000);
+ TestHelper.assertNoEvents(listener);
+ serviceSemaphore.release(1);
+ Thread.sleep(1000);
+ assertEvents(listener, EventFactory.newInitEvent(view1));
+ mgr.handleChanging();
+ assertEvents(listener, EventFactory.newChangingEvent(view1));
+ final SimpleTopologyView view2 = SimpleTopologyView.clone(view1).removeInstance(slingId2);
+ async(new Runnable() {
+
+ public void run() {
+ mgr.handleNewView(view2);
+ }
+
+ });
+ logger.debug("run: waiting for 1sec");
+ Thread.sleep(1000);
+ logger.debug("run: asserting no events");
+ TestHelper.assertNoEvents(listener);
+ logger.debug("run: releasing consistencyService");
+ serviceSemaphore.release(1);
+ logger.debug("run: waiting 1sec");
+ Thread.sleep(1000);
+ logger.debug("run: asserting 1 event");
+ assertEvents(listener, EventFactory.newChangedEvent(view1, view2));
+ commonsLogger.setLevel(Level.INFO); // back to default
+ }
+
+ private void async(Runnable runnable) {
+ new Thread(runnable).start();
+ }
+
+ @Test
+ public void testConsistencyService_withConcurrency() throws Exception {
+ final org.apache.log4j.Logger commonsLogger = LogManager.getRootLogger().getLogger("org.apache.sling.discovery.commons.providers");
+ final org.apache.log4j.Level logLevel = commonsLogger.getLevel();
+ commonsLogger.setLevel(Level.INFO); // change here to DEBUG in case of issues with this test
+ final Semaphore serviceSemaphore = new Semaphore(0);
+ final Semaphore testSemaphore = new Semaphore(0);
+ final ReentrantLock lock = new ReentrantLock();
+ final ConsistencyServiceWithSemaphore cs = new ConsistencyServiceWithSemaphore(lock, serviceSemaphore );
+ mgr = new ViewStateManagerImpl(lock, cs);
+ final Listener listener = new Listener();
+ mgr.bind(listener);
+ TestHelper.assertNoEvents(listener);
+ mgr.handleActivated();
+ TestHelper.assertNoEvents(listener);
+ final String slingId1 = UUID.randomUUID().toString();
+ final String slingId2 = UUID.randomUUID().toString();
+ final String slingId3 = UUID.randomUUID().toString();
+ final String clusterId = UUID.randomUUID().toString();
+ final SimpleClusterView cluster = new SimpleClusterView(clusterId);
+ final SimpleTopologyView view1 = new SimpleTopologyView()
+ .addInstance(slingId1, cluster, true, true)
+ .addInstance(slingId2, cluster, false, false)
+ .addInstance(slingId3, cluster, false, false);
+ final SimpleTopologyView view2 = SimpleTopologyView.clone(view1).removeInstance(slingId2);
+ final SimpleTopologyView view3 = SimpleTopologyView.clone(view1).removeInstance(slingId2).removeInstance(slingId3);
+ async(new Runnable() {
+
+ public void run() {
+ mgr.handleNewView(view1);
+ }
+
+ });
+ Thread.sleep(1000);
+ TestHelper.assertNoEvents(listener);
+ serviceSemaphore.release(1); // release the first one only
+ Thread.sleep(1000);
+ assertEvents(listener, EventFactory.newInitEvent(view1));
+ mgr.handleChanging();
+ assertEvents(listener, EventFactory.newChangingEvent(view1));
+ async(new Runnable() {
+
+ public void run() {
+ mgr.handleNewView(view2);
+ }
+
+ });
+ logger.debug("run: waiting 1sec");
+ Thread.sleep(1000);
+ logger.debug("run: asserting no events");
+ TestHelper.assertNoEvents(listener);
+ assertFalse("should not be locked", lock.isLocked());
+
+ logger.debug("run: issuing a second event");
+ // before releasing, issue another event, lets do a combination of changing/changed
+ async(new Runnable() {
- private BaseTopologyView clone(final BaseTopologyView view) {
- return new View(view);
+ public void run() {
+ logger.debug("run2: calling handleChanging...");
+ mgr.handleChanging();
+ try {
+ logger.debug("run2: done with handleChanging, acquiring testSemaphore...");
+ testSemaphore.acquire();
+ logger.debug("run2: calling handleNewView...");
+ mgr.handleNewView(view3);
+ logger.debug("run2: done with handleNewView...");
+ } catch (InterruptedException e) {
+ // fail
+ logger.error("interrupted: "+e, e);
+ }
+ }
+
+ });
+ logger.debug("run: waiting 1sec");
+ Thread.sleep(1000);
+ assertEquals("should be acquiring (by thread2)", 1, testSemaphore.getQueueLength());
+ // releasing the testSemaphore
+ testSemaphore.release();
+ logger.debug("run: waiting 1sec");
+ Thread.sleep(1000);
+ assertEquals("should have both threads now waiting", 2, serviceSemaphore.getQueueLength());
+ logger.debug("run: releasing consistencyService");
+ serviceSemaphore.release(1); // release the first one only
+ logger.debug("run: waiting 1sec");
+ Thread.sleep(1000);
+ assertFalse("should not be locked", lock.isLocked());
+ TestHelper.assertNoEvents(listener); // this should not have triggered any event
+ serviceSemaphore.release(1); // then release the 2nd one
+ logger.debug("run: waiting 1sec");
+ Thread.sleep(1000);
+ logger.debug("run: asserting 1 event");
+ final TopologyEvent changedEvent = EventFactory.newChangedEvent(view1, view3);
+ assertEvents(listener, changedEvent);
+ commonsLogger.setLevel(Level.INFO); // back to default
}
+
}
Added: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/DiscoLite.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/DiscoLite.java?rev=1707548&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/DiscoLite.java (added)
+++ sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/DiscoLite.java Thu Oct 8 14:31:45 2015
@@ -0,0 +1,74 @@
+/*
+ * 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.commons.providers.spi.impl;
+
+import java.util.Arrays;
+
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+// {"seq":8,"final":true,"id":"aae34e9a-b08d-409e-be10-9ff4106e5387","me":4,"active":[4],"deactivating":[],"inactive":[1,2,3]}
+public class DiscoLite {
+
+ private int seqNum;
+ private int me;
+ private Integer[] activeIds = new Integer[0];
+ private Integer[] inactiveIds = new Integer[0];
+ private Integer[] deactivating = new Integer[0];
+
+ public DiscoLite() {
+ // nothing here
+ }
+
+ public DiscoLite seq(int seqNum) {
+ this.seqNum = seqNum;
+ return this;
+ }
+
+ public DiscoLite me(int me) {
+ this.me = me;
+ return this;
+ }
+
+ public DiscoLite activeIds(Integer... activeIds) {
+ this.activeIds = activeIds;
+ return this;
+ }
+
+ public DiscoLite inactiveIds(Integer... inactiveIds) {
+ this.inactiveIds = inactiveIds;
+ return this;
+ }
+
+ public DiscoLite deactivatingIds(Integer... deactivating) {
+ this.deactivating = deactivating;
+ return this;
+ }
+
+ public String asJson() throws JSONException {
+ JSONObject json = new JSONObject();
+ json.put("me", me);
+ json.put("seq", seqNum);
+ json.put("active", new JSONArray(Arrays.asList(activeIds)));
+ json.put("inactive", new JSONArray(Arrays.asList(inactiveIds)));
+ json.put("deactivating", new JSONArray(Arrays.asList(deactivating)));
+ return json.toString();
+ }
+}
Propchange: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/DiscoLite.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockFactory.java?rev=1707548&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockFactory.java (added)
+++ sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockFactory.java Thu Oct 8 14:31:45 2015
@@ -0,0 +1,85 @@
+/*
+ * 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.commons.providers.spi.impl;
+
+import javax.jcr.Session;
+
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.commons.testing.jcr.RepositoryProvider;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.hamcrest.Description;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.api.Action;
+import org.jmock.api.Invocation;
+import org.jmock.integration.junit4.JUnit4Mockery;
+
+public class MockFactory {
+
+ public final Mockery context = new JUnit4Mockery();
+
+ public static ResourceResolverFactory mockResourceResolverFactory()
+ throws Exception {
+ return mockResourceResolverFactory(null);
+ }
+
+ public static ResourceResolverFactory mockResourceResolverFactory(final SlingRepository repositoryOrNull)
+ throws Exception {
+ Mockery context = new JUnit4Mockery();
+
+ final ResourceResolverFactory resourceResolverFactory = context
+ .mock(ResourceResolverFactory.class);
+ // final ResourceResolver resourceResolver = new MockResourceResolver();
+ // final ResourceResolver resourceResolver = new
+ // MockedResourceResolver();
+
+ context.checking(new Expectations() {
+ {
+ allowing(resourceResolverFactory)
+ .getAdministrativeResourceResolver(null);
+ will(new Action() {
+
+ public Object invoke(Invocation invocation)
+ throws Throwable {
+ return new MockedResourceResolver(repositoryOrNull);
+ }
+
+ public void describeTo(Description arg0) {
+ arg0.appendText("whateva - im going to create a new mockedresourceresolver");
+ }
+ });
+ }
+ });
+ return resourceResolverFactory;
+ }
+
+ public static void resetRepo() throws Exception {
+ Session l = RepositoryProvider.instance().getRepository()
+ .loginAdministrative(null);
+ try {
+ l.removeItem("/var");
+ l.save();
+ l.logout();
+ } catch (Exception e) {
+ l.refresh(false);
+ l.logout();
+ }
+ }
+
+}
Propchange: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResource.java?rev=1707548&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResource.java (added)
+++ sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResource.java Thu Oct 8 14:31:45 2015
@@ -0,0 +1,296 @@
+/*
+ * 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.commons.providers.spi.impl;
+
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+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.ModifiableValueMap;
+import org.apache.sling.api.resource.SyntheticResource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MockedResource extends SyntheticResource {
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ private final MockedResourceResolver mockedResourceResolver;
+ private Session session;
+
+ public MockedResource(MockedResourceResolver resourceResolver, String path,
+ String resourceType) {
+ super(resourceResolver, path, resourceType);
+ mockedResourceResolver = resourceResolver;
+
+ resourceResolver.register(this);
+ }
+
+ private Session getSession() {
+ synchronized (this) {
+ if (session == null) {
+ try {
+ session = mockedResourceResolver.getSession();
+ } catch (RepositoryException e) {
+ throw new RuntimeException("RepositoryException: " + e, e);
+ }
+ }
+ return session;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+// close();
+ super.finalize();
+ }
+
+ public void close() {
+ synchronized (this) {
+ if (session != null) {
+ if (session.isLive()) {
+ session.logout();
+ }
+ session = null;
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+ if (type.equals(Node.class)) {
+ try {
+ return (AdapterType) getSession().getNode(getPath());
+ } catch (Exception e) {
+ logger.error("Exception occurred: "+e, e);
+ throw new RuntimeException("Exception occurred: " + e, e);
+ }
+ } else if (type.equals(ValueMap.class)) {
+ try {
+ Session session = getSession();
+ Node node = session.getNode(getPath());
+ HashMap<String, Object> map = new HashMap<String, Object>();
+
+ PropertyIterator properties = node.getProperties();
+ while (properties.hasNext()) {
+ Property p = properties.nextProperty();
+ if (p.getType() == PropertyType.BOOLEAN) {
+ map.put(p.getName(), p.getBoolean());
+ } else if (p.getType() == PropertyType.STRING) {
+ map.put(p.getName(), p.getString());
+ } else if (p.getType() == PropertyType.DATE) {
+ map.put(p.getName(), p.getDate().getTime());
+ } else if (p.getType() == PropertyType.NAME) {
+ map.put(p.getName(), p.getName());
+ } else if (p.getType() == PropertyType.LONG) {
+ map.put(p.getName(), p.getLong());
+ } else {
+ throw new RuntimeException(
+ "Unsupported property type: " + p.getType());
+ }
+ }
+ ValueMap valueMap = new ValueMapDecorator(map);
+ return (AdapterType) valueMap;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ } else if (type.equals(ModifiableValueMap.class)) {
+ return (AdapterType) new ModifiableValueMap() {
+
+ public Collection<Object> values() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int size() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(Object arg0) {
+ Session session = getSession();
+ try{
+ final Node node = session.getNode(getPath());
+ final Property p = node.getProperty(String.valueOf(arg0));
+ if (p!=null) {
+ p.remove();
+ }
+ // this is not according to the spec - but OK for tests since
+ // the return value is never used
+ return null;
+ } catch(PathNotFoundException pnfe) {
+ // perfectly fine
+ return null;
+ } catch(RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void putAll(Map<? extends String, ? extends Object> arg0) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object put(String arg0, Object arg1) {
+ Session session = getSession();
+ try{
+ final Node node = session.getNode(getPath());
+ Object result = null;
+ if (node.hasProperty(arg0)) {
+ final Property previous = node.getProperty(arg0);
+ if (previous==null) {
+ // null
+ } else if (previous.getType() == PropertyType.STRING) {
+ result = previous.getString();
+ } else if (previous.getType() == PropertyType.DATE) {
+ result = previous.getDate();
+ } else if (previous.getType() == PropertyType.BOOLEAN) {
+ result = previous.getBoolean();
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ }
+ if (arg1 instanceof String) {
+ node.setProperty(arg0, (String)arg1);
+ } else if (arg1 instanceof Calendar) {
+ node.setProperty(arg0, (Calendar)arg1);
+ } else if (arg1 instanceof Boolean) {
+ node.setProperty(arg0, (Boolean)arg1);
+ } else if (arg1 instanceof Date) {
+ final Calendar c = Calendar.getInstance();
+ c.setTime((Date)arg1);
+ node.setProperty(arg0, c);
+ } else if (arg1 instanceof Number) {
+ Number n = (Number)arg1;
+ node.setProperty(arg0, n.longValue());
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ return result;
+ } catch(RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Set<String> keySet() {
+ Session session = getSession();
+ try {
+ final Node node = session.getNode(getPath());
+ final PropertyIterator pi = node.getProperties();
+ final Set<String> result = new HashSet<String>();
+ while(pi.hasNext()) {
+ final Property p = pi.nextProperty();
+ result.add(p.getName());
+ }
+ return result;
+ } catch (RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean isEmpty() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object get(Object arg0) {
+ Session session = getSession();
+ try{
+ final Node node = session.getNode(getPath());
+ final String key = String.valueOf(arg0);
+ if (node.hasProperty(key)) {
+ return node.getProperty(key);
+ } else {
+ return null;
+ }
+ } catch(RepositoryException re) {
+ throw new RuntimeException(re);
+ }
+ }
+
+ public Set<Entry<String, Object>> entrySet() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean containsValue(Object arg0) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean containsKey(Object arg0) {
+ Session session = getSession();
+ try{
+ final Node node = session.getNode(getPath());
+ return node.hasProperty(String.valueOf(arg0));
+ } catch(RepositoryException re) {
+ throw new RuntimeException(re);
+ }
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public <T> T get(String name, T defaultValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ public <T> T get(String name, Class<T> type) {
+ Session session = getSession();
+ try{
+ final Node node = session.getNode(getPath());
+ if (node==null) {
+ return null;
+ }
+ if (!node.hasProperty(name)) {
+ return null;
+ }
+ Property p = node.getProperty(name);
+ if (p==null) {
+ return null;
+ }
+ if (type.equals(Calendar.class)) {
+ return (T) p.getDate();
+ } else if (type.equals(String.class)) {
+ return (T) p.getString();
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ } catch(RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ } else {
+ return super.adaptTo(type);
+ }
+ }
+
+}
Propchange: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResourceResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResourceResolver.java?rev=1707548&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResourceResolver.java (added)
+++ sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResourceResolver.java Thu Oct 8 14:31:45 2015
@@ -0,0 +1,329 @@
+/*
+ * 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.commons.providers.spi.impl;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sling.api.resource.LoginException;
+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.commons.testing.jcr.RepositoryProvider;
+import org.apache.sling.commons.testing.jcr.RepositoryUtil;
+import org.apache.sling.jcr.api.SlingRepository;
+
+public class MockedResourceResolver implements ResourceResolver {
+
+ private final SlingRepository repository;
+
+ private Session session;
+
+ private List<MockedResource> resources = new LinkedList<MockedResource>();
+
+ public MockedResourceResolver() throws RepositoryException {
+ this(null);
+ }
+
+ public MockedResourceResolver(SlingRepository repositoryOrNull) throws RepositoryException {
+ if (repositoryOrNull==null) {
+ this.repository = RepositoryProvider.instance().getRepository();
+ Session adminSession = null;
+ try {
+ adminSession = this.repository.loginAdministrative(null);
+ RepositoryUtil.registerSlingNodeTypes(adminSession);
+ } catch ( final IOException ioe ) {
+ throw new RepositoryException(ioe);
+ } finally {
+ if ( adminSession != null ) {
+ adminSession.logout();
+ }
+ }
+ } else {
+ this.repository = repositoryOrNull;
+ }
+ }
+
+ public Session getSession() throws RepositoryException {
+ synchronized (this) {
+ if (session != null) {
+ return session;
+ }
+ session = createSession();
+ return session;
+ }
+ }
+
+ private Repository getRepository() {
+ return repository;
+ }
+
+ private Session createSession() throws RepositoryException {
+ final Credentials credentials = new SimpleCredentials("admin",
+ "admin".toCharArray());
+ return repository.login(credentials, "default");
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+ if (type.equals(Session.class)) {
+ try {
+ return (AdapterType) getSession();
+ } catch (RepositoryException e) {
+ throw new RuntimeException("RepositoryException: " + e, e);
+ }
+ } else if (type.equals(Repository.class)) {
+ return (AdapterType) getRepository();
+ }
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public Resource resolve(HttpServletRequest request, String absPath) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public Resource resolve(String absPath) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ @Deprecated
+ public Resource resolve(HttpServletRequest request) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public String map(String resourcePath) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public String map(HttpServletRequest request, String resourcePath) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public Resource getResource(String path) {
+ Session session;
+ try {
+ session = getSession();
+ session.getNode(path);
+ } catch (PathNotFoundException e) {
+ return null;
+ } catch (RepositoryException e) {
+ throw new RuntimeException("RepositoryException: " + e, e);
+ }
+ return new MockedResource(this, path, "nt:unstructured");
+ }
+
+ public Resource getResource(Resource base, String path) {
+ if (base.getPath().equals("/")) {
+ return getResource("/" + path);
+ } else {
+ return getResource(base.getPath() + "/" + path);
+ }
+ }
+
+ public String[] getSearchPath() {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public Iterator<Resource> listChildren(Resource parent) {
+ try {
+ Node node = parent.adaptTo(Node.class);
+ final NodeIterator nodes = node.getNodes();
+ return new Iterator<Resource>() {
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Resource next() {
+ Node next = nodes.nextNode();
+ try {
+ return new MockedResource(MockedResourceResolver.this,
+ next.getPath(), "nt:unstructured");
+ } catch (RepositoryException e) {
+ throw new RuntimeException("RepositoryException: " + e,
+ e);
+ }
+ }
+
+ public boolean hasNext() {
+ return nodes.hasNext();
+ }
+ };
+ } catch (RepositoryException e) {
+ throw new RuntimeException("RepositoryException: " + e, e);
+ }
+ }
+
+ public Iterable<Resource> getChildren(Resource parent) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public Iterator<Resource> findResources(String query, String language) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public Iterator<Map<String, Object>> queryResources(String query,
+ String language) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public ResourceResolver clone(Map<String, Object> authenticationInfo)
+ throws LoginException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public boolean isLive() {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public void close() {
+ Iterator<MockedResource> it = resources.iterator();
+ while (it.hasNext()) {
+ MockedResource r = it.next();
+ r.close();
+ }
+ if (session != null) {
+ if (session.isLive()) {
+ session.logout();
+ }
+ session = null;
+ }
+ }
+
+ public void register(MockedResource mockedResource) {
+ resources.add(mockedResource);
+ }
+
+ public String getUserID() {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public Iterator<String> getAttributeNames() {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public Object getAttribute(String name) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public void delete(Resource resource) throws PersistenceException {
+ if (resources.contains(resource)) {
+ resources.remove(resource);
+ Node node = resource.adaptTo(Node.class);
+ try {
+ node.remove();
+ } catch (RepositoryException e) {
+ throw new PersistenceException("RepositoryException: "+e, e);
+ }
+ } else {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+ }
+
+ public Resource create(Resource parent, String name,
+ Map<String, Object> properties) throws PersistenceException {
+ final Node parentNode = parent.adaptTo(Node.class);
+ try {
+ final Node child;
+ if (properties!=null && properties.containsKey("jcr:primaryType")) {
+ child = parentNode.addNode(name, (String) properties.get("jcr:primaryType"));
+ } else {
+ child = parentNode.addNode(name);
+ }
+ if (properties!=null) {
+ final Iterator<Entry<String, Object>> it = properties.entrySet().iterator();
+ while(it.hasNext()) {
+ final Entry<String, Object> entry = it.next();
+ if (entry.getKey().equals("jcr:primaryType")) {
+ continue;
+ }
+ if (entry.getValue() instanceof String) {
+ child.setProperty(entry.getKey(), (String)entry.getValue());
+ } else if (entry.getValue() instanceof Boolean) {
+ child.setProperty(entry.getKey(), (Boolean)entry.getValue());
+ } else if (entry.getValue() instanceof Calendar) {
+ child.setProperty(entry.getKey(), (Calendar)entry.getValue());
+ } else {
+ throw new UnsupportedOperationException("Not implemented (entry.getValue(): "+entry.getValue()+")");
+ }
+ }
+ }
+ return getResource(parent, name);
+ } catch (RepositoryException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void revert() {
+ try {
+ this.session.refresh(false);
+ } catch (final RepositoryException re) {
+ throw new RuntimeException("Unable to commit changes.", re);
+ }
+ }
+
+ public void commit() throws PersistenceException {
+ try {
+ this.session.save();
+ } catch (final RepositoryException re) {
+ throw new PersistenceException("Unable to commit changes.", re);
+ }
+ }
+
+ public boolean hasChanges() {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public String getParentResourceType(Resource resource) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getParentResourceType(String resourceType) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean isResourceType(Resource resource, String resourceType) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void refresh() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Propchange: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/MockedResourceResolver.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/RepositoryHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/RepositoryHelper.java?rev=1707548&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/RepositoryHelper.java (added)
+++ sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/RepositoryHelper.java Thu Oct 8 14:31:45 2015
@@ -0,0 +1,281 @@
+/*
+ * 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.commons.providers.spi.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.naming.NamingException;
+
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl;
+import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
+import org.apache.jackrabbit.oak.plugins.commit.JcrConflictHandler;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
+import org.apache.jackrabbit.oak.plugins.name.NamespaceEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
+import org.apache.jackrabbit.oak.plugins.version.VersionEditorProvider;
+import org.apache.jackrabbit.oak.spi.commit.EditorHook;
+import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.commons.testing.jcr.RepositoryUtil;
+import org.apache.sling.commons.testing.jcr.RepositoryUtil.RepositoryWrapper;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RepositoryHelper {
+
+ private static class ShutdownThread extends Thread {
+
+ private SlingRepository repository;
+
+ public ShutdownThread(SlingRepository repository) {
+ this.repository = repository;
+ }
+ @Override
+ public void run() {
+ try {
+ stopRepository(repository);
+ } catch(Exception e) {
+ System.out.println("Exception in ShutdownThread:" + e);
+ }
+ }
+
+ }
+
+ private final static Logger logger = LoggerFactory.getLogger(RepositoryHelper.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 if (p.getType() == PropertyType.LONG) {
+ sb.append(p.getLong());
+ } 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);
+ }
+ }
+
+ static Map<SlingRepository,Session> adminSessions = new HashMap<SlingRepository, Session>();
+ /** from commons.testing.jcr **/
+ public static final String CONFIG_FILE = "jackrabbit-test-config.xml";
+
+ public static SlingRepository newRepository(String homeDir) throws RepositoryException {
+ SlingRepository repository = startRepository(homeDir);
+ Runtime.getRuntime().addShutdownHook(new ShutdownThread(repository));
+ return repository;
+ }
+
+ public static SlingRepository newOakRepository(NodeStore nodeStore) throws RepositoryException {
+ SlingRepository repository = new RepositoryWrapper(createOakRepository(nodeStore));
+ // Runtime.getRuntime().addShutdownHook(new ShutdownThread(repository));
+ return repository;
+ }
+
+ public static void initSlingNodeTypes(SlingRepository repository) throws RepositoryException {
+ Session adminSession = null;
+ try {
+ adminSession = repository.loginAdministrative(null);
+ RepositoryUtil.registerSlingNodeTypes(adminSession);
+ } catch ( final IOException ioe ) {
+ throw new RepositoryException(ioe);
+ } finally {
+ if ( adminSession != null ) {
+ adminSession.logout();
+ }
+ }
+ }
+
+ /**
+ * Start a new repository
+ * @return
+ *
+ * @throws RepositoryException when it is not possible to start the
+ * repository.
+ */
+ private static RepositoryWrapper startRepository(String homeDir) throws RepositoryException {
+ // copy the repository configuration file to the repository HOME_DIR
+ InputStream ins = RepositoryUtil.class.getClassLoader().getResourceAsStream(
+ CONFIG_FILE);
+ if (ins == null) {
+ throw new RepositoryException("Cannot get " + CONFIG_FILE);
+ }
+
+ File configFile = new File(homeDir, "repository.xml");
+ configFile.getParentFile().mkdirs();
+
+ FileOutputStream out = null;
+ try {
+ out = new FileOutputStream(configFile);
+ byte[] buf = new byte[1024];
+ int rd;
+ while ((rd = ins.read(buf)) >= 0) {
+ out.write(buf, 0, rd);
+ }
+ } catch (IOException ioe) {
+ throw new RepositoryException("Cannot copy configuration file to "
+ + configFile);
+ } finally {
+ try {
+ ins.close();
+ } catch (IOException ignore) {
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ignore) {
+ }
+ }
+ }
+
+ // somewhat dirty hack to have the derby.log file in a sensible
+ // location, but don't overwrite anything already set
+ if (System.getProperty("derby.stream.error.file") == null) {
+ String derbyLog = homeDir + "/derby.log";
+ System.setProperty("derby.stream.error.file", derbyLog);
+ }
+
+ final File f = new File(homeDir);
+ RepositoryWrapper repository = new RepositoryWrapper(JcrUtils.getRepository(f.toURI().toString()));
+ Session adminSession = repository.loginAdministrative(null);
+ adminSessions.put(repository, adminSession);
+ return repository;
+ }
+
+ /**
+ * Stop a repository.
+ */
+ public static void stopRepository(SlingRepository repository) throws NamingException {
+ Session adminSession = adminSessions.remove(repository);
+ if ( adminSession != null ) {
+ adminSession.logout();
+ }
+ }
+
+ public static Repository createOakRepository() {
+ return createOakRepository(new MemoryNodeStore());
+ }
+
+ public static Repository createOakRepository(NodeStore nodeStore) {
+ DefaultWhiteboard whiteboard = new DefaultWhiteboard();
+ final Oak oak = new Oak(nodeStore)
+ .with(new InitialContent())
+// .with(new ExtraSlingContent())
+
+ .with(JcrConflictHandler.createJcrConflictHandler())
+ .with(new EditorHook(new VersionEditorProvider()))
+
+ .with(new OpenSecurityProvider())
+
+// .with(new ValidatorProvider() {
+//
+// @Override
+// public Validator getRootValidator(
+// NodeState before, NodeState after, CommitInfo info) {
+// HashSet<String> set = newHashSet(after
+// .getChildNode(JCR_SYSTEM)
+// .getChildNode(REP_NAMESPACES)
+// .getChildNode(REP_NSDATA)
+// .getStrings(REP_PREFIXES));
+// set.add("sling");
+// return new NameValidator(set);
+// }
+// })
+ .with(new NamespaceEditorProvider())
+ .with(new TypeEditorProvider())
+// .with(new RegistrationEditorProvider())
+ .with(new ConflictValidatorProvider())
+
+ // index stuff
+// .with(indexProvider)
+// .with(indexEditorProvider)
+ .with("default")//getDefaultWorkspace())
+// .withAsyncIndexing()
+ .with(whiteboard)
+ ;
+
+// if (commitRateLimiter != null) {
+// oak.with(commitRateLimiter);
+// }
+
+ final ContentRepository contentRepository = oak.createContentRepository();
+ return new RepositoryImpl(contentRepository, whiteboard, new OpenSecurityProvider(), 1000, null);
+ }
+
+
+}
Propchange: sling/trunk/bundles/extensions/discovery/commons/src/test/java/org/apache/sling/discovery/commons/providers/spi/impl/RepositoryHelper.java
------------------------------------------------------------------------------
svn:eol-style = native