/* * ModeShape (http://www.modeshape.org) * * Licensed 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.modeshape.jcr.bus; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.modeshape.jcr.ClusteringHelper; import org.modeshape.jcr.cache.change.ChangeSet; import org.modeshape.jcr.cache.change.ChangeSetListener; import org.modeshape.jcr.clustering.ClusteringService; /** * Unit test for {@link ClusteredChangeBus} * * @author Horia Chiorean */ public class ClusteredChangeBusTest extends AbstractChangeBusTest { private static List<ClusteringService> clusteringServices; private ExecutorService executorService = Executors.newCachedThreadPool(); private List<ChangeBus> buses = new ArrayList<>(); @BeforeClass public static void beforeClass() throws Exception { ClusteringHelper.bindJGroupsToLocalAddress(); clusteringServices = IntStream.range(0, 3).mapToObj(i -> ClusteringService.startStandalone("clustered-change-bus-test", "config/cluster/jgroups-test-config.xml")) .collect(Collectors.toList()); } @AfterClass public static void afterClass() throws Exception { clusteringServices.forEach(ClusteringService::shutdown); ClusteringHelper.removeJGroupsBindings(); } @Override protected ChangeBus createRepositoryChangeBus() throws Exception { return startNewBus(0); } @Override public void afterEach() { super.afterEach(); try { buses.forEach(ChangeBus::shutdown); } finally { executorService.shutdownNow(); } } @Test public void oneBusShouldNotifyRegisteredListeners() throws Exception { // Create three observers ... TestListener listener1 = new TestListener(1); startBusWithRegisteredListener(listener1); // Send a change from the first bus ... ChangeSet changeSet = new TestChangeSet("ws1"); ChangeBus bus1 = buses.get(1); bus1.notify(changeSet); listener1.assertExpectedEvents(changeSet); } @Test public void twoBusesShouldNotifyEachOther() throws Exception { // Create three observers ... TestListener listener1 = new TestListener(2); TestListener listener2 = new TestListener(2); startBusWithRegisteredListener(listener1, listener2); // Send changeSet to one of the buses ... ChangeSet changeSet1 = new TestChangeSet("bus1"); buses.get(1).notify(changeSet1); ChangeSet changeSet2 = new TestChangeSet("bus2"); buses.get(2).notify(changeSet2); // Wait for the observers to be notified ... listener1.assertExpectedEvents(changeSet1, changeSet2); listener2.assertExpectedEvents(changeSet1, changeSet2); } @Test public void shouldNotSendChangesIfBusIsShutdown() throws Exception { // Create three observers ... TestListener listener1 = new TestListener(1); TestListener listener2 = new TestListener(1); TestListener listener3 = new TestListener(1); startBusWithRegisteredListener(listener1, listener2, listener3); // Send changeSet to one of the buses ... ChangeSet changeSet = new TestChangeSet("bus3"); buses.get(3).notify(changeSet); listener1.assertExpectedEvents(changeSet); listener2.assertExpectedEvents(changeSet); listener3.assertExpectedEvents(changeSet); // shut down buses buses.get(3).shutdown(); buses.get(2).shutdown(); listener3.clear(); listener2.clear(); changeSet = new TestChangeSet("bus1"); buses.get(1).notify(changeSet); listener2.assertNoEvents(); listener3.assertNoEvents(); } private ClusteredChangeBus startNewBus(int clusteringServiceIdx) throws Exception { ChangeBus internalBus = new RepositoryChangeBus("repo", executorService); ClusteredChangeBus bus = new ClusteredChangeBus(internalBus, clusteringServices.get(clusteringServiceIdx)); bus.start(); buses.add(bus); return bus; } private void startBusWithRegisteredListener(ChangeSetListener... listeners) throws Exception { for (int i = 0; i < listeners.length; i++) { ClusteredChangeBus bus = startNewBus(i); bus.register(listeners[i]); } } }