package org.infinispan.server.hotrod.event; import static org.infinispan.server.hotrod.event.AbstractHotRodClusterEventsTest.addLengthPrefix; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.k; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.v; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.withClientListener; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.Optional; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.notifications.cachelistener.filter.CacheEventConverter; import org.infinispan.notifications.cachelistener.filter.CacheEventConverterFactory; import org.infinispan.server.hotrod.HotRodServer; import org.infinispan.server.hotrod.HotRodSingleNodeTest; import org.infinispan.server.hotrod.test.HotRodTestingUtil; import org.infinispan.util.KeyValuePair; import org.testng.annotations.Test; /** * @author Galder ZamarreƱo */ @Test(groups = "functional", testName = "server.hotrod.event.HotRodCustomEventsTest") public class HotRodCustomEventsTest extends HotRodSingleNodeTest { @Override protected HotRodServer createStartHotRodServer(EmbeddedCacheManager cacheManager) { HotRodServer server = HotRodTestingUtil.startHotRodServer(cacheManager); server.addCacheEventConverterFactory("static-converter-factory", new StaticConverterFactory()); server.addCacheEventConverterFactory("dynamic-converter-factory", new DynamicConverterFactory()); return server; } public void testCustomEvents(Method m) { EventLogListener eventListener = new EventLogListener(); withClientListener(client(), eventListener, Optional.empty(), Optional.of(new KeyValuePair<>("static-converter-factory", Collections.emptyList())), () -> { eventListener.expectNoEvents(Optional.empty()); byte[] key = k(m); client().remove(key); eventListener.expectNoEvents(Optional.empty()); byte[] value = v(m); client().put(key, 0, 0, value); eventListener.expectSingleCustomEvent(cache, addLengthPrefix(key, value)); byte[] value2 = v(m, "v2-"); client().put(key, 0, 0, value2); eventListener.expectSingleCustomEvent(cache, addLengthPrefix(key, value2)); client().remove(key); eventListener.expectSingleCustomEvent(cache, addLengthPrefix(key)); }); } public void testParameterBasedConversion(Method m) { EventLogListener eventListener = new EventLogListener(); byte[] customConvertKey = new byte[]{4, 5, 6}; withClientListener(client(), eventListener, Optional.empty(), Optional.of( new KeyValuePair<>("dynamic-converter-factory", Collections.singletonList(new byte[]{4, 5, 6}))), () -> { eventListener.expectNoEvents(Optional.empty()); byte[] key = k(m); byte[] value = v(m); client().put(key, 0, 0, value); eventListener.expectSingleCustomEvent(cache, addLengthPrefix(key, value)); byte[] value2 = v(m, "v2-"); client().put(key, 0, 0, value2); eventListener.expectSingleCustomEvent(cache, addLengthPrefix(key, value2)); client().remove(key); eventListener.expectSingleCustomEvent(cache, addLengthPrefix(key)); client().put(customConvertKey, 0, 0, value); eventListener.expectSingleCustomEvent(cache, addLengthPrefix(customConvertKey)); }); } public void testConvertedEventsNoReplay(Method m) { EventLogListener eventListener = new EventLogListener(); byte[] key = new byte[]{1}; byte[] value = new byte[]{2}; client().put(key, 0, 0, value); withClientListener(client(), eventListener, Optional.empty(), Optional.of(new KeyValuePair<>("static-converter-factory", Collections.emptyList())), () -> { eventListener.expectNoEvents(Optional.empty()); }); } public void testConvertedEventsReplay(Method m) { EventLogListener eventListener = new EventLogListener(); byte[] key = new byte[]{1}; byte[] value = new byte[]{2}; client().put(key, 0, 0, value); withClientListener(client(), eventListener, Optional.empty(), Optional .of(new KeyValuePair<>("static-converter-factory", Collections.emptyList())), true, true, () -> { eventListener.expectSingleCustomEvent(cache, addLengthPrefix(key, value)); }); } private static class StaticConverterFactory implements CacheEventConverterFactory { @Override public <K, V, C> CacheEventConverter<K, V, C> getConverter(Object[] params) { return (CacheEventConverter<K, V, C>) (CacheEventConverter<byte[], byte[], byte[]>) (key, oldValue, oldMetadata, newValue, newMetadata, eventType) -> { if (newValue == null) return addLengthPrefix(key); else return addLengthPrefix(key, newValue); }; } } class DynamicConverterFactory implements CacheEventConverterFactory { @Override public <K, V, C> CacheEventConverter<K, V, C> getConverter(Object[] params) { return (CacheEventConverter<K, V, C>) (CacheEventConverter<byte[], byte[], byte[]>) (key, oldValue, oldMetadata, newValue, newMetadata, eventType) -> { if (newValue == null || Arrays.equals((byte[]) params[0], key)) return addLengthPrefix(key); else return addLengthPrefix(key, newValue); }; } } }