| /* |
| * 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.geode.internal.cache.ha; |
| |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import java.util.Properties; |
| |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| import org.mockito.AdditionalAnswers; |
| |
| import org.apache.geode.cache.AttributesFactory; |
| import org.apache.geode.cache.CacheFactory; |
| import org.apache.geode.cache.DataPolicy; |
| import org.apache.geode.cache.Region; |
| import org.apache.geode.cache.Scope; |
| import org.apache.geode.distributed.DistributedSystem; |
| import org.apache.geode.internal.cache.EventID; |
| import org.apache.geode.internal.cache.GemFireCacheImpl; |
| import org.apache.geode.internal.cache.HARegion; |
| import org.apache.geode.internal.cache.InternalCache; |
| import org.apache.geode.test.dunit.Host; |
| import org.apache.geode.test.dunit.VM; |
| import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; |
| import org.apache.geode.test.junit.categories.ClientSubscriptionTest; |
| |
| /** |
| * Test to verify : |
| * |
| * 1)put() on a mirrored HARegion does not propagate 2)localDestroy() allowed on a mirrored region |
| * 3) GII happens normally |
| */ |
| @Category({ClientSubscriptionTest.class}) |
| public class HARegionDUnitTest extends JUnit4DistributedTestCase { |
| |
| VM vm0 = null; |
| |
| VM vm1 = null; |
| |
| private static InternalCache cache = null; |
| private static final String REGION_NAME = "HARegionDUnitTest_region"; |
| |
| /** constructor */ |
| public HARegionDUnitTest() { |
| super(); |
| } |
| |
| /** |
| * get the VM's |
| */ |
| @Override |
| public final void postSetUp() throws Exception { |
| final Host host = Host.getHost(0); |
| vm0 = host.getVM(0); |
| vm1 = host.getVM(1); |
| } |
| |
| /** |
| * close the cache in tearDown |
| */ |
| @Override |
| public final void preTearDown() throws Exception { |
| vm0.invoke(() -> HARegionDUnitTest.closeCache()); |
| vm1.invoke(() -> HARegionDUnitTest.closeCache()); |
| } |
| |
| /** |
| * create cache |
| * |
| */ |
| private InternalCache createCache() throws Exception { |
| Properties props = new Properties(); |
| DistributedSystem ds = getSystem(props); |
| ds.disconnect(); |
| ds = getSystem(props); |
| InternalCache cache = null; |
| cache = (InternalCache) CacheFactory.create(ds); |
| if (cache == null) { |
| throw new Exception("CacheFactory.create() returned null "); |
| } |
| return cache; |
| } |
| |
| /** |
| * 1) Create mirrored HARegion region1 in VM1 and VM2 2) do a put in VM1 3) assert that the put |
| * has not propagated from VM1 to VM2 4) do a put in VM2 5) assert that the value in VM1 has not |
| * changed to due to put in VM2 6) assert put in VM2 was successful by doing a get |
| * |
| */ |
| @Test |
| public void testLocalPut() { |
| vm0.invoke(() -> HARegionDUnitTest.createRegion()); |
| vm1.invoke(() -> HARegionDUnitTest.createRegion()); |
| vm0.invoke(() -> HARegionDUnitTest.putValue1()); |
| vm1.invoke(() -> HARegionDUnitTest.getNull()); |
| vm1.invoke(() -> HARegionDUnitTest.putValue2()); |
| vm0.invoke(() -> HARegionDUnitTest.getValue1()); |
| vm1.invoke(() -> HARegionDUnitTest.getValue2()); |
| |
| } |
| |
| /** |
| * 1) Create mirrored HARegion region1 in VM1 and VM2 2) do a put in VM1 3) assert that the put |
| * has not propagated from VM1 to VM2 4) do a put in VM2 5) assert that the value in VM1 has not |
| * changed to due to put in VM2 6) assert respective puts the VMs were successful by doing a get |
| * 7) localDestroy key in VM1 8) assert key has been destroyed in VM1 9) assert key has not been |
| * destroyed in VM2 |
| * |
| */ |
| @Test |
| public void testLocalDestroy() { |
| vm0.invoke(() -> HARegionDUnitTest.createRegion()); |
| vm1.invoke(() -> HARegionDUnitTest.createRegion()); |
| vm0.invoke(() -> HARegionDUnitTest.putValue1()); |
| vm1.invoke(() -> HARegionDUnitTest.getNull()); |
| vm1.invoke(() -> HARegionDUnitTest.putValue2()); |
| vm0.invoke(() -> HARegionDUnitTest.getValue1()); |
| vm1.invoke(() -> HARegionDUnitTest.getValue2()); |
| vm0.invoke(() -> HARegionDUnitTest.destroy()); |
| vm0.invoke(() -> HARegionDUnitTest.getNull()); |
| vm1.invoke(() -> HARegionDUnitTest.getValue2()); |
| } |
| |
| /** |
| * 1) Create mirrored HARegion region1 in VM1 2) do a put in VM1 3) get the value in VM1 to assert |
| * put has happened successfully 4) Create mirrored HARegion region1 in VM2 5) do a get in VM2 to |
| * verify that value was got through GII 6) do a put in VM2 7) assert put in VM2 was successful |
| * |
| */ |
| @Test |
| public void testGII() { |
| vm0.invoke(() -> HARegionDUnitTest.createRegion()); |
| vm0.invoke(() -> HARegionDUnitTest.putValue1()); |
| vm0.invoke(() -> HARegionDUnitTest.getValue1()); |
| vm1.invoke(() -> HARegionDUnitTest.createRegion()); |
| vm1.invoke(() -> HARegionDUnitTest.getValue1()); |
| vm1.invoke(() -> HARegionDUnitTest.putValue2()); |
| vm1.invoke(() -> HARegionDUnitTest.getValue2()); |
| |
| } |
| |
| /** |
| * 1) Create mirrored HARegion region1 in VM1 2) do a put in VM1 3) get the value in VM1 to assert |
| * put has happened successfully 4) Create mirrored HARegion region1 in VM2 5) do a get in VM2 to |
| * verify that value was got through GII 6) do a put in VM2 7) assert put in VM2 was successful |
| * |
| */ |
| @Test |
| public void testLocalDestroyRegion() { |
| vm0.invoke(() -> HARegionDUnitTest.createRegion()); |
| vm1.invoke(() -> HARegionDUnitTest.createRegion()); |
| vm0.invoke(() -> HARegionDUnitTest.destroyRegion()); |
| vm1.invoke(() -> HARegionDUnitTest.verifyRegionNotDestroyed()); |
| |
| } |
| |
| /** |
| * Destroy the region |
| * |
| */ |
| public static void destroyRegion() { |
| cache.getRegion(REGION_NAME).localDestroyRegion(null); |
| } |
| |
| /** |
| * Verify Region exists |
| * |
| */ |
| public static void verifyRegionNotDestroyed() { |
| assertTrue(cache.getRegion(REGION_NAME) != null); |
| } |
| |
| /** |
| * 1) Create mirrored HARegion region1 in VM1 2) do a put in VM1 3) get the value in VM1 to assert |
| * put has happened successfully 4) Create mirrored HARegion region1 in VM2 5) do a get in VM2 to |
| * verify that value was got through GII 6) do a put in VM2 7) assert put in VM2 was successful |
| * |
| */ |
| @Test |
| public void testQRM() { |
| vm0.invoke(() -> HARegionDUnitTest.createRegionQueue()); |
| vm1.invoke(() -> HARegionDUnitTest.createRegionQueue()); |
| vm0.invoke(() -> HARegionDUnitTest.verifyAddingDispatchMesgs()); |
| try { |
| Thread.sleep(5000); |
| } catch (InterruptedException e) { |
| fail("interrupted"); |
| } |
| vm1.invoke(() -> HARegionDUnitTest.verifyDispatchedMessagesRemoved()); |
| } |
| |
| /** |
| * create a client with 2 regions sharing a common writer |
| * |
| */ |
| |
| public static void createRegion() throws Exception { |
| HARegionDUnitTest test = new HARegionDUnitTest(); |
| cache = test.createCache(); |
| AttributesFactory factory = new AttributesFactory(); |
| factory.setScope(Scope.DISTRIBUTED_ACK); |
| factory.setDataPolicy(DataPolicy.REPLICATE); |
| |
| // Mock the HARegionQueue and answer the input CachedDeserializable when updateHAEventWrapper is |
| // called |
| HARegionQueue harq = mock(HARegionQueue.class); |
| when(harq.updateHAEventWrapper(any(), any(), any())) |
| .thenAnswer(AdditionalAnswers.returnsSecondArg()); |
| |
| HARegion.getInstance(REGION_NAME, (GemFireCacheImpl) cache, harq, factory.create()); |
| } |
| |
| private static HARegionQueue hrq = null; |
| |
| // private static int counter = 0; |
| |
| public static void createRegionQueue() throws Exception { |
| HARegionDUnitTest test = new HARegionDUnitTest(); |
| cache = test.createCache(); |
| /* |
| * AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.DISTRIBUTED_ACK); |
| * factory.setDataPolicy(DataPolicy.REPLICATE); |
| */ |
| hrq = HARegionQueue.getHARegionQueueInstance(REGION_NAME, cache, |
| HARegionQueue.NON_BLOCKING_HA_QUEUE, false); |
| EventID id1 = new EventID(new byte[] {1}, 1, 1); |
| EventID id2 = new EventID(new byte[] {1}, 1, 2); |
| ConflatableObject c1 = new ConflatableObject("1", "1", id1, false, REGION_NAME); |
| ConflatableObject c2 = new ConflatableObject("2", "2", id2, false, REGION_NAME); |
| hrq.put(c1); |
| hrq.put(c2); |
| |
| } |
| |
| public static void verifyAddingDispatchMesgs() { |
| assertTrue(HARegionQueue.getDispatchedMessagesMapForTesting().isEmpty()); |
| hrq.addDispatchedMessage(new ThreadIdentifier(new byte[1], 1), 1); |
| assertTrue(!HARegionQueue.getDispatchedMessagesMapForTesting().isEmpty()); |
| } |
| |
| |
| |
| public static void verifyDispatchedMessagesRemoved() { |
| try { |
| Region region = hrq.getRegion(); |
| if (region.get(new Long(0)) != null) { |
| fail("Expected message to have been deleted but it is not deleted"); |
| } |
| |
| if (region.get(new Long(1)) == null) { |
| fail("Expected message not to have been deleted but it is deleted"); |
| } |
| } catch (Exception e) { |
| fail("test failed due to an exception : " + e); |
| } |
| } |
| |
| /** |
| * close the cache |
| * |
| */ |
| public static void closeCache() { |
| if (cache != null && !cache.isClosed()) { |
| cache.close(); |
| cache.getDistributedSystem().disconnect(); |
| } |
| } |
| |
| /** |
| * do three puts on key-1 |
| * |
| */ |
| public static void putValue1() { |
| try { |
| Region r1 = cache.getRegion(Region.SEPARATOR + REGION_NAME); |
| r1.put("key-1", "value-1"); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| org.apache.geode.test.dunit.Assert.fail("failed while region.put()", ex); |
| } |
| } |
| |
| /** |
| * do three puts on key-1 |
| * |
| */ |
| public static void putValue2() { |
| try { |
| Region r1 = cache.getRegion(Region.SEPARATOR + REGION_NAME); |
| r1.put("key-1", "value-2"); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| org.apache.geode.test.dunit.Assert.fail("failed while region.put()", ex); |
| } |
| } |
| |
| /** |
| * do a get on region1 |
| * |
| */ |
| public static void getValue1() { |
| try { |
| Region r = cache.getRegion(Region.SEPARATOR + REGION_NAME); |
| if (!(r.get("key-1").equals("value-1"))) { |
| fail("expected value to be value-1 but it is not so"); |
| } |
| |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| org.apache.geode.test.dunit.Assert.fail("failed while region.get()", ex); |
| } |
| } |
| |
| /** |
| * do a get on region1 |
| * |
| */ |
| public static void getNull() { |
| try { |
| Region r = cache.getRegion(Region.SEPARATOR + REGION_NAME); |
| if (!(r.get("key-1") == (null))) { |
| fail("expected value to be null but it is not so"); |
| } |
| |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| org.apache.geode.test.dunit.Assert.fail("failed while region.get()", ex); |
| } |
| } |
| |
| /** |
| * do a get on region1 |
| * |
| */ |
| public static void getValue2() { |
| try { |
| Region r = cache.getRegion(Region.SEPARATOR + REGION_NAME); |
| if (!(r.get("key-1").equals("value-2"))) { |
| fail("expected value to be value-2 but it is not so"); |
| } |
| |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| org.apache.geode.test.dunit.Assert.fail("failed while region.get()", ex); |
| } |
| } |
| |
| /** |
| * destroy key-1 |
| * |
| */ |
| public static void destroy() { |
| try { |
| Region region1 = cache.getRegion(Region.SEPARATOR + REGION_NAME); |
| region1.localDestroy("key-1"); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| fail("test failed due to exception in destroy "); |
| } |
| } |
| |
| } |