blob: 4f536820a4281197d10ae833b0589b4ef9ccf246 [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.cache.client;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.UnknownHostException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.cache.util.CacheListenerAdapter;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.test.dunit.DistributedTestCase;
import org.apache.geode.test.dunit.DistributedTestUtils;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.junit.categories.ClientServerTest;
@Category({ClientServerTest.class})
public class RemoveAllCacheListenerClientServerRegressionTest extends DistributedTestCase {
private final AtomicInteger serverPort = new AtomicInteger(0);
private final String REGION_NAME = "TestRegion";
private VM clientVM = null;
private VM serverVM = null;
private final String BB_MAILBOX_KEY = "error";
private final String NON_EXISTENT_KEY = "nonExistentKey";
@Override
public final void postSetUp() throws Exception {
disconnectAllFromDS();
IgnoredException.addIgnoredException("java.net.ConnectException");
reset();
}
@Override
public final void preTearDown() throws Exception {
disconnectAllFromDS();
reset();
}
private void reset() {
getBlackboard().initBlackboard();
getBlackboard().setMailbox(BB_MAILBOX_KEY, "");
clientVM = null;
serverVM = null;
serverPort.set(0);
}
// ================================================================================
// replicate on server
// caching proxy client
// server concurrency checks enabled
// client concurrency checks enabled
@Test
public void removeAllListenerReplicateCachingProxyServerChecksClientChecksTest() {
doRemoveAllTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, true, true);
}
@Test
public void destroyListenerReplicateCachingProxyServerChecksClientChecksTest() {
doDestroyTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, true, true);
}
@Test
public void removeListenerReplicateCachingProxyServerChecksClientChecksTest() {
doRemoveTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, true, true);
}
// ================================================================================
// partitioned on server
// caching proxy client
// server concurrency checks enabled
// client concurrency checks enabled
@Test
public void removeAllListenerPartitionCachingProxyServerChecksClientChecksTest() {
doRemoveAllTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, true, true);
}
@Test
public void destroyListenerPartitionCachingProxyServerChecksClientChecksTest() {
doDestroyTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, true, true);
}
@Test
public void removeListenerPartitionCachingProxyServerChecksClientChecksTest() {
doRemoveTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, true, true);
}
// ================================================================================
// replicate on server
// caching proxy client
// server concurrency checks disabled
// client concurrency checks enabled
@Test
public void removeAllListenerReplicateCachingProxyClientChecksOnlyTest() {
doRemoveAllTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, false, true);
}
@Test
public void destroyListenerReplicateCachingProxyClientChecksOnlyTest() {
doDestroyTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, false, true);
}
@Test
public void removeListenerReplicateCachingProxyClientChecksOnlyTest() {
doRemoveTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, false, true);
}
// ================================================================================
// partitioned on server
// caching proxy client
// server concurrency checks disabled
// client concurrency checks enabled
@Test
public void removeAllListenerPartitionCachingProxyClientChecksOnlyTest() {
doRemoveAllTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, false, true);
}
@Test
public void destroyListenerPartitionCachingProxyClientChecksOnlyTest() {
doDestroyTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, false, true);
}
@Test
public void removeListenerPartitionCachingProxyClientChecksOnlyTest() {
doRemoveTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, false, true);
}
// ================================================================================
// replicate on server
// caching proxy client
// server concurrency checks enabled
// client concurrency checks disabled
@Test
public void removeAllListenerReplicateCachingProxyServerChecksOnlyTest() {
doRemoveAllTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, true, false);
}
@Test
public void destroyListenerReplicateCachingProxyServerChecksOnlyTest() {
doDestroyTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, true, false);
}
@Test
public void removeListenerReplicateCachingProxyServerChecksOnlyTest() {
doRemoveTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, true, false);
}
// ================================================================================
// partitioned on server
// caching proxy client
// server concurrency checks enabled
// client concurrency checks disabled
@Test
public void removeAllListenerPartitionCachingProxyServerChecksOnlyTest() {
doRemoveAllTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, true, false);
}
@Test
public void destroyListenerPartitionCachingProxyServerChecksOnlyTest() {
doDestroyTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, true, false);
}
@Test
public void removeListenerPartitionCachingProxyServerChecksOnlyTest() {
doRemoveTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, true, false);
}
// ================================================================================
// replicate on server
// caching proxy client
// server concurrency checks disabled
// client concurrency checks disabled
@Test
public void removeAllListenerReplicateCachingProxyChecksDisabledTest() {
doRemoveAllTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, false, false);
}
@Test
public void destroyListenerReplicateCachingProxyChecksDisabledTest() {
doDestroyTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, false, false);
}
@Test
public void removeListenerReplicateCachingProxyChecksDisabledTest() {
doRemoveTest(RegionShortcut.REPLICATE, ClientRegionShortcut.CACHING_PROXY, false, false);
}
// ================================================================================
// partitioned on server
// caching proxy client
// server concurrency checks disabled
// client concurrency checks disabled
@Test
public void removeAllListenerPartitionCachingProxyChecksDisabledTest() {
doRemoveAllTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, false, false);
}
@Test
public void destroyListenerPartitionCachingProxyChecksDisabledTest() {
doDestroyTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, false, false);
}
@Test
public void removeListenerPartitionCachingProxyChecksDisabledTest() {
doRemoveTest(RegionShortcut.PARTITION, ClientRegionShortcut.CACHING_PROXY, false, false);
}
// ================================================================================
private void setupGemFireCacheServer(RegionShortcut shortcut, boolean concChecks) {
serverVM = Host.getHost(0).getVM(0);
serverPort.set(AvailablePortHelper.getRandomAvailableTCPPort());
String serverName = this.getClass().getSimpleName() + "_server";
serverVM.invoke(new SerializableRunnable() {
@Override
public void run() {
try {
Cache cache = new CacheFactory().set("name", serverName).set(MCAST_PORT, "0")
.set(LOG_FILE, serverName + ".log").set(LOG_LEVEL, "config")
.set("locators", "localhost[" + DistributedTestUtils.getDUnitLocatorPort() + "]")
.create();
RegionFactory<String, String> regionFactory = cache.createRegionFactory(shortcut);
regionFactory.addCacheListener(new TestListener());
regionFactory.setConcurrencyChecksEnabled(concChecks);
regionFactory.create(REGION_NAME);
CacheServer cacheServer = cache.addCacheServer();
cacheServer.setPort(serverPort.get());
cacheServer.setMaxConnections(10);
cacheServer.start();
assertTrue("Cache Server is not running!", cacheServer.isRunning());
} catch (UnknownHostException ignore) {
throw new RuntimeException(ignore);
} catch (IOException e) {
throw new RuntimeException("Failed to start cache server " + serverName + " on port "
+ serverPort.get() + ": " + e.getStackTrace());
}
}
});
}
private void setupGemFireClientCache(ClientRegionShortcut shortcut, boolean concChecks) {
clientVM = Host.getHost(0).getVM(1);
clientVM.invoke(() -> {
ClientCache clientCache = new ClientCacheFactory().create();
PoolFactory poolFactory = PoolManager.createFactory();
poolFactory.setMaxConnections(10);
poolFactory.setMinConnections(1);
poolFactory.setReadTimeout(5000);
poolFactory.setSubscriptionEnabled(true);
poolFactory.addServer("localhost", serverPort.get());
Pool pool = poolFactory.create("serverConnectionPool");
assertNotNull("The 'serverConnectionPool' was not properly configured and initialized!",
pool);
ClientRegionFactory<String, String> regionFactory =
clientCache.createClientRegionFactory(shortcut);
regionFactory.setPoolName(pool.getName());
regionFactory.addCacheListener(new TestListener());
regionFactory.setConcurrencyChecksEnabled(concChecks);
Region<String, String> aRegion = regionFactory.create(REGION_NAME);
assertNotNull("The region " + REGION_NAME + " was not properly configured and initialized",
aRegion);
aRegion.registerInterest("ALL_KEYS", InterestResultPolicy.KEYS_VALUES);
});
}
private class TestListener extends CacheListenerAdapter<String, String> {
@Override
public void afterDestroy(EntryEvent event) {
if (event.getKey().equals(NON_EXISTENT_KEY)) {
String errStr = "event fired for non-existent key " + event.getKey() + "; " + event + "\n"
+ getStackTrace();
getBlackboard().setMailbox(BB_MAILBOX_KEY, errStr);
}
}
}
/**
* Add values to a region, then do a removeAll using both existent and non-existent keys. If a
* listener event is invoked on a non-existent key, the listener writes it to the blackboard. Read
* from the blackboard and fail the test if a listener event was invoked for a non-existent key.
*/
private void doRemoveAllTest(RegionShortcut serverShortcut, ClientRegionShortcut clientShortcut,
boolean serverConcChecks, boolean clientConcChecks) {
setupGemFireCacheServer(serverShortcut, serverConcChecks);
setupGemFireClientCache(clientShortcut, clientConcChecks);
clientVM.invoke(() -> {
Region<String, String> aRegion = ClientCacheFactory.getAnyInstance().getRegion(REGION_NAME);
aRegion.put("key1", "value1");
aRegion.put("key2", "value2");
aRegion.put("key3", "value3");
Set<String> removeAllSet = new HashSet<String>();
removeAllSet.add("key1");
removeAllSet.add("key2");
removeAllSet.add(NON_EXISTENT_KEY);
aRegion.removeAll(removeAllSet);
Object error = getBlackboard().getMailbox(BB_MAILBOX_KEY);
assertNotNull(error);
assertEquals("", error);
});
}
private void doDestroyTest(RegionShortcut serverShortcut, ClientRegionShortcut clientShortcut,
boolean serverConcChecks, boolean clientConcChecks) {
setupGemFireCacheServer(serverShortcut, serverConcChecks);
setupGemFireClientCache(clientShortcut, clientConcChecks);
clientVM.invoke(() -> {
Region<String, String> aRegion = ClientCacheFactory.getAnyInstance().getRegion(REGION_NAME);
try {
aRegion.destroy(NON_EXISTENT_KEY);
} catch (EntryNotFoundException e) {
// expected
}
Object error = getBlackboard().getMailbox(BB_MAILBOX_KEY);
assertNotNull(error);
assertEquals("", error);
});
}
private void doRemoveTest(RegionShortcut serverShortcut, ClientRegionShortcut clientShortcut,
boolean serverConcChecks, boolean clientConcChecks) {
setupGemFireCacheServer(serverShortcut, serverConcChecks);
setupGemFireClientCache(clientShortcut, clientConcChecks);
clientVM.invoke(() -> {
getBlackboard().setMailbox(BB_MAILBOX_KEY, "");
Region<String, String> aRegion = ClientCacheFactory.getAnyInstance().getRegion(REGION_NAME);
Object returnedValue = aRegion.remove(NON_EXISTENT_KEY);
assertNull(returnedValue);
Object error = getBlackboard().getMailbox(BB_MAILBOX_KEY);
assertNotNull(error);
assertEquals("", error);
});
}
/** Get a stack trace of the current stack and return it as a String */
public static String getStackTrace() {
try {
throw new Exception("Exception to get stack trace");
} catch (Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw, true));
return sw.toString();
}
}
}