package org.infinispan.client.hotrod; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.assertHotRodEquals; import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; import static org.infinispan.test.TestingUtil.k; import static org.infinispan.test.TestingUtil.v; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Method; import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import org.infinispan.client.hotrod.test.HotRodClientTestingUtil; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.server.hotrod.HotRodServer; import org.infinispan.test.SingleCacheManagerTest; import org.infinispan.test.fwk.TestCacheManagerFactory; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; /** * @author mmarkus * @since 4.1 */ @Test (testName = "client.hotrod.HotRodIntegrationTest", groups = "functional" ) public class HotRodIntegrationTest extends SingleCacheManagerTest { private static final Log log = LogFactory.getLog(HotRodIntegrationTest.class); private static final String CACHE_NAME = "replSync"; RemoteCache<String, String> defaultRemote; RemoteCache<Object, String> remoteCache; private RemoteCacheManager remoteCacheManager; protected HotRodServer hotrodServer; @Override protected EmbeddedCacheManager createCacheManager() throws Exception { ConfigurationBuilder builder = hotRodCacheConfiguration( getDefaultStandaloneCacheConfig(false)); EmbeddedCacheManager cm = TestCacheManagerFactory .createCacheManager(hotRodCacheConfiguration()); cm.defineConfiguration(CACHE_NAME, builder.build()); cm.getCache(CACHE_NAME); return cm; } @Override protected void setup() throws Exception { super.setup(); //pass the config file to the cache hotrodServer = HotRodClientTestingUtil.startHotRodServer(cacheManager); log.info("Started server on port: " + hotrodServer.getPort()); remoteCacheManager = getRemoteCacheManager(); defaultRemote = remoteCacheManager.getCache(); remoteCache = remoteCacheManager.getCache(CACHE_NAME); } protected RemoteCacheManager getRemoteCacheManager() { Properties config = new Properties(); org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); clientBuilder.addServer().host("localhost").port(hotrodServer.getPort()); return new RemoteCacheManager(clientBuilder.build()); } @AfterClass public void testDestroyRemoteCacheFactory() { HotRodClientTestingUtil.killRemoteCacheManager(remoteCacheManager); HotRodClientTestingUtil.killServers(hotrodServer); } public void testPut() throws Exception { assert null == remoteCache.put("aKey", "aValue"); assertHotRodEquals(cacheManager, CACHE_NAME, "aKey", "aValue"); assert null == defaultRemote.put("otherKey", "otherValue"); assertHotRodEquals(cacheManager, "otherKey", "otherValue"); assert remoteCache.containsKey("aKey"); assert defaultRemote.containsKey("otherKey"); assert remoteCache.get("aKey").equals("aValue"); assert defaultRemote.get("otherKey").equals("otherValue"); } public void testRemove() throws Exception { assert null == remoteCache.put("aKey", "aValue"); assertHotRodEquals(cacheManager, CACHE_NAME, "aKey", "aValue"); assert remoteCache.get("aKey").equals("aValue"); assert null == remoteCache.remove("aKey"); assertHotRodEquals(cacheManager, CACHE_NAME, "aKey", null); assert !remoteCache.containsKey("aKey"); } public void testContains() { assert !remoteCache.containsKey("aKey"); remoteCache.put("aKey", "aValue"); assert remoteCache.containsKey("aKey"); } public void testGetVersionedCacheEntry() { VersionedValue value = remoteCache.getVersioned("aKey"); assertNull("expected null but received: " + value, remoteCache.getVersioned("aKey")); remoteCache.put("aKey", "aValue"); assert remoteCache.get("aKey").equals("aValue"); VersionedValue valueBinary = remoteCache.getVersioned("aKey"); assert valueBinary != null; assertEquals(valueBinary.getValue(), "aValue"); log.info("Version is: " + valueBinary.getVersion()); //now put the same value remoteCache.put("aKey", "aValue"); VersionedValue entry2 = remoteCache.getVersioned("aKey"); assertEquals(entry2.getValue(), "aValue"); assert entry2.getVersion() != valueBinary.getVersion(); assert !valueBinary.equals(entry2); //now put a different value remoteCache.put("aKey", "anotherValue"); VersionedValue entry3 = remoteCache.getVersioned("aKey"); assertEquals(entry3.getValue(), "anotherValue"); assert entry3.getVersion() != entry2.getVersion(); assert !entry3.equals(entry2); } public void testGetWithMetadata() { MetadataValue<?> value = remoteCache.getWithMetadata("aKey"); assertNull("expected null but received: " + value, value); remoteCache.put("aKey", "aValue"); assert remoteCache.get("aKey").equals("aValue"); MetadataValue<?> immortalValue = remoteCache.getWithMetadata("aKey"); assertNotNull(immortalValue); assertEquals("aValue", immortalValue.getValue()); assertEquals(-1, immortalValue.getLifespan()); assertEquals(-1, immortalValue.getMaxIdle()); remoteCache.put("bKey", "bValue", 60, TimeUnit.SECONDS); MetadataValue<?> mortalValueWithLifespan = remoteCache.getWithMetadata("bKey"); assertNotNull(mortalValueWithLifespan); assertEquals("bValue", mortalValueWithLifespan.getValue()); assertEquals(60, mortalValueWithLifespan.getLifespan()); assertEquals(-1, mortalValueWithLifespan.getMaxIdle()); remoteCache.put("cKey", "cValue", 60, TimeUnit.SECONDS, 30, TimeUnit.SECONDS); MetadataValue<?> mortalValueWithMaxIdle = remoteCache.getWithMetadata("cKey"); assertNotNull(mortalValueWithMaxIdle); assertEquals("cValue", mortalValueWithMaxIdle.getValue()); assertEquals(60, mortalValueWithMaxIdle.getLifespan()); assertEquals(30, mortalValueWithMaxIdle.getMaxIdle()); } public void testReplace() { assert null == remoteCache.replace("aKey", "anotherValue"); remoteCache.put("aKey", "aValue"); assert null == remoteCache.replace("aKey", "anotherValue"); assert remoteCache.get("aKey").equals("anotherValue"); } public void testReplaceIfUnmodified() { assert null == remoteCache.replace("aKey", "aValue"); remoteCache.put("aKey", "aValue"); VersionedValue valueBinary = remoteCache.getVersioned("aKey"); assert remoteCache.replaceWithVersion("aKey", "aNewValue", valueBinary.getVersion()); VersionedValue entry2 = remoteCache.getVersioned("aKey"); assert entry2.getVersion() != valueBinary.getVersion(); assertEquals(entry2.getValue(), "aNewValue"); assert !remoteCache.replaceWithVersion("aKey", "aNewValue", valueBinary.getVersion()); } public void testReplaceIfUnmodifiedWithExpiry(Method m) throws InterruptedException { final int key = 1; remoteCache.put(key, v(m)); VersionedValue valueBinary = remoteCache.getVersioned(key); int lifespanSecs = 3; // seconds long lifespan = TimeUnit.SECONDS.toMillis(lifespanSecs); long startTime = System.currentTimeMillis(); String newValue = v(m, 2); assert remoteCache.replaceWithVersion(key, newValue, valueBinary.getVersion(), lifespanSecs); while (true) { Object value = remoteCache.get(key); if (System.currentTimeMillis() >= startTime + lifespan) break; assertEquals(v(m, 2), value); Thread.sleep(100); } while (System.currentTimeMillis() < startTime + lifespan + 2000) { if (remoteCache.get(key) == null) break; Thread.sleep(50); } assertNull(remoteCache.get(key)); } public void testReplaceWithVersionWithLifespanAsync(Method m) throws Exception { int lifespanInSecs = 1; //seconds final String k = k(m), v = v(m), newV = v(m, 2); assertNull(remoteCache.replace(k, v)); remoteCache.put(k, v); VersionedValue valueBinary = remoteCache.getVersioned(k); long lifespan = TimeUnit.SECONDS.toMillis(lifespanInSecs); long startTime = System.currentTimeMillis(); CompletableFuture<Boolean> future = remoteCache.replaceWithVersionAsync( k, newV, valueBinary.getVersion(), lifespanInSecs); assert future.get(); while (true) { VersionedValue entry2 = remoteCache.getVersioned(k); if (System.currentTimeMillis() >= startTime + lifespan) break; // version should have changed; value should have changed assert entry2.getVersion() != valueBinary.getVersion(); assertEquals(newV, entry2.getValue()); Thread.sleep(100); } while (System.currentTimeMillis() < startTime + lifespan + 2000) { if (remoteCache.get(k) == null) break; Thread.sleep(50); } assertNull(remoteCache.getVersioned(k)); } public void testRemoveIfUnmodified() { assert !remoteCache.removeWithVersion("aKey", 12321212l); remoteCache.put("aKey", "aValue"); VersionedValue valueBinary = remoteCache.getVersioned("aKey"); assert remoteCache.removeWithVersion("aKey", valueBinary.getVersion()); assertHotRodEquals(cacheManager, CACHE_NAME, "aKey", null); remoteCache.put("aKey", "aNewValue"); VersionedValue entry2 = remoteCache.getVersioned("aKey"); assert entry2.getVersion() != valueBinary.getVersion(); assertEquals(entry2.getValue(), "aNewValue"); assert !remoteCache.removeWithVersion("aKey", valueBinary.getVersion()); } public void testPutIfAbsent() { remoteCache.put("aKey", "aValue"); assert null == remoteCache.putIfAbsent("aKey", "anotherValue"); assertEquals(remoteCache.get("aKey"),"aValue"); assertEquals(remoteCache.get("aKey"),"aValue"); assert remoteCache.containsKey("aKey"); assert true : remoteCache.replace("aKey", "anotherValue"); } public void testClear() { remoteCache.put("aKey", "aValue"); remoteCache.put("aKey2", "aValue"); remoteCache.clear(); assert !remoteCache.containsKey("aKey"); assert !remoteCache.containsKey("aKey2"); assert cache.isEmpty(); } public void testPutWithPrevious() { assert null == remoteCache.put("aKey", "aValue"); assert "aValue".equals(remoteCache.withFlags(Flag.FORCE_RETURN_VALUE).put("aKey", "otherValue")); assert remoteCache.containsKey("aKey"); assert remoteCache.get("aKey").equals("otherValue"); } public void testRemoveWithPrevious() { assert null == remoteCache.put("aKey", "aValue"); assert remoteCache.get("aKey").equals("aValue"); assert "aValue".equals(remoteCache.withFlags(Flag.FORCE_RETURN_VALUE).remove("aKey")); assert !remoteCache.containsKey("aKey"); } public void testRemoveNonExistForceReturnPrevious() { assertNull(remoteCache.withFlags(Flag.FORCE_RETURN_VALUE).remove("aKey")); remoteCache.put("k", "v"); } public void testReplaceWithPrevious() { assert null == remoteCache.replace("aKey", "anotherValue"); remoteCache.put("aKey", "aValue"); assert "aValue".equals(remoteCache.withFlags(Flag.FORCE_RETURN_VALUE).replace("aKey", "anotherValue")); assert remoteCache.get("aKey").equals("anotherValue"); } public void testPutIfAbsentWithPrevious() { remoteCache.put("aKey", "aValue"); assert null == remoteCache.putIfAbsent("aKey", "anotherValue"); Object existingValue = remoteCache.withFlags(Flag.FORCE_RETURN_VALUE).putIfAbsent("aKey", "anotherValue"); assert "aValue".equals(existingValue) : "Existing value was:" + existingValue; } public void testPutSerializableByteArray() { RemoteCache<Object, byte[]> binaryRemote = remoteCacheManager.getCache(); byte[] bytes = serializeObject(new MyValue<>("aValue")); binaryRemote.put("aKey", bytes); assertArrayEquals(bytes, binaryRemote.get("aKey")); } private byte[] serializeObject(Object obj) { ByteArrayOutputStream bs = new ByteArrayOutputStream(); try { ObjectOutputStream os = new ObjectOutputStream(bs); os.writeObject(obj); os.close(); return bs.toByteArray(); } catch (IOException ioe) { throw new AssertionError(ioe); } } static class MyValue<V> implements Serializable { final V value; MyValue(V value) { this.value = value; } } }