/* * 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.clustering; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; 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.common.FixFor; import org.modeshape.jcr.ClusteringHelper; /** * Unit test for {@link ClusteringService} * * @author Horia Chiorean (hchiorea@redhat.com) */ public class ClusteringServiceTest { private static List<ClusteringService> cluster; @BeforeClass public static void beforeClass() throws Exception { ClusteringHelper.bindJGroupsToLocalAddress(); cluster = IntStream.range(0, 4) .mapToObj(i -> { String clusterName = "test-cluster" + (i % 2 == 0 ? "1" : "2"); return ClusteringService.startStandalone(clusterName, "config/cluster/jgroups-test-config.xml"); }) .collect(Collectors.toList()); } @AfterClass public static void afterClass() throws Exception { cluster.forEach(ClusteringService::shutdown); cluster.clear(); ClusteringHelper.removeJGroupsBindings(); } @Test public void shouldBroadcastMessagesBetweenServices() throws Exception { ClusteringService service1 = cluster.get(0); TestConsumer consumer1 = new TestConsumer("hello_1", "hello_2"); service1.addConsumer(consumer1); ClusteringService service2 = cluster.get(2); TestConsumer consumer2 = new TestConsumer("hello_1", "hello_2"); service2.addConsumer(consumer2); service1.sendMessage("hello_1"); service2.sendMessage("hello_2"); consumer1.assertAllPayloadsConsumed(); consumer2.assertAllPayloadsConsumed(); } @Test @FixFor( "MODE-2226" ) public void shouldAllowMultipleForksOffTheSameChannel() throws Exception { ClusteringService main11 = cluster.get(0); //cluster1 ClusteringService main12 = cluster.get(1); //cluster2 //fork11 communicates via the same fork stack to fork21 ClusteringService fork11 = startForked(main11); TestConsumer consumer11 = new TestConsumer("11", "21"); fork11.addConsumer(consumer11); //fork12 communicates via the same fork stack to fork22 ClusteringService fork12 = startForked(main12); TestConsumer consumer12 = new TestConsumer("12", "22"); fork12.addConsumer(consumer12); ClusteringService main21 = cluster.get(2); //cluster1 ClusteringService main22 = cluster.get(3); //cluster2 //fork21 communicates via the same fork stack to fork11 ClusteringService fork21 = startForked(main21); TestConsumer consumer21 = new TestConsumer("11", "21"); fork21.addConsumer(consumer21); //fork22 communicates via the same fork stack to fork12 ClusteringService fork22 = startForked(main22); TestConsumer consumer22 = new TestConsumer("12", "22"); fork22.addConsumer(consumer22); fork11.sendMessage("11"); fork21.sendMessage("21"); fork12.sendMessage("12"); fork22.sendMessage("22"); consumer11.assertAllPayloadsConsumed(); consumer12.assertAllPayloadsConsumed(); consumer21.assertAllPayloadsConsumed(); consumer22.assertAllPayloadsConsumed(); } private ClusteringService startForked(ClusteringService mainService) { ClusteringService service = ClusteringService.startForked(mainService.getChannel()); cluster.add(service); return service; } protected class TestConsumer extends MessageConsumer<String> { private List<String> payloads = new ArrayList<>(); private CountDownLatch payloadsLatch; protected TestConsumer(String... expectedPayloads) { super(String.class); payloads = Arrays.asList(expectedPayloads); payloadsLatch = new CountDownLatch(expectedPayloads.length); } @Override public void consume(String payload) { assertTrue(payload + " not expected", payloads.contains(payload)); payloadsLatch.countDown(); } protected void assertAllPayloadsConsumed() throws InterruptedException { assertTrue("Not all payloads received", payloadsLatch.await(1, TimeUnit.SECONDS)); } } }