blob: 234aec23d860ccd7d0533862a1354b4ef830658c [file] [log] [blame]
/*
* 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());
}
}