/* * 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.cache30; import org.junit.experimental.categories.Category; import org.junit.Test; import static org.junit.Assert.*; import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase; import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; import org.apache.geode.test.junit.categories.DistributedTest; import org.apache.geode.cache.AttributesFactory; import org.apache.geode.cache.CacheException; import org.apache.geode.cache.CacheListener; import org.apache.geode.cache.CacheTransactionManager; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.EntryEvent; import org.apache.geode.cache.Region; import org.apache.geode.cache.Scope; import org.apache.geode.cache.UnsupportedOperationInTransactionException; import org.apache.geode.cache.util.CacheListenerAdapter; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.distributed.internal.InternalDistributedSystem; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.test.dunit.Host; import org.apache.geode.test.dunit.VM; /** * Test create + localDestroy for bug 34387 * * @since GemFire 5.0 */ @Category(DistributedTest.class) public class Bug34387DUnitTest extends JUnit4CacheTestCase { // private transient Region r; // private transient DistributedMember otherId; protected transient int invokeCount; static volatile boolean callbackFailure; public Bug34387DUnitTest() { super(); } protected static void callbackAssertEquals(String message, Object expected, Object actual) { if (expected == null && actual == null) return; if (expected != null && expected.equals(actual)) return; callbackFailure = true; // Throws an error that is ignored, but... assertEquals(message, expected, actual); } private VM getOtherVm() { Host host = Host.getHost(0); return host.getVM(0); } private void initOtherId() { VM vm = getOtherVm(); vm.invoke(new CacheSerializableRunnable("Connect") { public void run2() throws CacheException { getCache(); } }); vm.invoke(() -> Bug34387DUnitTest.getVMDistributedMember()); } private void doCommitOtherVm(final boolean doDestroy) { VM vm = getOtherVm(); vm.invoke(new CacheSerializableRunnable("create root") { public void run2() throws CacheException { AttributesFactory af = new AttributesFactory(); af.setScope(Scope.DISTRIBUTED_ACK); af.setConcurrencyChecksEnabled(true); Region r1 = createRootRegion("r1", af.create()); CacheTransactionManager ctm = getCache().getCacheTransactionManager(); ctm.begin(); r1.create("createKey", "createValue"); if (doDestroy) { try { r1.localDestroy("createKey"); fail("expected exception not thrown"); } catch (UnsupportedOperationInTransactionException e) { assertEquals(e.getMessage(), LocalizedStrings.TXStateStub_LOCAL_DESTROY_NOT_ALLOWED_IN_TRANSACTION .toLocalizedString()); } } else { try { r1.localInvalidate("createKey"); fail("expected exception not thrown"); } catch (UnsupportedOperationInTransactionException e) { assertEquals(e.getMessage(), LocalizedStrings.TXStateStub_LOCAL_INVALIDATE_NOT_ALLOWED_IN_TRANSACTION .toLocalizedString()); } } ctm.commit(); } }); } public static DistributedMember getVMDistributedMember() { return InternalDistributedSystem.getAnyInstance().getDistributedMember(); } ////////////////////// Test Methods ////////////////////// /** * test create followed by localDestroy */ @Test public void testCreateAndLD() throws CacheException { initOtherId(); AttributesFactory af = new AttributesFactory(); af.setDataPolicy(DataPolicy.REPLICATE); af.setScope(Scope.DISTRIBUTED_ACK); af.setConcurrencyChecksEnabled(true); callbackFailure = false; CacheListener cl1 = new CacheListenerAdapter() { public void afterCreate(EntryEvent e) { callbackAssertEquals("Keys not equal", "createKey", e.getKey()); callbackAssertEquals("Values not equal", "createValue", e.getNewValue()); Bug34387DUnitTest.this.invokeCount++; } }; af.addCacheListener(cl1); Region r1 = createRootRegion("r1", af.create()); this.invokeCount = 0; assertNull(r1.getEntry("createKey")); doCommitOtherVm(true); assertNotNull(r1.getEntry("createKey")); assertEquals("createValue", r1.getEntry("createKey").getValue()); assertEquals(1, this.invokeCount); assertFalse("Errors in callbacks; check logs for details", callbackFailure); } /** * test create followed by localInvalidate */ @Test public void testCreateAndLI() throws CacheException { initOtherId(); AttributesFactory af = new AttributesFactory(); af.setDataPolicy(DataPolicy.REPLICATE); af.setScope(Scope.DISTRIBUTED_ACK); af.setConcurrencyChecksEnabled(true); callbackFailure = false; CacheListener cl1 = new CacheListenerAdapter() { public void afterCreate(EntryEvent e) { callbackAssertEquals("key not equal", "createKey", e.getKey()); callbackAssertEquals("value not equal", "createValue", e.getNewValue()); Bug34387DUnitTest.this.invokeCount++; } }; af.addCacheListener(cl1); Region r1 = createRootRegion("r1", af.create()); this.invokeCount = 0; assertNull(r1.getEntry("createKey")); doCommitOtherVm(false); assertNotNull(r1.getEntry("createKey")); assertEquals("createValue", r1.getEntry("createKey").getValue()); assertEquals(1, this.invokeCount); assertFalse("Errors in callbacks; check logs for details", callbackFailure); } }