package org.infinispan.rest;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.infinispan.commons.api.BasicCacheContainer;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
import org.infinispan.rest.configuration.RestServerConfigurationBuilder;
import org.infinispan.test.AbstractCacheTest;
import org.infinispan.test.TestingUtil;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.infinispan.transaction.lookup.EmbeddedTransactionManagerLookup;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Test with two REST Servers.
*
* @author Michal Linhard (mlinhard@redhat.com)
*/
@Test(groups = {"functional"}, testName = "rest.TwoServerTest")
public class TwoServerTest extends RestServerTestBase {
private static final String PATH1 = "http://localhost:8890/rest/___defaultcache/";
private static final String PATH2 = "http://localhost:8891/rest/___defaultcache/";
private static final String EXPIRY_PATH1 = "http://localhost:8890/rest/expiry/";
private static final String EXPIRY_PATH2 = "http://localhost:8891/rest/expiry/";
@BeforeClass
private void setUp() throws Exception {
ConfigurationBuilder cfgBuilder = AbstractCacheTest.getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, true);
cfgBuilder.transaction().transactionManagerLookup(new EmbeddedTransactionManagerLookup());
cfgBuilder.clustering().hash().numOwners(2);
cfgBuilder.clustering().stateTransfer().fetchInMemoryState(true);
cfgBuilder.clustering().stateTransfer().timeout(20000);
ConfigurationBuilder expiryCfgBuilder = AbstractCacheTest.getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, true);
expiryCfgBuilder.expiration().lifespan(2000).maxIdle(2000);
EmbeddedCacheManager cm1 = TestCacheManagerFactory.createClusteredCacheManager(cfgBuilder);
cm1.defineConfiguration("expiry", expiryCfgBuilder.build());
addServer("1", cm1, new RestServerConfigurationBuilder().port(8890).build());
EmbeddedCacheManager cm2 = TestCacheManagerFactory.createClusteredCacheManager(cfgBuilder);
cm2.defineConfiguration("expiry", expiryCfgBuilder.build());
addServer("2", cm2, new RestServerConfigurationBuilder().port(8891).build());
startServers();
TestingUtil.blockUntilViewsReceived(10000, getCacheManager("1").getCache(BasicCacheContainer.DEFAULT_CACHE_NAME),
getCacheManager("2").getCache(BasicCacheContainer.DEFAULT_CACHE_NAME));
createClient();
}
@AfterClass
private void tearDown() throws Exception {
stopServers();
destroyClient();
}
public void testPutReplication() throws Exception {
PutMethod put = new PutMethod(PATH1 + "a");
put.setRequestEntity(new StringRequestEntity("data", "application/text", null));
call(put);
assertEquals(put.getStatusCode(), HttpStatus.SC_OK);
put.releaseConnection();
GetMethod get = new GetMethod(PATH1 + "a");
call(get);
assertEquals(get.getStatusCode(), HttpStatus.SC_OK);
get.releaseConnection();
get = new GetMethod(PATH2 + "a");
call(get);
assertEquals(get.getStatusCode(), HttpStatus.SC_OK);
assertEquals("data", get.getResponseBodyAsString());
get.releaseConnection();
}
public void testReplace() throws Exception {
PutMethod put = new PutMethod(PATH1 + "testReplace");
put.setRequestEntity(new StringRequestEntity("data", "application/text", null));
call(put);
assertEquals(put.getStatusCode(), HttpStatus.SC_OK);
put.releaseConnection();
put = new PutMethod(PATH1 + "testReplace");
put.setRequestEntity(new StringRequestEntity("data2", "application/text", null));
call(put);
assertEquals(put.getStatusCode(), HttpStatus.SC_OK);
put.releaseConnection();
GetMethod get = new GetMethod(PATH2 + "testReplace");
call(get);
assertEquals(get.getStatusCode(), HttpStatus.SC_OK);
assertEquals("data2", get.getResponseBodyAsString());
get.releaseConnection();
}
public void testExtendedHeaders() throws Exception {
PutMethod put = new PutMethod(PATH1 + "testExtendedHeaders");
put.setRequestEntity(new StringRequestEntity("data", "application/text", null));
call(put);
assertEquals(put.getStatusCode(), HttpStatus.SC_OK);
put.releaseConnection();
GetMethod get = new GetMethod(PATH2 + "testExtendedHeaders?extended");
call(get);
assertEquals(get.getStatusCode(), HttpStatus.SC_OK);
Header po = get.getResponseHeader("Cluster-Primary-Owner");
assertNotNull(po);
Address primaryLocation = getCacheManager("1").getCache(BasicCacheContainer.DEFAULT_CACHE_NAME).getAdvancedCache().getDistributionManager().getPrimaryLocation("testExtendedHeaders");
assertEquals(primaryLocation.toString(), po.getValue());
Header sa = get.getResponseHeader("Cluster-Server-Address");
assertNotNull(sa);
JGroupsTransport transport = (JGroupsTransport) getCacheManager("2").getTransport();
assertEquals(transport.getPhysicalAddresses().toString(), sa.getValue());
Header nn = get.getResponseHeader("Cluster-Node-Name");
assertNotNull(nn);
assertEquals(transport.getAddress().toString(), nn.getValue());
get.releaseConnection();
}
public void testExpiration() throws Exception {
String key1Path = EXPIRY_PATH1 + "k1";
String key2Path = EXPIRY_PATH2 + "k2";
String key3Path = EXPIRY_PATH1 + "k3";
String key4Path = EXPIRY_PATH1 + "k4";
// specific entry timeToLiveSeconds and maxIdleTimeSeconds that overrides the default
post(key1Path, "v1", "application/text", HttpStatus.SC_OK, "Content-Type", "application/text",
"timeToLiveSeconds", "3", "maxIdleTimeSeconds", "3");
// no value means never expire
post(key2Path, "v2", "application/text", HttpStatus.SC_OK, "Content-Type", "application/text");
// 0 value means use default
post(key3Path, "v3", "application/text", HttpStatus.SC_OK, "Content-Type", "application/text",
"timeToLiveSeconds", "0", "maxIdleTimeSeconds", "0");
post(key4Path, "v4", "application/text", HttpStatus.SC_OK, "Content-Type", "application/text",
"timeToLiveSeconds", "0", "maxIdleTimeSeconds", "2");
TestingUtil.sleepThread(1000);
get(key1Path, "v1");
get(key3Path, "v3");
get(key4Path, "v4");
TestingUtil.sleepThread(1100);
// k3 and k4 expired
get(key1Path, "v1");
head(key3Path, HttpStatus.SC_NOT_FOUND);
head(key4Path, HttpStatus.SC_NOT_FOUND);
TestingUtil.sleepThread(1000);
// k1 expired
head(key1Path, HttpStatus.SC_NOT_FOUND);
// k2 should not be expired because without timeToLive/maxIdle parameters,
// the entries live forever. To use default values, 0 must be passed in.
head(key2Path, HttpStatus.SC_OK);
}
private void post(String uri, String data, String contentType, int expectedCode, Object... headers) throws Exception {
PostMethod post = new PostMethod(uri);
for (int i = 0; i < headers.length; i += 2)
post.setRequestHeader(headers[i].toString(), headers[i + 1].toString());
post.setRequestEntity(new StringRequestEntity(data, contentType, null));
call(post);
assertEquals(expectedCode, post.getStatusCode());
}
private void get(String uri, String expectedResponseBody) throws Exception {
GetMethod get = new GetMethod(uri);
call(get);
assertEquals(expectedResponseBody, get.getResponseBodyAsString());
}
private void head(String uri, int expectedCode) throws Exception {
HeadMethod head = new HeadMethod(uri);
call(head);
assertEquals(expectedCode, head.getStatusCode());
}
}