blob: 1ab613eb44218821427af9fb64464d88d184ab28 [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.internal.cache.tier.sockets;
import static org.apache.geode.cache.Region.SEPARATOR;
import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPort;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.LogWriter;
import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.CacheWriterException;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.ServerConnectivityException;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.test.dunit.Assert;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.NetworkUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.Wait;
import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;
import org.apache.geode.test.junit.categories.ClientSubscriptionTest;
/**
* DUnit Test for use-cases of various {@link InterestResultPolicy} types.
*/
@Category({ClientSubscriptionTest.class})
public class InterestResultPolicyDUnitTest extends JUnit4DistributedTestCase {
/** test VM */
VM vm0, vm1 = null;
/** total entries pre-populated on server */
static final int PREPOPULATED_ENTRIES = 10;
/** the cache instance for the test */
private static Cache cache = null;
private int PORT;
private static final String REGION_NAME =
InterestResultPolicyDUnitTest.class.getSimpleName() + "_region";
private IgnoredException expectedEx;
/**
* Creates the server cache and populates it with some entries
*/
@Override
public final void postSetUp() throws Exception {
disconnectAllFromDS();
Wait.pause(5000);
final Host host = Host.getHost(0);
vm0 = host.getVM(0);
vm1 = host.getVM(1);
PORT =
((Integer) vm0.invoke(() -> InterestResultPolicyDUnitTest.createServerCache())).intValue();
vm0.invoke(() -> InterestResultPolicyDUnitTest.populateServerCache());
}
/**
* Closes the cache on server and client
*/
@Override
public final void preTearDown() throws Exception {
// might get ServerConnectivityExceptions during shutdown
this.expectedEx =
IgnoredException.addIgnoredException(ServerConnectivityException.class.getName());
// close server
vm0.invoke(() -> InterestResultPolicyDUnitTest.closeCache());
// close client
vm1.invoke(() -> InterestResultPolicyDUnitTest.closeCache());
}
@Override
public final void postTearDown() throws Exception {
if (this.expectedEx != null) {
this.expectedEx.remove();
}
}
/**
* This test does the following<br>
* 1)Create client cache and region<br>
* 2)Call registerInterest with all keys pre-populated on server and policy:NONE<br>
* 3)At the end of registerInterest call, verify that no entries are created in the client
* cache<br>
*/
@Test
public void testPolicyNone() {
LogWriter logger = getSystem().getLogWriter();
logger.fine("testPolicyNone BEGIN");
Object[] objArr = new Object[2];
objArr[0] = InterestResultPolicy.NONE;
objArr[1] = new Integer(PREPOPULATED_ENTRIES);
Host host = Host.getHost(0);
vm1.invoke(() -> InterestResultPolicyDUnitTest
.createClientCache(NetworkUtils.getServerHostName(host), new Integer(PORT)));
vm1.invoke(InterestResultPolicyDUnitTest.class, "registerInterest", objArr);
vm1.invoke(InterestResultPolicyDUnitTest.class, "verifyResult", objArr);
logger.fine("testPolicyNone END");
}
/**
* This test does the following<br>
* 1)Create client cache and region<br>
* 2)Call registerInterest with all keys pre-populated on server and policy:KEYS<br>
* 3)At the end of registerInterest call, verify that entries are created in the client cache with
* value null<br>
*/
@Test
public void testPolicyKeys() {
LogWriter logger = getSystem().getLogWriter();
logger.fine("testPolicyKeys BEGIN");
Object[] objArr = new Object[2];
objArr[0] = InterestResultPolicy.KEYS;
objArr[1] = new Integer(PREPOPULATED_ENTRIES);
Host host = Host.getHost(0);
vm1.invoke(() -> InterestResultPolicyDUnitTest
.createClientCache(NetworkUtils.getServerHostName(host), new Integer(PORT)));;
vm1.invoke(InterestResultPolicyDUnitTest.class, "registerInterest", objArr);
vm1.invoke(InterestResultPolicyDUnitTest.class, "verifyResult", objArr);
logger.fine("testPolicyKeys END");
}
/**
* This test does the following<br>
* 1)Create client cache and region<br>
* 2)Call registerInterest with all keys pre-populated on server and policy:KEYS_VALUES<br>
* 3)At the end of registerInterest call, verify that all entries are created in the client cache
* with values<br>
*/
@Test
public void testPolicyKeysValues() {
LogWriter logger = getSystem().getLogWriter();
logger.fine("testPolicyKeyValues BEGIN");
Object[] objArr = new Object[2];
objArr[0] = InterestResultPolicy.KEYS_VALUES;
objArr[1] = new Integer(PREPOPULATED_ENTRIES);
Host host = Host.getHost(0);
vm1.invoke(() -> InterestResultPolicyDUnitTest
.createClientCache(NetworkUtils.getServerHostName(host), new Integer(PORT)));
vm1.invoke(InterestResultPolicyDUnitTest.class, "registerInterest", objArr);
vm1.invoke(InterestResultPolicyDUnitTest.class, "verifyResult", objArr);
logger.fine("testPolicyKeyValues END");
}
/**
* This test does the following<br>
* 1)Create client cache and region<br>
* 2)Call registerInterest with specific keys (having extra keys other than those pre-populated on
* server cache) and policy:KEYS<br>
* 3)At the end of registerInterest call, verify that only prepolulated entries are created in the
* client cache with null values (entries for keys in the keylist which are not on the server
* should not be created on the client as a result of registerInterest call)<br>
*/
@Test
public void testBug35358() {
Host host = Host.getHost(0);
LogWriter logger = getSystem().getLogWriter();
logger.fine("testBug35358 BEGIN");
Object[] objArr = new Object[2];
objArr[0] = InterestResultPolicy.KEYS;
/* registering for 5 extra keys */
objArr[1] = new Integer(PREPOPULATED_ENTRIES + 5);
vm1.invoke(() -> InterestResultPolicyDUnitTest
.createClientCache(NetworkUtils.getServerHostName(host), new Integer(PORT)));
vm1.invoke(InterestResultPolicyDUnitTest.class, "registerInterest", objArr);
vm1.invoke(InterestResultPolicyDUnitTest.class, "verifyResult", objArr);
Integer cnt = (Integer) vm0.invoke(() -> InterestResultPolicyDUnitTest.getEntryCount());
assertEquals(cnt.intValue(), PREPOPULATED_ENTRIES);
logger.fine("testBug35358 END");
}
/**
* Creates cache instance
*
* @param props - properties of the distributed system
* @throws Exception - thrown if any problem occurs while connecting to distributed system or
* creating cache
*/
private Cache createCache(Properties props) throws Exception {
DistributedSystem ds = getSystem(props);
Cache cache = null;
cache = CacheFactory.create(ds);
if (cache == null) {
throw new Exception("CacheFactory.create() returned null ");
}
return cache;
}
/**
* Closes the cache instance created and disconnects from the distributed system.
*/
public static void closeCache() {
if (cache != null && !cache.isClosed()) {
cache.close();
cache.getDistributedSystem().disconnect();
}
}
/**
* Creates the cache and starts the server
*
* @throws Exception - thrown if any problem occurs in creating server cache or starting the
* server
*/
public static Integer createServerCache() throws Exception {
InterestResultPolicyDUnitTest test = new InterestResultPolicyDUnitTest();
cache = test.createCache(new Properties());
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.DISTRIBUTED_ACK);
RegionAttributes attrs = factory.create();
cache.createRegion(REGION_NAME, attrs);
CacheServer server = cache.addCacheServer();
int port = getRandomAvailableTCPPort();
server.setPort(port);
server.setNotifyBySubscription(true);
server.setSocketBufferSize(32768);
server.start();
return new Integer(port);
}
/**
* Populates the server cache by putting some entries
*
* @throws Exception - thrown if any problem occurs while creating entries at server cache
*/
public static void populateServerCache() throws Exception {
Region region1 = cache.getRegion(SEPARATOR + REGION_NAME);
for (int i = 0; i < PREPOPULATED_ENTRIES; i++) {
region1.put("key-" + i, "val-" + i);
}
}
/**
* Creates the client cache and region.
*
* @throws Exception - thrown if any problem occurs in creating cache or region
*/
public static void createClientCache(String host, Integer port) throws Exception {
int PORT = port.intValue();
InterestResultPolicyDUnitTest test = new InterestResultPolicyDUnitTest();
Properties props = new Properties();
props.setProperty(MCAST_PORT, "0");
props.setProperty(LOCATORS, "");
cache = test.createCache(props);
Pool p = PoolManager.createFactory().addServer(host, port.intValue())
.setSubscriptionEnabled(true).setSubscriptionRedundancy(-1).setReadTimeout(10000)
.setSocketBufferSize(32768).setMinConnections(3)
// .setRetryAttempts(5)
// .setRetryInterval(10000)
.create("InterestResultPolicyDUnitTestPool");
AttributesFactory factory = new AttributesFactory();
factory.setScope(Scope.DISTRIBUTED_ACK);
factory.setPoolName(p.getName());
RegionAttributes attrs = factory.create();
cache.createRegion(REGION_NAME, attrs);
}
/**
* Registers the test region on client with a keylist containing all keys pre-populated on server
* and a given {@link InterestResultPolicy} type.
*
* @param interestPolicy - InterestResultPolicy type specified (NONE,KEYS,KEY_VALUES or DEFAULT)
*/
public static void registerInterest(Object interestPolicy, Object totalKeysToRegister) {
InterestResultPolicy policy = (InterestResultPolicy) interestPolicy;
int totalKeys = ((Integer) totalKeysToRegister).intValue();
Region region1 = cache.getRegion(SEPARATOR + REGION_NAME);
LogWriter logger = cache.getLogger();
logger.fine("Registering interest in " + totalKeys + " keys");
List keylist = new ArrayList();
for (int i = 0; i < totalKeys; i++) {
keylist.add("key-" + i);
}
try {
region1.registerInterest(keylist, policy);
} catch (CacheWriterException e) {
Assert.fail("failed to register interestlist for the client", e);
}
}
/**
* Verifies the number of entries (including values) created on the test region at the end of
* {@link Region#registerInterest} call depending on the type of {@link InterestResultPolicy}
* registered for the region.
*
* @param interestPolicy - {@link InterestResultPolicy} registered for the region
*/
public static void verifyResult(Object interestPolicy, Object totalKeysRegistered) {
Region region1 = cache.getRegion(SEPARATOR + REGION_NAME);
int entriesSize = region1.entrySet(false).size();
int keysSize = region1.keySet().size();
int valuesSize = region1.values().size();
InterestResultPolicy policy = (InterestResultPolicy) interestPolicy;
LogWriter logger = cache.getLogger();
logger.fine("policy = " + policy + " ==> entries = " + entriesSize + " ;keys = " + keysSize
+ ";values = " + valuesSize);
if (policy.isNone()) {
// nothing should be created on client cache
assertEquals(0, entriesSize);
assertEquals(0, keysSize);
assertEquals(0, valuesSize);
} else if (policy.isKeys()) {
// all keys should be created with values null
assertEquals(PREPOPULATED_ENTRIES, entriesSize);
assertEquals(PREPOPULATED_ENTRIES, keysSize);
assertEquals(0, valuesSize);
} else if (policy.isKeysValues()) {
// all the keys and values should be created
assertEquals(PREPOPULATED_ENTRIES, entriesSize);
assertEquals(PREPOPULATED_ENTRIES, keysSize);
assertEquals(PREPOPULATED_ENTRIES, valuesSize);
}
}
/**
* Gets the total number of keys in the test region
*
* @return - total keys
*/
public static Object getEntryCount() {
Region region1 = cache.getRegion(SEPARATOR + REGION_NAME);
int keysSize = region1.keySet().size();
return new Integer(keysSize);
}
}