| /* |
| * 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 static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import org.junit.Test; |
| |
| import org.apache.geode.cache.AttributesFactory; |
| import org.apache.geode.cache.CacheException; |
| import org.apache.geode.cache.CacheListener; |
| import org.apache.geode.cache.EntryEvent; |
| import org.apache.geode.cache.EntryNotFoundException; |
| import org.apache.geode.cache.Region; |
| import org.apache.geode.cache.RegionAttributes; |
| import org.apache.geode.cache.RegionEvent; |
| import org.apache.geode.internal.cache.AbstractRegionMap; |
| import org.apache.geode.test.dunit.Wait; |
| |
| /** |
| * An abstract class whose test methods test the functionality of {@link CacheListener}s that are |
| * invoked locally. |
| * |
| * @see MultiVMRegionTestCase#testRemoteCacheWriter |
| * |
| * |
| * @since GemFire 3.0 |
| */ |
| public abstract class CacheListenerTestCase extends CacheLoaderTestCase { |
| |
| public CacheListenerTestCase() { |
| super(); |
| } |
| |
| /////////////////////// Test Methods /////////////////////// |
| |
| /** |
| * Tests that the <code>CacheListener</code> is called after an entry is |
| * {@linkplain CacheListener#afterCreate created}. |
| */ |
| @Test |
| public void testCacheListenerAfterCreate() throws CacheException { |
| String name = getUniqueName(); |
| final Object key = getUniqueName(); |
| final Object value = 42; |
| Object arg = "ARG"; |
| |
| TestCacheListener listener = new TestCacheListener() { |
| @Override |
| public void afterCreate2(EntryEvent event) { |
| assertEquals(key, event.getKey()); |
| assertEquals(value, event.getNewValue()); |
| assertNull(event.getOldValue()); |
| verifyEventProps(event); |
| } |
| |
| @Override |
| public void afterDestroy2(EntryEvent event) { |
| // This method will get invoked when the entry is destroyed |
| } |
| }; |
| |
| AttributesFactory factory = new AttributesFactory(getRegionAttributes()); |
| factory.setCacheListener(listener); |
| Region region = createRegion(name, factory.create()); |
| |
| region.create(key, value); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| |
| region.put(key, value); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| |
| region.create(key, value, arg); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| |
| region.put(key, value, arg); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| } |
| |
| /** |
| * Tests that the <code>CacheListener</code> is called after an entry is |
| * {@linkplain CacheListener#afterUpdate updated}. |
| */ |
| @Test |
| public void testCacheListenerAfterUpdate() throws CacheException { |
| String name = getUniqueName(); |
| final Object key = getUniqueName(); |
| final Object oldValue = 42; |
| final Object newValue = 43; |
| Object arg = "ARG"; |
| |
| TestCacheListener listener = new TestCacheListener() { |
| @Override |
| public void afterCreate2(EntryEvent event) { |
| // This method will get invoked when the region is populated |
| } |
| |
| @Override |
| public void afterDestroy2(EntryEvent event) { |
| // This method will get invoked when an entry is destroyed |
| } |
| |
| @Override |
| public void afterUpdate2(EntryEvent event) { |
| assertEquals(key, event.getKey()); |
| assertEquals(newValue, event.getNewValue()); |
| assertEquals(oldValue, event.getOldValue()); |
| verifyEventProps(event); |
| } |
| }; |
| |
| AttributesFactory factory = new AttributesFactory(getRegionAttributes()); |
| factory.setCacheListener(listener); |
| Region region = createRegion(name, factory.create()); |
| |
| region.create(key, oldValue); |
| assertTrue(listener.wasInvoked()); |
| region.put(key, newValue); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| |
| region.put(key, oldValue); |
| assertTrue(listener.wasInvoked()); |
| region.put(key, newValue); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| |
| region.create(key, oldValue); |
| assertTrue(listener.wasInvoked()); |
| region.put(key, newValue, arg); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| |
| region.put(key, oldValue); |
| assertTrue(listener.wasInvoked()); |
| region.put(key, newValue, arg); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| } |
| |
| /** |
| * Tests that the <code>CacheListener</code> is called after an entry is |
| * {@linkplain CacheListener#afterDestroy destroyed}. |
| */ |
| @Test |
| public void testCacheListenerAfterDestroy() throws CacheException { |
| String name = getUniqueName(); |
| final Object key = getUniqueName(); |
| final Object value = 42; |
| Object arg = "ARG"; |
| // final boolean localScope = getRegionAttributes().getScope().isLocal(); |
| |
| TestCacheListener listener = new TestCacheListener() { |
| @Override |
| public void afterCreate2(EntryEvent event) { |
| // This method will get invoked when the region is populated |
| } |
| |
| @Override |
| public void afterDestroy2(EntryEvent event) { |
| assertEquals(key, event.getKey()); |
| assertEquals(value, event.getOldValue()); |
| assertNull(event.getNewValue()); |
| verifyEventProps(event); |
| } |
| }; |
| |
| AttributesFactory factory = new AttributesFactory(getRegionAttributes()); |
| factory.setCacheListener(listener); |
| Region region = createRegion(name, factory.create()); |
| |
| region.create(key, value); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key); |
| assertTrue(listener.wasInvoked()); |
| |
| region.create(key, value); |
| assertTrue(listener.wasInvoked()); |
| region.destroy(key, arg); |
| assertTrue(listener.wasInvoked()); |
| } |
| |
| /** |
| * Tests that the <code>CacheListener</code> is called after an entry is |
| * {@linkplain CacheListener#afterInvalidate invalidated}. |
| */ |
| @Test |
| public void testCacheListenerAfterInvalidate() throws CacheException { |
| String name = getUniqueName(); |
| final Object key = getUniqueName(); |
| final Object value = 42; |
| // Object arg = "ARG"; |
| |
| TestCacheListener listener = new TestCacheListener() { |
| @Override |
| public void afterCreate2(EntryEvent event) { |
| // This method will get invoked when the region is populated |
| } |
| |
| @Override |
| public void afterInvalidate2(EntryEvent event) { |
| assertEquals(key, event.getKey()); |
| assertEquals(value, event.getOldValue()); |
| assertNull(event.getNewValue()); |
| verifyEventProps(event); |
| } |
| }; |
| |
| AttributesFactory factory = new AttributesFactory(getRegionAttributes()); |
| factory.setCacheListener(listener); |
| Region region = createRegion(name, factory.create()); |
| |
| // Does not exist so should not invoke listener |
| try { |
| region.invalidate(key); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ignored) { |
| } |
| assertFalse(listener.wasInvoked()); |
| |
| region.create(key, value); |
| assertTrue(listener.wasInvoked()); |
| region.invalidate(key); |
| assertTrue(listener.wasInvoked()); |
| |
| // already invalid so should not invoke listener |
| region.invalidate(key); |
| assertFalse(listener.wasInvoked()); |
| } |
| |
| @Test |
| public void testCacheListenerAfterInvalidateWithForce() throws CacheException { |
| AbstractRegionMap.FORCE_INVALIDATE_EVENT = true; |
| try { |
| String name = getUniqueName(); |
| final Object key = getUniqueName(); |
| final Object value = 42; |
| |
| TestCacheListener listener = new TestCacheListener() { |
| int invalidateCount = 0; |
| |
| @Override |
| public void afterCreate2(EntryEvent event) { |
| // This method will get invoked when the region is populated |
| } |
| |
| @Override |
| public void afterInvalidate2(EntryEvent event) { |
| invalidateCount++; |
| assertEquals(key, event.getKey()); |
| if (invalidateCount == 2) { |
| assertEquals(value, event.getOldValue()); |
| } else { |
| assertNull(event.getOldValue()); |
| } |
| assertNull(event.getNewValue()); |
| verifyEventProps(event); |
| } |
| }; |
| |
| AttributesFactory factory = new AttributesFactory(getRegionAttributes()); |
| factory.setCacheListener(listener); |
| Region region = createRegion(name, factory.create()); |
| |
| // Does not exist but should still invoke listener |
| try { |
| region.invalidate(key); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ignored) { |
| } |
| assertTrue(listener.wasInvoked()); |
| |
| region.create(key, value); |
| assertTrue(listener.wasInvoked()); |
| region.invalidate(key); |
| assertTrue(listener.wasInvoked()); |
| // already invalid but should still invoke listener |
| region.invalidate(key); |
| assertTrue(listener.wasInvoked()); |
| } finally { |
| AbstractRegionMap.FORCE_INVALIDATE_EVENT = false; |
| } |
| } |
| |
| /** |
| * Tests that the <code>CacheListener</code> is called after a region is destroyed. |
| * |
| * @see CacheListener#afterRegionDestroy |
| * @see CacheListener#close |
| */ |
| @Test |
| public void testCacheListenerAfterRegionDestroy() throws CacheException, InterruptedException { |
| |
| final String name = getUniqueName(); |
| Object arg = "ARG"; |
| // final String exception = "EXCEPTION"; |
| // final boolean localScope = getRegionAttributes().getScope().isLocal(); |
| |
| TestCacheListener listener = new TestCacheListener() { |
| private boolean closed = false; |
| private boolean destroyed = false; |
| |
| @Override |
| public boolean wasInvoked() { |
| boolean value = closed && destroyed; |
| super.wasInvoked(); |
| return value; |
| } |
| |
| @Override |
| public void close2() { |
| closed = true; |
| } |
| |
| @Override |
| public void afterRegionDestroy2(RegionEvent event) { |
| assertEquals(name, event.getRegion().getName()); |
| // this should be a distributed destroy unless the region |
| // is local scope |
| assertFalse(event.getOperation().isExpiration()); |
| assertFalse(event.isOriginRemote()); |
| |
| destroyed = true; |
| } |
| }; |
| |
| AttributesFactory factory = new AttributesFactory(getRegionAttributes()); |
| factory.setCacheListener(listener); |
| RegionAttributes attrs = factory.create(); |
| Region region; |
| |
| region = createRegion(name, attrs); |
| assertTrue(region.getAttributes().getCacheListener() != null); |
| region.destroyRegion(); |
| Wait.pause(100); // extra pause |
| assertTrue(region.isDestroyed()); |
| assertTrue(listener.wasInvoked()); |
| |
| region = createRegion(name, attrs); |
| region.destroyRegion(arg); |
| assertTrue(listener.wasInvoked()); |
| assertTrue(region.isDestroyed()); |
| } |
| |
| /** |
| * Tests that the <code>CacheListener</code> is called after a region is invalidated. |
| * |
| * @see CacheListener#afterRegionInvalidate |
| * @see CacheListener#close |
| */ |
| @Test |
| public void testCacheListenerAfterRegionInvalidate() throws CacheException, InterruptedException { |
| |
| final String name = getUniqueName(); |
| |
| TestCacheListener listener = new TestCacheListener() { |
| private boolean closed = false; |
| private boolean invalidated = false; |
| |
| @Override |
| public boolean wasInvoked() { |
| boolean value = invalidated; |
| super.wasInvoked(); |
| return value; |
| } |
| |
| @Override |
| public void close2() { |
| closed = true; |
| } |
| |
| @Override |
| public void afterRegionInvalidate2(RegionEvent event) { |
| assertEquals(name, event.getRegion().getName()); |
| assertFalse(event.getOperation().isExpiration()); |
| assertFalse(event.isOriginRemote()); |
| |
| invalidated = true; |
| } |
| }; |
| |
| AttributesFactory factory = new AttributesFactory(getRegionAttributes()); |
| factory.setCacheListener(listener); |
| RegionAttributes attrs = factory.create(); |
| Region region; |
| |
| region = createRegion(name, attrs); |
| region.invalidateRegion(); |
| Wait.pause(500); |
| assertTrue(listener.wasInvoked()); |
| assertEquals(0, region.values().size()); |
| } |
| |
| private void verifyEventProps(EntryEvent event) { |
| assertFalse(event.getOperation().isLoad()); |
| assertFalse(event.getOperation().isLocalLoad()); |
| assertFalse(event.getOperation().isNetLoad()); |
| assertFalse(event.getOperation().isNetSearch()); |
| } |
| |
| } |