package org.infinispan.partitionhandling; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; import java.util.HashSet; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.distribution.MagicKey; import org.infinispan.partitionhandling.impl.PartitionHandlingManager; import org.infinispan.remoting.transport.Address; import org.infinispan.test.TestingUtil; import org.testng.annotations.Test; @Test(groups = "functional", testName = "partitionhandling.ThreeNodesReplicatedSplitAndMergeTest") public class ThreeNodesReplicatedSplitAndMergeTest extends BasePartitionHandlingTest { public ThreeNodesReplicatedSplitAndMergeTest() { numMembersInCluster = 3; cacheMode = CacheMode.REPL_SYNC; } public void testSplitAndMerge0() throws Exception { testSplitAndMerge(new PartitionDescriptor(0, 1), new PartitionDescriptor(2)); } public void testSplitAndMerge1() throws Exception { testSplitAndMerge(new PartitionDescriptor(0, 2), new PartitionDescriptor(1)); } public void testSplitAndMerge2() throws Exception { testSplitAndMerge(new PartitionDescriptor(1, 2), new PartitionDescriptor(0)); } private void testSplitAndMerge(PartitionDescriptor p0, PartitionDescriptor p1) throws Exception { Object k0 = new MagicKey(cache(p0.node(0)), cache(p0.node(1))); cache(0).put(k0, "v0"); Object k1 = new MagicKey(cache(p0.node(1)), cache(p1.node(0))); cache(1).put(k1, "v1"); Object k2 = new MagicKey(cache(p1.node(0)), cache(p0.node(0))); cache(2).put(k2, "v2"); HashSet<Address> allMembers = new HashSet<>(advancedCache(0).getRpcManager().getMembers()); //use set comparison as the merge view will reshuffle the order of nodes assertStableTopologyMembers(allMembers, partitionHandlingManager(0)); assertStableTopologyMembers(allMembers, partitionHandlingManager(1)); assertStableTopologyMembers(allMembers, partitionHandlingManager(2)); for (int i = 0; i < numMembersInCluster; i++) { assertEquals(AvailabilityMode.AVAILABLE, partitionHandlingManager(i).getAvailabilityMode()); } splitCluster(p0.getNodes(), p1.getNodes()); TestingUtil.waitForNoRebalance(cache(p0.node(0)), cache(p0.node(1))); partition(0).assertAvailabilityMode(AvailabilityMode.AVAILABLE); partition(1).assertAvailabilityMode(AvailabilityMode.DEGRADED_MODE); assertStableTopologyMembers(allMembers, partitionHandlingManager(p1.node(0))); //1. check key visibility in partition 1 partition(0).assertKeyAvailableForRead(k0, "v0"); partition(0).assertKeyAvailableForRead(k1, "v1"); partition(0).assertKeyAvailableForRead(k2, "v2"); //2. check key visibility in partition 2 partition(1).assertKeysNotAvailableForRead(k0, k1, k2); //3. check key ownership assertTrue(dataContainer(p0.node(0)).containsKey(k0)); assertTrue(dataContainer(p0.node(0)).containsKey(k1)); assertTrue(dataContainer(p0.node(0)).containsKey(k2)); assertTrue(dataContainer(p0.node(1)).containsKey(k0)); assertTrue(dataContainer(p0.node(1)).containsKey(k1)); assertTrue(dataContainer(p0.node(1)).containsKey(k2)); assertTrue(dataContainer(p1.node(0)).containsKey(k0)); assertTrue(dataContainer(p1.node(0)).containsKey(k1)); assertTrue(dataContainer(p1.node(0)).containsKey(k2)); //4. check writes on partition one partition(0).assertKeyAvailableForWrite(k0, "v00"); partition(0).assertKeyAvailableForWrite(k1, "v11"); partition(0).assertKeyAvailableForWrite(k2, "v22"); //5. check writes on partition two partition(1).assertKeyNotAvailableForWrite(k0); partition(1).assertKeyNotAvailableForWrite(k1); partition(1).assertKeyNotAvailableForWrite(k2); partition(0).merge(partition(1)); //use set comparison as the merge view will reshuffle the order of nodes expectStableTopologyMembers(allMembers, partitionHandlingManager(0)); expectStableTopologyMembers(allMembers, partitionHandlingManager(1)); expectStableTopologyMembers(allMembers, partitionHandlingManager(2)); partition(0).assertAvailabilityMode(AvailabilityMode.AVAILABLE); // 4. check data seen correctly assertExpectedValue("v00", k0); assertExpectedValue("v11", k1); assertExpectedValue("v22", k2); //5. recheck key ownership assertTrue(dataContainer(p0.node(0)).containsKey(k0)); assertTrue(dataContainer(p0.node(0)).containsKey(k1)); assertTrue(dataContainer(p0.node(0)).containsKey(k2)); assertTrue(dataContainer(p0.node(1)).containsKey(k0)); assertTrue(dataContainer(p0.node(1)).containsKey(k1)); assertTrue(dataContainer(p0.node(1)).containsKey(k2)); assertTrue(dataContainer(p1.node(0)).containsKey(k0)); assertTrue(dataContainer(p1.node(0)).containsKey(k1)); assertTrue(dataContainer(p1.node(0)).containsKey(k2)); cache(0).put(k0, "v000"); cache(1).put(k1, "v111"); cache(2).put(k2, "v222"); assertExpectedValue("v000", k0); assertExpectedValue("v111", k1); assertExpectedValue("v222", k2); assertNull(cache(0).get("nonExistentKey")); } private void assertStableTopologyMembers(HashSet<Address> allMembers, PartitionHandlingManager phm) { assertEquals(allMembers, new HashSet<Address>(phm.getLastStableTopology().getMembers())); } private void expectStableTopologyMembers(HashSet<Address> expected, PartitionHandlingManager phm) { eventuallyEquals(expected, () -> new HashSet<Address>(phm.getLastStableTopology().getMembers())); } }