package org.infinispan.it.compatibility;
import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.withClientListener;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import org.infinispan.Cache;
import org.infinispan.client.hotrod.Flag;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.VersionedValue;
import org.infinispan.client.hotrod.annotation.ClientListener;
import org.infinispan.client.hotrod.event.ClientEvent;
import org.infinispan.client.hotrod.event.CustomEventLogListener.CustomEvent;
import org.infinispan.client.hotrod.event.CustomEventLogListener.DynamicConverterFactory;
import org.infinispan.client.hotrod.event.CustomEventLogListener.DynamicCustomEventLogListener;
import org.infinispan.client.hotrod.event.CustomEventLogListener.StaticConverterFactory;
import org.infinispan.client.hotrod.event.CustomEventLogListener.StaticCustomEventLogListener;
import org.infinispan.client.hotrod.event.EventLogListener;
import org.infinispan.client.hotrod.event.EventLogListener.DynamicCacheEventFilterFactory;
import org.infinispan.client.hotrod.event.EventLogListener.DynamicFilteredEventLogListener;
import org.infinispan.client.hotrod.event.EventLogListener.StaticCacheEventFilterFactory;
import org.infinispan.client.hotrod.event.EventLogListener.StaticFilteredEventLogListener;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.server.hotrod.HotRodServer;
import org.infinispan.test.AbstractInfinispanTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Test compatibility between embedded caches and Hot Rod endpoints.
*
* @author Galder ZamarreƱo
* @since 5.3
*/
@Test(groups = "functional", testName = "it.compatibility.EmbeddedHotRodTest")
public class EmbeddedHotRodTest extends AbstractInfinispanTest {
CompatibilityCacheFactory<Integer, String> cacheFactory;
@BeforeClass
protected void setup() throws Exception {
cacheFactory = new CompatibilityCacheFactory<Integer, String>(CacheMode.LOCAL).setup();
HotRodServer hotrod = cacheFactory.getHotrodServer();
hotrod.addCacheEventFilterFactory("static-filter-factory", new StaticCacheEventFilterFactory(2));
hotrod.addCacheEventFilterFactory("dynamic-filter-factory", new DynamicCacheEventFilterFactory());
hotrod.addCacheEventConverterFactory("static-converter-factory", new StaticConverterFactory());
hotrod.addCacheEventConverterFactory("dynamic-converter-factory", new DynamicConverterFactory());
}
@AfterClass
protected void teardown() {
CompatibilityCacheFactory.killCacheFactories(cacheFactory);
}
public void testEmbeddedPutHotRodGet() {
final Integer key = 1;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, embedded.put(key, "v1"));
assertEquals("v1", remote.get(key));
assertEquals("v1", embedded.put(key, "v2"));
assertEquals("v2", remote.get(key));
assertEquals("v2", embedded.remove(key));
}
public void testHotRodPutEmbeddedGet() {
final Integer key = 2;
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, "v1"));
assertEquals("v1", embedded.get(key));
assertEquals(null, remote.put(key, "v2"));
assertEquals("v2", remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, "v3"));
assertEquals("v3", embedded.get(key));
assertEquals("v3", remote.withFlags(Flag.FORCE_RETURN_VALUE).remove(key));
}
public void testEmbeddedPutIfAbsentHotRodGet() {
final Integer key = 3;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, embedded.putIfAbsent(key, "v1"));
assertEquals("v1", remote.get(key));
assertEquals("v1", embedded.putIfAbsent(key, "v2"));
assertEquals("v1", remote.get(key));
assertEquals("v1", embedded.remove(key));
}
public void testHotRodPutIfAbsentEmbeddedGet() {
final Integer key = 4;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).putIfAbsent(key, "v1"));
assertEquals("v1", embedded.get(key));
assertEquals(null, remote.putIfAbsent(key, "v2"));
assertEquals("v1", remote.withFlags(Flag.FORCE_RETURN_VALUE).putIfAbsent(key, "v2"));
assertEquals("v1", embedded.get(key));
assertEquals("v1", remote.withFlags(Flag.FORCE_RETURN_VALUE).remove(key));
}
public void testEmbeddedReplaceHotRodGet() {
final Integer key = 5;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, embedded.replace(key, "v1"));
assertEquals(null, embedded.put(key, "v1"));
assertEquals("v1", embedded.replace(key, "v2"));
assertEquals("v2", remote.get(key));
assertEquals("v2", embedded.remove(key));
}
public void testHotRodReplaceEmbeddedGet() {
final Integer key = 6;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).replace(key, "v1"));
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, "v1"));
assertEquals("v1", remote.withFlags(Flag.FORCE_RETURN_VALUE).replace(key, "v2"));
assertEquals("v2", embedded.get(key));
}
public void testEmbeddedReplaceConditionalHotRodGet() {
final Integer key = 7;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, embedded.put(key, "v1"));
assertTrue(embedded.replace(key, "v1", "v2"));
assertEquals("v2", remote.get(key));
assertEquals("v2", embedded.remove(key));
}
public void testHotRodReplaceConditionalEmbeddedGet() {
final Integer key = 8;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.put(key, "v1"));
VersionedValue<String> versioned = remote.getVersioned(key);
assertEquals("v1", versioned.getValue());
assertTrue(0 != versioned.getVersion());
assertFalse(remote.replaceWithVersion(key, "v2", Long.MAX_VALUE));
assertTrue(remote.replaceWithVersion(key, "v2", versioned.getVersion()));
assertEquals("v2", embedded.get(key));
assertEquals("v2", remote.withFlags(Flag.FORCE_RETURN_VALUE).remove(key));
}
public void testEmbeddedRemoveHotRodGet() {
final Integer key = 9;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, embedded.put(key, "v1"));
assertEquals("v1", embedded.remove(key));
assertEquals(null, remote.get(key));
}
public void testHotRodRemoveEmbeddedGet() {
final Integer key = 10;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, "v1"));
assertEquals("v1", remote.withFlags(Flag.FORCE_RETURN_VALUE).remove(key));
assertEquals(null, embedded.get(key));
}
public void testEmbeddedRemoveConditionalHotRodGet() {
final Integer key = 11;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, embedded.put(key, "v1"));
assertFalse(embedded.remove(key, "vX"));
assertTrue(embedded.remove(key, "v1"));
assertEquals(null, remote.get(key));
}
public void testHotRodRemoveConditionalEmbeddedGet() {
final Integer key = 12;
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, "v1"));
VersionedValue<String> versioned = remote.getVersioned(key);
assertFalse(remote.withFlags(Flag.FORCE_RETURN_VALUE).removeWithVersion(key, Long.MAX_VALUE));
assertTrue(remote.withFlags(Flag.FORCE_RETURN_VALUE).removeWithVersion(key, versioned.getVersion()));
assertEquals(null, embedded.get(key));
}
public void testEventReceiveBasic() {
EventLogListener<Integer> l = new EventLogListener<>(cacheFactory.getHotRodCache());
withClientListener(l, remote -> {
l.expectNoEvents();
remote.remove(1);
l.expectNoEvents();
remote.put(1, "one");
assertEquals("one", cacheFactory.getEmbeddedCache().get(1));
l.expectOnlyCreatedEvent(1);
remote.put(1, "new-one");
assertEquals("new-one", cacheFactory.getEmbeddedCache().get(1));
l.expectOnlyModifiedEvent(1);
remote.remove(1);
l.expectOnlyRemovedEvent(1);
});
}
public void testEventReceiveConditional() {
EventLogListener<Integer> l = new EventLogListener<>(cacheFactory.getHotRodCache());
withClientListener(l, remote -> {
l.expectNoEvents();
// Put if absent
remote.putIfAbsent(1, "one");
l.expectOnlyCreatedEvent(1);
remote.putIfAbsent(1, "again");
l.expectNoEvents();
// Replace
remote.replace(1, "newone");
l.expectOnlyModifiedEvent(1);
// Replace with version
remote.replaceWithVersion(1, "one", 0);
l.expectNoEvents();
VersionedValue<?> versioned = remote.getVersioned(1);
remote.replaceWithVersion(1, "one", versioned.getVersion());
l.expectOnlyModifiedEvent(1);
// Remove with version
remote.removeWithVersion(1, 0);
l.expectNoEvents();
versioned = remote.getVersioned(1);
remote.removeWithVersion(1, versioned.getVersion());
l.expectOnlyRemovedEvent(1);
});
}
public void testEventReplayAfterAddingListener() {
EventLogWithStateListener<Integer> l = new EventLogWithStateListener<>(cacheFactory.getHotRodCache());
createRemove();
l.expectNoEvents();
withClientListener(l, remote -> {
l.expectUnorderedEvents(ClientEvent.Type.CLIENT_CACHE_ENTRY_CREATED, 1, 2);
remote.remove(1);
l.expectOnlyRemovedEvent(1);
remote.remove(2);
l.expectOnlyRemovedEvent(2);
});
}
public void testEventNoReplayAfterAddingListener() {
createRemove();
EventLogListener<Integer> l = new EventLogListener<>(cacheFactory.getHotRodCache());
l.expectNoEvents();
withClientListener(l, remote -> {
l.expectNoEvents();
remote.remove(1);
l.expectOnlyRemovedEvent(1);
remote.remove(2);
l.expectOnlyRemovedEvent(2);
});
}
private void createRemove() {
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
remote.put(1, "one");
assertEquals("one", embedded.get(1));
remote.put(2, "two");
assertEquals("two", embedded.get(2));
remote.put(3, "three");
assertEquals("three", embedded.get(3));
remote.remove(3);
assertNull(embedded.get(3));
}
public void testEventFilteringStatic() {
StaticFilteredEventLogListener<Integer> l =
new StaticFilteredEventLogListener<>(cacheFactory.getHotRodCache());
withClientListener(l, remote -> {
l.expectNoEvents();
remote.put(1, "one");
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
assertEquals("one", embedded.get(1));
l.expectNoEvents();
remote.put(2, "two");
assertEquals("two", embedded.get(2));
l.expectOnlyCreatedEvent(2);
remote.remove(1);
assertNull(embedded.get(1));
l.expectNoEvents();
remote.remove(2);
assertNull(embedded.get(2));
l.expectOnlyRemovedEvent(2);
});
}
public void testEventFilteringDynamic() {
RemoteCache<Integer, String> remote = cacheFactory.getHotRodCache();
DynamicFilteredEventLogListener<Integer> eventListener = new DynamicFilteredEventLogListener<>(remote);
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
remote.addClientListener(eventListener, new Object[]{3}, null);
try {
eventListener.expectNoEvents();
remote.put(1, "one");
assertEquals("one", embedded.get(1));
eventListener.expectNoEvents();
remote.put(2, "two");
assertEquals("two", embedded.get(2));
eventListener.expectNoEvents();
remote.put(3, "three");
assertEquals("three", embedded.get(3));
eventListener.expectOnlyCreatedEvent(3);
remote.replace(1, "new-one");
assertEquals("new-one", embedded.get(1));
eventListener.expectNoEvents();
remote.replace(2, "new-two");
assertEquals("new-two", embedded.get(2));
eventListener.expectNoEvents();
remote.replace(3, "new-three");
assertEquals("new-three", embedded.get(3));
eventListener.expectOnlyModifiedEvent(3);
remote.remove(1);
assertNull(embedded.get(1));
eventListener.expectNoEvents();
remote.remove(2);
assertNull(embedded.get(2));
eventListener.expectNoEvents();
remote.remove(3);
assertNull(embedded.get(3));
eventListener.expectOnlyRemovedEvent(3);
} finally {
remote.removeClientListener(eventListener);
}
}
public void testCustomEvents() {
StaticCustomEventLogListener<Integer> l =
new StaticCustomEventLogListener<>(cacheFactory.getHotRodCache());
withClientListener(l, remote -> {
l.expectNoEvents();
remote.put(1, "one");
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
assertEquals("one", embedded.get(1));
l.expectCreatedEvent(new CustomEvent(1, "one", 0));
remote.put(1, "new-one");
assertEquals("new-one", embedded.get(1));
l.expectModifiedEvent(new CustomEvent(1, "new-one", 0));
remote.remove(1);
assertNull(embedded.get(1));
l.expectRemovedEvent(new CustomEvent(1, null, 0));
});
}
public void testCustomEventsDynamic() {
DynamicCustomEventLogListener<Integer> l = new DynamicCustomEventLogListener<>(cacheFactory.getHotRodCache());
withClientListener(l, null, new Object[]{2}, remote -> {
l.expectNoEvents();
remote.put(1, "one");
Cache<Integer, String> embedded = cacheFactory.getEmbeddedCache();
assertEquals("one", embedded.get(1));
l.expectCreatedEvent(new CustomEvent(1, "one", 0));
remote.put(2, "two");
assertEquals("two", embedded.get(2));
l.expectCreatedEvent(new CustomEvent(2, null, 0));
remote.remove(1);
assertNull(embedded.get(1));
l.expectRemovedEvent(new CustomEvent(1, null, 0));
remote.remove(2);
assertNull(embedded.get(2));
l.expectRemovedEvent(new CustomEvent(2, null, 0));
});
}
@ClientListener(includeCurrentState = true)
public static class EventLogWithStateListener<K> extends EventLogListener<K> {
public EventLogWithStateListener(RemoteCache<K, ?> r) { super(r); }
}
}