package org.infinispan.client.hotrod;
import static org.infinispan.client.hotrod.Flag.FORCE_RETURN_VALUE;
import static org.infinispan.client.hotrod.Flag.SKIP_INDEXING;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.infinispan.client.hotrod.test.HotRodClientTestingUtil;
import org.infinispan.commands.FlagAffectedCommand;
import org.infinispan.commands.VisitableCommand;
import org.infinispan.commons.CacheException;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.impl.FlagBitSets;
import org.infinispan.interceptors.base.BaseCustomInterceptor;
import org.infinispan.interceptors.base.CommandInterceptor;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.server.hotrod.HotRodServer;
import org.infinispan.test.SingleCacheManagerTest;
import org.infinispan.test.fwk.CleanupAfterTest;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Tests if the {@link org.infinispan.client.hotrod.Flag#SKIP_INDEXING} flag is received on HotRod server.
*
* @author Tristan Tarrant
* @author Pedro Ruivo
* @since 7.0
*/
@Test(testName = "client.hotrod.SkipIndexingFlagTest", groups = "functional")
@CleanupAfterTest
public class SkipIndexingFlagTest extends SingleCacheManagerTest {
private static final String KEY = "key";
private static final String VALUE = "value";
private FlagCheckCommandInterceptor commandInterceptor;
private RemoteCache<String, String> remoteCache;
private RemoteCacheManager remoteCacheManager;
private HotRodServer hotRodServer;
public void testPut() {
performTest(RequestType.PUT);
}
public void testReplace() {
performTest(RequestType.REPLACE);
}
public void testPutIfAbsent() {
performTest(RequestType.PUT_IF_ABSENT);
}
public void testReplaceIfUnmodified() {
performTest(RequestType.REPLACE_IF_UNMODIFIED);
}
public void testGet() {
performTest(RequestType.GET);
}
public void testGetWithVersion() {
performTest(RequestType.GET_WITH_VERSION);
}
public void testGetWithMetadata() {
performTest(RequestType.GET_WITH_METADATA);
}
public void testRemove() {
performTest(RequestType.REMOVE);
}
public void testRemoveIfUnmodified() {
performTest(RequestType.REMOVE_IF_UNMODIFIED);
}
public void testContainsKey() {
performTest(RequestType.CONTAINS);
}
public void testPutAll() {
performTest(RequestType.PUT_ALL);
}
@Override
protected EmbeddedCacheManager createCacheManager() throws Exception {
cacheManager = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration());
cache = cacheManager.getCache();
hotRodServer = HotRodClientTestingUtil.startHotRodServer(cacheManager);
Properties hotRodClientConf = new Properties();
hotRodClientConf.put("infinispan.client.hotrod.server_list", "localhost:" + hotRodServer.getPort());
org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder =
new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
clientBuilder.addServer().host("localhost").port(hotRodServer.getPort());
remoteCacheManager = new RemoteCacheManager(clientBuilder.build());
remoteCache = remoteCacheManager.getCache();
return cacheManager;
}
@Override
protected void teardown() {
HotRodClientTestingUtil.killRemoteCacheManager(remoteCacheManager);
HotRodClientTestingUtil.killServers(hotRodServer);
super.teardown();
}
private void performTest(RequestType type) {
commandInterceptor.expectSkipIndexingFlag = false;
type.execute(remoteCache);
commandInterceptor.expectSkipIndexingFlag = RequestType.expectsFlag(type);
type.execute(remoteCache.withFlags(SKIP_INDEXING));
type.execute(remoteCache.withFlags(SKIP_INDEXING, FORCE_RETURN_VALUE));
}
@BeforeClass(alwaysRun = true)
private void injectCommandInterceptor() {
if (remoteCache == null) {
return;
}
for (CommandInterceptor commandInterceptor : cache.getAdvancedCache().getInterceptorChain()) {
if (commandInterceptor instanceof FlagCheckCommandInterceptor) {
this.commandInterceptor = (FlagCheckCommandInterceptor) commandInterceptor;
}
}
this.commandInterceptor = new FlagCheckCommandInterceptor();
cache.getAdvancedCache().addInterceptor(commandInterceptor, 1);
}
@AfterClass(alwaysRun = true)
private void resetCommandInterceptor() {
if (commandInterceptor != null) {
commandInterceptor.expectSkipIndexingFlag = false;
}
}
private static enum RequestType {
PUT {
@Override
void execute(RemoteCache<String, String> cache) {
cache.put(KEY, VALUE);
}
},
REPLACE {
@Override
void execute(RemoteCache<String, String> cache) {
cache.replace(KEY, VALUE);
}
},
PUT_IF_ABSENT {
@Override
void execute(RemoteCache<String, String> cache) {
cache.putIfAbsent(KEY, VALUE);
}
},
REPLACE_IF_UNMODIFIED {
@Override
void execute(RemoteCache<String, String> cache) {
cache.replaceWithVersion(KEY, VALUE, 0);
}
},
GET {
@Override
void execute(RemoteCache<String, String> cache) {
cache.get(KEY);
}
},
GET_WITH_VERSION {
@Override
void execute(RemoteCache<String, String> cache) {
cache.getVersioned(KEY);
}
},
GET_WITH_METADATA {
@Override
void execute(RemoteCache<String, String> cache) {
cache.getWithMetadata(KEY);
}
},
REMOVE {
@Override
void execute(RemoteCache<String, String> cache) {
cache.remove(KEY);
}
},
REMOVE_IF_UNMODIFIED {
@Override
void execute(RemoteCache<String, String> cache) {
cache.removeWithVersion(KEY, 0);
}
},
CONTAINS {
@Override
void execute(RemoteCache<String, String> cache) {
cache.containsKey(KEY);
}
},
PUT_ALL {
@Override
void execute(RemoteCache<String, String> cache) {
Map<String, String> data = new HashMap<String, String>();
data.put(KEY, VALUE);
cache.putAll(data);
}
},
;
private static boolean expectsFlag(RequestType type) {
return type != CONTAINS && type != GET && type != GET_WITH_METADATA && type != GET_WITH_VERSION;
}
abstract void execute(RemoteCache<String, String> cache);
}
private static class FlagCheckCommandInterceptor extends BaseCustomInterceptor {
private volatile boolean expectSkipIndexingFlag;
@Override
protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
if (command instanceof FlagAffectedCommand) {
boolean hasFlag = ((FlagAffectedCommand) command).hasAnyFlag(FlagBitSets.SKIP_INDEXING);
if (expectSkipIndexingFlag && !hasFlag) {
throw new CacheException("SKIP_INDEXING flag is expected!");
} else if (!expectSkipIndexingFlag && hasFlag) {
throw new CacheException("SKIP_INDEXING flag is *not* expected!");
}
}
return super.handleDefault(ctx, command);
}
}
}