From d97184aeb2a87d1b95893da491baaf28147a5cb0 Mon Sep 17 00:00:00 2001 From: Ben Cotton Date: Mon, 17 Mar 2014 18:59:57 -0400 Subject: [PATCH] complete re-synch of OffHeapDataContainer.java and @Test --- .../test/cache/remote/DefaultCacheTest.java | 88 ++ .../cdi/test/cache/remote/NamedCacheTest.java | 95 ++ .../cdi/test/cache/remote/Small.java | 25 + .../remote/SpecificCacheManagerTest.java | 86 ++ .../client/hotrod/ApacheCommonsPoolTest.java | 103 ++ .../client/hotrod/BaseBulkGetKeysTest.java | 110 ++ .../client/hotrod/BaseBulkGetTest.java | 122 ++ .../client/hotrod/BulkGetKeysDistTest.java | 46 + .../client/hotrod/BulkGetKeysReplTest.java | 26 + .../client/hotrod/BulkGetKeysSimpleTest.java | 28 + .../client/hotrod/BulkGetReplTest.java | 26 + .../client/hotrod/BulkGetSimpleTest.java | 42 + .../client/hotrod/CSAIntegrationTest.java | 173 +++ .../client/hotrod/CacheContainerTest.java | 58 + .../hotrod/CacheManagerNotStartedTest.java | 123 ++ .../hotrod/CacheManagerStoppedTest.java | 125 ++ .../hotrod/ClientAsymmetricClusterTest.java | 47 + .../hotrod/ClientConnectionPoolingTest.java | 286 ++++ .../hotrod/ClientSocketReadTimeoutTest.java | 122 ++ .../hotrod/ConsistentHashComparisonTest.java | 185 +++ .../hotrod/ConsistentHashFactoryTest.java | 37 + .../hotrod/ConsistentHashPerformanceTest.java | 76 + .../ConsistentHashV1IntegrationTest.java | 198 +++ .../client/hotrod/ConsistentHashV1Test.java | 152 ++ .../client/hotrod/DefaultExpirationTest.java | 72 + .../client/hotrod/DistTopologyChangeTest.java | 15 + .../client/hotrod/DroppedConnectionsTest.java | 80 ++ .../infinispan/client/hotrod/ExpiryTest.java | 43 + .../client/hotrod/ForceReturnValueTest.java | 88 ++ .../client/hotrod/ForceReturnValuesTest.java | 57 + .../HeavyLoadConnectionPoolingTest.java | 122 ++ .../hotrod/HitsAwareCacheManagersTest.java | 120 ++ .../hotrod/HotRod10CSAIntegrationTest.java | 22 + .../hotrod/HotRodAsyncReplicationTest.java | 61 + .../client/hotrod/HotRodIntegrationTest.java | 274 ++++ .../hotrod/HotRodServerStartStopTest.java | 57 + .../client/hotrod/HotRodStatisticsTest.java | 140 ++ .../client/hotrod/PingOnStartupTest.java | 141 ++ .../client/hotrod/RemoteAsyncAPITest.java | 297 ++++ .../client/hotrod/RemoteCacheManagerTest.java | 140 ++ .../client/hotrod/ReplTopologyChangeTest.java | 147 ++ .../RoundRobinBalancingIntegrationTest.java | 225 +++ .../RoundRobinBalancingStrategyTest.java | 155 ++ .../client/hotrod/ServerErrorTest.java | 94 ++ .../client/hotrod/ServerRestartTest.java | 72 + .../client/hotrod/ServerShutdownTest.java | 70 + .../client/hotrod/SocketTimeoutErrorTest.java | 111 ++ .../hotrod/SomeAsyncExecutorFactory.java | 7 + .../hotrod/SomeCustomConsistentHashV1.java | 7 + .../hotrod/SomeRequestBalancingStrategy.java | 7 + .../client/hotrod/SomeTransportfactory.java | 7 + .../org/infinispan/client/hotrod/SslTest.java | 110 ++ .../infinispan/client/hotrod/TestHelper.java | 68 + .../hotrod/TransportObjectFactoryTest.java | 36 + .../client/hotrod/WorkerThread.java | 110 ++ .../configuration/ConfigurationTest.java | 119 ++ .../marshall/ApacheAvroMarshallerTest.java | 152 ++ .../hotrod/marshall/EmbeddedAccount.java | 62 + .../marshall/EmbeddedAccountMarshaller.java | 42 + .../hotrod/marshall/EmbeddedCompatTest.java | 194 +++ .../marshall/ProtoStreamMarshallerTest.java | 113 ++ .../query/HotRodQueryFileSystemTest.java | 52 + .../query/HotRodQueryIspnDirectoryTest.java | 20 + .../client/hotrod/query/HotRodQueryTest.java | 224 +++ .../hotrod/query/HotRodTunedQueryTest.java | 63 + .../MultiHotRodServerIspnDirQueryTest.java | 63 + ...MultiHotRodServerIspnDirReplQueryTest.java | 66 + .../query/MultiHotRodServerQueryTest.java | 163 +++ ...RemoteQueryDslConditionsFilestoreTest.java | 58 + .../RemoteQueryDslConditionsIspnDirTest.java | 58 + .../query/RemoteQueryDslConditionsTest.java | 1269 +++++++++++++++++ .../query/RemoteQueryDslIterationTest.java | 206 +++ .../hotrod/query/RemoteQueryJmxTest.java | 196 +++ .../hotrod/retry/AbstractRetryTest.java | 109 ++ .../hotrod/retry/DistributionRetryTest.java | 159 +++ .../hotrod/retry/ReplicationRetryTest.java | 141 ++ .../hotrod/retry/RetryOnFailureUnitTest.java | 106 ++ .../hotrod/retry/ServerFailureRetryTest.java | 54 + .../stress/ClientConsistentHashPerfTest.java | 63 + .../hotrod/test/HotRodClientTestingUtil.java | 84 ++ .../hotrod/test/MultiHotRodServersTest.java | 91 ++ .../test/RemoteCacheManagerCallable.java | 23 + .../infinispan/container/DataContainer.java | 10 +- .../container/DefaultDataContainer.java | 2 +- .../configuration/QueryableDataContainer.java | 6 +- ...oncurrentOperationsInPrimaryOwnerTest.java | 4 +- .../org/infinispan/jcache/JCacheEntry.java | 1 - maven-settings.xml | 107 -- maven-settings.xml.redhat | 32 - off-heap/pom.xml.off-heap | 294 ++++ .../query/remote/QueryFacadeImpl.java | 6 +- .../query/remote/QueryFacadeImplTest.java | 5 +- 92 files changed, 9592 insertions(+), 159 deletions(-) create mode 100644 cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/DefaultCacheTest.java create mode 100644 cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/NamedCacheTest.java create mode 100644 cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/Small.java create mode 100644 cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/SpecificCacheManagerTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ApacheCommonsPoolTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BaseBulkGetKeysTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BaseBulkGetTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysDistTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysReplTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysSimpleTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetReplTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetSimpleTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CSAIntegrationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheContainerTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheManagerNotStartedTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheManagerStoppedTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientAsymmetricClusterTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientConnectionPoolingTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientSocketReadTimeoutTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashComparisonTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashFactoryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashPerformanceTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashV1IntegrationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashV1Test.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DefaultExpirationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DistTopologyChangeTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DroppedConnectionsTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ExpiryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValueTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValuesTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HeavyLoadConnectionPoolingTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HitsAwareCacheManagersTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRod10CSAIntegrationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodAsyncReplicationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodIntegrationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodServerStartStopTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodStatisticsTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/PingOnStartupTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RemoteAsyncAPITest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RemoteCacheManagerTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ReplTopologyChangeTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RoundRobinBalancingIntegrationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RoundRobinBalancingStrategyTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerErrorTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerRestartTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerShutdownTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SocketTimeoutErrorTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeAsyncExecutorFactory.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeCustomConsistentHashV1.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeRequestBalancingStrategy.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeTransportfactory.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SslTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/TestHelper.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/TransportObjectFactoryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/WorkerThread.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/configuration/ConfigurationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/ApacheAvroMarshallerTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedAccount.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedAccountMarshaller.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedCompatTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/ProtoStreamMarshallerTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryFileSystemTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryIspnDirectoryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodTunedQueryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerIspnDirQueryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerIspnDirReplQueryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerQueryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsFilestoreTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsIspnDirTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslIterationTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryJmxTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/AbstractRetryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/DistributionRetryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/ReplicationRetryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/RetryOnFailureUnitTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/ServerFailureRetryTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/stress/ClientConsistentHashPerfTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/HotRodClientTestingUtil.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/MultiHotRodServersTest.java create mode 100644 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/RemoteCacheManagerCallable.java delete mode 100644 maven-settings.xml create mode 100644 off-heap/pom.xml.off-heap diff --git a/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/DefaultCacheTest.java b/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/DefaultCacheTest.java new file mode 100644 index 000000000000..b46f9a05f820 --- /dev/null +++ b/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/DefaultCacheTest.java @@ -0,0 +1,88 @@ +package org.infinispan.cdi.test.cache.remote; + +import org.infinispan.cdi.Remote; +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.core.test.ServerTestingUtil; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.testng.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; + +import static org.infinispan.cdi.test.testutil.Deployments.baseDeployment; +import static org.infinispan.client.hotrod.TestHelper.startHotRodServer; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.Assert.assertEquals; + +/** + * Tests the default cache injection. + * + * @author Kevin Pollet (C) 2011 SERLI + */ +@Test(groups = "functional", testName = "cdi.test.cache.remote.DefaultCacheTest") +public class DefaultCacheTest extends Arquillian { + + private static final String SERVER_LIST_KEY = "infinispan.client.hotrod.server_list"; + + @Deployment + public static Archive deployment() { + return baseDeployment() + .addClass(DefaultCacheTest.class); + } + + private static HotRodServer hotRodServer; + private static EmbeddedCacheManager embeddedCacheManager; + + @Inject + @Remote + private RemoteCache cache; + + @Inject + private RemoteCache remoteCache; + + @BeforeTest + public void beforeMethod() { + embeddedCacheManager = TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration(TestCacheManagerFactory + .getDefaultCacheConfiguration(false))); + hotRodServer = startHotRodServer(embeddedCacheManager); + } + + @AfterTest(alwaysRun = true) + public void afterMethod() { + TestingUtil.killCacheManagers(embeddedCacheManager); + ServerTestingUtil.killServer(hotRodServer); + } + + public void testDefaultCache() { + cache.put("pete", "British"); + cache.put("manik", "Sri Lankan"); + + assertEquals(cache.get("pete"), "British"); + assertEquals(cache.get("manik"), "Sri Lankan"); + assertEquals(remoteCache.get("pete"), "British"); + assertEquals(remoteCache.get("manik"), "Sri Lankan"); + } + + /** + * Overrides the default remote cache manager. + */ + @Produces + @ApplicationScoped + public static RemoteCacheManager defaultRemoteCacheManager() { + return new RemoteCacheManager( + new org.infinispan.client.hotrod.configuration.ConfigurationBuilder() + .addServers("127.0.0.1:" + hotRodServer.getPort()).build()); + } + +} diff --git a/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/NamedCacheTest.java b/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/NamedCacheTest.java new file mode 100644 index 000000000000..7663c4cad2aa --- /dev/null +++ b/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/NamedCacheTest.java @@ -0,0 +1,95 @@ +package org.infinispan.cdi.test.cache.remote; + +import org.infinispan.cdi.Remote; +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.testng.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; + +import static org.infinispan.cdi.test.testutil.Deployments.baseDeployment; +import static org.infinispan.client.hotrod.TestHelper.startHotRodServer; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.Assert.assertEquals; + +/** + * Tests the named cache injection. + * + * @author Kevin Pollet (C) 2011 SERLI + */ +@Test(groups = "functional", testName = "cdi.test.cache.remote.NamedCacheTest") +public class NamedCacheTest extends Arquillian { + + private static final String SERVER_LIST_KEY = "infinispan.client.hotrod.server_list"; + + @Deployment + public static Archive deployment() { + return baseDeployment() + .addClass(NamedCacheTest.class) + .addClass(Small.class); + } + + private static HotRodServer hotRodServer; + private static EmbeddedCacheManager embeddedCacheManager; + + @Inject + @Remote("small") + private RemoteCache cache; + + @Inject + @Small + private RemoteCache cacheWithQualifier; + + @BeforeTest + public void beforeMethod() { + embeddedCacheManager = TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration(TestCacheManagerFactory + .getDefaultCacheConfiguration(false))); + embeddedCacheManager.defineConfiguration("small", embeddedCacheManager.getDefaultCacheConfiguration()); + hotRodServer = startHotRodServer(embeddedCacheManager); + } + + @AfterTest(alwaysRun = true) + public void afterMethod() { + if (embeddedCacheManager != null) embeddedCacheManager.stop(); + if (hotRodServer != null) hotRodServer.stop(); + } + + public void testNamedCache() { + cache.put("pete", "British"); + cache.put("manik", "Sri Lankan"); + + assertEquals(cache.getName(), "small"); + assertEquals(cache.get("pete"), "British"); + assertEquals(cache.get("manik"), "Sri Lankan"); + + // here we check that the cache injection with the @Small qualifier works + // like the injection with the @Remote qualifier + + assertEquals(cacheWithQualifier.getName(), "small"); + assertEquals(cacheWithQualifier.get("pete"), "British"); + assertEquals(cacheWithQualifier.get("manik"), "Sri Lankan"); + } + + /** + * Overrides the default remote cache manager. + */ + @Produces + @ApplicationScoped + public static RemoteCacheManager defaultRemoteCacheManager() { + return new RemoteCacheManager( + new org.infinispan.client.hotrod.configuration.ConfigurationBuilder() + .addServers("127.0.0.1:" + hotRodServer.getPort()).build()); + } + +} diff --git a/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/Small.java b/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/Small.java new file mode 100644 index 000000000000..5971a08b90bb --- /dev/null +++ b/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/Small.java @@ -0,0 +1,25 @@ +package org.infinispan.cdi.test.cache.remote; + +import org.infinispan.cdi.Remote; + +import javax.inject.Qualifier; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * @author Kevin Pollet (C) 2011 SERLI + */ +@Remote("small") +@Qualifier +@Target({TYPE, METHOD, PARAMETER, FIELD}) +@Retention(RUNTIME) +@Documented +public @interface Small { +} diff --git a/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/SpecificCacheManagerTest.java b/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/SpecificCacheManagerTest.java new file mode 100644 index 000000000000..6ea7194828d2 --- /dev/null +++ b/cdi/extension/src/test/java/org/infinispan/cdi/test/cache/remote/SpecificCacheManagerTest.java @@ -0,0 +1,86 @@ +package org.infinispan.cdi.test.cache.remote; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.testng.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; + +import static org.infinispan.cdi.test.testutil.Deployments.baseDeployment; +import static org.infinispan.client.hotrod.TestHelper.startHotRodServer; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.Assert.assertEquals; + +/** + * Tests that the use of a specific cache manager for one cache. + * + * @author Kevin Pollet (C) 2011 SERLI + */ +@Test(groups = "functional", testName = "cdi.test.cache.remote.SpecificCacheManagerTest") +public class SpecificCacheManagerTest extends Arquillian { + + private static final String SERVER_LIST_KEY = "infinispan.client.hotrod.server_list"; + + @Deployment + public static Archive deployment() { + return baseDeployment() + .addClass(SpecificCacheManagerTest.class) + .addClass(Small.class); + } + + private static HotRodServer hotRodServer; + private static EmbeddedCacheManager embeddedCacheManager; + + @Inject + @Small + private RemoteCache cache; + + @BeforeTest + public void beforeMethod() { + embeddedCacheManager = TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration(TestCacheManagerFactory + .getDefaultCacheConfiguration(false))); + embeddedCacheManager.defineConfiguration("small", embeddedCacheManager.getDefaultCacheConfiguration()); + hotRodServer = startHotRodServer(embeddedCacheManager); + } + + @AfterTest(alwaysRun = true) + public void afterMethod() { + if (embeddedCacheManager != null) embeddedCacheManager.stop(); + if (hotRodServer != null) hotRodServer.stop(); + } + + public void testSpecificCacheManager() { + cache.put("pete", "British"); + cache.put("manik", "Sri Lankan"); + + assertEquals(cache.getName(), "small"); + assertEquals(cache.get("pete"), "British"); + assertEquals(cache.get("manik"), "Sri Lankan"); + } + + /** + * Produces a specific cache manager for the small cache. + * + * @see Small + */ + @Small + @Produces + @ApplicationScoped + public static RemoteCacheManager smallRemoteCacheManager() { + return new RemoteCacheManager( + new org.infinispan.client.hotrod.configuration.ConfigurationBuilder() + .addServers("127.0.0.1:" + hotRodServer.getPort()).build()); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ApacheCommonsPoolTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ApacheCommonsPoolTest.java new file mode 100644 index 000000000000..cdd7f8dc4b8c --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ApacheCommonsPoolTest.java @@ -0,0 +1,103 @@ +package org.infinispan.client.hotrod; + +import org.apache.commons.pool.BaseKeyedPoolableObjectFactory; +import org.apache.commons.pool.KeyedObjectPool; +import org.apache.commons.pool.KeyedObjectPoolFactory; +import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.fail; + +/** + * // TODO: Document this + * + * @author Galder Zamarreño + * @since // TODO + */ +@Test(groups = "functional", testName = "client.hotrod.ApacheCommonsPoolTest") +public class ApacheCommonsPoolTest { + + public void testBorrowValidObjectFromPool() throws Exception { + KeyedObjectPool pool = + BasicPoolFactory.createPoolFactory().createPool(); + String obj = pool.borrowObject(1); + assertEquals("1", obj); + } + + @Test(expectedExceptions = TooHighException.class) + public void testBorrowFromPoolException() throws Exception { + GenericKeyedObjectPoolFactory poolFactory = + BasicPoolFactory.createPoolFactory(); + try { + poolFactory.createPool().borrowObject(Integer.MAX_VALUE); + } finally { + BasicPoolFactory basicPoolFactory = + (BasicPoolFactory) poolFactory.getFactory(); + assertEquals("invalid", basicPoolFactory.getState(Integer.MAX_VALUE)); + } + } + + public void testInvalidateBorrowFromPool() throws Exception { + GenericKeyedObjectPoolFactory poolFactory = + BasicPoolFactory.createPoolFactory(); + KeyedObjectPool pool = poolFactory.createPool(); + try { + pool.borrowObject(Integer.MAX_VALUE); + fail("Should have thrown a TooHighException"); + } catch (TooHighException e) { + // Expected, now invalidate object + pool.invalidateObject(Integer.MAX_VALUE, null); + BasicPoolFactory basicPoolFactory = + (BasicPoolFactory) poolFactory.getFactory(); + assertEquals("destroyed", basicPoolFactory.getState(Integer.MAX_VALUE)); + } + } + + private static class BasicPoolFactory + extends BaseKeyedPoolableObjectFactory { + + private Map state = new HashMap(); + + private BasicPoolFactory() { + // Singleton + } + + @Override + public String makeObject(Integer key) throws Exception { + if (Integer.MAX_VALUE == key.intValue()) { + state.put(key, "invalid"); + throw new TooHighException("Too high"); + } + + return key.toString(); + } + + @Override + public void destroyObject(Integer key, String obj) throws Exception { + state.put(key, "destroyed"); + } + + public String getState(Integer key) { + return state.get(key); + } + + public static GenericKeyedObjectPoolFactory createPoolFactory() { + return new GenericKeyedObjectPoolFactory( + new BasicPoolFactory()); + } + + } + + private static class TooHighException extends RuntimeException { + + public TooHighException(String message) { + super(message); // TODO: Customise this generated block + } + + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BaseBulkGetKeysTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BaseBulkGetKeysTest.java new file mode 100644 index 000000000000..7efe35edc3cc --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BaseBulkGetKeysTest.java @@ -0,0 +1,110 @@ +package org.infinispan.client.hotrod; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +/** + * Tests functionality related to getting multiple entries from a HotRod server + * in bulk. + * + * @author Ray Tsang + * @since 5.2 + */ +@Test(groups = "functional") +public abstract class BaseBulkGetKeysTest extends MultipleCacheManagersTest { + protected HotRodServer[] hotrodServers; + protected RemoteCacheManager remoteCacheManager; + protected RemoteCache remoteCache; + + abstract protected int numberOfHotRodServers(); + + abstract protected ConfigurationBuilder clusterConfig(); + + @Override + protected void createCacheManagers() throws Throwable { + final int numServers = numberOfHotRodServers(); + hotrodServers = new HotRodServer[numServers]; + + createCluster(hotRodCacheConfiguration(clusterConfig()), numberOfHotRodServers()); + + for (int i = 0; i < numServers; i++) { + EmbeddedCacheManager cm = cacheManagers.get(i); + hotrodServers[i] = TestHelper.startHotRodServer(cm); + } + + String servers = TestHelper.getServersString(hotrodServers); + + remoteCacheManager = new RemoteCacheManager(servers); + remoteCache = remoteCacheManager.getCache(); + }; + + @AfterClass(alwaysRun = true) + public void release() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServers); + } + + protected void populateCacheManager() { + for (int i = 0; i < 100; i++) { + remoteCache.put(i, i); + } + } + + public void testBulkGetKeys() { + populateCacheManager(); + Set set = remoteCache.keySet(); + assert set.size() == 100; + for (int i = 0; i < 100; i++) { + assert set.contains(i); + } + } + + @Test(groups = "unstable", description = "See ISPN-4017") + public void testBulkGetAfterLifespanExpire() throws InterruptedException { + Map dataIn = new HashMap(); + dataIn.put("aKey", "aValue"); + dataIn.put("bKey", "bValue"); + final long startTime = System.currentTimeMillis(); + final long lifespan = 10000; + remoteCache.putAll(dataIn, lifespan, TimeUnit.MILLISECONDS); + + Set dataOut = new HashSet(); + while (true) { + dataOut = remoteCache.keySet(); + if (System.currentTimeMillis() >= startTime + lifespan) + break; + assert dataOut.size() == dataIn.size() : String + .format("Data size not the same, put in %s elements, keySet has %s elements", + dataIn.size(), dataOut.size()); + for (Object outKey : dataOut) { + assert dataIn.containsKey(outKey); + } + Thread.sleep(100); + } + + // Make sure that in the next 30 secs data is removed + while (System.currentTimeMillis() < startTime + lifespan + 30000) { + dataOut = remoteCache.keySet(); + if (dataOut.size() == 0) + return; + } + + assert dataOut.size() == 0 : String.format( + "Data not empty, it contains: %s elements", dataOut.size()); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BaseBulkGetTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BaseBulkGetTest.java new file mode 100644 index 000000000000..c1380554ea88 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BaseBulkGetTest.java @@ -0,0 +1,122 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertEquals; + +/** + * Tests functionality related to getting multiple entries from a HotRod server + * in bulk. + * + * @author Jiri Holusa [jholusa@redhat.com] + * @since 5.2 + */ + +@Test(groups = "functional") +public abstract class BaseBulkGetTest extends MultipleCacheManagersTest { + protected HotRodServer[] hotrodServers; + protected RemoteCacheManager remoteCacheManager; + protected RemoteCache remoteCache; + + abstract protected int numberOfHotRodServers(); + + abstract protected ConfigurationBuilder clusterConfig(); + + @Override + protected void createCacheManagers() throws Throwable { + final int numServers = numberOfHotRodServers(); + hotrodServers = new HotRodServer[numServers]; + + createCluster(hotRodCacheConfiguration(clusterConfig()), numberOfHotRodServers()); + + for (int i = 0; i < numServers; i++) { + EmbeddedCacheManager cm = cacheManagers.get(i); + hotrodServers[i] = TestHelper.startHotRodServer(cm); + } + + String servers = TestHelper.getServersString(hotrodServers); + + remoteCacheManager = new RemoteCacheManager(servers); + remoteCache = remoteCacheManager.getCache(); + } + + @AfterClass + public void release() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServers); + } + + private void populateCacheManager() { + for (int i = 0; i < 100; i++) { + remoteCache.put(i, i); + } + } + + public void testBulkGet() { + populateCacheManager(); + Map map = remoteCache.getBulk(); + assert map.size() == 100; + for (int i = 0; i < 100; i++) { + assert map.get(i).equals(i); + } + assert map.size() == 100; + + } + + public void testBulkGetWithSize() { + populateCacheManager(); + Map map = remoteCache.getBulk(50); + assertEquals(50, map.size()); + for (int i = 0; i < 100; i++) { + if (map.containsKey(i)) { + Integer value = (Integer) map.get(i); + assertEquals((Integer)i, value); + } + } + } + + public void testBulkGetAfterLifespanExpire() throws InterruptedException { + Map dataIn = new HashMap(); + dataIn.put("aKey", "aValue"); + dataIn.put("bKey", "bValue"); + final long startTime = System.currentTimeMillis(); + final long lifespan = 10000; + remoteCache.putAll(dataIn, lifespan, TimeUnit.MILLISECONDS); + + Map dataOut = new HashMap(); + while (true) { + dataOut = remoteCache.getBulk(); + if (System.currentTimeMillis() >= startTime + lifespan) + break; + assertEquals(dataIn, dataOut); + Thread.sleep(100); + } + + // Make sure that in the next 30 secs data is removed + while (System.currentTimeMillis() < startTime + lifespan + 30000) { + dataOut = remoteCache.getBulk(); + if (dataOut.size() == 0) return; + } + + assert dataOut.size() == 0 : + String.format("Data not empty, it contains: %s elements", dataOut.size()); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysDistTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysDistTest.java new file mode 100644 index 000000000000..01943833f3b7 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysDistTest.java @@ -0,0 +1,46 @@ +package org.infinispan.client.hotrod; + +import java.util.Set; + +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.testng.annotations.Test; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * Tests functionality related to getting multiple entries from a HotRod server + * in bulk. + * + * @author Ray Tsang + * @since 5.2 + */ +@Test(testName = "client.hotrod.BulkGetKeysDistTest", groups = "functional") +public class BulkGetKeysDistTest extends BaseBulkGetKeysTest { + @Override + protected int numberOfHotRodServers() { + return 3; + } + + @Override + protected ConfigurationBuilder clusterConfig() { + return hotRodCacheConfiguration(getDefaultClusteredCacheConfig( + CacheMode.DIST_SYNC, false)); + } + + public void testDistribution() { + for (int i = 0; i < 100; i++) { + remoteCache.put(i, i); + } + + for (int i = 0 ; i < numberOfHotRodServers(); i++) { + assert cache(i).size() < 100; + } + + Set set = remoteCache.keySet(); + assert set.size() == 100; + for (int i = 0; i < 100; i++) { + assert set.contains(i); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysReplTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysReplTest.java new file mode 100644 index 000000000000..9d2b4cf7274a --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysReplTest.java @@ -0,0 +1,26 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.testng.annotations.Test; + +/** + * Tests functionality related to getting multiple entries from a HotRod server + * in bulk. + * + * @author Ray Tsang + * @since 5.2 + */ +@Test(testName = "client.hotrod.BulkGetKeysReplTest", groups = "functional") +public class BulkGetKeysReplTest extends BaseBulkGetKeysTest { + @Override + protected int numberOfHotRodServers() { + return 3; + } + + @Override + protected ConfigurationBuilder clusterConfig() { + return getDefaultClusteredCacheConfig( + CacheMode.REPL_SYNC, true); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysSimpleTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysSimpleTest.java new file mode 100644 index 000000000000..ed7e6683ebc7 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetKeysSimpleTest.java @@ -0,0 +1,28 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.testng.annotations.Test; + +/** + * Tests functionality related to getting multiple entries from a HotRod server + * in bulk. + * + * @author Ray Tsang + * @since 5.2 + */ +@Test(testName = "client.hotrod.BulkGetKeysSimpleTest", groups = "functional") +public class BulkGetKeysSimpleTest extends BaseBulkGetKeysTest { + + @Override + protected int numberOfHotRodServers() { + return 1; + } + + @Override + protected ConfigurationBuilder clusterConfig() { + return getDefaultClusteredCacheConfig( + CacheMode.LOCAL, true); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetReplTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetReplTest.java new file mode 100644 index 000000000000..4b6daf22ddec --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetReplTest.java @@ -0,0 +1,26 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.testng.annotations.Test; + +/** + * Tests functionality related to getting multiple entries from a HotRod server + * in bulk. + * + * @author Ray Tsang + * @since 5.2 + */ +@Test(testName = "client.hotrod.BulkGetReplTest", groups = "functional") +public class BulkGetReplTest extends BaseBulkGetTest { + @Override + protected int numberOfHotRodServers() { + return 3; + } + + @Override + protected ConfigurationBuilder clusterConfig() { + return getDefaultClusteredCacheConfig( + CacheMode.REPL_SYNC, true); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetSimpleTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetSimpleTest.java new file mode 100644 index 000000000000..236334e3f439 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/BulkGetSimpleTest.java @@ -0,0 +1,42 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.configuration.cache.CacheMode; +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.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertEquals; + +/** + * Tests functionality related to getting multiple entries from a HotRod server + * in bulk. + * + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.BulkGetSimpleTest", groups = "functional") +public class BulkGetSimpleTest extends BaseBulkGetTest { + + @Override + protected int numberOfHotRodServers() { + return 1; + } + + @Override + protected ConfigurationBuilder clusterConfig() { + return getDefaultClusteredCacheConfig( + CacheMode.LOCAL, true); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CSAIntegrationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CSAIntegrationTest.java new file mode 100644 index 000000000000..b88c151d4a75 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CSAIntegrationTest.java @@ -0,0 +1,173 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransport; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.distribution.DistributionManager; +import org.infinispan.distribution.ch.ConsistentHash; +import org.infinispan.lifecycle.ComponentStatus; +import org.infinispan.manager.CacheContainer; +import org.infinispan.remoting.transport.Address; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.util.logging.Log; +import org.infinispan.util.logging.LogFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.Random; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.*; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; + +import static org.infinispan.test.TestingUtil.*; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(groups = "functional", testName = "client.hotrod.CSAIntegrationTest") +public class CSAIntegrationTest extends HitsAwareCacheManagersTest { + + private HotRodServer hotRodServer1; + private HotRodServer hotRodServer2; + private HotRodServer hotRodServer3; + private RemoteCacheManager remoteCacheManager; + private RemoteCache remoteCache; + private TcpTransportFactory tcpConnectionFactory; + + private static final Log log = LogFactory.getLog(CSAIntegrationTest.class); + + @AfterMethod + @Override + protected void clearContent() throws Throwable { + } + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder builder = hotRodCacheConfiguration( + getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false)); + builder.clustering().hash().numOwners(1); + builder.unsafe().unreliableReturnValues(true); + addClusterEnabledCacheManager(builder); + addClusterEnabledCacheManager(builder); + addClusterEnabledCacheManager(builder); + + hotRodServer1 = TestHelper.startHotRodServer(manager(0)); + hrServ2CacheManager.put(new InetSocketAddress(hotRodServer1.getHost(), hotRodServer1.getPort()), manager(0)); + hotRodServer2 = TestHelper.startHotRodServer(manager(1)); + hrServ2CacheManager.put(new InetSocketAddress(hotRodServer2.getHost(), hotRodServer2.getPort()), manager(1)); + hotRodServer3 = TestHelper.startHotRodServer(manager(2)); + hrServ2CacheManager.put(new InetSocketAddress(hotRodServer3.getHost(), hotRodServer3.getPort()), manager(2)); + + assert manager(0).getCache() != null; + assert manager(1).getCache() != null; + assert manager(2).getCache() != null; + + blockUntilViewReceived(manager(0).getCache(), 3); + blockUntilCacheStatusAchieved(manager(0).getCache(), ComponentStatus.RUNNING, 10000); + blockUntilCacheStatusAchieved(manager(1).getCache(), ComponentStatus.RUNNING, 10000); + blockUntilCacheStatusAchieved(manager(2).getCache(), ComponentStatus.RUNNING, 10000); + + //Important: this only connects to one of the two servers! + Properties props = new Properties(); + props.put("infinispan.client.hotrod.server_list", "localhost:" + hotRodServer2.getPort() + ";localhost:" + hotRodServer2.getPort()); + props.put("infinispan.client.hotrod.ping_on_startup", "true"); + setHotRodProtocolVersion(props); + remoteCacheManager = new RemoteCacheManager(props); + remoteCache = remoteCacheManager.getCache(); + + tcpConnectionFactory = (TcpTransportFactory) extractField(remoteCacheManager, "transportFactory"); + } + + protected void setHotRodProtocolVersion(Properties props) { + // No-op, use default Hot Rod protocol version + } + + @AfterClass + @Override + protected void destroy() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer1, hotRodServer2, hotRodServer3); + super.destroy(); + } + + public void testHashInfoRetrieved() throws InterruptedException { + assertEquals(3, tcpConnectionFactory.getServers().size()); + for (int i = 0; i < 10; i++) { + remoteCache.put("k", "v"); + if (tcpConnectionFactory.getServers().size() == 3) break; + Thread.sleep(1000); + } + assertEquals(3, tcpConnectionFactory.getServers().size()); + assertNotNull(tcpConnectionFactory.getConsistentHash()); + } + + @Test(dependsOnMethods = "testHashInfoRetrieved") + public void testCorrectSetup() { + remoteCache.put("k", "v"); + assert remoteCache.get("k").equals("v"); + } + + @Test(dependsOnMethods = "testCorrectSetup") + public void testHashFunctionReturnsSameValues() { + for (int i = 0; i < 1000; i++) { + byte[] key = generateKey(i); + TcpTransport transport = (TcpTransport) tcpConnectionFactory.getTransport(key, null); + SocketAddress serverAddress = transport.getServerAddress(); + CacheContainer cacheContainer = hrServ2CacheManager.get(serverAddress); + assertNotNull("For server address " + serverAddress + " found " + cacheContainer + ". Map is: " + hrServ2CacheManager, cacheContainer); + DistributionManager distributionManager = cacheContainer.getCache().getAdvancedCache().getDistributionManager(); + Address clusterAddress = cacheContainer.getCache().getAdvancedCache().getRpcManager().getAddress(); + + ConsistentHash serverCh = distributionManager.getReadConsistentHash(); + int numSegments = serverCh.getNumSegments(); + int keySegment = serverCh.getSegment(key); + Address serverOwner = serverCh.locatePrimaryOwnerForSegment(keySegment); + Address serverPreviousOwner = serverCh.locatePrimaryOwnerForSegment((keySegment - 1 + numSegments) % numSegments); + assert clusterAddress.equals(serverOwner) || clusterAddress.equals(serverPreviousOwner); + tcpConnectionFactory.releaseTransport(transport); + } + } + + @Test(dependsOnMethods = "testHashFunctionReturnsSameValues") + public void testRequestsGoToExpectedServer() throws Exception { + addInterceptors(); + List keys = new ArrayList(); + for (int i = 0; i < 500; i++) { + byte[] key = generateKey(i); + keys.add(key); + String keyStr = new String(key); + remoteCache.put(keyStr, "value"); + TcpTransport transport = (TcpTransport) tcpConnectionFactory.getTransport(marshall(keyStr), null); + assertHotRodEquals(hrServ2CacheManager.get(transport.getServerAddress()), keyStr, "value"); + tcpConnectionFactory.releaseTransport(transport); + } + + log.info("Right before first get."); + + for (byte[] key : keys) { + resetStats(); + String keyStr = new String(key); + assert remoteCache.get(keyStr).equals("value"); + TcpTransport transport = (TcpTransport) tcpConnectionFactory.getTransport(marshall(keyStr), null); + assertOnlyServerHit(transport.getServerAddress()); + tcpConnectionFactory.releaseTransport(transport); + } + } + + private byte[] generateKey(int i) { + Random r = new Random(); + byte[] result = new byte[i]; + r.nextBytes(result); + return result; + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheContainerTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheContainerTest.java new file mode 100644 index 000000000000..c53d25d531d6 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheContainerTest.java @@ -0,0 +1,58 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.api.BasicCache; +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.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.infinispan.test.TestingUtil.*; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(groups = "functional", testName = "client.hotrod.CacheContainerTest") +public class CacheContainerTest extends SingleCacheManagerTest { + + private static final String CACHE_NAME = "someName"; + + EmbeddedCacheManager cacheManager = null; + HotRodServer hotrodServer = null; + RemoteCacheManager remoteCacheManager; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration()); + cacheManager.defineConfiguration(CACHE_NAME, hotRodCacheConfiguration().build()); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + remoteCacheManager = new RemoteCacheManager("localhost:" + hotrodServer.getPort(), true); + return cacheManager; + } + + @AfterTest + public void release() { + killCacheManagers(cacheManager); + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServer); + } + + public void testObtainingSameInstanceMultipleTimes() { + RemoteCache objectCache = remoteCacheManager.getCache(); + RemoteCache objectCache2 = remoteCacheManager.getCache(); + assert objectCache == objectCache2; + } + + public void testObtainingSameInstanceMultipleTimes2() { + RemoteCache objectCache = remoteCacheManager.getCache(CACHE_NAME); + RemoteCache objectCache2 = remoteCacheManager.getCache(CACHE_NAME); + assert objectCache == objectCache2; + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheManagerNotStartedTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheManagerNotStartedTest.java new file mode 100644 index 000000000000..e33a2d77ab74 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheManagerNotStartedTest.java @@ -0,0 +1,123 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.exceptions.RemoteCacheManagerNotStartedException; +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.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import java.util.HashMap; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test (testName = "client.hotrod.CacheManagerNotStartedTest", groups = "functional") +public class CacheManagerNotStartedTest extends SingleCacheManagerTest { + + private static final String CACHE_NAME = "someName"; + + EmbeddedCacheManager cacheManager = null; + HotRodServer hotrodServer = null; + RemoteCacheManager remoteCacheManager; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory + .createCacheManager(hotRodCacheConfiguration()); + cacheManager.defineConfiguration(CACHE_NAME, hotRodCacheConfiguration().build()); + return cacheManager; + } + + @Override + protected void setup() throws Exception { + super.setup(); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + remoteCacheManager = new RemoteCacheManager( + "127.0.0.1:" + hotrodServer.getPort(), false); + } + + @AfterClass + @Override + protected void destroyAfterClass() { + super.destroyAfterClass(); + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServer); + } + + public void testGetCacheOperations() { + assert remoteCacheManager.getCache() != null; + assert remoteCacheManager.getCache(CACHE_NAME) != null; + assert !remoteCacheManager.isStarted(); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testGetCacheOperations2() { + remoteCacheManager.getCache().put("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testGetCacheOperations3() { + remoteCacheManager.getCache(CACHE_NAME).put("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testPut() { + remoteCache().put("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testPutAsync() { + remoteCache().putAsync("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testGet() { + remoteCache().get("k"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testReplace() { + remoteCache().replace("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testReplaceAsync() { + remoteCache().replaceAsync("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testPutAll() { + remoteCache().putAll(new HashMap()); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testPutAllAsync() { + remoteCache().putAllAsync(new HashMap()); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testVersionedGet() { + remoteCache().getVersioned("key"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testVersionedRemove() { + remoteCache().removeWithVersion("key", 12312321l); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class) + public void testVersionedRemoveAsync() { + remoteCache().removeWithVersionAsync("key", 12312321l); + } + + private RemoteCache remoteCache() { + return remoteCacheManager.getCache(); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheManagerStoppedTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheManagerStoppedTest.java new file mode 100644 index 000000000000..b5798afcf5fb --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/CacheManagerStoppedTest.java @@ -0,0 +1,125 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.exceptions.RemoteCacheManagerNotStartedException; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import java.util.HashMap; + +import static org.infinispan.test.TestingUtil.*; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test (testName = "client.hotrod.CacheManagerStoppedTest", groups = "functional") +public class CacheManagerStoppedTest extends SingleCacheManagerTest { + + private static final String CACHE_NAME = "someName"; + + EmbeddedCacheManager cacheManager = null; + HotRodServer hotrodServer = null; + RemoteCacheManager remoteCacheManager; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()); + cacheManager.defineConfiguration(CACHE_NAME, hotRodCacheConfiguration().build()); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + remoteCacheManager = new RemoteCacheManager("localhost:" + hotrodServer.getPort(), true); + return cacheManager; + } + + @AfterTest + public void release() { + killRemoteCacheManager(remoteCacheManager); + killCacheManagers(cacheManager); + killServers(hotrodServer); + } + + public void testGetCacheOperations() { + assert remoteCacheManager.getCache() != null; + assert remoteCacheManager.getCache(CACHE_NAME) != null; + remoteCache().put("k", "v"); + assert remoteCache().get("k").equals("v"); + } + + @Test (dependsOnMethods = "testGetCacheOperations") + public void testStopCacheManager() { + assert remoteCacheManager.isStarted(); + remoteCacheManager.stop(); + assert !remoteCacheManager.isStarted(); + assert remoteCacheManager.getCache() != null; + assert remoteCacheManager.getCache(CACHE_NAME) != null; + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testGetCacheOperations2() { + remoteCacheManager.getCache().put("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testGetCacheOperations3() { + remoteCacheManager.getCache(CACHE_NAME).put("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testPut() { + remoteCache().put("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testPutAsync() { + remoteCache().putAsync("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testGet() { + remoteCache().get("k"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testReplace() { + remoteCache().replace("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testReplaceAsync() { + remoteCache().replaceAsync("k", "v"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testPutAll() { + remoteCache().putAll(new HashMap()); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testPutAllAsync() { + remoteCache().putAllAsync(new HashMap()); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testVersionedGet() { + remoteCache().getVersioned("key"); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testVersionedRemove() { + remoteCache().removeWithVersion("key", 12312321l); + } + + @Test(expectedExceptions = RemoteCacheManagerNotStartedException.class, dependsOnMethods = "testStopCacheManager") + public void testVersionedRemoveAsync() { + remoteCache().removeWithVersionAsync("key", 12312321l); + } + + private RemoteCache remoteCache() { + return remoteCacheManager.getCache(); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientAsymmetricClusterTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientAsymmetricClusterTest.java new file mode 100644 index 000000000000..f8afad5619e1 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientAsymmetricClusterTest.java @@ -0,0 +1,47 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.exceptions.HotRodClientException; +import org.infinispan.client.hotrod.test.MultiHotRodServersTest; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.testng.annotations.Test; + +import static org.testng.AssertJUnit.assertEquals; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * Tests behaviour of Hot Rod clients with asymmetric clusters. + * + * @author Galder Zamarreño + * @since 5.2 + */ +@Test(groups = "functional", testName = "client.hotrod.ClientAsymmetricClusterTest") +public class ClientAsymmetricClusterTest extends MultiHotRodServersTest { + + private static final String CACHE_NAME = "asymmetricCache"; + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder builder = hotRodCacheConfiguration( + getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, false)); + + createHotRodServers(2, builder); + + // Define replicated cache in only one of the nodes + manager(0).defineConfiguration(CACHE_NAME, builder.build()); + } + + @Test(expectedExceptions = HotRodClientException.class, + expectedExceptionsMessageRegExp = ".*CacheNotFoundException.*") + public void testAsymmetricCluster() { + RemoteCacheManager client0 = client(0); + RemoteCache cache0 = client0.getCache(CACHE_NAME); + cache0.put(1, "v1"); + assertEquals("v1", cache0.get(1)); + cache0.put(2, "v1"); + assertEquals("v1", cache0.get(2)); + cache0.put(3, "v1"); + assertEquals("v1", cache0.get(3)); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientConnectionPoolingTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientConnectionPoolingTest.java new file mode 100644 index 000000000000..594b13e7d76f --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientConnectionPoolingTest.java @@ -0,0 +1,286 @@ +package org.infinispan.client.hotrod; + +import org.apache.commons.pool.impl.GenericKeyedObjectPool; +import org.infinispan.Cache; +import org.infinispan.client.hotrod.impl.ConfigurationProperties; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.commands.VisitableCommand; +import org.infinispan.context.InvocationContext; +import org.infinispan.interceptors.base.CommandInterceptor; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.infinispan.util.logging.Log; +import org.infinispan.util.logging.LogFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.util.Properties; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.locks.ReentrantLock; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertTrue; + +import static org.infinispan.test.TestingUtil.*; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.ClientConnectionPoolingTest", groups="functional") +public class ClientConnectionPoolingTest extends MultipleCacheManagersTest { + + private static final Log log = LogFactory.getLog(ClientConnectionPoolingTest.class); + + Cache c1; + Cache c2; + private HotRodServer hotRodServer1; + private HotRodServer hotRodServer2; + + RemoteCache remoteCache; + private RemoteCacheManager remoteCacheManager; + private GenericKeyedObjectPool connectionPool; + private InetSocketAddress hrServ1Addr; + private InetSocketAddress hrServ2Addr; + + + private WorkerThread workerThread1; + private WorkerThread workerThread2; + private WorkerThread workerThread3; + private WorkerThread workerThread4; + private WorkerThread workerThread5; + private WorkerThread workerThread6; + + + @Override + protected void assertSupportedConfig() { + // No-op + } + + @Override + protected void createCacheManagers() throws Throwable { + // The caches are not configured to form a cluster + // so the client will have to use round-robin for balancing. + // This means requests will alternate between server 1 and server 2. + c1 = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()).getCache(); + c2 = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()).getCache(); + registerCacheManager(c1.getCacheManager(), c2.getCacheManager()); + + hotRodServer1 = TestHelper.startHotRodServer(c1.getCacheManager()); + hotRodServer2 = TestHelper.startHotRodServer(c2.getCacheManager()); + + String servers = TestHelper.getServersString(hotRodServer1, hotRodServer2); + Properties hotrodClientConf = new Properties(); + hotrodClientConf.setProperty(ConfigurationProperties.SERVER_LIST, servers); + hotrodClientConf.setProperty("maxActive", "2"); + hotrodClientConf.setProperty("maxTotal", "8"); + hotrodClientConf.setProperty("maxIdle", "6"); + hotrodClientConf.setProperty("whenExhaustedAction", "1"); + hotrodClientConf.setProperty("testOnBorrow", "false"); + hotrodClientConf.setProperty("testOnReturn", "false"); + hotrodClientConf.setProperty("timeBetweenEvictionRunsMillis", "-2"); + hotrodClientConf.setProperty("minEvictableIdleTimeMillis", "7"); + hotrodClientConf.setProperty("testWhileIdle", "true"); + hotrodClientConf.setProperty("minIdle", "-5"); + hotrodClientConf.setProperty("lifo", "true"); + hotrodClientConf.setProperty("infinispan.client.hotrod.ping_on_startup", "false"); + + remoteCacheManager = new RemoteCacheManager(hotrodClientConf); + remoteCache = remoteCacheManager.getCache(); + + TcpTransportFactory tcpConnectionFactory = (TcpTransportFactory) extractField(remoteCacheManager, "transportFactory"); + connectionPool = (GenericKeyedObjectPool) extractField(tcpConnectionFactory, "connectionPool"); + workerThread1 = new WorkerThread(remoteCache); + workerThread2 = new WorkerThread(remoteCache); + workerThread3 = new WorkerThread(remoteCache); + workerThread4 = new WorkerThread(remoteCache); + workerThread5 = new WorkerThread(remoteCache); + workerThread6 = new WorkerThread(remoteCache); + + hrServ1Addr = new InetSocketAddress("localhost", hotRodServer1.getPort()); + hrServ2Addr = new InetSocketAddress("localhost", hotRodServer2.getPort()); + } + + @AfterMethod + public void tearDown() throws ExecutionException, InterruptedException { + killServers(hotRodServer1, hotRodServer2); + + workerThread1.stop(); + workerThread2.stop(); + workerThread3.stop(); + workerThread4.stop(); + workerThread5.stop(); + workerThread6.stop(); + + workerThread1.awaitTermination(); + workerThread2.awaitTermination(); + workerThread3.awaitTermination(); + workerThread4.awaitTermination(); + workerThread5.awaitTermination(); + workerThread6.awaitTermination(); + + killRemoteCacheManager(remoteCacheManager); + } + + @Test + public void testPropsCorrectlySet() { + assertEquals(2, connectionPool.getMaxActive()); + assertEquals(8, connectionPool.getMaxTotal()); + assertEquals(6, connectionPool.getMaxIdle()); + assertEquals(1, connectionPool.getWhenExhaustedAction()); + assertFalse(connectionPool.getTestOnBorrow()); + assertFalse(connectionPool.getTestOnReturn()); + assertEquals(-2, connectionPool.getTimeBetweenEvictionRunsMillis()); + assertEquals(7, connectionPool.getMinEvictableIdleTimeMillis()); + assertTrue(connectionPool.getTestWhileIdle()); + assertEquals(-5, connectionPool.getMinIdle()); + assertTrue(connectionPool.getLifo()); + } + + public void testMaxActiveReached() throws Exception { + workerThread1.put("k1", "v1"); + workerThread1.put("k2", "v2"); + + // verify that each cache got a request + assertEquals(1, c1.size()); + assertEquals(1, c2.size()); + + assertEquals("v1", remoteCache.get("k1")); + assertEquals(1, c1.size()); + assertEquals("v2", remoteCache.get("k2")); + assertEquals(1, c2.size()); + + // there should be no active connections to any server + assertEquals(0, connectionPool.getNumActive(hrServ1Addr)); + assertEquals(0, connectionPool.getNumActive(hrServ2Addr)); + assertEquals(1, connectionPool.getNumIdle(hrServ1Addr)); + assertEquals(1, connectionPool.getNumIdle(hrServ2Addr)); + + // install an interceptor that will block all requests on the server until the allow() call + DelayTransportInterceptor dt1 = new DelayTransportInterceptor(true); + DelayTransportInterceptor dt2 = new DelayTransportInterceptor(true); + c1.getAdvancedCache().addInterceptor(dt1, 0); + c2.getAdvancedCache().addInterceptor(dt2, 0); + log.info("Cache operations blocked"); + + try { + // start one operation on each server, using the existing connections + workerThread1.putAsync("k3", "v3"); + workerThread2.putAsync("k4", "v4"); + log.info("Async calls for k3 and k4 is done."); + + eventually(new Condition() { + @Override + public boolean isSatisfied() throws Exception { + return 1 == connectionPool.getNumActive(hrServ1Addr) && + 1 == connectionPool.getNumActive(hrServ2Addr) && + 0 == connectionPool.getNumIdle(hrServ1Addr) && + 0 == connectionPool.getNumIdle(hrServ2Addr); + } + }); + + + // another operation for each server, creating new connections + workerThread3.putAsync("k5", "v5"); + workerThread4.putAsync("k6", "v6"); + eventually(new Condition() { + @Override + public boolean isSatisfied() throws Exception { + return 2 == connectionPool.getNumActive(hrServ1Addr) && + 2 == connectionPool.getNumActive(hrServ2Addr) && + 0 == connectionPool.getNumIdle(hrServ1Addr) && + 0 == connectionPool.getNumIdle(hrServ2Addr); + } + }); + + // we've reached the connection pool limit, the new operations will block + // until a connection is released + workerThread5.putAsync("k7", "v7"); + workerThread6.putAsync("k8", "v8"); + Thread.sleep(2000); //sleep a bit longer to make sure the async threads do their job + assertEquals(2, connectionPool.getNumActive(hrServ1Addr)); + assertEquals(2, connectionPool.getNumActive(hrServ2Addr)); + assertEquals(0, connectionPool.getNumIdle(hrServ1Addr)); + assertEquals(0, connectionPool.getNumIdle(hrServ2Addr)); + } + catch (Exception e) { + log.error(e); + } finally { + //now allow + dt1.allow(); + dt2.allow(); + } + + // give the servers some time to process the operations + eventually(new Condition() { + @Override + public boolean isSatisfied() throws Exception { + return connectionPool.getNumActive() == 0; + } + }, 1000); + + assertExistKeyValue("k3", "v3"); + assertExistKeyValue("k4", "v4"); + assertExistKeyValue("k5", "v5"); + assertExistKeyValue("k6", "v6"); + assertExistKeyValue("k7", "v7"); + assertExistKeyValue("k8", "v8"); + + // all the connections have been released to the pool, but haven't been closed + assertEquals(0, connectionPool.getNumActive(hrServ1Addr)); + assertEquals(0, connectionPool.getNumActive(hrServ2Addr)); + assertEquals(2, connectionPool.getNumIdle(hrServ1Addr)); + assertEquals(2, connectionPool.getNumIdle(hrServ2Addr)); + } + + private void assertExistKeyValue(String key, String value) throws InterruptedException { + boolean exists = false; + for (int i = 0; i < 10; i++) { + exists = value.equals(remoteCache.get(key)) || value.equals(remoteCache.get(key)); + if (exists) break; + Thread.sleep(1000); + } + assertEquals("key value not found: (" + key + ", " + value + ")", true, exists); + } + + public static class DelayTransportInterceptor extends CommandInterceptor { + + private final ReentrantLock lock = new ReentrantLock(); + + public DelayTransportInterceptor(boolean lock) { + if (lock) + block(); + } + + @Override + protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable { + log.trace("Acquiring lock. " + lockInfo()); + lock.lock(); + try { + return super.handleDefault(ctx, command); + } finally { + log.trace("Done operation, releasing lock" + lockInfo()); + lock.unlock(); + } + } + + private String lockInfo() { + return " Is locked? " + lock.isLocked() + ". Lock held by me? " + lock.isHeldByCurrentThread(); + } + + public void block() { + log.trace("block. " + lockInfo()); + lock.lock(); + } + + public void allow() { + log.trace("allow." + lockInfo()); + lock.unlock(); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientSocketReadTimeoutTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientSocketReadTimeoutTest.java new file mode 100644 index 000000000000..1ca5703160e8 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ClientSocketReadTimeoutTest.java @@ -0,0 +1,122 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.Cache; +import org.infinispan.client.hotrod.exceptions.TransportException; +import org.infinispan.commons.CacheException; +import org.infinispan.manager.AbstractDelegatingEmbeddedCacheManager; +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.Test; + +import java.lang.reflect.Method; +import java.net.SocketTimeoutException; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.infinispan.test.TestingUtil.*; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; + +/** + * This test is used to verify that clients get a timeout when the server does + * not respond with the requested bytes. + * + * @author Galder Zamarreño + * @since 4.2 + */ +@Test(testName = "client.hotrod.ClientSocketReadTimeoutTest", groups = "functional" ) +public class ClientSocketReadTimeoutTest extends SingleCacheManagerTest { + + HotRodServer hotrodServer; + RemoteCacheManager remoteCacheManager; + RemoteCache defaultRemote; + CountDownLatch latch; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + latch = new CountDownLatch(1); + cacheManager = new HangingCacheManager( + TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()), + latch); + // cacheManager = TestCacheManagerFactory.createLocalCacheManager(); + // pass the config file to the cache + hotrodServer = TestHelper.startHotRodServer(cacheManager); + log.info("Started server on port: " + hotrodServer.getPort()); + + remoteCacheManager = getRemoteCacheManager(); + defaultRemote = remoteCacheManager.getCache(); + + return cacheManager; + } + + protected RemoteCacheManager getRemoteCacheManager() { + Properties config = new Properties(); + config.put("infinispan.client.hotrod.server_list", "127.0.0.1:" + hotrodServer.getPort()); + config.put("infinispan.client.hotrod.socket_timeout", "5000"); + config.put("infinispan.client.hotrod.connect_timeout", "5000"); + config.put("maxActive", 2); + // Set ping on startup false, so that the hang can happen + // when the put comes, and not when the remote cache manager is built. + config.put("infinispan.client.hotrod.ping_on_startup", "false"); + return new RemoteCacheManager(config); + } + + @Override + protected void teardown() { + latch.countDown(); + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServer); + super.teardown(); + } + + @Test(expectedExceptions = SocketTimeoutException.class) + public void testPutTimeout(Method m) throws Throwable { + try { + assert null == defaultRemote.put(k(m), v(m)); + } catch (TransportException e) { + throw e.getCause(); + } + + } + + private static class HangingCacheManager extends AbstractDelegatingEmbeddedCacheManager { + + static Log log = LogFactory.getLog(HangingCacheManager.class); + + final CountDownLatch latch; + + public HangingCacheManager(EmbeddedCacheManager delegate, CountDownLatch latch) { + super(delegate); + this.latch = latch; + } + + @Override + public Cache getCache(String cacheName) { + log.info("Retrieve cache from hanging cache manager"); + // TODO: Hacky but it's the easiest thing to do - consider ByteMan + // ByteMan apparently supports testng since 1.5.1 but no clear + // example out there, with more time it should be considered. + String threadName = Thread.currentThread().getName(); + if (threadName.startsWith("HotRod")) { + log.info("Thread is a HotRod server worker thread, so force wait"); + try { + // Wait a max of 3 minutes, otherwise socket timeout's not working + latch.await(180, TimeUnit.SECONDS); + log.info("Wait finished, return the cache"); + return super.getCache(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new CacheException(e); + } + } + return super.getCache(cacheName); + } + + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashComparisonTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashComparisonTest.java new file mode 100644 index 000000000000..c041e39805ad --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashComparisonTest.java @@ -0,0 +1,185 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHash; +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHashV1; +import org.infinispan.commons.hash.Hash; +import org.infinispan.commons.hash.MurmurHash2; +import org.infinispan.commons.logging.BasicLogFactory; +import org.infinispan.commons.util.Util; +import org.jboss.logging.BasicLogger; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +import static org.testng.Assert.assertEquals; + +/** + * The ConsistentHashV1 was reimplemented to be more efficient. This test makes sure that the new implementation behaves + * exactly like the previous implementation. + * + * @author Mircea Markus (C) 2011 Red Hat Inc. + */ +@Test(groups = "functional") +public class ConsistentHashComparisonTest { + + public static final int PHISYCAL_NODES = 10; + public static final int VIRTUAL_NODES = 5; + private LinkedHashMap> ch; + CustomRandom customRandom = new CustomRandom(); + ConsistentHashV1Old vOld = new ConsistentHashV1Old(customRandom); + ConsistentHashV1 vNew = new ConsistentHashV1(customRandom); + + @BeforeTest + public void init() { + + int hashSpace = Integer.MAX_VALUE; + int share = hashSpace / PHISYCAL_NODES; + int virtualNodesSpan = share / VIRTUAL_NODES - 1; + + ch = new LinkedHashMap>(); + for (int i = 0; i < PHISYCAL_NODES; i++) { + Set virtualNodes = new HashSet(); + for (int j = 0; j < VIRTUAL_NODES; j++) { + virtualNodes.add(share * i + virtualNodesSpan * j); + } + ch.put(new InetSocketAddress(i), virtualNodes); + } + vOld.init(ch, 2, Integer.MAX_VALUE); + vNew.init(ch, 2, Integer.MAX_VALUE); + } + + public void testSameValues() { + for (int i = 0; i < 1000; i++) { + byte[] key = String.valueOf(i).getBytes(); + assertEquals(vOld.getServer(key), vNew.getServer(key), "int value is " + i); + } + } + + public void testSameValues2() { + Random rnd = new Random(); + for (int i = 0; i < 10000; i++) { + byte[] key = new byte[i+1]; + rnd.nextBytes(key); + assertEquals(vOld.getServer(key), vNew.getServer(key), "int value is " + i); + } + } + + public void testIsolatedValue() { + byte[] key = String.valueOf(0).getBytes(); + SocketAddress newOne = vNew.getServer(key); + SocketAddress oldOne = vOld.getServer(key); + assertEquals(oldOne, newOne); + } + + public void testIsolatedValue2() { + byte[] key = String.valueOf(7).getBytes(); + SocketAddress newOne = vNew.getServer(key); + SocketAddress oldOne = vOld.getServer(key); + assertEquals(oldOne, newOne); + } + + public static class CustomRandom extends Random { + + int callCount = 0; + int toReturn; + + @Override + public int nextInt(int val) { + if (callCount % 2 == 0) { + toReturn = super.nextInt(val); + } + callCount ++; + return toReturn; + } + } + + /** + * Version one consistent hash function based on {@link org.infinispan.commons.hash.MurmurHash2}; + * + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ + static class ConsistentHashV1Old implements ConsistentHash { + + private static final BasicLogger log = BasicLogFactory.getLog(ConsistentHashV1Old.class); + + private final SortedMap positions = new TreeMap(); + + private int hashSpace; + + protected Hash hash = new MurmurHash2(); + + private int numKeyOwners; + + private final Random rnd; + + public ConsistentHashV1Old(Random rnd) { + this.rnd = rnd; + } + + public ConsistentHashV1Old() { + this(new Random()); + } + + @Override + public void init(Map> servers2Hash, int numKeyOwners, int hashSpace) { + + log.infof("Parameters received by CH are: server2Hash: %s, numKeyOwners: %s, hashSpace: %s", servers2Hash, + numKeyOwners, hashSpace); + + for (Map.Entry> entry : servers2Hash.entrySet()){ + SocketAddress addr = entry.getKey(); + for (Integer hash : entry.getValue()) { + SocketAddress prev = positions.put(hash, addr); + if (prev != null) + log.debugf("Adding hash (%d) again, this time for %s. Previously it was associated with: %s", hash, addr, prev); + } + } + + log.tracef("Positions (%d entries) are: %s", positions.size(), positions); + this.hashSpace = hashSpace; + this.numKeyOwners = numKeyOwners; + } + + @Override + public SocketAddress getServer(byte[] key) { + int keyHashCode = getNormalizedHash(key); + if (keyHashCode == Integer.MIN_VALUE) keyHashCode += 1; + int hash = Math.abs(keyHashCode); + + SortedMap candidates = positions.tailMap(hash % hashSpace); + if (log.isTraceEnabled()) { + log.tracef("Found possible candidates: %s", candidates); + } + return (candidates.size() > 0 ? candidates : positions).entrySet().iterator().next().getValue(); + } + + private SocketAddress getItemAtPosition(int position, SortedMap map) { + Iterator> iterator = map.entrySet().iterator(); + for (int i = 0; i < position; i++) { + iterator.next(); + } + return iterator.next().getValue(); + } + + public void setHash(Hash hash) { + this.hash = hash; + } + + @Override + public int getNormalizedHash(Object key) { + return Util.getNormalizedHash(key, hash); + } + + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashFactoryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashFactoryTest.java new file mode 100644 index 000000000000..5c15f91cb5ec --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashFactoryTest.java @@ -0,0 +1,37 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHash; +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHashFactory; +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHashV1; +import org.testng.annotations.Test; +import static org.testng.AssertJUnit.*; + +/** + * Tester for ConsistentHashFactory. + * + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.ConsistentHashFactoryTest", groups = "functional") +public class ConsistentHashFactoryTest { + + public void testPropertyCorrectlyRead() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.consistentHashImpl(1, SomeCustomConsistentHashV1.class); + ConsistentHashFactory chf = new ConsistentHashFactory(); + chf.init(builder.build()); + ConsistentHash hash = chf.newConsistentHash(1); + assertNotNull(hash); + assertEquals(hash.getClass(), SomeCustomConsistentHashV1.class); + } + + public void testNoChDefined() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + ConsistentHashFactory chf = new ConsistentHashFactory(); + chf.init(builder.build()); + ConsistentHash hash = chf.newConsistentHash(1); + assertNotNull(hash); + assertEquals(hash.getClass(), ConsistentHashV1.class); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashPerformanceTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashPerformanceTest.java new file mode 100644 index 000000000000..17b980c1d144 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashPerformanceTest.java @@ -0,0 +1,76 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHash; +import org.infinispan.commons.hash.MurmurHash3; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * @author Mircea Markus (C) 2011 Red Hat Inc. + * @since 5.1 + */ +@Test (groups = "performance", testName = "client.hotrod.ConsistentHashPerformanceTest") +public class ConsistentHashPerformanceTest { + + + public static final int KEY_POOL_SIZE = 1000; + static List keys = new ArrayList(KEY_POOL_SIZE); + + static { + Random rnd = new Random(); + for (int i = 0; i < KEY_POOL_SIZE; i++) { + byte[] bytes = new byte[12]; + rnd.nextBytes(bytes); + keys.add(bytes); + } + } + + private void testConsistentHashSpeed(ConsistentHash ch) { + + int loopSize = 1000000; + Random rnd = new Random(); + long duration = 0; + + for (int i = 0; i < loopSize; i++) { + int keyIndex = rnd.nextInt(KEY_POOL_SIZE); + + long start = System.nanoTime(); + SocketAddress server = ch.getServer(keys.get(keyIndex)); + duration += System.nanoTime() - start; + + //just make sure this code is not removed from JIT + if (server.hashCode() == loopSize) { + System.out.println(""); + } + } + + System.out.printf("It took %s millis for consistent hash %s to execute %s operations \n" , TimeUnit.NANOSECONDS.toMillis(duration), ch.getClass().getSimpleName(), loopSize); + } + + public void testVariousVersion1() { + ConsistentHashComparisonTest.ConsistentHashV1Old dch2 = new ConsistentHashComparisonTest.ConsistentHashV1Old(); + initConsistentHash(dch2); + testConsistentHashSpeed(dch2); + } + + private void initConsistentHash(ConsistentHashComparisonTest.ConsistentHashV1Old dch) { + int numAddresses = 1500; + LinkedHashMap> map = new LinkedHashMap>(); + for (int i = 0; i < numAddresses; i++) { + map.put(new InetSocketAddress(i), Collections.singleton(i * 1000)); + } + + + dch.init(map, 2, 10024); + dch.setHash(new MurmurHash3()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashV1IntegrationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashV1IntegrationTest.java new file mode 100644 index 000000000000..e98ea4e574b6 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashV1IntegrationTest.java @@ -0,0 +1,198 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.affinity.KeyAffinityService; +import org.infinispan.affinity.KeyAffinityServiceFactory; +import org.infinispan.client.hotrod.impl.RemoteCacheImpl; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.client.hotrod.retry.DistributionRetryTest; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.distribution.ch.ConsistentHash; +import org.infinispan.interceptors.InterceptorChain; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.remoting.transport.Address; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.infinispan.test.TestingUtil; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import java.util.Properties; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + +/** + * @author Mircea Markus + */ +@Test (groups = "functional", testName = "client.hotrod.ConsistentHashV1IntegrationTest") +public class ConsistentHashV1IntegrationTest extends MultipleCacheManagersTest { + public static final int NUM_KEYS = 200; + + private HotRodServer hotRodServer1; + private HotRodServer hotRodServer2; + private HotRodServer hotRodServer3; + private HotRodServer hotRodServer4; //tod add shutdown behaviour + private RemoteCacheManager remoteCacheManager; + private RemoteCacheImpl remoteCache; + private KeyAffinityService kas; + private ExecutorService ex; + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder builder = buildConfiguration(); + + addClusterEnabledCacheManager(builder); + addClusterEnabledCacheManager(builder); + addClusterEnabledCacheManager(builder); + addClusterEnabledCacheManager(builder); + + hotRodServer1 = TestHelper.startHotRodServer(manager(0)); + hotRodServer2 = TestHelper.startHotRodServer(manager(1)); + hotRodServer3 = TestHelper.startHotRodServer(manager(2)); + hotRodServer4 = TestHelper.startHotRodServer(manager(3)); + + + waitForClusterToForm(); + + Properties clientConfig = new Properties(); + clientConfig.put("infinispan.client.hotrod.server_list", "localhost:" + hotRodServer2.getPort()); + + remoteCacheManager = new RemoteCacheManager(clientConfig); + remoteCache = (RemoteCacheImpl) remoteCacheManager.getCache(); + assert super.cacheManagers.size() == 4; + + ex = Executors.newSingleThreadExecutor(); + kas = KeyAffinityServiceFactory.newKeyAffinityService(cache(0), + ex, new DistributionRetryTest.ByteKeyGenerator(), 2, true); + + for (int i = 0; i < 4; i++) { + advancedCache(i).addInterceptor(new HitsAwareCacheManagersTest.HitCountInterceptor(), 1); + } + } + + private ConfigurationBuilder buildConfiguration() { + ConfigurationBuilder builder = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false); + builder.jmxStatistics().enable(); + builder.clustering().hash().numOwners(2).stateTransfer().fetchInMemoryState(false); + return hotRodCacheConfiguration(builder); + } + + @AfterMethod + @Override + protected void clearContent() throws Throwable { + } + + @AfterTest + public void cleanUp() { + ex.shutdownNow(); + kas.stop(); + + stopServer(hotRodServer1); + stopServer(hotRodServer2); + stopServer(hotRodServer3); + stopServer(hotRodServer4); + + remoteCache.stop(); + remoteCacheManager.stop(); + } + + private void stopServer(HotRodServer hrs) { + killServers(hrs); + } + + public void testCorrectBalancingOfKeys() { + runTest(0); + runTest(1); + runTest(2); + runTest(3); + } + + private void runTest(int cacheIndex) { + ConsistentHash serverCH = advancedCache(cacheIndex).getDistributionManager().getConsistentHash(); + + for (int i = 0; i < NUM_KEYS; i++) { + byte[] keyBytes = (byte[]) kas.getKeyForAddress(address(cacheIndex)); + String key = DistributionRetryTest.ByteKeyGenerator.getStringObject(keyBytes); + Address serverPrimary = serverCH.locatePrimaryOwner(keyBytes); + assertEquals(address(cacheIndex), serverPrimary); + + remoteCache.put(key, "v"); + } + + // compatibility with 1.0/1.1 clients is not perfect, so we must allow for some misses + assertTrue(hitCountInterceptor(cacheIndex).getHits() > NUM_KEYS * 0.99); + hitCountInterceptor(cacheIndex).reset(); + } + + public void testCorrectBalancingOfKeysAfterNodeKill() { + final AtomicInteger clientTopologyId = (AtomicInteger) TestingUtil.extractField(remoteCacheManager, "topologyId"); + + final int topologyIdBeforeJoin = clientTopologyId.get(); + log.tracef("Starting test with client topology id %d", topologyIdBeforeJoin); + EmbeddedCacheManager cm5 = addClusterEnabledCacheManager(buildConfiguration()); + HotRodServer hotRodServer5 = TestHelper.startHotRodServer(cm5); + + // Rebalancing to include the joiner will increment the topology id by 2 + eventually(new Condition() { + @Override + public boolean isSatisfied() throws Exception { + log.tracef("Client topology id is %d, waiting for it to become %d", clientTopologyId.get(), + topologyIdBeforeJoin + 2); + // The put operation will update the client topology (if necessary) + remoteCache.put("k", "v"); + return clientTopologyId.get() >= topologyIdBeforeJoin + 2; + } + }); + + resetHitInterceptors(); + runTest(0); + runTest(1); + runTest(2); + runTest(3); + + stopServer(hotRodServer5); + TestingUtil.killCacheManagers(cm5); + + // Rebalancing to exclude the leaver will again increment the topology id by 2 + eventually(new Condition() { + @Override + public boolean isSatisfied() throws Exception { + log.tracef("Client topology id is %d, waiting for it to become %d", clientTopologyId.get(), + topologyIdBeforeJoin + 4); + // The put operation will update the client topology (if necessary) + remoteCache.put("k", "v"); + return clientTopologyId.get() >= topologyIdBeforeJoin + 4; + } + }); + + resetHitInterceptors(); + runTest(0); + runTest(1); + runTest(2); + runTest(3); + } + + private org.infinispan.client.hotrod.impl.consistenthash.ConsistentHash extractClientConsistentHash() { + TcpTransportFactory transport = (TcpTransportFactory) TestingUtil.extractField(remoteCacheManager, "transport"); + return transport.getConsistentHash(); + } + + private void resetHitInterceptors() { + for (int i = 0; i < 4; i++) { + HitsAwareCacheManagersTest.HitCountInterceptor interceptor = hitCountInterceptor(i); + interceptor.reset(); + } + } + + private HitsAwareCacheManagersTest.HitCountInterceptor hitCountInterceptor(int i) { + InterceptorChain ic = advancedCache(i).getComponentRegistry().getComponent(InterceptorChain.class); + return (HitsAwareCacheManagersTest.HitCountInterceptor) ic.getInterceptorsWithClass(HitsAwareCacheManagersTest.HitCountInterceptor.class).get(0); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashV1Test.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashV1Test.java new file mode 100644 index 000000000000..ae5f82346a7d --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ConsistentHashV1Test.java @@ -0,0 +1,152 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHashV1; +import org.infinispan.commons.hash.Hash; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +/** + * @author Mircea Markus + * @since 5.0 + */ +@Test(groups = "unit", testName = "client.hotrod.ConsistentHashV1Test") +public class ConsistentHashV1Test { + + private InetSocketAddress a1; + private InetSocketAddress a2; + private InetSocketAddress a3; + private InetSocketAddress a4; + private DummyHash hash; + private ConsistentHashV1 v1; + + + private void setUp(int numOwners) { + a1 = new InetSocketAddress(1); + a2 = new InetSocketAddress(2); + a3 = new InetSocketAddress(3); + a4 = new InetSocketAddress(4); + LinkedHashMap> map = new LinkedHashMap>(); + map.put(a1, Collections.singleton(0)); + map.put(a2, Collections.singleton(1000)); + map.put(a3, Collections.singleton(2000)); + map.put(a4, Collections.singleton(3000)); + + this.v1 = new ConsistentHashV1(); + this.v1.init(map, numOwners, 10000); + hash = new DummyHash(); + this.v1.setHash(hash); + } + + + public void simpleTest() { + setUp(1); + hash.value = 0; + assert v1.getServer(new byte[0]).equals(a1); + hash.value = 1; + assert v1.getServer(new byte[0]).equals(a2); + hash.value = 1001; + assert v1.getServer(new byte[0]).equals(a3); + hash.value = 2001; + assertEquals(v1.getServer(new byte[0]), a4); + hash.value = 3001; + assert v1.getServer(new byte[0]).equals(a1); + } + + public void numOwners2Test() { + setUp(2); + hash.value = 0; + assert list(a1, a2).contains(v1.getServer(new byte[0])); + + hash.value = 1; + assert list(a2, a3).contains(v1.getServer(new byte[0])); + + hash.value = 1001; + assert list(a3, a4).contains(v1.getServer(new byte[0])); + + hash.value = 2001; + assert list(a4, a1).contains(v1.getServer(new byte[0])); + + hash.value = 3001; + assert list(a1, a2).contains(v1.getServer(new byte[0])); + } + + public void numOwners3Test() { + setUp(3); + hash.value = 0; + assert list(a1, a2, a3).contains(v1.getServer(new byte[0])); + + hash.value = 1; + assert list(a2, a3, a4).contains(v1.getServer(new byte[0])); + + hash.value = 1001; + assert list(a3, a4, a1).contains(v1.getServer(new byte[0])); + + hash.value = 2001; + assert list(a4, a1, a2).contains(v1.getServer(new byte[0])); + + hash.value = 3001; + assert list(a1, a2, a3).contains(v1.getServer(new byte[0])); + } + + //now a bit more extreme... + public void numOwners4Test() { + setUp(4); + + List list = list(a1, a2, a3, a4); + + hash.value = 0; + assert list.contains(v1.getServer(new byte[0])); + + hash.value = 1; + assert list.contains(v1.getServer(new byte[0])); + + hash.value = 1001; + assert list.contains(v1.getServer(new byte[0])); + + hash.value = 2001; + assert list.contains(v1.getServer(new byte[0])); + + hash.value = 3001; + assert list.contains(v1.getServer(new byte[0])); + } + + private List list(InetSocketAddress... a) { + return Arrays.asList(a); + } + + + public void testCorrectHash() { + hash.value = 1; + v1.getServer(new byte[0]); + } + + public static class DummyHash implements Hash { + + public int value; + + @Override + public int hash(byte[] payload) { + return value; + } + + @Override + public int hash(int hashcode) { + return value; + } + + @Override + public int hash(Object o) { + return value; + } + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DefaultExpirationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DefaultExpirationTest.java new file mode 100644 index 000000000000..a65c2186fd27 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DefaultExpirationTest.java @@ -0,0 +1,72 @@ +package org.infinispan.client.hotrod; + +import org.testng.annotations.Test; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +import org.infinispan.client.hotrod.test.HotRodClientTestingUtil; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.container.entries.InternalCacheEntry; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterClass; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.assertHotRodEquals; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.*; + +/** + * @author Tristan Tarrant + * @since 5.2 + */ +@Test (testName = "client.hotrod.DefaultExpirationTest", groups = "functional" ) +public class DefaultExpirationTest extends SingleCacheManagerTest { + private RemoteCache remoteCache; + private RemoteCacheManager remoteCacheManager; + protected HotRodServer hotrodServer; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + ConfigurationBuilder builder = hotRodCacheConfiguration( + getDefaultStandaloneCacheConfig(false)); + builder.expiration().lifespan(3, TimeUnit.SECONDS).maxIdle(2, TimeUnit.SECONDS); + return TestCacheManagerFactory.createCacheManager(builder); + } + + @Override + protected void setup() throws Exception { + super.setup(); + //pass the config file to the cache + hotrodServer = TestHelper.startHotRodServer(cacheManager); + log.info("Started server on port: " + hotrodServer.getPort()); + remoteCacheManager = getRemoteCacheManager(); + remoteCache = remoteCacheManager.getCache(); + } + + protected RemoteCacheManager getRemoteCacheManager() { + Properties config = new Properties(); + config.put("infinispan.client.hotrod.server_list", "127.0.0.1:" + hotrodServer.getPort()); + return new RemoteCacheManager(config); + } + + + @AfterClass + public void testDestroyRemoteCacheFactory() { + HotRodClientTestingUtil.killRemoteCacheManager(remoteCacheManager); + HotRodClientTestingUtil.killServers(hotrodServer); + } + + @Test + public void testDefaultExpiration() throws Exception { + remoteCache.put("Key", "Value"); + InternalCacheEntry entry = assertHotRodEquals(cacheManager, "Key", "Value"); + assertTrue(entry.canExpire()); + assertEquals(3000, entry.getLifespan()); + assertEquals(2000, entry.getMaxIdle()); + Thread.sleep(5000); + assertFalse(remoteCache.containsKey("Key")); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DistTopologyChangeTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DistTopologyChangeTest.java new file mode 100644 index 000000000000..7e2629d538e8 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DistTopologyChangeTest.java @@ -0,0 +1,15 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.configuration.cache.CacheMode; +import org.testng.annotations.Test; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(groups = "functional" , testName = "client.hotrod.DistTopologyChangeTest") +public class DistTopologyChangeTest extends ReplTopologyChangeTest { + protected CacheMode getCacheMode() { + return CacheMode.DIST_SYNC; + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DroppedConnectionsTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DroppedConnectionsTest.java new file mode 100644 index 000000000000..e733d343f21f --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DroppedConnectionsTest.java @@ -0,0 +1,80 @@ +package org.infinispan.client.hotrod; + +import org.apache.commons.pool.impl.GenericKeyedObjectPool; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransport; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.client.hotrod.test.HotRodClientTestingUtil; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.util.Properties; + +import static org.testng.AssertJUnit.assertEquals; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test (testName = "client.hotrod.DroppedConnectionsTest", groups = "functional") +public class DroppedConnectionsTest extends SingleCacheManagerTest { + private HotRodServer hotRodServer; + private RemoteCacheManager remoteCacheManager; + private RemoteCache rc; + private TcpTransportFactory transportFactory; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration(getDefaultStandaloneCacheConfig(false))); + hotRodServer = TestHelper.startHotRodServer(cacheManager); + Properties hrClientConfig = new Properties(); + hrClientConfig.put("testWhileIdle", "false"); + hrClientConfig.put("minIdle","1"); + hrClientConfig.put("maxIdle","2"); + hrClientConfig.put("maxActive","2"); + hrClientConfig.put("infinispan.client.hotrod.server_list", "127.0.0.1:" + hotRodServer.getPort()); + remoteCacheManager = new RemoteCacheManager(hrClientConfig); + rc = remoteCacheManager.getCache(); + transportFactory = (TcpTransportFactory) TestingUtil.extractField(remoteCacheManager, "transportFactory"); + return cacheManager; + } + + @AfterClass + @Override + protected void teardown() { + super.teardown(); + HotRodClientTestingUtil.killRemoteCacheManager(remoteCacheManager); + HotRodClientTestingUtil.killServers(hotRodServer); + } + + public void testClosedConnection() throws Exception { + rc.put("k","v"); //make sure a connection is created + + GenericKeyedObjectPool keyedObjectPool = transportFactory.getConnectionPool(); + InetSocketAddress address = new InetSocketAddress("127.0.0.1", hotRodServer.getPort()); + + assertEquals(0, keyedObjectPool.getNumActive(address)); + assertEquals(1, keyedObjectPool.getNumIdle(address)); + + TcpTransport tcpConnection = (TcpTransport) keyedObjectPool.borrowObject(address); + keyedObjectPool.returnObject(address, tcpConnection);//now we have a reference to the single connection in pool + + tcpConnection.destroy(); + + assertEquals("v", rc.get("k")); + assertEquals(0, keyedObjectPool.getNumActive(address)); + assertEquals(1, keyedObjectPool.getNumIdle(address)); + + TcpTransport tcpConnection2 = (TcpTransport) keyedObjectPool.borrowObject(address); + + assert tcpConnection2.getId() != tcpConnection.getId(); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ExpiryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ExpiryTest.java new file mode 100644 index 000000000000..c0ee37c72da7 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ExpiryTest.java @@ -0,0 +1,43 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.test.MultiHotRodServersTest; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.testng.annotations.Test; + +import java.lang.reflect.Method; + +import static org.infinispan.test.TestingUtil.v; +import static org.testng.AssertJUnit.assertEquals; + +/** + * This test verifies that an entry can be expired from the Hot Rod server + * using the default expiry lifespan or maxIdle.

+ * + * This test is disabled because the limitations of the protocol do not allow + * for this to work as expected. This test will be enabled once v2 of the + * protocol has been implemented and the functionality is there to support it. + * + * @author Galder Zamarreño + * @since 5.0 + */ +@Test(groups = "unstable", testName = "client.hotrod.ExpiryTest", description = "original group: functional") +public class ExpiryTest extends MultiHotRodServersTest { + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder builder = getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, false); + builder.expiration().lifespan(2000L).maxIdle(3000L); + createHotRodServers(1, builder); + } + + public void testGlobalExpiry(Method m) throws Exception { + RemoteCacheManager client0 = client(0); + RemoteCache cache0 = client0.getCache(); + String v1 = v(m); + cache0.put(1, v1); + Thread.sleep(2500); + assertEquals(null, cache0.get(1)); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValueTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValueTest.java new file mode 100644 index 000000000000..58978ca914e9 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValueTest.java @@ -0,0 +1,88 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertNull; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.ForceReturnValueTest", groups = "functional") +public class ForceReturnValueTest extends SingleCacheManagerTest { + + RemoteCache remoteCache; + + private RemoteCacheManager remoteCacheManager; + + private HotRodServer hotrodServer; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + // This method should be limited to starting the cache manager, to avoid + // leaks as a result of code after creating the cache manager failing. + return TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration()); + } + + @Override + protected void setup() throws Exception { + super.setup(); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + remoteCacheManager = new RemoteCacheManager("localhost",hotrodServer.getPort()); + remoteCache = remoteCacheManager.getCache(); + } + + @AfterClass + public void destroy() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServer); + super.teardown(); + } + + public void testPut() { + 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 testRemove() { + 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 testContains() { + assert !remoteCache.containsKey("aKey"); + remoteCache.put("aKey", "aValue"); + assert remoteCache.containsKey("aKey"); + } + + public void testReplace() { + 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 testPutIfAbsent() { + 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; + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValuesTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValuesTest.java new file mode 100644 index 000000000000..443d2871de49 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValuesTest.java @@ -0,0 +1,57 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.test.HotRodClientTestingUtil; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import java.util.Properties; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +@Test(testName = "client.hotrod.ForceReturnValuesTest", groups = "functional") +@CleanupAfterMethod +public class ForceReturnValuesTest extends SingleCacheManagerTest { + private HotRodServer hotRodServer; + private RemoteCacheManager remoteCacheManager; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()); + cache = cacheManager.getCache(); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + Properties hotrodClientConf = new Properties(); + hotrodClientConf.put("infinispan.client.hotrod.server_list", "localhost:" + hotRodServer.getPort()); + remoteCacheManager = new RemoteCacheManager(hotrodClientConf); + return cacheManager; + } + + @AfterMethod + void shutdown() { + HotRodClientTestingUtil.killRemoteCacheManager(remoteCacheManager); + HotRodClientTestingUtil.killServers(hotRodServer); + } + + public void testDontForceReturnValues() { + RemoteCache rc = remoteCacheManager.getCache(); + String rv = rc.put("Key", "Value"); + assert rv == null; + rv = rc.put("Key", "Value2"); + assert rv == null; + } + + public void testForceReturnValues() { + RemoteCache rc = remoteCacheManager.getCache(true); + String rv = rc.put("Key", "Value"); + assert rv == null; + rv = rc.put("Key", "Value2"); + assert rv != null; + assert "Value".equals(rv); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HeavyLoadConnectionPoolingTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HeavyLoadConnectionPoolingTest.java new file mode 100644 index 000000000000..b55cace6d738 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HeavyLoadConnectionPoolingTest.java @@ -0,0 +1,122 @@ +package org.infinispan.client.hotrod; + +import org.apache.commons.pool.impl.GenericKeyedObjectPool; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.commands.VisitableCommand; +import org.infinispan.context.InvocationContext; +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.TestingUtil; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ExecutionException; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test (testName = "client.hotrod.HeavyLoadConnectionPoolingTest", groups = "functional") +public class HeavyLoadConnectionPoolingTest extends SingleCacheManagerTest { + private HotRodServer hotRodServer; + private RemoteCacheManager remoteCacheManager; + private RemoteCache remoteCache; + private GenericKeyedObjectPool connectionPool; + + @AfterMethod + @Override + protected void clearContent() { + } + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()); + cache = cacheManager.getCache(); + + // make sure all operations take at least 100 msecs + cache.getAdvancedCache().addInterceptor(new ConstantDelayTransportInterceptor(100), 0); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + Properties hotrodClientConf = new Properties(); + hotrodClientConf.setProperty("infinispan.client.hotrod.server_list", "localhost:"+hotRodServer.getPort()); + hotrodClientConf.setProperty("timeBetweenEvictionRunsMillis", "500"); + hotrodClientConf.setProperty("minEvictableIdleTimeMillis", "100"); + hotrodClientConf.setProperty("numTestsPerEvictionRun", "10"); + hotrodClientConf.setProperty("infinispan.client.hotrod.ping_on_startup", "true"); + remoteCacheManager = new RemoteCacheManager(hotrodClientConf); + remoteCache = remoteCacheManager.getCache(); + + TcpTransportFactory tcpConnectionFactory = (TcpTransportFactory) TestingUtil.extractField(remoteCacheManager, "transportFactory"); + connectionPool = (GenericKeyedObjectPool) TestingUtil.extractField(tcpConnectionFactory, "connectionPool"); + + return cacheManager; + } + + @AfterClass + @Override + protected void destroyAfterClass() { + super.destroyAfterClass(); + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer); + } + + public void testHeavyLoad() throws InterruptedException, ExecutionException { + List workers = new ArrayList(); + + //create 20 threads and do work with them + for (int i =0; i < 20; i++) { + WorkerThread workerThread = new WorkerThread(remoteCache); + workers.add(workerThread); + workerThread.stress(); + } + while (connectionPool.getNumActive() <= 15) { + Thread.sleep(10); + } + + for (WorkerThread wt: workers) { + wt.stop(); + } + + for (WorkerThread wt: workers) { + wt.awaitTermination(); + } + + //now wait for the idle thread to wake up and clean them + + eventually(new Condition() { + @Override + public boolean isSatisfied() throws Exception { + int numIdle = connectionPool.getNumIdle(); + int numActive = connectionPool.getNumActive(); + return numIdle == 0 && numActive == 0; + } + }); + } + + public static class ConstantDelayTransportInterceptor extends CommandInterceptor { + + private int millis; + + public ConstantDelayTransportInterceptor(int millis) { + this.millis = millis; + } + + @Override + protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable { + Thread.sleep(millis); + return super.handleDefault(ctx, command); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HitsAwareCacheManagersTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HitsAwareCacheManagersTest.java new file mode 100644 index 000000000000..2d455db81383 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HitsAwareCacheManagersTest.java @@ -0,0 +1,120 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.Cache; +import org.infinispan.commands.VisitableCommand; +import org.infinispan.context.InvocationContext; +import org.infinispan.interceptors.base.CommandInterceptor; +import org.infinispan.manager.CacheContainer; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.testng.annotations.BeforeMethod; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +public abstract class HitsAwareCacheManagersTest extends MultipleCacheManagersTest { + + protected Map hrServ2CacheManager = new HashMap(); + protected Map addr2hrServer = new HashMap(); + + @Override + @BeforeMethod(alwaysRun=true) + public void createBeforeMethod() throws Throwable { + if (cleanupAfterMethod()) { + hrServ2CacheManager.clear(); + addr2hrServer.clear(); + } + super.createBeforeMethod(); + } + + protected HitCountInterceptor getHitCountInterceptor(Cache cache) { + HitCountInterceptor hitCountInterceptor = null; + List interceptorChain = cache.getAdvancedCache().getInterceptorChain(); + for (CommandInterceptor interceptor : interceptorChain) { + boolean isHitCountInterceptor = interceptor instanceof HitCountInterceptor; + if (hitCountInterceptor != null && isHitCountInterceptor) { + throw new IllegalStateException("Two HitCountInterceptors! " + interceptorChain); + } + if (isHitCountInterceptor) { + hitCountInterceptor = (HitCountInterceptor) interceptor; + } + } + return hitCountInterceptor; + } + + protected void assertOnlyServerHit(SocketAddress serverAddress) { + CacheContainer cacheContainer = hrServ2CacheManager.get(serverAddress); + HitCountInterceptor interceptor = getHitCountInterceptor(cacheContainer.getCache()); + assert interceptor.getHits() == 1 : "Expected one hit but received " + interceptor.getHits(); + for (CacheContainer cm : hrServ2CacheManager.values()) { + if (cm != cacheContainer) { + interceptor = getHitCountInterceptor(cm.getCache()); + assert interceptor.getHits() == 0 : "Expected 0 hits but got " + interceptor.getHits(); + } + } + } + + protected void assertNoHits() { + for (CacheContainer cm : hrServ2CacheManager.values()) { + HitCountInterceptor interceptor = getHitCountInterceptor(cm.getCache()); + assert interceptor.getHits() == 0 : "Expected 0 hits but got " + interceptor.getHits(); + } + } + + protected InetSocketAddress getAddress(HotRodServer hotRodServer) { + InetSocketAddress socketAddress = new InetSocketAddress(hotRodServer.getHost(), hotRodServer.getPort()); + addr2hrServer.put(socketAddress, hotRodServer); + return socketAddress; + } + + protected void resetStats() { + for (EmbeddedCacheManager manager : cacheManagers) { + HitCountInterceptor cmi = getHitCountInterceptor(manager.getCache()); + cmi.reset(); + } + } + + protected void addInterceptors() { + for (EmbeddedCacheManager manager : cacheManagers) { + addHitCountInterceptor(manager.getCache()); + } + } + + private void addHitCountInterceptor(Cache cache) { + HitCountInterceptor interceptor = new HitCountInterceptor(); + cache.getAdvancedCache().addInterceptor(interceptor, 1); + } + + /** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ + public static class HitCountInterceptor extends CommandInterceptor{ + + private volatile int invocationCount; + + @Override + protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable { + if (ctx.isOriginLocal()) { + invocationCount ++; + } + return super.handleDefault(ctx, command); + } + + public int getHits() { + return invocationCount; + } + + public void reset() { + invocationCount = 0; + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRod10CSAIntegrationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRod10CSAIntegrationTest.java new file mode 100644 index 000000000000..caa319db820f --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRod10CSAIntegrationTest.java @@ -0,0 +1,22 @@ +package org.infinispan.client.hotrod; + +import org.testng.annotations.Test; + +import java.util.Properties; + +/** + * Tests consistent hash algorithm consistency between the client and server + * using Hot Rod's 1.0 protocol. + * + * @author Galder Zamarreño + * @since 5.1 + */ +@Test(groups = "functional", testName = "client.hotrod.HotRod10CSAIntegrationTest") +public class HotRod10CSAIntegrationTest extends CSAIntegrationTest { + + @Override + protected void setHotRodProtocolVersion(Properties props) { + props.setProperty("infinispan.client.hotrod.protocol_version", "1.0"); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodAsyncReplicationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodAsyncReplicationTest.java new file mode 100644 index 000000000000..441f4f11a53b --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodAsyncReplicationTest.java @@ -0,0 +1,61 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.test.MultiHotRodServersTest; +import org.infinispan.commands.write.PutKeyValueCommand; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.test.ReplListener; +import org.testng.annotations.Test; + +import java.lang.reflect.Method; + +import static org.infinispan.test.TestingUtil.v; +import static org.testng.AssertJUnit.assertEquals; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +@Test(groups = "functional", testName = "client.hotrod.HotRodAsyncReplicationTest") +public class HotRodAsyncReplicationTest extends MultiHotRodServersTest { + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder builder = hotRodCacheConfiguration( + getDefaultClusteredCacheConfig(CacheMode.REPL_ASYNC, false)); + builder.clustering().async().replQueueInterval(1000L).useReplQueue(true); + builder.eviction().maxEntries(3); + + createHotRodServers(2, builder); + } + + public void testPutKeyValue(Method m) { + final RemoteCache remoteCache0 = client(0).getCache(); + final RemoteCache remoteCache1 = client(1).getCache(); + + ReplListener replList0 = getReplListener(0); + ReplListener replList1 = getReplListener(1); + + replList0.expect(PutKeyValueCommand.class); + replList1.expect(PutKeyValueCommand.class); + + final String v1 = v(m); + remoteCache0.put(1, v1); + + replList0.waitForRpc(); + replList1.waitForRpc(); + + assertEquals(v1, remoteCache1.get(1)); + assertEquals(v1, remoteCache1.get(1)); // Called twice to cover all round robin options + assertEquals(v1, remoteCache0.get(1)); + assertEquals(v1, remoteCache0.get(1)); // Called twice to cover all round robin options + } + + private ReplListener getReplListener(int cacheIndex) { + ReplListener replList = listeners.get(cache(cacheIndex)); + if (replList == null) + replList = new ReplListener(cache(cacheIndex), true, true); + else + replList.reconfigureListener(true, true); + + return replList; + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodIntegrationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodIntegrationTest.java new file mode 100644 index 000000000000..1e9604a9ea28 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodIntegrationTest.java @@ -0,0 +1,274 @@ +package org.infinispan.client.hotrod; + +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.commons.util.concurrent.NotifyingFuture; +import org.infinispan.util.logging.Log; +import org.infinispan.util.logging.LogFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import java.lang.reflect.Method; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +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.infinispan.server.hotrod.test.HotRodTestingUtil.*; + +/** + * @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 defaultRemote; + RemoteCache 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()); + return cm; + } + + @Override + protected void setup() throws Exception { + super.setup(); + //pass the config file to the cache + hotrodServer = TestHelper.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(); + config.put("infinispan.client.hotrod.server_list", "127.0.0.1:" + hotrodServer.getPort()); + return new RemoteCacheManager(config); + } + + + @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(); + NotifyingFuture 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(); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodServerStartStopTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodServerStartStopTest.java new file mode 100644 index 000000000000..d5834ec4d02f --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodServerStartStopTest.java @@ -0,0 +1,57 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertEquals; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.HotRodServerStartStopTest", groups = "functional") +public class HotRodServerStartStopTest extends MultipleCacheManagersTest { + private HotRodServer hotRodServer1; + private HotRodServer hotRodServer2; + + @AfterMethod + @Override + protected void clearContent() throws Throwable { + } + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder builder = hotRodCacheConfiguration( + getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false)); + addClusterEnabledCacheManager(builder); + addClusterEnabledCacheManager(builder); + + hotRodServer1 = TestHelper.startHotRodServer(manager(0)); + hotRodServer2 = TestHelper.startHotRodServer(manager(1)); + + assert manager(0).getCache() != null; + assert manager(1).getCache() != null; + + waitForClusterToForm(); + } + + public void testTouchServer() { + RemoteCacheManager remoteCacheManager = new RemoteCacheManager("localhost", hotRodServer1.getPort(), true); + RemoteCache remoteCache = remoteCacheManager.getCache(); + remoteCache.put("k", "v"); + assertEquals("v", remoteCache.get("k")); + killRemoteCacheManager(remoteCacheManager); + } + + @Test (dependsOnMethods = "testTouchServer") + public void testHrServerStop() { + killServers(hotRodServer1, hotRodServer2); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodStatisticsTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodStatisticsTest.java new file mode 100644 index 000000000000..e523402fd163 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodStatisticsTest.java @@ -0,0 +1,140 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.CacheContainer; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.Map; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.*; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertTrue; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(groups = "functional", testName = "client.hotrod.HotRodStatisticsTest") +public class HotRodStatisticsTest { + + private HotRodServer hotrodServer; + private CacheContainer cacheContainer; + private RemoteCacheManager rcm; + private RemoteCache remoteCache; + long startTime; + + @BeforeMethod + protected void setup() throws Exception { + ConfigurationBuilder cfg = hotRodCacheConfiguration(); + cfg.jmxStatistics().enable(); + cacheContainer = TestCacheManagerFactory + .createClusteredCacheManagerEnforceJmxDomain(getClass().getSimpleName(), cfg); + + hotrodServer = TestHelper.startHotRodServer((EmbeddedCacheManager) cacheContainer); + startTime = System.currentTimeMillis(); + rcm = new RemoteCacheManager("localhost", hotrodServer.getPort()); + remoteCache = rcm.getCache(); + } + + @AfterMethod + void tearDown() { + TestingUtil.killCacheManagers(cacheContainer); + killRemoteCacheManager(rcm); + killServers(hotrodServer); + } + + public void testAllStatsArePresent() { + ServerStatistics serverStatistics = remoteCache.stats(); + Map statsMap = serverStatistics.getStatsMap(); + assertEquals(statsMap.get(ServerStatistics.STORES), "0"); + assertEquals(statsMap.get(ServerStatistics.CURRENT_NR_OF_ENTRIES), "0"); + assertEquals(statsMap.get(ServerStatistics.HITS),"0"); + assertEquals(statsMap.get(ServerStatistics.MISSES),"0"); + assertEquals(statsMap.get(ServerStatistics.REMOVE_HITS),"0"); + assertEquals(statsMap.get(ServerStatistics.REMOVE_MISSES),"0"); + assertEquals(statsMap.get(ServerStatistics.RETRIEVALS),"0"); + assertEquals(statsMap.get(ServerStatistics.TOTAL_NR_OF_ENTRIES),"0"); + assert 0 == remoteCache.size(); + assert remoteCache.isEmpty(); + + Integer number = serverStatistics.getIntStatistic(ServerStatistics.TIME_SINCE_START); + assertTrue(number >= 0); + } + + public void testStoresAndEntries() { + assert 0 == remoteCache.size(); + assert remoteCache.isEmpty(); + remoteCache.put("a","v"); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.STORES)); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.CURRENT_NR_OF_ENTRIES)); + assert 1 == remoteCache.size(); + assert !remoteCache.isEmpty(); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.TOTAL_NR_OF_ENTRIES)); + remoteCache.put("a2","v2"); + assertEquals((Integer)2, remoteCache.stats().getIntStatistic(ServerStatistics.STORES)); + assertEquals((Integer)2, remoteCache.stats().getIntStatistic(ServerStatistics.CURRENT_NR_OF_ENTRIES)); + assertEquals((Integer)2, remoteCache.stats().getIntStatistic(ServerStatistics.TOTAL_NR_OF_ENTRIES)); + assert 2 == remoteCache.size(); + assert !remoteCache.isEmpty(); + remoteCache.put("a2","v3"); + assertEquals((Integer)3, remoteCache.stats().getIntStatistic(ServerStatistics.STORES)); + assertEquals((Integer)2, remoteCache.stats().getIntStatistic(ServerStatistics.CURRENT_NR_OF_ENTRIES)); + assertEquals((Integer)3, remoteCache.stats().getIntStatistic(ServerStatistics.TOTAL_NR_OF_ENTRIES)); + assert 2 == remoteCache.size(); + assert !remoteCache.isEmpty(); + } + + public void testHitsAndMisses() { + remoteCache.get("a"); + assertEquals((Integer)0, remoteCache.stats().getIntStatistic(ServerStatistics.HITS)); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.MISSES)); + remoteCache.put("a","v"); + assertEquals((Integer)0, remoteCache.stats().getIntStatistic(ServerStatistics.HITS)); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.MISSES)); + remoteCache.get("a"); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.HITS)); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.MISSES)); + remoteCache.get("a"); + remoteCache.get("a"); + remoteCache.get("a"); + assertEquals((Integer)4, remoteCache.stats().getIntStatistic(ServerStatistics.HITS)); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.MISSES)); + } + + public void testRemoveHitsAndMisses() { + remoteCache.remove("a"); + assertEquals((Integer)0, remoteCache.stats().getIntStatistic(ServerStatistics.REMOVE_HITS)); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.REMOVE_MISSES)); + remoteCache.put("a","v"); + remoteCache.remove("a"); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.REMOVE_HITS)); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.REMOVE_MISSES)); + remoteCache.put("a","v"); + remoteCache.put("b","v"); + remoteCache.put("c","v"); + + remoteCache.remove("a"); + remoteCache.remove("b"); + remoteCache.remove("c"); + assertEquals((Integer)4, remoteCache.stats().getIntStatistic(ServerStatistics.REMOVE_HITS)); + assertEquals((Integer)1, remoteCache.stats().getIntStatistic(ServerStatistics.REMOVE_MISSES)); + } + + public void testNumberOfEntriesAfterClear() { + assertEquals((Integer)0, remoteCache.stats().getIntStatistic(ServerStatistics.CURRENT_NR_OF_ENTRIES)); + remoteCache.put("k", "v"); + remoteCache.put("k2", "v"); + assertEquals((Integer)2, remoteCache.stats().getIntStatistic(ServerStatistics.CURRENT_NR_OF_ENTRIES)); + remoteCache.clear(); + assertEquals((Integer)0, remoteCache.stats().getIntStatistic(ServerStatistics.CURRENT_NR_OF_ENTRIES)); + assertEquals((Integer)2, remoteCache.stats().getIntStatistic(ServerStatistics.TOTAL_NR_OF_ENTRIES)); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/PingOnStartupTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/PingOnStartupTest.java new file mode 100644 index 000000000000..72a0bac1204d --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/PingOnStartupTest.java @@ -0,0 +1,141 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.client.hotrod.test.MultiHotRodServersTest; +import org.infinispan.client.hotrod.test.RemoteCacheManagerCallable; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.TestingUtil; +import org.testng.annotations.Test; + +import java.util.Properties; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.withRemoteCacheManager; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; + +/** + * Tests ping-on-startup logic whose objective is to retrieve the Hot Rod + * server topology before a client executes an operation against the server. + * + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(groups = "functional", testName = "client.hotrod.PingOnStartupTest") +public class PingOnStartupTest extends MultiHotRodServersTest { + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder builder = hotRodCacheConfiguration( + getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false)); + createHotRodServers(2, builder); + } + + public void testTopologyFetched() { + Properties props = new Properties(); + HotRodServer hotRodServer2 = server(1); + props.put("infinispan.client.hotrod.server_list", + "localhost:" + hotRodServer2.getPort() + ";localhost:" + hotRodServer2.getPort()); + props.put("infinispan.client.hotrod.ping_on_startup", "true"); + + withRemoteCacheManager(new RemoteCacheManagerCallable( + new RemoteCacheManager(props)) { + @Override + public void call() { + TcpTransportFactory tcpConnectionFactory = (TcpTransportFactory) + TestingUtil.extractField(rcm, "transportFactory"); + for (int i = 0; i < 10; i++) { + if (tcpConnectionFactory.getServers().size() == 1) { + TestingUtil.sleepThread(1000); + } else { + break; + } + } + assertEquals(2, tcpConnectionFactory.getServers().size()); + } + }); + } + + public void testTopologyNotFetched() { + Properties props = new Properties(); + HotRodServer hotRodServer2 = server(1); + props.put("infinispan.client.hotrod.server_list", + "localhost:" + hotRodServer2.getPort()); + props.put("infinispan.client.hotrod.ping_on_startup", "false"); + + withRemoteCacheManager(new RemoteCacheManagerCallable( + new RemoteCacheManager(props)) { + @Override + public void call() { + TcpTransportFactory tcpConnectionFactory = (TcpTransportFactory) + TestingUtil.extractField(rcm, "transportFactory"); + assertEquals(1, tcpConnectionFactory.getServers().size()); + } + }); + } + + public void testGetCacheWithPingOnStartupDisabledSingleNode() { + Properties props = new Properties(); + props.put("infinispan.client.hotrod.server_list", "boomoo:12345"); + props.put("infinispan.client.hotrod.ping_on_startup", "false"); + + withRemoteCacheManager(new RemoteCacheManagerCallable( + new RemoteCacheManager(props)) { + @Override + public void call() { + rcm.getCache(); + } + }); + } + + public void testGetCacheWithPingOnStartupDisabledMultipleNodes() { + Properties props = new Properties(); + HotRodServer hotRodServer2 = server(1); + props.put("infinispan.client.hotrod.server_list", + "boomoo:12345;localhost:" + hotRodServer2.getPort()); + props.put("infinispan.client.hotrod.ping_on_startup", "false"); + + withRemoteCacheManager(new RemoteCacheManagerCallable( + new RemoteCacheManager(props)) { + @Override + public void call() { + RemoteCache cache = rcm.getCache(); + assertFalse(cache.containsKey("k")); + } + }); + } + + public void testGetCacheWorksIfNodeDown() { + Properties props = new Properties(); + HotRodServer hotRodServer2 = server(1); + props.put("infinispan.client.hotrod.server_list", + "boomoo:12345;localhost:" + hotRodServer2.getPort()); + props.put("infinispan.client.hotrod.ping_on_startup", "true"); + + withRemoteCacheManager(new RemoteCacheManagerCallable( + new RemoteCacheManager(props)) { + @Override + public void call() { + rcm.getCache(); + } + }); + } + + public void testGetCacheWorksIfNodeNotDown() { + Properties props = new Properties(); + HotRodServer hotRodServer2 = server(1); + props.put("infinispan.client.hotrod.server_list", + "localhost:" + hotRodServer2.getPort()); + props.put("infinispan.client.hotrod.ping_on_startup", "true"); + withRemoteCacheManager(new RemoteCacheManagerCallable( + new RemoteCacheManager(props)) { + @Override + public void call() { + rcm.getCache(); + } + }); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RemoteAsyncAPITest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RemoteAsyncAPITest.java new file mode 100644 index 000000000000..bc6f7241c73e --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RemoteAsyncAPITest.java @@ -0,0 +1,297 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.commons.util.concurrent.FutureListener; +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.commons.util.concurrent.NotifyingFuture; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import java.util.Collections; +import java.util.Properties; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNotSame; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.Assert.assertNotEquals; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(groups = "functional", testName = "client.hotrod.RemoteAsyncAPITest") +public class RemoteAsyncAPITest extends SingleCacheManagerTest { + private HotRodServer hotrodServer; + private RemoteCacheManager rcm; + private RemoteCache c; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + return TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration()); + } + + @Override + protected void setup() throws Exception { + super.setup(); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + Properties props = new Properties(); + props.put("infinispan.client.hotrod.server_list", "127.0.0.1:" + hotrodServer.getPort()); + props.put("infinispan.client.hotrod.force_return_values","true"); + props.put("testOnBorrow", "false"); + rcm = new RemoteCacheManager(props); + c = rcm.getCache(true); + } + + @AfterClass + @Override + protected void destroyAfterClass() { + super.destroyAfterClass(); + killRemoteCacheManager(rcm); + killServers(hotrodServer); + } + + public void testPutAsync() throws Exception { + // put + Future f = c.putAsync("k", "v"); + testFuture(f, null); + testK("v"); + + f = c.putAsync("k", "v2"); + testFuture(f, "v"); + testK("v2"); + } + + public void testPutAsyncWithListener() throws Exception { + NotifyingFuture f = c.putAsync("k", "v"); + testFutureWithListener(f, null); + testK("v"); + + f = c.putAsync("k", "v2"); + testFutureWithListener(f, "v"); + testK("v2"); + } + + public void testPutAllAsync() throws Exception { + Future f = c.putAllAsync(Collections.singletonMap("k", "v3")); + testFuture(f, null); + testK("v3"); + } + + public void testPutAllAsyncWithListener() throws Exception { + NotifyingFuture f = c.putAllAsync(Collections.singletonMap("k", "v3")); + testFutureWithListener(f, null); + testK("v3"); + } + + public void testPutIfAbsentAsync() throws Exception { + c.put("k", "v3"); + testK("v3"); + + Future f = c.putIfAbsentAsync("k", "v4"); + testFuture(f, "v3"); + assertEquals("v3", c.remove("k")); + + f = c.putIfAbsentAsync("k", "v5"); + testFuture(f, null); + testK("v5"); + } + + public void testPutIfAbsentAsyncWithListener() throws Exception { + c.put("k", "v3"); + testK("v3"); + + NotifyingFuture f = c.putIfAbsentAsync("k", "v4"); + testFutureWithListener(f, "v3"); + assertEquals("v3", c.remove("k")); + + f = c.putIfAbsentAsync("k", "v5"); + testFutureWithListener(f, null); + testK("v5"); + } + + public void testRemoveAsync() throws Exception { + c.put("k","v3"); + testK("v3"); + + Future f = c.removeAsync("k"); + testFuture(f, "v3"); + testK(null); + } + + public void testRemoveAsyncWithListener() throws Exception { + c.put("k","v3"); + testK("v3"); + + NotifyingFuture f = c.removeAsync("k"); + testFutureWithListener(f, "v3"); + testK(null); + } + + public void testGetAsync() throws Exception { + c.put("k", "v"); + testK("v"); + + Future f = c.getAsync("k"); + testFuture(f, "v"); + testK("v"); + } + + public void testGetAsyncWithListener() throws Exception { + c.put("k", "v"); + testK("v"); + + NotifyingFuture f = c.getAsync("k"); + testFutureWithListener(f, "v"); + } + + public void testRemoveWithVersionAsync() throws Exception { + c.put("k","v4"); + VersionedValue value = c.getVersioned("k"); + + Future f = c.removeWithVersionAsync("k", value.getVersion() + 1); + testFuture(f, false); + testK("v4"); + + f = c.removeWithVersionAsync("k", value.getVersion()); + testFuture(f, true); + testK(null); + } + + public void testRemoveWithVersionAsyncWithListener() throws Exception { + c.put("k","v4"); + VersionedValue value = c.getVersioned("k"); + + NotifyingFuture f = c.removeWithVersionAsync("k", value.getVersion() + 1); + testFutureWithListener(f, false); + testK("v4"); + + f = c.removeWithVersionAsync("k", value.getVersion()); + testFutureWithListener(f, true); + testK(null); + } + + public void testReplaceAsync() throws Exception { + testK(null); + Future f = c.replaceAsync("k", "v5"); + testFuture(f, null); + testK(null); + + c.put("k", "v"); + testK("v"); + f = c.replaceAsync("k", "v5"); + testFuture(f, "v"); + testK("v5"); + } + + public void testReplaceAsyncWithListener() throws Exception { + testK(null); + NotifyingFuture f = c.replaceAsync("k", "v5"); + testFutureWithListener(f, null); + testK(null); + + c.put("k", "v"); + testK("v"); + f = c.replaceAsync("k", "v5"); + testFutureWithListener(f, "v"); + testK("v5"); + } + + public void testReplaceWithVersionAsync() throws Exception { + c.put("k", "v"); + VersionedValue versioned1 = c.getVersioned("k"); + + Future f = c.replaceWithVersionAsync("k", "v2", versioned1.getVersion()); + testFuture(f, true); + + VersionedValue versioned2 = c.getVersioned("k"); + assertNotEquals(versioned1.getVersion(), versioned2.getVersion()); + assertEquals(versioned2.getValue(), "v2"); + + f = c.replaceWithVersionAsync("k", "v3", versioned1.getVersion()); + testFuture(f, false); + testK("v2"); + } + + public void testReplaceWithVersionAsyncWithListener() throws Exception { + c.put("k", "v"); + VersionedValue versioned1 = c.getVersioned("k"); + + NotifyingFuture f = c.replaceWithVersionAsync("k", "v2", versioned1.getVersion()); + testFutureWithListener(f, true); + + VersionedValue versioned2 = c.getVersioned("k"); + assertNotEquals(versioned1.getVersion(), versioned2.getVersion()); + assertEquals(versioned2.getValue(), "v2"); + + f = c.replaceWithVersionAsync("k", "v3", versioned1.getVersion()); + testFutureWithListener(f, false); + testK("v2"); + } + + private void testK(T expected) { + assertEquals(expected, c.get("k")); + } + + private void testFuture(Future f, T expected) throws ExecutionException, InterruptedException { + assertNotNull(f); + assertFalse(f.isCancelled()); + T value = f.get(); + assertEquals("Obtained " + value, expected, value); + assertTrue(f.isDone()); + } + + private void testFutureWithListener(NotifyingFuture f, T expected) throws InterruptedException { + assertNotNull(f); + AtomicReference ex = new AtomicReference(); + CountDownLatch latch = new CountDownLatch(1); + f.attachListener(new TestingListener(expected, ex, latch)); + if (!latch.await(5, TimeUnit.SECONDS)) { + fail("Not finished within 5 seconds"); + } + if (ex.get() != null) { + throw new AssertionError(ex.get()); + } + } + + private static class TestingListener implements FutureListener { + private final T expected; + private final AtomicReference exception; + private final CountDownLatch latch; + + private TestingListener(T expected, AtomicReference exception, CountDownLatch latch) { + this.expected = expected; + this.exception = exception; + this.latch = latch; + } + + @Override + public void futureDone(Future future) { + try { + assertNotNull(future); + assertFalse(future.isCancelled()); + assertTrue(future.isDone()); + T value = future.get(); + assertEquals("Obtained " + value, expected, value); + } catch (Throwable t) { + exception.set(t); + } finally { + latch.countDown(); + } + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RemoteCacheManagerTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RemoteCacheManagerTest.java new file mode 100644 index 000000000000..9cc5360e5aef --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RemoteCacheManagerTest.java @@ -0,0 +1,140 @@ +package org.infinispan.client.hotrod; + +import static org.testng.AssertJUnit.assertTrue; +import static org.testng.AssertJUnit.assertFalse; +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.client.hotrod.impl.ConfigurationProperties; +import org.infinispan.client.hotrod.test.HotRodClientTestingUtil; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.commons.marshall.jboss.GenericJBossMarshaller; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import java.net.URL; +import java.util.Properties; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.RemoteCacheManagerTest", groups = "functional" ) +public class RemoteCacheManagerTest extends SingleCacheManagerTest { + + HotRodServer hotrodServer; + int port; + RemoteCacheManager remoteCacheManager; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + return TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration()); + } + + @Override + protected void setup() throws Exception { + super.setup(); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + port = hotrodServer.getPort(); + remoteCacheManager = null; + } + + @AfterTest + public void release() { + try { + TestingUtil.killCacheManagers(cacheManager); + HotRodClientTestingUtil.killServers(hotrodServer); + HotRodClientTestingUtil.killRemoteCacheManager(remoteCacheManager); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void testNoArgConstructor() { + remoteCacheManager = new RemoteCacheManager(); + assertTrue(remoteCacheManager.isStarted()); + } + + public void testBooleanConstructor() { + remoteCacheManager = new RemoteCacheManager(false); + assertFalse(remoteCacheManager.isStarted()); + remoteCacheManager.start(); + } + + public void testConfigurationConstructor() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder + .addServer() + .host("127.0.0.1") + .port(port); + remoteCacheManager = new RemoteCacheManager(builder.build()); + assertTrue(remoteCacheManager.isStarted()); + } + + public void testUrlAndBooleanConstructor() throws Exception { + URL resource = Thread.currentThread().getContextClassLoader().getResource("empty-config.properties"); + assert resource != null; + remoteCacheManager = new RemoteCacheManager(resource, false); + assert !remoteCacheManager.isStarted(); + Properties properties = remoteCacheManager.getProperties(); + properties.setProperty(ConfigurationProperties.SERVER_LIST, "127.0.0.1:" + port); + remoteCacheManager = new RemoteCacheManager(properties, false); + assert !remoteCacheManager.isStarted(); + remoteCacheManager.start(); + assertWorks(remoteCacheManager); + } + + public void testPropertiesConstructor() { + Properties p = new Properties(); + p.setProperty(ConfigurationProperties.SERVER_LIST, "127.0.0.1:" + port); + remoteCacheManager = new RemoteCacheManager(p); + assert remoteCacheManager.isStarted(); + assertWorks(remoteCacheManager); + remoteCacheManager.stop(); + } + + public void testPropertiesAndBooleanConstructor() { + Properties p = new Properties(); + p.setProperty(ConfigurationProperties.SERVER_LIST, "127.0.0.1:" + port); + remoteCacheManager = new RemoteCacheManager(p, false); + assert !remoteCacheManager.isStarted(); + remoteCacheManager.start(); + assertWorks(remoteCacheManager); + } + + public void testStringAndBooleanConstructor() { + remoteCacheManager = new RemoteCacheManager("localhost:"+hotrodServer.getPort(), false); + assert !remoteCacheManager.isStarted(); + remoteCacheManager.start(); + assertWorks(remoteCacheManager); + } + + public void testGetUndefinedCache() { + Properties p = new Properties(); + p.setProperty(ConfigurationProperties.SERVER_LIST, "127.0.0.1:" + port); + remoteCacheManager = new RemoteCacheManager(p, false); + assert !remoteCacheManager.isStarted(); + remoteCacheManager.start(); + assert null == remoteCacheManager.getCache("Undefined1234"); + } + + private void assertWorks(RemoteCacheManager remoteCacheManager) { + RemoteCache cache = remoteCacheManager.getCache(); + cache.put("aKey", "aValue"); + assert cache.get("aKey").equals("aValue"); + } + + public void testMarshallerInstance() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.addServer().host("127.0.0.1").port(port); + GenericJBossMarshaller marshaller = new GenericJBossMarshaller(); + builder.marshaller(marshaller); + remoteCacheManager = new RemoteCacheManager(builder.build()); + assertTrue(marshaller == remoteCacheManager.getMarshaller()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ReplTopologyChangeTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ReplTopologyChangeTest.java new file mode 100644 index 000000000000..ea8dc9a3fce0 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ReplTopologyChangeTest.java @@ -0,0 +1,147 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.lifecycle.ComponentStatus; +import org.infinispan.manager.CacheContainer; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Collection; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertEquals; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.ReplTopologyChangeTest", groups = "functional") +public class ReplTopologyChangeTest extends MultipleCacheManagersTest { + + HotRodServer hotRodServer1; + HotRodServer hotRodServer2; + HotRodServer hotRodServer3 ; + + RemoteCache remoteCache; + private RemoteCacheManager remoteCacheManager; + private TcpTransportFactory tcpConnectionFactory; + private ConfigurationBuilder config; + + @Override + protected void assertSupportedConfig() { + } + + @AfterMethod + @Override + protected void clearContent() throws Throwable { + } + + @AfterClass + @Override + protected void destroy() { + super.destroy(); + killServers(hotRodServer1, hotRodServer2); + killRemoteCacheManager(remoteCacheManager); + } + + @Override + protected void createCacheManagers() throws Throwable { + config = hotRodCacheConfiguration(getDefaultClusteredCacheConfig(getCacheMode(), false)); + CacheContainer cm1 = TestCacheManagerFactory.createClusteredCacheManager(config); + CacheContainer cm2 = TestCacheManagerFactory.createClusteredCacheManager(config); + registerCacheManager(cm1); + registerCacheManager(cm2); + waitForClusterToForm(); + } + + @BeforeClass + @Override + public void createBeforeClass() throws Throwable { + super.createBeforeClass(); // Create cache managers + hotRodServer1 = TestHelper.startHotRodServer(manager(0)); + hotRodServer2 = TestHelper.startHotRodServer(manager(1)); + + //Important: this only connects to one of the two servers! + remoteCacheManager = new RemoteCacheManager("localhost", hotRodServer2.getPort()); + remoteCache = remoteCacheManager.getCache(); + + tcpConnectionFactory = (TcpTransportFactory) TestingUtil.extractField(remoteCacheManager, "transportFactory"); + } + + protected CacheMode getCacheMode() { + return CacheMode.REPL_SYNC; + } + + public void testTwoMembers() { + InetSocketAddress server1Address = new InetSocketAddress("localhost", hotRodServer1.getPort()); + expectTopologyChange(server1Address, true); + assertEquals(2, tcpConnectionFactory.getServers().size()); + } + + @Test(dependsOnMethods = "testTwoMembers") + public void testAddNewServer() { + CacheContainer cm3 = TestCacheManagerFactory.createClusteredCacheManager(config); + registerCacheManager(cm3); + hotRodServer3 = TestHelper.startHotRodServer(manager(2)); + manager(2).getCache(); + + waitForClusterToForm(); + + try { + expectTopologyChange(new InetSocketAddress("localhost", hotRodServer3.getPort()), true); + assertEquals(3, tcpConnectionFactory.getServers().size()); + } finally { + log.info("Members are: " + manager(0).getCache().getAdvancedCache().getRpcManager().getTransport().getMembers()); + log.info("Members are: " + manager(1).getCache().getAdvancedCache().getRpcManager().getTransport().getMembers()); + log.info("Members are: " + manager(2).getCache().getAdvancedCache().getRpcManager().getTransport().getMembers()); + } + } + + @Test(dependsOnMethods = "testAddNewServer") + public void testDropServer() { + hotRodServer3.stop(); + manager(2).stop(); + log.trace("Just stopped server 2"); + + waitForServerToDie(2); + + InetSocketAddress server3Address = new InetSocketAddress("localhost", hotRodServer3.getPort()); + + try { + expectTopologyChange(server3Address, false); + assertEquals(2, tcpConnectionFactory.getServers().size()); + } finally { + log.info("Members are: " + manager(0).getCache().getAdvancedCache().getRpcManager().getTransport().getMembers()); + log.info("Members are: " + manager(1).getCache().getAdvancedCache().getRpcManager().getTransport().getMembers()); + if (manager(2).getStatus() != ComponentStatus.RUNNING) + log.info("Members are: 0"); + else + log.info("Members are: " + manager(2).getCache().getAdvancedCache().getRpcManager().getTransport().getMembers()); + } + } + + private void expectTopologyChange(InetSocketAddress server1Address, boolean added) { + for (int i = 0; i < 10; i++) { + remoteCache.put("k" + i, "v" + i); + if (added == tcpConnectionFactory.getServers().contains(server1Address)) break; + } + Collection addresses = tcpConnectionFactory.getServers(); + assertEquals(server1Address + " not found in " + addresses, added, addresses.contains(server1Address)); + } + + protected void waitForServerToDie(int memberCount) { + TestingUtil.blockUntilViewReceived(manager(0).getCache(), memberCount, 30000, false); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RoundRobinBalancingIntegrationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RoundRobinBalancingIntegrationTest.java new file mode 100644 index 000000000000..aa1d80372923 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RoundRobinBalancingIntegrationTest.java @@ -0,0 +1,225 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.Cache; +import org.infinispan.client.hotrod.impl.transport.tcp.RoundRobinBalancingStrategy; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.infinispan.util.logging.Log; +import org.infinispan.util.logging.LogFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.List; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertEquals; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.RoundRobinBalancingIntegrationTest", groups="functional") +public class RoundRobinBalancingIntegrationTest extends MultipleCacheManagersTest { + + private static final Log log = LogFactory.getLog(RoundRobinBalancingIntegrationTest.class); + + Cache c1; + Cache c2; + Cache c3; + Cache c4; + + HotRodServer hotRodServer1; + HotRodServer hotRodServer2; + + HotRodServer hotRodServer3; + HotRodServer hotRodServer4; + + RemoteCache remoteCache; + + private RemoteCacheManager remoteCacheManager; + + @Override + protected void assertSupportedConfig() { + return; + } + + @Override + protected void createCacheManagers() throws Throwable { + c1 = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()).getCache(); + c2 = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()).getCache(); + c3 = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()).getCache(); + registerCacheManager(c1.getCacheManager(), c2.getCacheManager(), c3.getCacheManager()); + + hotRodServer1 = TestHelper.startHotRodServer(c1.getCacheManager()); + hotRodServer2 = TestHelper.startHotRodServer(c2.getCacheManager()); + hotRodServer3 = TestHelper.startHotRodServer(c3.getCacheManager()); + + log.trace("Server 1 port: " + hotRodServer1.getPort()); + log.trace("Server 2 port: " + hotRodServer2.getPort()); + log.trace("Server 3 port: " + hotRodServer3.getPort()); + String servers = TestHelper.getServersString(hotRodServer1, hotRodServer2, hotRodServer3); + log.trace("Server list is: " + servers); + remoteCacheManager = new RemoteCacheManager(servers); + remoteCache = remoteCacheManager.getCache(); + } + + @AfterTest + public void tearDown() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer1, hotRodServer2, hotRodServer3, hotRodServer4); + } + + public void testRoundRobinLoadBalancing() { + remoteCache.put("k1", "v1"); + remoteCache.put("k2", "v2"); + remoteCache.put("k3", "v3"); + + assertEquals(1, c1.size()); + assertEquals(1, c2.size()); + assertEquals(1, c3.size()); + + assertEquals("v1", remoteCache.get("k1")); + assertEquals("v2", remoteCache.get("k2")); + assertEquals("v3", remoteCache.get("k3")); + + remoteCache.put("k4", "v1"); + remoteCache.put("k5", "v2"); + remoteCache.put("k6", "v3"); + remoteCache.put("k7", "v1"); + remoteCache.put("k8", "v2"); + remoteCache.put("k9", "v3"); + + assertEquals(3, c1.size()); + assertEquals(3, c2.size()); + assertEquals(3, c3.size()); + } + + @Test(dependsOnMethods = "testRoundRobinLoadBalancing") + public void testAddNewHotrodServer() { + c4 = TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration()).getCache(); + hotRodServer4 = TestHelper.startHotRodServer(c4.getCacheManager()); + registerCacheManager(c4.getCacheManager()); + + List serverAddresses = new ArrayList(); + serverAddresses.add(new InetSocketAddress("localhost", hotRodServer1.getPort())); + serverAddresses.add(new InetSocketAddress("localhost", hotRodServer2.getPort())); + serverAddresses.add(new InetSocketAddress("localhost", hotRodServer3.getPort())); + serverAddresses.add(new InetSocketAddress("localhost", hotRodServer4.getPort())); + + RoundRobinBalancingStrategy balancer = getBalancer(); + balancer.setServers(serverAddresses); + + remoteCache.put("k1", "v1"); + remoteCache.put("k2", "v2"); + remoteCache.put("k3", "v3"); + remoteCache.put("k4", "v4"); + + assertEquals(1, c1.size()); + assertEquals(1, c2.size()); + assertEquals(1, c3.size()); + assertEquals(1, c4.size()); + + assertEquals("v1", remoteCache.get("k1")); + assertEquals("v2", remoteCache.get("k2")); + assertEquals("v3", remoteCache.get("k3")); + assertEquals("v4", remoteCache.get("k4")); + + remoteCache.put("k5", "v2"); + remoteCache.put("k6", "v3"); + remoteCache.put("k7", "v1"); + remoteCache.put("k8", "v2"); + remoteCache.put("k9", "v3"); + remoteCache.put("k10", "v3"); + remoteCache.put("k11", "v3"); + remoteCache.put("k12", "v3"); + + assertEquals(3, c1.size()); + assertEquals(3, c2.size()); + assertEquals(3, c3.size()); + assertEquals(3, c4.size()); + } + + @Test(dependsOnMethods = "testAddNewHotrodServer") + public void testStopServer() { + remoteCache.put("k1", "v1"); + remoteCache.put("k2", "v2"); + remoteCache.put("k3", "v3"); + remoteCache.put("k4", "v4"); + + assertEquals(1, c1.size()); + assertEquals(1, c2.size()); + assertEquals(1, c3.size()); + assertEquals(1, c4.size()); + + assertEquals("v1", remoteCache.get("k1")); + assertEquals("v2", remoteCache.get("k2")); + assertEquals("v3", remoteCache.get("k3")); + assertEquals("v4", remoteCache.get("k4")); + + hotRodServer4.stop(); + + try { + remoteCache.put("k5", "v1"); + remoteCache.put("k6", "v2"); + remoteCache.put("k7", "v3"); + remoteCache.put("k8", "v4"); + } catch (Exception e) { + assert false : "exception should not happen even if the balancer redirects to failed node at the beggining"; + } + } + + @Test(dependsOnMethods = "testStopServer") + public void testRemoveServers() { + List serverAddresses = new ArrayList(); + serverAddresses.add(new InetSocketAddress("localhost", hotRodServer1.getPort())); + serverAddresses.add(new InetSocketAddress("localhost", hotRodServer2.getPort())); + + RoundRobinBalancingStrategy balancer = getBalancer(); + balancer.setServers(serverAddresses); + + remoteCache.put("k1", "v1"); + remoteCache.put("k2", "v2"); + remoteCache.put("k3", "v3"); + remoteCache.put("k4", "v4"); + + assertEquals(2, c1.size()); + assertEquals(2, c2.size()); + assertEquals(0, c3.size()); + assertEquals(0, c4.size()); + + assertEquals("v1", remoteCache.get("k1")); + assertEquals("v2", remoteCache.get("k2")); + assertEquals("v3", remoteCache.get("k3")); + assertEquals("v4", remoteCache.get("k4")); + + remoteCache.put("k5", "v2"); + remoteCache.put("k6", "v3"); + remoteCache.put("k7", "v1"); + remoteCache.put("k8", "v2"); + remoteCache.put("k9", "v3"); + remoteCache.put("k10", "v3"); + remoteCache.put("k11", "v3"); + remoteCache.put("k12", "v3"); + + assertEquals(6, c1.size()); + assertEquals(6, c2.size()); + assertEquals(0, c3.size()); + assertEquals(0, c4.size()); + + } + + private RoundRobinBalancingStrategy getBalancer() { + TcpTransportFactory transportFactory = (TcpTransportFactory) TestingUtil.extractField(remoteCache.getRemoteCacheManager(), "transportFactory"); + return (RoundRobinBalancingStrategy) TestingUtil.extractField(transportFactory, "balancer"); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RoundRobinBalancingStrategyTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RoundRobinBalancingStrategyTest.java new file mode 100644 index 000000000000..271cd6aac653 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/RoundRobinBalancingStrategyTest.java @@ -0,0 +1,155 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.transport.tcp.RoundRobinBalancingStrategy; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNotSame; +import static org.testng.AssertJUnit.assertTrue; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test (groups = "unit", testName = "client.hotrod.RoundRobinBalancingStrategyTest") +public class RoundRobinBalancingStrategyTest { + + + SocketAddress addr1 = new InetSocketAddress("localhost",1111); + SocketAddress addr2 = new InetSocketAddress("localhost",2222); + SocketAddress addr3 = new InetSocketAddress("localhost",3333); + SocketAddress addr4 = new InetSocketAddress("localhost",4444); + private List defaultServers; + private RoundRobinBalancingStrategy strategy; + + @BeforeMethod + public void setUp() { + strategy = new RoundRobinBalancingStrategy(); + defaultServers = new ArrayList(); + defaultServers.add(addr1); + defaultServers.add(addr2); + defaultServers.add(addr3); + strategy.setServers(defaultServers); + } + + public void simpleTest() { + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + } + + public void testAddServer() { + List newServers = new ArrayList(defaultServers); + newServers.add(addr4); + strategy.setServers(newServers); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr4, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr4, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + } + + public void testRemoveServer() { + List newServers = new ArrayList(defaultServers); + newServers.remove(addr3); + strategy.setServers(newServers); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + } + + public void testRemoveServerAfterActivity() { + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + List newServers = new ArrayList(defaultServers); + newServers.remove(addr3); + strategy.setServers(newServers); + // the next server index is reset to 0 because it would have been out of bounds + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + } + + public void testAddServerAfterActivity() { + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + List newServers = new ArrayList(defaultServers); + newServers.add(addr4); + strategy.setServers(newServers); + // the next server index is still valid, so it is not reset + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr4, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr4, strategy.nextServer(null)); + assertEquals(addr1, strategy.nextServer(null)); + assertEquals(addr2, strategy.nextServer(null)); + assertEquals(addr3, strategy.nextServer(null)); + assertEquals(addr4, strategy.nextServer(null)); + } + + public void testFailedServers1() { + strategy.setServers(defaultServers); + Set failedServers = Collections.singleton(addr1); + // other servers should be available + final int LOOPS = 10; + int c1 = 0, c2 = 0; + for (int i = 0; i < LOOPS; ++i) { + SocketAddress server = strategy.nextServer(failedServers); + assertNotNull(server); + assertNotSame(addr1, server); + if (server.equals(addr2)) { + c1++; + } else if (server.equals(addr3)) { + c2++; + } + } + assertEquals(LOOPS, c1 + c2); + assertTrue(Math.abs(c1 - c2) <= 1); + } + + public void testFailedServers2() { + strategy.setServers(defaultServers); + Set failedServers = new HashSet(defaultServers); + // with all servers failed, the behaviour should be the same + assertEquals(addr1, strategy.nextServer(failedServers)); + assertEquals(addr2, strategy.nextServer(failedServers)); + assertEquals(addr3, strategy.nextServer(failedServers)); + assertEquals(addr1, strategy.nextServer(failedServers)); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerErrorTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerErrorTest.java new file mode 100644 index 000000000000..4d0c6cf4b9e0 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerErrorTest.java @@ -0,0 +1,94 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.exceptions.HotRodClientException; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.notifications.Listener; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated; +import org.infinispan.notifications.cachelistener.event.CacheEntryEvent; +import org.infinispan.remoting.transport.jgroups.SuspectException; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import java.lang.reflect.Method; +import java.util.Properties; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.*; +import static org.infinispan.test.TestingUtil.k; +import static org.infinispan.test.TestingUtil.v; + +/** + * Tests HotRod client and server behaivour when server throws a server error + * + * @author Galder Zamarreño + * @since 4.2 + */ +@Test(groups = "functional", testName = "client.hotrod.ServerErrorTest") +public class ServerErrorTest extends SingleCacheManagerTest { + + private HotRodServer hotrodServer; + private RemoteCacheManager remoteCacheManager; + private RemoteCache remoteCache; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory + .createCacheManager(hotRodCacheConfiguration()); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + + remoteCacheManager = getRemoteCacheManager(); + remoteCache = remoteCacheManager.getCache(); + + return cacheManager; + } + + protected RemoteCacheManager getRemoteCacheManager() { + Properties config = new Properties(); + config.put("infinispan.client.hotrod.server_list", "127.0.0.1:" + hotrodServer.getPort()); + return new RemoteCacheManager(config); + } + + @AfterClass + public void shutDownHotrod() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServer); + } + + public void testErrorWhileDoingPut(Method m) throws Exception { + cache.addListener(new ErrorInducingListener()); + remoteCache = remoteCacheManager.getCache(); + + remoteCache.put(k(m), v(m)); + assert remoteCache.get(k(m)).equals(v(m)); + + try { + remoteCache.put("FailFailFail", "whatever..."); + } catch (HotRodClientException e) { + // ignore + } + + try { + remoteCache.put(k(m, 2), v(m, 2)); + assert remoteCache.get(k(m, 2)).equals(v(m, 2)); + } catch (Exception e) { + log.error("Error sending request after server failure", e); + throw e; + } + + } + + @Listener + public static class ErrorInducingListener { + @CacheEntryCreated + @SuppressWarnings("unused") + public void entryCreated(CacheEntryEvent event) throws Exception { + if (event.isPre() && unmarshall(event.getKey()) == "FailFailFail") { + throw new SuspectException("Simulated suspicion"); + } + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerRestartTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerRestartTest.java new file mode 100644 index 000000000000..2450d56f7df9 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerRestartTest.java @@ -0,0 +1,72 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.server.hotrod.configuration.HotRodServerConfigurationBuilder; +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; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.ServerRestartTest", groups = "functional") +public class ServerRestartTest extends SingleCacheManagerTest { + + private static final Log log = LogFactory.getLog(HotRodIntegrationTest.class); + + private RemoteCache defaultRemote; + private RemoteCacheManager remoteCacheManager; + + protected HotRodServer hotrodServer; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + return TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration()); + } + + @Override + protected void setup() throws Exception { + super.setup(); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + log.info("Started server on port: " + hotrodServer.getPort()); + + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.addServer().host("127.0.0.1").port(hotrodServer.getPort()).connectionPool().timeBetweenEvictionRuns(2000); + remoteCacheManager = new RemoteCacheManager(builder.build()); + defaultRemote = remoteCacheManager.getCache(); + } + + @AfterClass + public void testDestroyRemoteCacheFactory() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServer); + } + + public void testServerShutdown() throws Exception { + defaultRemote.put("k","v"); + assert defaultRemote.get("k").equals("v"); + + int port = hotrodServer.getPort(); + hotrodServer.stop(); + + HotRodServerConfigurationBuilder builder = new HotRodServerConfigurationBuilder(); + builder.host("127.0.0.1").port(port).workerThreads(2).idleTimeout(20000).tcpNoDelay(true).sendBufSize(15000).recvBufSize(25000); + hotrodServer.start(builder.build(), cacheManager); + + Thread.sleep(3000); + + assert defaultRemote.get("k").equals("v"); + defaultRemote.put("k","v"); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerShutdownTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerShutdownTest.java new file mode 100644 index 000000000000..c9890362edb8 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ServerShutdownTest.java @@ -0,0 +1,70 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.test.RemoteCacheManagerCallable; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.CacheManagerCallable; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.Test; + +import static junit.framework.Assert.assertEquals; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.withRemoteCacheManager; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.infinispan.test.TestingUtil.withCacheManager; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.ServerShutdownTest", groups = "functional") +public class ServerShutdownTest { + + public void testServerShutdownWithConnectedClient() { + withCacheManager(new CacheManagerCallable( + TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration())) { + @Override + public void call() { + HotRodServer hotrodServer = TestHelper.startHotRodServer(cm); + try { + withRemoteCacheManager(new RemoteCacheManagerCallable( + new RemoteCacheManager("localhost", hotrodServer.getPort())) { + @Override + public void call() { + RemoteCache remoteCache = rcm.getCache(); + remoteCache.put("k","v"); + assertEquals("v", remoteCache.get("k")); + } + }); + } finally { + killServers(hotrodServer); + } + } + }); + } + + public void testServerShutdownWithoutConnectedClient() { + withCacheManager(new CacheManagerCallable( + TestCacheManagerFactory.createCacheManager( + hotRodCacheConfiguration())) { + @Override + public void call() { + HotRodServer hotrodServer = TestHelper.startHotRodServer(cm); + try { + withRemoteCacheManager(new RemoteCacheManagerCallable( + new RemoteCacheManager("localhost", hotrodServer.getPort())) { + @Override + public void call() { + RemoteCache remoteCache = rcm.getCache(); + remoteCache.put("k","v"); + assertEquals("v", remoteCache.get("k")); + } + }); + } finally { + killServers(hotrodServer); + } + } + }); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SocketTimeoutErrorTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SocketTimeoutErrorTest.java new file mode 100644 index 000000000000..5e6e741d5bdd --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SocketTimeoutErrorTest.java @@ -0,0 +1,111 @@ +package org.infinispan.client.hotrod; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.test.TestingUtil.*; + +import java.lang.reflect.Method; +import java.net.SocketTimeoutException; +import java.util.Properties; + +import org.infinispan.client.hotrod.exceptions.HotRodClientException; +import org.infinispan.client.hotrod.impl.ConfigurationProperties; +import org.infinispan.commands.write.PutKeyValueCommand; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.context.InvocationContext; +import org.infinispan.interceptors.EntryWrappingInterceptor; +import org.infinispan.interceptors.base.CommandInterceptor; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.commons.marshall.Marshaller; +import org.infinispan.marshall.core.JBossMarshaller; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.Assert; +import org.testng.annotations.Test; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * Tests the behaviour of the client upon a socket timeout exception + * and any invocation after that. + * + * @author Galder Zamarreño + * @since 4.2 + */ +@Test(groups = "functional", testName = "client.hotrod.SocketTimeoutErrorTest") +public class SocketTimeoutErrorTest extends SingleCacheManagerTest { + + protected HotRodServer hotrodServer; + protected RemoteCacheManager remoteCacheManager; + protected RemoteCache remoteCache; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.customInterceptors().addInterceptor().interceptor( + new TimeoutInducingInterceptor()).after(EntryWrappingInterceptor.class); + return TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration(builder)); + } + + @Override + protected void setup() throws Exception { + super.setup(); + hotrodServer = TestHelper.startHotRodServer(cacheManager); + remoteCacheManager = new RemoteCacheManager(getClientProperties()); + remoteCache = remoteCacheManager.getCache(); + } + + @Override + protected void teardown() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotrodServer); + super.teardown(); + } + + protected Properties getClientProperties() { + Properties props = new Properties(); + props.put("infinispan.client.hotrod.server_list", "127.0.0.1:" + hotrodServer.getPort()); + props.setProperty(ConfigurationProperties.SO_TIMEOUT, "3000"); + props.setProperty("maxActive", "1"); + props.setProperty("maxTotal", "1"); + props.setProperty("maxIdle", "1"); + return props; + } + + public void testErrorWhileDoingPut(Method m) throws Exception { + remoteCache = remoteCacheManager.getCache(); + + remoteCache.put(k(m), v(m)); + assert remoteCache.get(k(m)).equals(v(m)); + + try { + remoteCache.put("FailFailFail", "whatever..."); + Assert.fail("No exception was thrown."); + } catch (HotRodClientException e) { + // ignore + assert e.getCause() instanceof SocketTimeoutException; + } + + // What counts is that socket timeout exception kicks in, operations + // after that do not add anything to the socket timeout test + } + + public static class TimeoutInducingInterceptor extends CommandInterceptor { + + @Override + public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable { + if (unmarshall(command.getKey()).equals("FailFailFail")) { + Thread.sleep(6000); + } + + return super.visitPutKeyValueCommand(ctx, command); + } + + private String unmarshall(Object key) throws Exception { + Marshaller marshaller = new JBossMarshaller(); + return (String) marshaller.objectFromByteBuffer((byte[]) key); + } + } + +} \ No newline at end of file diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeAsyncExecutorFactory.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeAsyncExecutorFactory.java new file mode 100644 index 000000000000..64c7a14324ba --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeAsyncExecutorFactory.java @@ -0,0 +1,7 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.async.DefaultAsyncExecutorFactory; + +public class SomeAsyncExecutorFactory extends DefaultAsyncExecutorFactory { + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeCustomConsistentHashV1.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeCustomConsistentHashV1.java new file mode 100644 index 000000000000..e052a85189c0 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeCustomConsistentHashV1.java @@ -0,0 +1,7 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHashV1; + +public class SomeCustomConsistentHashV1 extends ConsistentHashV1 { + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeRequestBalancingStrategy.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeRequestBalancingStrategy.java new file mode 100644 index 000000000000..72f94ecd9984 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeRequestBalancingStrategy.java @@ -0,0 +1,7 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.transport.tcp.RoundRobinBalancingStrategy; + +public class SomeRequestBalancingStrategy extends RoundRobinBalancingStrategy { + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeTransportfactory.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeTransportfactory.java new file mode 100644 index 000000000000..450f4b32868d --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SomeTransportfactory.java @@ -0,0 +1,7 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; + +public class SomeTransportfactory extends TcpTransportFactory { + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SslTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SslTest.java new file mode 100644 index 000000000000..c8984023f57f --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/SslTest.java @@ -0,0 +1,110 @@ +package org.infinispan.client.hotrod; + +import java.net.SocketTimeoutException; + +import javax.net.ssl.SSLException; + +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.client.hotrod.exceptions.TransportException; +import org.infinispan.client.hotrod.test.HotRodClientTestingUtil; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.server.hotrod.configuration.HotRodServerConfigurationBuilder; +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.AfterMethod; +import org.testng.annotations.Test; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertTrue; +import static org.testng.AssertJUnit.fail; + +/** + * @author Adrian Brock + * @author Tristan Tarrant + * @since 5.3 + */ +@Test(testName = "client.hotrod.SslTest", groups = "functional") +public class SslTest extends SingleCacheManagerTest { + + private static final Log log = LogFactory.getLog(SslTest.class); + + RemoteCache defaultRemote; + private RemoteCacheManager remoteCacheManager; + + protected HotRodServer hotrodServer; + + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()); + cacheManager.getCache(); + + return cacheManager; + } + + private void initServerAndClient(boolean sslServer, boolean sslClient) { + hotrodServer = new HotRodServer(); + HotRodServerConfigurationBuilder serverBuilder = new HotRodServerConfigurationBuilder(); + + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + String keyStoreFileName = tccl.getResource("keystore.jks").getPath(); + String trustStoreFileName = tccl.getResource("truststore.jks").getPath(); + serverBuilder.ssl() + .enabled(sslServer) + .keyStoreFileName(keyStoreFileName) + .keyStorePassword("secret".toCharArray()) + .trustStoreFileName(trustStoreFileName) + .trustStorePassword("secret".toCharArray()); + hotrodServer.start(serverBuilder.build(), cacheManager); + log.info("Started server on port: " + hotrodServer.getPort()); + + ConfigurationBuilder clientBuilder = new ConfigurationBuilder(); + clientBuilder + .addServer() + .host("127.0.0.1") + .port(hotrodServer.getPort()) + .socketTimeout(3000) + .connectionPool() + .maxActive(1) + .ssl() + .enabled(sslClient) + .keyStoreFileName(keyStoreFileName) + .keyStorePassword("secret".toCharArray()) + .trustStoreFileName(trustStoreFileName) + .trustStorePassword("secret".toCharArray()) + .connectionPool() + .timeBetweenEvictionRuns(2000); + remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); + defaultRemote = remoteCacheManager.getCache(); + } + + @AfterMethod + public void testDestroyRemoteCacheFactory() { + HotRodClientTestingUtil.killRemoteCacheManager(remoteCacheManager); + HotRodClientTestingUtil.killServers(hotrodServer); + } + + public void testSSLServerSSLClient() throws Exception { + initServerAndClient(true, true); + defaultRemote.put("k","v"); + assert defaultRemote.get("k").equals("v"); + } + + @Test(expectedExceptions = TransportException.class) + public void testSSLServerPlainClient() throws Exception { + // The server just disconnect the client + initServerAndClient(true, false); + } + + public void testPlainServerSSLClient() throws Exception { + try { + initServerAndClient(false, true); + fail("Expecting a SSLException"); + } catch (TransportException e) { + assertTrue(e.getCause() instanceof SSLException); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/TestHelper.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/TestHelper.java new file mode 100644 index 000000000000..3f63d0e1d164 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/TestHelper.java @@ -0,0 +1,68 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.server.hotrod.test.HotRodTestingUtil; +import org.infinispan.util.logging.Log; +import org.infinispan.util.logging.LogFactory; +import io.netty.channel.ChannelException; + +import java.net.BindException; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +public class TestHelper { + + private static final Log log = LogFactory.getLog(TestHelper.class); + + /** + * This needs to be different than the one used in the server tests in order to make sure that there's no clash. + */ + private static final AtomicInteger uniquePort = new AtomicInteger(15232); + + public static HotRodServer startHotRodServer(EmbeddedCacheManager cacheManager) { + // TODO: This is very rudimentary!! HotRodTestingUtil needs a more robust solution where ports are generated randomly and retries if already bound + HotRodServer server = null; + int maxTries = 10; + int currentTries = 0; + ChannelException lastException = null; + while (server == null && currentTries < maxTries) { + try { + server = HotRodTestingUtil.startHotRodServer(cacheManager, uniquePort.incrementAndGet()); + } catch (ChannelException e) { + if (!(e.getCause() instanceof BindException)) { + throw e; + } else { + log.debug("Address already in use: [" + e.getMessage() + "], so let's try next port"); + currentTries++; + lastException = e; + } + } + } + if (server == null && lastException != null) + throw lastException; + + return server; + } + + public static String getServersString(HotRodServer... servers) { + StringBuilder builder = new StringBuilder(); + for (HotRodServer server : servers) { + builder.append("localhost").append(':').append(server.getPort()).append(";"); + } + return builder.toString(); + } + + public static RemoteCacheManager getRemoteCacheManager(HotRodServer server) { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.addServer() + .host(server.getHost()) + .port(server.getPort()); + return new RemoteCacheManager(builder.build()); + + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/TransportObjectFactoryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/TransportObjectFactoryTest.java new file mode 100644 index 000000000000..51206d451e39 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/TransportObjectFactoryTest.java @@ -0,0 +1,36 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.client.hotrod.exceptions.TransportException; +import org.infinispan.client.hotrod.impl.protocol.Codec; +import org.infinispan.client.hotrod.impl.protocol.HeaderParams; +import org.infinispan.client.hotrod.impl.transport.Transport; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransport; +import org.infinispan.client.hotrod.impl.transport.tcp.TransportObjectFactory; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.testng.AssertJUnit.assertFalse; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; + +/** + * @author Mircea Markus + * @since 6.0 + */ +@Test (groups = "unit", testName = "client.hotrod.TransportObjectFactoryTest") +public class TransportObjectFactoryTest { + + public void testValidate() { + Codec codec = mock(Codec.class); + TransportObjectFactory objectFactory = new TransportObjectFactory(codec, null, + new AtomicInteger(), false); + doThrow(new TransportException("induced!", null)) + .when(codec).writeHeader(any(Transport.class), any(HeaderParams.class)); + + InetSocketAddress address = new InetSocketAddress(123); + assertFalse("Exception shouldn't be thrown here", objectFactory.validateObject(address, any(TcpTransport.class))); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/WorkerThread.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/WorkerThread.java new file mode 100644 index 000000000000..9f1b4f42197f --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/WorkerThread.java @@ -0,0 +1,110 @@ +package org.infinispan.client.hotrod; + +import org.infinispan.util.logging.Log; +import org.infinispan.util.logging.LogFactory; + +import java.util.Random; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Mircea.Markus@jboss.com + * @author dberinde@redhat.com + * @since 4.1 + */ +public class WorkerThread { + + private static final AtomicInteger WORKER_INDEX = new AtomicInteger(); + + private static final Log log = LogFactory.getLog(WorkerThread.class); + + private final RemoteCache remoteCache; + private volatile Future future; + + private final ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() { + public Thread newThread(Runnable r) { + return new Thread(r, String.format("%s-Worker-%d", + Thread.currentThread().getName(), WORKER_INDEX.getAndIncrement())); + } + }); + + public WorkerThread(RemoteCache remoteCache) { + this.remoteCache = remoteCache; + } + + private void stressInternal() throws Exception { + Random rnd = new Random(); + while (!executor.isShutdown()) { + remoteCache.put(rnd.nextLong(), rnd.nextLong()); + Thread.sleep(50); + } + } + + /** + * Only returns when this thread added the given key value. + */ + public String put(final String key, final String value) { + Future result = executor.submit(new Callable() { + public Object call() { + return remoteCache.put(key, value); + } + }); + + try { + return (String) result.get(); + } catch (InterruptedException e) { + throw new IllegalStateException(); + } catch (ExecutionException e) { + throw new RuntimeException("Error during put", e.getCause()); + } + } + + /** + * Does a put on the worker thread. + * Doesn't wait for the put operation to finish. However, it will wait for the previous operation on this thread to finish. + */ + public Future putAsync(final String key, final String value) throws ExecutionException, InterruptedException { + if (future != null) { + future.get(); + } + return executor.submit(new Callable() { + public Object call() throws Exception { + return remoteCache.put(key, value); + } + }); + } + + /** + * Starts doing cache put operations in a loop on the worker thread. + * Doesn't wait for the loop to finish - in fact the loop will finish only when the worker is stopped. + * However, it will wait for the previous operation on this thread to finish. + */ + public Future stress() throws InterruptedException, ExecutionException { + if (future != null) { + future.get(); + } + return executor.submit(new Callable() { + public Object call() throws Exception { + stressInternal(); + return null; + } + }); + } + + /** + * Returns without waiting for the threads to finish. + */ + public void stop() { + executor.shutdown(); + } + + /** + * Only returns when the last operation on this thread has finished. + */ + public void awaitTermination() throws InterruptedException, ExecutionException { + executor.awaitTermination(1, TimeUnit.SECONDS); + if (future != null) { + future.get(); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/configuration/ConfigurationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/configuration/ConfigurationTest.java new file mode 100644 index 000000000000..a67f2068573f --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/configuration/ConfigurationTest.java @@ -0,0 +1,119 @@ +package org.infinispan.client.hotrod.configuration; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertTrue; + +import org.infinispan.client.hotrod.SomeAsyncExecutorFactory; +import org.infinispan.client.hotrod.SomeCustomConsistentHashV1; +import org.infinispan.client.hotrod.SomeRequestBalancingStrategy; +import org.infinispan.client.hotrod.SomeTransportfactory; +import org.infinispan.client.hotrod.impl.ConfigurationProperties; +import org.infinispan.commons.CacheConfigurationException; +import org.testng.annotations.Test; + +@Test(testName = "client.hotrod.configuration.ConfigurationTest", groups = "functional" ) +public class ConfigurationTest { + + public void testConfiguration() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder + .addServer() + .host("host1") + .port(11222) + .addServer() + .host("host2") + .port(11222) + .asyncExecutorFactory() + .factoryClass(SomeAsyncExecutorFactory.class) + .balancingStrategy(SomeRequestBalancingStrategy.class) + .connectionPool() + .maxActive(100) + .maxTotal(150) + .maxWait(1000) + .maxIdle(20) + .minIdle(10) + .exhaustedAction(ExhaustedAction.WAIT) + .numTestsPerEvictionRun(5) + .testOnBorrow(true) + .testOnReturn(true) + .testWhileIdle(false) + .minEvictableIdleTime(12000) + .timeBetweenEvictionRuns(15000) + .connectionTimeout(100) + .consistentHashImpl(1, SomeCustomConsistentHashV1.class) + .socketTimeout(100) + .tcpNoDelay(false) + .pingOnStartup(false) + .keySizeEstimate(128) + .valueSizeEstimate(1024) + .maxRetries(0) + .transportFactory(SomeTransportfactory.class); + + Configuration configuration = builder.build(); + validateConfiguration(configuration); + + ConfigurationBuilder newBuilder = new ConfigurationBuilder(); + newBuilder.read(configuration); + Configuration newConfiguration = newBuilder.build(); + validateConfiguration(newConfiguration); + } + + public void testParseServerAddresses() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.addServers("1.1.1.1:9999"); + builder.addServers("2.2.2.2"); + builder.addServers("[fe80::290:bff:fe1b:5762]:7777"); + builder.addServers("[ff01::1]"); + builder.addServers("localhost"); + builder.addServers("localhost:8382"); + Configuration cfg = builder.build(); + assertServer("1.1.1.1", 9999, cfg.servers().get(0)); + assertServer("2.2.2.2", ConfigurationProperties.DEFAULT_HOTROD_PORT, cfg.servers().get(1)); + assertServer("fe80::290:bff:fe1b:5762", 7777, cfg.servers().get(2)); + assertServer("ff01::1", ConfigurationProperties.DEFAULT_HOTROD_PORT, cfg.servers().get(3)); + assertServer("localhost", ConfigurationProperties.DEFAULT_HOTROD_PORT, cfg.servers().get(4)); + assertServer("localhost", 8382, cfg.servers().get(5)); + } + + @Test(expectedExceptions = CacheConfigurationException.class, + expectedExceptionsMessageRegExp = "ISPN(\\d)*: Invalid max_retries \\(value=-1\\). " + + "Value should be greater or equal than zero.") + public void testNegativeRetriesPerServer() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.maxRetries(-1); + builder.build(); + } + + private void assertServer(String host, int port, ServerConfiguration serverCfg) { + assertEquals(host, serverCfg.host()); + assertEquals(port, serverCfg.port()); + } + + private void validateConfiguration(Configuration configuration) { + assertEquals(2, configuration.servers().size()); + assertEquals(SomeAsyncExecutorFactory.class, configuration.asyncExecutorFactory().factoryClass()); + assertEquals(SomeRequestBalancingStrategy.class, configuration.balancingStrategy()); + assertEquals(SomeTransportfactory.class, configuration.transportFactory()); + assertEquals(SomeCustomConsistentHashV1.class, configuration.consistentHashImpl(1)); + assertEquals(100, configuration.connectionPool().maxActive()); + assertEquals(150, configuration.connectionPool().maxTotal()); + assertEquals(1000, configuration.connectionPool().maxWait()); + assertEquals(20, configuration.connectionPool().maxIdle()); + assertEquals(10, configuration.connectionPool().minIdle()); + assertEquals(ExhaustedAction.WAIT, configuration.connectionPool().exhaustedAction()); + assertEquals(5, configuration.connectionPool().numTestsPerEvictionRun()); + assertEquals(15000, configuration.connectionPool().timeBetweenEvictionRuns()); + assertEquals(12000, configuration.connectionPool().minEvictableIdleTime()); + assertTrue(configuration.connectionPool().testOnBorrow()); + assertTrue(configuration.connectionPool().testOnReturn()); + assertFalse(configuration.connectionPool().testWhileIdle()); + assertEquals(100, configuration.connectionTimeout()); + assertEquals(100, configuration.socketTimeout()); + assertFalse(configuration.tcpNoDelay()); + assertFalse(configuration.pingOnStartup()); + assertEquals(128, configuration.keySizeEstimate()); + assertEquals(1024, configuration.valueSizeEstimate()); + assertEquals(0, configuration.maxRetries()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/ApacheAvroMarshallerTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/ApacheAvroMarshallerTest.java new file mode 100644 index 000000000000..cc1a53daf381 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/ApacheAvroMarshallerTest.java @@ -0,0 +1,152 @@ +package org.infinispan.client.hotrod.marshall; + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Test(groups = "functional", testName = "client.hotrod.marshall.ApacheAvroMarshallerTest") +public class ApacheAvroMarshallerTest { + + private final ApacheAvroMarshaller marshaller = new ApacheAvroMarshaller(); + + public void testStringMarshalling() { + String x = "Galder"; + String y = (String) marshallUnmarshall(x); + assert y.equals(x); + } + + public void testBooleanMarshalling() { + boolean x = true; + boolean y = ((Boolean) marshallUnmarshall(x)).booleanValue(); + assert x == y; + assertEquality(new Boolean(false)); + } + + public void testIntegerMarshalling() { + int x = 99; + int y = ((Integer) marshallUnmarshall(x)).intValue(); + assert x == y; + assertEquality(new Integer(12345)); + } + + public void testLongMarshalling() { + long x = 9223372036854775807L; + long y = ((Long) marshallUnmarshall(x)).longValue(); + assert x == y; + assertEquality(new Long(72057594037927936L)); + } + + public void testFloatMarshalling() { + float x = 123.4f; + float y = ((Float) marshallUnmarshall(x)).floatValue(); + assert x == y; + assertEquality(new Float(56789.9)); + } + + public void testDoubleMarshalling() { + double x = 1.234e2; + double y = ((Double) marshallUnmarshall(x)).doubleValue(); + assert x == y; + assertEquality(new Double(5.678e9)); + } + + public void testNullMarshalling() { + assert null == marshallUnmarshall(null); + } + + public void testBytesMarshalling() { + byte[] x = new byte[]{1, 2, 3, 4}; + byte[] y = (byte[]) marshallUnmarshall(x); + assert Arrays.equals(x, y); + } + + public void testStringArrayMarshalling() { + assertArrayEquality(new String[]{"Basque Country", "Spain", "UK", "Switzerland"}); + } + + public void testIntArrayMarshalling() { + assertArrayEquality(new Integer[]{1234, 5678, 9101112}); + } + + public void testLongArrayMarshalling() { + assertArrayEquality(new Long[]{9223372036854775807L, 72057594037927936L}); + } + + public void testBooleanArrayMarshalling() { + assertArrayEquality(new Boolean[] {true, false, true, true}); + } + + public void testFloatArrayMarshalling() { + assertArrayEquality(new Float[] {56789.9f, 1234.6f, 85894.303f, 67484.32f, 4732.4f}); + } + + public void testDoubleArrayMarshalling() { + assertArrayEquality(new Double[] {5.678e9, 1.623435e9, 5.654545e5, 9.6232323e1}); + } + + public void testListMarshalling() { + List cities = new ArrayList(); + cities.add("algorta"); + cities.add("neuchatel"); + cities.add("ibiza"); + assertEquality(cities); + + List numbers = new ArrayList(); + numbers.add(12); + numbers.add(3232412); + numbers.add(4345132); + numbers.add(898979); + assertEquality(numbers); + + List testimony = new LinkedList(); + testimony.add(false); + testimony.add(true); + testimony.add(true); + testimony.add(true); + assertEquality(testimony); + } + + public void testMapMarshalling() { + Map numbers = new HashMap(); + numbers.put(9223372036854775807L, 4732.4f); + numbers.put(72057594037927936L, 67484.32f); + numbers.put(7205759412424936L, 132367484.32f); + assertEquality(numbers); + } + + public void testSetMarshalling() { + Set words = new HashSet(); + words.add("cat"); + words.add("dog"); + words.add("perro"); + words.add("txakur"); + assertEquality(words); + } + + private Object marshallUnmarshall(Object o) { + try { + byte[] buffer = marshaller.objectToByteBuffer(o); + return marshaller.objectFromByteBuffer(buffer); + } catch(Exception e) { + throw new RuntimeException("Error marshalling or unmarshalling", e); + } + } + + private void assertArrayEquality(T[] x) { + T[] y = (T[]) ApacheAvroMarshallerTest.this.marshallUnmarshall(x); + assert Arrays.equals(x, y); + } + + private void assertEquality(T x) { + T y = (T) ApacheAvroMarshallerTest.this.marshallUnmarshall(x); + assert x.equals(y); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedAccount.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedAccount.java new file mode 100644 index 000000000000..2dc90b65713f --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedAccount.java @@ -0,0 +1,62 @@ +package org.infinispan.client.hotrod.marshall; + +import org.hibernate.search.annotations.Analyze; +import org.hibernate.search.annotations.Field; +import org.hibernate.search.annotations.Indexed; +import org.hibernate.search.annotations.Store; + +import java.util.Date; + +/** + * A class similar to {@code org.infinispan.protostream.sampledomain.Account}, that maps to the same protobuf type, + * {@code sample_bank_account.Account}. + * + * @author anistor@redhat.com + * @since 6.0 + */ +@Indexed +public class EmbeddedAccount { + + @Field(store = Store.YES, analyze = Analyze.NO) + private int id; + + @Field(store = Store.YES, analyze = Analyze.NO) + private String description; + + @Field(store = Store.YES, analyze = Analyze.NO) + private Date creationDate; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + + @Override + public String toString() { + return "EmbeddedAccount{" + + "id=" + id + + ", description='" + description + '\'' + + ", creationDate='" + creationDate + '\'' + + "}"; + + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedAccountMarshaller.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedAccountMarshaller.java new file mode 100644 index 000000000000..f2c28f7dd73a --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedAccountMarshaller.java @@ -0,0 +1,42 @@ +package org.infinispan.client.hotrod.marshall; + +import org.infinispan.protostream.MessageMarshaller; + +import java.io.IOException; +import java.util.Date; + +/** + * @author anistor@redhat.com + */ +public class EmbeddedAccountMarshaller implements MessageMarshaller { + + @Override + public String getTypeName() { + return "sample_bank_account.Account"; + } + + @Override + public Class getJavaClass() { + return EmbeddedAccount.class; + } + + @Override + public EmbeddedAccount readFrom(ProtoStreamReader reader) throws IOException { + int id = reader.readInt("id"); + String description = reader.readString("description"); + long creationDate = reader.readLong("creationDate"); + + EmbeddedAccount account = new EmbeddedAccount(); + account.setId(id); + account.setDescription(description); + account.setCreationDate(new Date(creationDate)); + return account; + } + + @Override + public void writeTo(ProtoStreamWriter writer, EmbeddedAccount account) throws IOException { + writer.writeInt("id", account.getId()); + writer.writeString("description", account.getDescription()); + writer.writeLong("creationDate", account.getCreationDate().getTime()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedCompatTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedCompatTest.java new file mode 100644 index 000000000000..61b0d25238c9 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/EmbeddedCompatTest.java @@ -0,0 +1,194 @@ +package org.infinispan.client.hotrod.marshall; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.Search; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.commons.equivalence.AnyEquivalence; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.Account; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.CacheQuery; +import org.infinispan.query.dsl.Query; +import org.infinispan.query.dsl.QueryFactory; +import org.infinispan.query.remote.CompatibilityProtoStreamMarshaller; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import java.util.Date; +import java.util.List; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.junit.Assert.*; + +/** + * Tests compatibility between remote query and embedded mode. + * + * @author anistor@redhat.com + * @since 6.0 + */ +@Test(testName = "client.hotrod.marshall.EmbeddedCompatTest", groups = "functional") +@CleanupAfterMethod +public class EmbeddedCompatTest extends SingleCacheManagerTest { + + private HotRodServer hotRodServer; + private RemoteCacheManager remoteCacheManager; + private RemoteCache remoteCache; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + org.infinispan.configuration.cache.ConfigurationBuilder builder = hotRodCacheConfiguration(); + builder.compatibility().enable().marshaller(new CompatibilityProtoStreamMarshaller()); + builder.indexing().enable() + .addProperty("default.directory_provider", "ram") + .addProperty("lucene_version", "LUCENE_CURRENT"); + + builder.dataContainer().keyEquivalence(AnyEquivalence.getInstance()); // TODO [anistor] hacks! + cacheManager = TestCacheManagerFactory.createCacheManager(builder); + cache = cacheManager.getCache(); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + ConfigurationBuilder clientBuilder = new ConfigurationBuilder(); + clientBuilder.addServer().host("127.0.0.1").port(hotRodServer.getPort()); + clientBuilder.marshaller(new ProtoStreamMarshaller()); + remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); + + remoteCache = remoteCacheManager.getCache(); + + //initialize client-side serialization context + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(remoteCacheManager)); + + //initialize server-side serialization context + ProtobufMetadataManager protobufMetadataManager = cacheManager.getGlobalComponentRegistry().getComponent(ProtobufMetadataManager.class); + protobufMetadataManager.registerProtofile("/sample_bank_account/bank.protobin"); + protobufMetadataManager.registerMarshaller(EmbeddedAccount.class, new EmbeddedAccountMarshaller()); + + return cacheManager; + } + + @AfterTest + public void release() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer); + } + + public void testPutAndGet() throws Exception { + Account account = createAccount(); + remoteCache.put(1, account); + + // try to get the object through the local cache interface and check it's the same object we put + assertEquals(1, cache.keySet().size()); + Object key = cache.keySet().iterator().next(); + Object localObject = cache.get(key); + assertNotNull(localObject); + assertTrue(localObject instanceof EmbeddedAccount); + assertEmbeddedAccount((EmbeddedAccount) localObject); + + // get the object through the remote cache interface and check it's the same object we put + Account fromRemoteCache = remoteCache.get(1); + assertAccount(fromRemoteCache); + } + + public void testPutAndGetForEmbeddedEntry() throws Exception { + EmbeddedAccount account = new EmbeddedAccount(); + account.setId(1); + account.setDescription("test description"); + account.setCreationDate(new Date(42)); + cache.put(1, account); + + // try to get the object through the local cache interface and check it's the same object we put + assertEquals(1, remoteCache.keySet().size()); + Object key = remoteCache.keySet().iterator().next(); + Object remoteObject = remoteCache.get(key); + assertNotNull(remoteObject); + assertTrue(remoteObject instanceof Account); + assertAccount((Account) remoteObject); + + // get the object through the embedded cache interface and check it's the same object we put + EmbeddedAccount fromEmbeddedCache = (EmbeddedAccount) cache.get(1); + assertEmbeddedAccount(fromEmbeddedCache); + } + + public void testRemoteQuery() throws Exception { + Account account = createAccount(); + remoteCache.put(1, account); + + // get account back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache); + Query query = qf.from(Account.class) + .having("description").like("%test%").toBuilder() + .build(); + List list = query.list(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(Account.class, list.get(0).getClass()); + assertAccount(list.get(0)); + } + + public void testRemoteQueryForEmbeddedEntry() throws Exception { + EmbeddedAccount account = new EmbeddedAccount(); + account.setId(1); + account.setDescription("test description"); + account.setCreationDate(new Date(42)); + cache.put(1, account); + + // get account back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache); + Query query = qf.from(Account.class) + .having("description").like("%test%").toBuilder() + .build(); + List list = query.list(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(Account.class, list.get(0).getClass()); + assertAccount(list.get(0)); + } + + public void testEmbeddedQuery() throws Exception { + Account account = createAccount(); + remoteCache.put(1, account); + + // get account back from local cache via query and check its attributes + org.apache.lucene.search.Query query = org.infinispan.query.Search.getSearchManager(cache) + .buildQueryBuilderForClass(EmbeddedAccount.class).get() + .keyword().wildcard().onField("description").matching("*test*").createQuery(); + CacheQuery cacheQuery = org.infinispan.query.Search.getSearchManager(cache).getQuery(query); + List list = cacheQuery.list(); + + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(EmbeddedAccount.class, list.get(0).getClass()); + assertEmbeddedAccount((EmbeddedAccount) list.get(0)); + } + + private Account createAccount() { + Account account = new Account(); + account.setId(1); + account.setDescription("test description"); + account.setCreationDate(new Date(42)); + return account; + } + + private void assertAccount(Account account) { + assertEquals(1, account.getId()); + assertEquals("test description", account.getDescription()); + assertEquals(42, account.getCreationDate().getTime()); + } + + private void assertEmbeddedAccount(EmbeddedAccount account) { + assertEquals(1, account.getId()); + assertEquals("test description", account.getDescription()); + assertEquals(42, account.getCreationDate().getTime()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/ProtoStreamMarshallerTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/ProtoStreamMarshallerTest.java new file mode 100644 index 000000000000..c7d33b96ec4c --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/marshall/ProtoStreamMarshallerTest.java @@ -0,0 +1,113 @@ +package org.infinispan.client.hotrod.marshall; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.ProtobufUtil; +import org.infinispan.protostream.sampledomain.Address; +import org.infinispan.protostream.sampledomain.User; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import java.util.Collections; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.junit.Assert.*; + +/** + * Tests integration between HotRod client and ProtoStream marshalling library. + * + * @author anistor@redhat.com + * @since 6.0 + */ +@Test(testName = "client.hotrod.marshall.ProtoStreamMarshallerTest", groups = "functional") +@CleanupAfterMethod +public class ProtoStreamMarshallerTest extends SingleCacheManagerTest { + + private HotRodServer hotRodServer; + private RemoteCacheManager remoteCacheManager; + private RemoteCache remoteCache; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + cacheManager = TestCacheManagerFactory.createCacheManager(hotRodCacheConfiguration()); + cache = cacheManager.getCache(); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + ConfigurationBuilder clientBuilder = new ConfigurationBuilder(); + clientBuilder.addServer().host("127.0.0.1").port(hotRodServer.getPort()); + clientBuilder.marshaller(new ProtoStreamMarshaller()); + remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); + + remoteCache = remoteCacheManager.getCache(); + + //initialize client-side serialization context + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(remoteCacheManager)); + + return cacheManager; + } + + @AfterTest + public void release() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer); + } + + public void testPutAndGet() throws Exception { + User user = createUser(); + remoteCache.put(1, user); + + // try to get the object through the local cache interface and check it's the same object we put + assertEquals(1, cache.keySet().size()); + byte[] key = (byte[]) cache.keySet().iterator().next(); + Object localObject = cache.get(key); + assertNotNull(localObject); + assertTrue(localObject instanceof byte[]); + Object unmarshalledObject = ProtobufUtil.fromWrappedByteArray(ProtoStreamMarshaller.getSerializationContext(remoteCacheManager), (byte[]) localObject); + assertTrue(unmarshalledObject instanceof User); + assertUser((User) unmarshalledObject); + + // get the object through the remote cache interface and check it's the same object we put + User fromRemoteCache = remoteCache.get(1); + assertUser(fromRemoteCache); + } + + private User createUser() { + User user = new User(); + user.setId(1); + user.setName("Tom"); + user.setSurname("Cat"); + user.setGender(User.Gender.MALE); + user.setAccountIds(Collections.singletonList(12)); + Address address = new Address(); + address.setStreet("Dark Alley"); + address.setPostCode("1234"); + user.setAddresses(Collections.singletonList(address)); + return user; + } + + private void assertUser(User user) { + assertNotNull(user); + assertEquals(1, user.getId()); + assertEquals("Tom", user.getName()); + assertEquals("Cat", user.getSurname()); + assertEquals(User.Gender.MALE, user.getGender()); + assertNotNull(user.getAccountIds()); + assertEquals(1, user.getAccountIds().size()); + assertEquals(12, user.getAccountIds().get(0).intValue()); + assertNotNull(user.getAddresses()); + assertEquals(1, user.getAddresses().size()); + assertEquals("Dark Alley", user.getAddresses().get(0).getStreet()); + assertEquals("1234", user.getAddresses().get(0).getPostCode()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryFileSystemTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryFileSystemTest.java new file mode 100644 index 000000000000..a7f1cac4a25b --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryFileSystemTest.java @@ -0,0 +1,52 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.junit.Assert; +import org.testng.annotations.Test; + +import java.io.File; + +/** + * Tests verifying the functionality of Remote queries for HotRod using FileSystem as a directory provider. + * + * @author Anna Manukyan + */ +@Test(testName = "client.hotrod.query.HotRodQueryFileSystemTest", groups = "functional") +@CleanupAfterMethod +public class HotRodQueryFileSystemTest extends HotRodQueryTest { + + private final String indexDirectory = TestingUtil.tmpDirectory(getClass()); + + @Override + protected ConfigurationBuilder getConfigurationBuilder() { + ConfigurationBuilder builder = super.getConfigurationBuilder(); + builder.indexing().addProperty("default.indexBase", indexDirectory); + return builder; + } + + @Override + protected String getLuceneDirectoryProvider() { + return "filesystem"; + } + + @Override + protected void setup() throws Exception { + TestingUtil.recursiveFileRemove(indexDirectory); + boolean created = new File(indexDirectory).mkdirs(); + Assert.assertTrue(created); + super.setup(); + } + + @Override + protected void teardown() { + try { + //first stop cache managers, then clear the index + super.teardown(); + } finally { + //delete the index otherwise it will mess up the index for next tests + TestingUtil.recursiveFileRemove(indexDirectory); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryIspnDirectoryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryIspnDirectoryTest.java new file mode 100644 index 000000000000..d0abd3ffd3b4 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryIspnDirectoryTest.java @@ -0,0 +1,20 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.testng.annotations.Test; + +/** + * Test remote queries against Infinispan Directory provider. + * + * @author anistor@redhat.com + * @since 6.0 + */ +@Test(testName = "client.hotrod.query.HotRodQueryIspnDirectoryTest", groups = "functional") +@CleanupAfterMethod +public class HotRodQueryIspnDirectoryTest extends HotRodQueryTest { + + @Override + protected String getLuceneDirectoryProvider() { + return "infinispan"; + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryTest.java new file mode 100644 index 000000000000..bac804e1c0e5 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodQueryTest.java @@ -0,0 +1,224 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.Search; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; +import org.infinispan.commons.equivalence.ByteArrayEquivalence; +import org.infinispan.commons.util.Util; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.configuration.global.GlobalConfigurationBuilder; +import org.infinispan.jmx.PerThreadMBeanServerLookup; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.Address; +import org.infinispan.protostream.sampledomain.User; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.dsl.Query; +import org.infinispan.query.dsl.QueryFactory; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.Test; + +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.List; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author anistor@redhat.com + * @since 6.0 + */ +@Test(testName = "client.hotrod.query.HotRodQueryTest", groups = "functional") +@CleanupAfterMethod +public class HotRodQueryTest extends SingleCacheManagerTest { + + public static final String JMX_DOMAIN = ProtobufMetadataManager.class.getSimpleName(); + + public static final String TEST_CACHE_NAME = "userCache"; + + private HotRodServer hotRodServer; + private RemoteCacheManager remoteCacheManager; + private RemoteCache remoteCache; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder().nonClusteredDefault(); + gcb.globalJmxStatistics() + .enable() + .allowDuplicateDomains(true) + .jmxDomain(JMX_DOMAIN) + .mBeanServerLookup(new PerThreadMBeanServerLookup()); + + ConfigurationBuilder builder = getConfigurationBuilder(); + + cacheManager = TestCacheManagerFactory.createCacheManager(gcb, new ConfigurationBuilder(), true); + cacheManager.defineConfiguration(TEST_CACHE_NAME, builder.build()); + cache = cacheManager.getCache(TEST_CACHE_NAME); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); + clientBuilder.addServer().host("127.0.0.1").port(hotRodServer.getPort()); + clientBuilder.marshaller(new ProtoStreamMarshaller()); + remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); + + remoteCache = remoteCacheManager.getCache(TEST_CACHE_NAME); + + ObjectName objName = new ObjectName(JMX_DOMAIN + ":type=RemoteQuery,name=" + + ObjectName.quote("DefaultCacheManager") + + ",component=" + ProtobufMetadataManager.OBJECT_NAME); + + //initialize server-side serialization context via JMX + byte[] descriptor = readClasspathResource("/sample_bank_account/bank.protobin"); + MBeanServer mBeanServer = PerThreadMBeanServerLookup.getThreadMBeanServer(); + mBeanServer.invoke(objName, "registerProtofile", new Object[]{descriptor}, new String[]{byte[].class.getName()}); + + //initialize client-side serialization context + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(remoteCacheManager)); + + return cacheManager; + } + + protected ConfigurationBuilder getConfigurationBuilder() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.dataContainer() + .keyEquivalence(ByteArrayEquivalence.INSTANCE) + .indexing().enable() + .addProperty("default.directory_provider", getLuceneDirectoryProvider()) + .addProperty("lucene_version", "LUCENE_CURRENT"); + return builder; + } + + protected String getLuceneDirectoryProvider() { + return "ram"; + } + + private byte[] readClasspathResource(String classPathResource) throws IOException { + InputStream is = getClass().getResourceAsStream(classPathResource); + try { + return Util.readStream(is); + } finally { + if (is != null) { + is.close(); + } + } + } + + @AfterTest + public void release() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer); + } + + public void testAttributeQuery() throws Exception { + remoteCache.put(1, createUser1()); + remoteCache.put(2, createUser2()); + + // get user back from remote cache and check its attributes + User fromCache = remoteCache.get(1); + assertUser(fromCache); + + // get user back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache); + Query query = qf.from(User.class) + .having("name").eq("Tom").toBuilder() + .build(); + List list = query.list(); + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(User.class, list.get(0).getClass()); + assertUser(list.get(0)); + } + + public void testEmbeddedAttributeQuery() throws Exception { + remoteCache.put(1, createUser1()); + remoteCache.put(2, createUser2()); + + // get user back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache); + Query query = qf.from(User.class) + .having("addresses.postCode").eq("1234").toBuilder() + .build(); + List list = query.list(); + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(User.class, list.get(0).getClass()); + assertUser(list.get(0)); + } + + public void testProjections() throws Exception { + remoteCache.put(1, createUser1()); + remoteCache.put(2, createUser2()); + + // get user back from remote cache and check its attributes + User fromCache = remoteCache.get(1); + assertUser(fromCache); + + // get user back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache); + Query query = qf.from(User.class) + .setProjection("name", "surname") + .having("name").eq("Tom").toBuilder() + .build(); + List list = query.list(); + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(Object[].class, list.get(0).getClass()); + assertEquals("Tom", list.get(0)[0]); + assertEquals("Cat", list.get(0)[1]); + } + + private User createUser1() { + User user = new User(); + user.setId(1); + user.setName("Tom"); + user.setSurname("Cat"); + user.setGender(User.Gender.MALE); + user.setAccountIds(Collections.singletonList(12)); + Address address = new Address(); + address.setStreet("Dark Alley"); + address.setPostCode("1234"); + user.setAddresses(Collections.singletonList(address)); + return user; + } + + private User createUser2() { + User user = new User(); + user.setId(1); + user.setName("Adrian"); + user.setSurname("Nistor"); + user.setGender(User.Gender.MALE); + Address address = new Address(); + address.setStreet("Old Street"); + address.setPostCode("XYZ"); + user.setAddresses(Collections.singletonList(address)); + return user; + } + + private void assertUser(User user) { + assertNotNull(user); + assertEquals(1, user.getId()); + assertEquals("Tom", user.getName()); + assertEquals("Cat", user.getSurname()); + assertEquals(User.Gender.MALE, user.getGender()); + assertNotNull(user.getAccountIds()); + assertEquals(1, user.getAccountIds().size()); + assertEquals(12, user.getAccountIds().get(0).intValue()); + assertNotNull(user.getAddresses()); + assertEquals(1, user.getAddresses().size()); + assertEquals("Dark Alley", user.getAddresses().get(0).getStreet()); + assertEquals("1234", user.getAddresses().get(0).getPostCode()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodTunedQueryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodTunedQueryTest.java new file mode 100644 index 000000000000..0624d95a7d0b --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/HotRodTunedQueryTest.java @@ -0,0 +1,63 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.commons.equivalence.ByteArrayEquivalence; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.testng.annotations.Test; + +import static org.testng.AssertJUnit.assertTrue; + +import java.io.File; + +/** + * Verifying that the tuned query configuration also works for Remote Queries. + * + * @author Anna Manukyan + */ +@Test(testName = "client.hotrod.query.HotRodTunedQueryTest", groups = "functional") +@CleanupAfterMethod +public class HotRodTunedQueryTest extends RemoteQueryDslConditionsTest { + + private final String indexDirectory = TestingUtil.tmpDirectory(getClass()); + + @Override + protected ConfigurationBuilder getConfigurationBuilder() { + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.dataContainer() + .keyEquivalence(ByteArrayEquivalence.INSTANCE) + .valueEquivalence(ByteArrayEquivalence.INSTANCE) + .indexing().enable() + .indexLocalOnly(false) + .addProperty("default.indexmanager", "near-real-time") + .addProperty("default.indexBase", indexDirectory) + .addProperty("default.exclusive_index_use", "true") + .addProperty("default.indexwriter.merge_factor", "30") + .addProperty("default.indexwriter.merge_max_size", "4096") + .addProperty("default.indexwriter.ram_buffer_size", "220") + .addProperty("default.locking_strategy", "native") + .addProperty("default.sharding_strategy.nbr_of_shards", "6") + .addProperty("lucene_version", "LUCENE_36"); + + return builder; + } + + @Override + protected void setup() throws Exception { + TestingUtil.recursiveFileRemove(indexDirectory); + boolean created = new File(indexDirectory).mkdirs(); + assertTrue(created); + super.setup(); + } + + @Override + protected void teardown() { + try { + //first stop cache managers, then clear the index + super.teardown(); + } finally { + //delete the index otherwise it will mess up the index for next tests + TestingUtil.recursiveFileRemove(indexDirectory); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerIspnDirQueryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerIspnDirQueryTest.java new file mode 100644 index 000000000000..a9ae54867268 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerIspnDirQueryTest.java @@ -0,0 +1,63 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.testng.annotations.Test; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * Verifying the functionality of Queries using ISPN directory_provider on clustered hotrod server configuration. + * + * @author Anna Manukyan + */ +@Test(testName = "client.hotrod.query.MultiHotRodServerIspnDirQueryTest", groups = "unstable", description = "Enable tests when ISPN-3672 is fixed. -- original group: functional") +public class MultiHotRodServerIspnDirQueryTest extends MultiHotRodServerQueryTest { + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder defaultConfiguration = new ConfigurationBuilder(); + ConfigurationBuilder builder = hotRodCacheConfiguration(getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, false)); + builder.indexing().enable().indexLocalOnly(false) + .addProperty("default.directory_provider", "infinispan") + .addProperty("lucene_version", "LUCENE_CURRENT"); + + createHotRodServers(2, defaultConfiguration); + + //initialize server-side serialization context + for (EmbeddedCacheManager cm : cacheManagers) { + cm.defineConfiguration("queryableCache", builder.build()); + + cm.getGlobalComponentRegistry().getComponent(ProtobufMetadataManager.class).registerProtofile("/sample_bank_account/bank.protobin"); + } + + //initialize client-side serialization context + for (RemoteCacheManager rcm : clients) { + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(rcm)); + } + + remoteCache0 = client(0).getCache("queryableCache"); + remoteCache1 = client(1).getCache("queryableCache"); + } + + @Test(groups = "unstable") + public void testAttributeQuery() throws Exception { + super.testAttributeQuery(); + + } + + @Test(groups = "unstable") + public void testEmbeddedAttributeQuery() throws Exception { + super.testEmbeddedAttributeQuery(); + } + + @Test(groups = "unstable") + public void testProjections() throws Exception { + super.testProjections(); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerIspnDirReplQueryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerIspnDirReplQueryTest.java new file mode 100644 index 000000000000..d6e93975008d --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerIspnDirReplQueryTest.java @@ -0,0 +1,66 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.testng.annotations.Test; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * Verifies the functionality of the Queries in case of REPL infinispan directory_provider for clustered Hotrod servers. + * + * @author Anna Manukyan + */ +@Test(testName = "client.hotrod.query.MultiHotRodServerIspnDirReplQueryTest", groups = "unstable", description = "Enable tests when ISPN-3672 is fixed. -- original group: functional") +public class MultiHotRodServerIspnDirReplQueryTest extends MultiHotRodServerQueryTest { + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder defaultConfiguration = getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, false); + ConfigurationBuilder builder = hotRodCacheConfiguration(getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, false)); + builder.indexing().enable().indexLocalOnly(true) + .addProperty("default.directory_provider", "infinispan") + .addProperty("default.exclusive_index_use", "false") + //.addProperty("default.indexmanager", "org.infinispan.query.indexmanager.InfinispanIndexManager") + .addProperty("lucene_version", "LUCENE_CURRENT"); + + createHotRodServers(2, defaultConfiguration); + + //initialize server-side serialization context + for (EmbeddedCacheManager cm : cacheManagers) { + cm.defineConfiguration("queryableCache", builder.build()); + + cm.getGlobalComponentRegistry().getComponent(ProtobufMetadataManager.class).registerProtofile("/sample_bank_account/bank.protobin"); + } + + //initialize client-side serialization context + for (RemoteCacheManager rcm : clients) { + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(rcm)); + } + + waitForClusterToForm(); + + remoteCache0 = client(0).getCache("queryableCache"); + remoteCache1 = client(1).getCache("queryableCache"); + } + + @Test(groups = "unstable") + public void testAttributeQuery() throws Exception { + super.testAttributeQuery(); + } + + @Test(groups = "unstable") + public void testEmbeddedAttributeQuery() throws Exception { + super.testEmbeddedAttributeQuery(); + } + + @Test(groups = "unstable") + public void testProjections() throws Exception { + super.testProjections(); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerQueryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerQueryTest.java new file mode 100644 index 000000000000..707d2241f909 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/MultiHotRodServerQueryTest.java @@ -0,0 +1,163 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.Search; +import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; +import org.infinispan.client.hotrod.test.MultiHotRodServersTest; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.Address; +import org.infinispan.protostream.sampledomain.User; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.dsl.Query; +import org.infinispan.query.dsl.QueryFactory; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.testng.annotations.Test; + +import java.util.Collections; +import java.util.List; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * @author anistor@redhat.com + * @since 6.0 + */ +@Test(testName = "client.hotrod.query.MultiHotRodServerQueryTest", groups = "functional") +public class MultiHotRodServerQueryTest extends MultiHotRodServersTest { + protected RemoteCache remoteCache0, remoteCache1; + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder builder = hotRodCacheConfiguration(getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, false)); + builder.indexing().enable() + .addProperty("default.directory_provider", "ram") + .addProperty("lucene_version", "LUCENE_CURRENT"); + + createHotRodServers(2, builder); + + //initialize server-side serialization context + for (EmbeddedCacheManager cm : cacheManagers) { + cm.getGlobalComponentRegistry().getComponent(ProtobufMetadataManager.class).registerProtofile("/sample_bank_account/bank.protobin"); + } + + //initialize client-side serialization context + for (RemoteCacheManager rcm : clients) { + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(rcm)); + } + + remoteCache0 = client(0).getCache(); + remoteCache1 = client(1).getCache(); + } + + @Override + protected org.infinispan.client.hotrod.configuration.ConfigurationBuilder createHotRodClientConfigurationBuilder(int serverPort) { + return super.createHotRodClientConfigurationBuilder(serverPort) + .marshaller(new ProtoStreamMarshaller()); + } + + public void testAttributeQuery() throws Exception { + remoteCache0.put(1, createUser1()); + remoteCache1.put(2, createUser2()); + + // get user back from remote cache and check its attributes + User fromCache = remoteCache0.get(1); + assertNotNull(fromCache); + assertUser(fromCache); + + // get user back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache1); + Query query = qf.from(User.class) + .having("name").eq("Tom").toBuilder() + .build(); + List list = query.list(); + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(User.class, list.get(0).getClass()); + assertUser(list.get(0)); + } + + public void testEmbeddedAttributeQuery() throws Exception { + remoteCache0.put(1, createUser1()); + remoteCache1.put(2, createUser2()); + + // get user back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache1); + Query query = qf.from(User.class) + .having("addresses.postCode").eq("1234").toBuilder() + .build(); + List list = query.list(); + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(User.class, list.get(0).getClass()); + assertUser(list.get(0)); + } + + public void testProjections() throws Exception { + remoteCache0.put(1, createUser1()); + remoteCache1.put(2, createUser2()); + + // get user back from remote cache and check its attributes + User fromCache = remoteCache0.get(1); + assertUser(fromCache); + + // get user back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache1); + Query query = qf.from(User.class) + .setProjection("name", "surname") + .having("name").eq("Tom").toBuilder() + .build(); + List list = query.list(); + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(Object[].class, list.get(0).getClass()); + assertEquals("Tom", list.get(0)[0]); + assertEquals("Cat", list.get(0)[1]); + } + + private User createUser1() { + User user = new User(); + user.setId(1); + user.setName("Tom"); + user.setSurname("Cat"); + user.setGender(User.Gender.MALE); + user.setAccountIds(Collections.singletonList(12)); + Address address = new Address(); + address.setStreet("Dark Alley"); + address.setPostCode("1234"); + user.setAddresses(Collections.singletonList(address)); + return user; + } + + private User createUser2() { + User user = new User(); + user.setId(2); + user.setName("Adrian"); + user.setSurname("Nistor"); + user.setGender(User.Gender.MALE); + Address address = new Address(); + address.setStreet("Old Street"); + address.setPostCode("XYZ"); + user.setAddresses(Collections.singletonList(address)); + return user; + } + + private void assertUser(User user) { + assertNotNull(user); + assertEquals(1, user.getId()); + assertEquals("Tom", user.getName()); + assertEquals("Cat", user.getSurname()); + assertEquals(User.Gender.MALE, user.getGender()); + assertNotNull(user.getAccountIds()); + assertEquals(1, user.getAccountIds().size()); + assertEquals(12, user.getAccountIds().get(0).intValue()); + assertNotNull(user.getAddresses()); + assertEquals(1, user.getAddresses().size()); + assertEquals("Dark Alley", user.getAddresses().get(0).getStreet()); + assertEquals("1234", user.getAddresses().get(0).getPostCode()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsFilestoreTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsFilestoreTest.java new file mode 100644 index 000000000000..89387c4fa169 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsFilestoreTest.java @@ -0,0 +1,58 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.testng.annotations.Test; + +import java.io.File; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.assertTrue; + +/** + * Verifying the functionality of Remote Queries for filesystem directory provider. + * + * @author Anna Manukyan + */ +@Test(testName = "client.hotrod.query.RemoteQueryDslConditionsFilestoreTest", groups = "functional") +@CleanupAfterMethod +public class RemoteQueryDslConditionsFilestoreTest extends RemoteQueryDslConditionsTest { + + private final String indexDirectory = TestingUtil.tmpDirectory(getClass()); + + @Override + protected ConfigurationBuilder getConfigurationBuilder() { + ConfigurationBuilder builder = hotRodCacheConfiguration(); + builder.indexing().enable() + .addProperty("default.directory_provider", getLuceneDirectoryProvider()) + .addProperty("default.indexBase", indexDirectory) + .addProperty("lucene_version", "LUCENE_CURRENT"); + + return builder; + } + + @Override + public String getLuceneDirectoryProvider() { + return "filesystem"; + } + + @Override + protected void setup() throws Exception { + TestingUtil.recursiveFileRemove(indexDirectory); + boolean created = new File(indexDirectory).mkdirs(); + assertTrue(created); + super.setup(); + } + + @Override + protected void teardown() { + try { + //first stop cache managers, then clear the index + super.teardown(); + } finally { + //delete the index otherwise it will mess up the index for next tests + TestingUtil.recursiveFileRemove(indexDirectory); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsIspnDirTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsIspnDirTest.java new file mode 100644 index 000000000000..62d8426fae9c --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsIspnDirTest.java @@ -0,0 +1,58 @@ +package org.infinispan.client.hotrod.query; + +import org.hibernate.search.infinispan.InfinispanIntegration; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.Test; + +/** + * Verifying the functionality of remote queries for infinispan directory_provider. + * + * @author Anna Manukyan + */ +@Test(testName = "client.hotrod.query.RemoteQueryDslConditionsIspnDirTest", groups = "functional") +@CleanupAfterMethod +public class RemoteQueryDslConditionsIspnDirTest extends RemoteQueryDslConditionsTest { + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + ConfigurationBuilder builder = getConfigurationBuilder(); + + cacheManager = TestCacheManagerFactory.createCacheManager(builder); + + ConfigurationBuilder defaultCacheConfiguration = new ConfigurationBuilder(); + cacheManager.defineConfiguration(InfinispanIntegration.DEFAULT_INDEXESDATA_CACHENAME, defaultCacheConfiguration.build()); + cacheManager.defineConfiguration(InfinispanIntegration.DEFAULT_LOCKING_CACHENAME, defaultCacheConfiguration.build()); + cacheManager.defineConfiguration(InfinispanIntegration.DEFAULT_INDEXESMETADATA_CACHENAME, defaultCacheConfiguration.build()); + + cache = cacheManager.getCache(); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); + clientBuilder.addServer().host("127.0.0.1").port(hotRodServer.getPort()); + clientBuilder.marshaller(new ProtoStreamMarshaller()); + remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); + remoteCache = remoteCacheManager.getCache(); + + //initialize server-side serialization context + cacheManager.getGlobalComponentRegistry().getComponent(ProtobufMetadataManager.class).registerProtofile("/sample_bank_account/bank.protobin"); + + //initialize client-side serialization context + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(remoteCacheManager)); + + return cacheManager; + } + + @Override + public String getLuceneDirectoryProvider() { + return "infinispan"; + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsTest.java new file mode 100644 index 000000000000..bf92f2690ebb --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslConditionsTest.java @@ -0,0 +1,1269 @@ +package org.infinispan.client.hotrod.query; + +import org.hibernate.search.engine.spi.SearchFactoryImplementor; +import org.hibernate.search.indexes.spi.IndexManager; +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.Search; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.Account; +import org.infinispan.protostream.sampledomain.Address; +import org.infinispan.protostream.sampledomain.Transaction; +import org.infinispan.protostream.sampledomain.User; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.dsl.FilterConditionEndContext; +import org.infinispan.query.dsl.Query; +import org.infinispan.query.dsl.QueryFactory; +import org.infinispan.query.dsl.SortOrder; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.infinispan.query.remote.indexing.ProtobufValueWrapper; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.junit.Assert.*; + + +//todo [anistor] unify embedded and remote query tests + +/** + * Test for query conditions (filtering). Exercises the whole query DSL on the sample domain model. + * + * @author anistor@redhat.com + * @since 6.0 + */ +@Test(groups = "functional", testName = "client.hotrod.query.RemoteQueryDslConditionsTest") +@CleanupAfterMethod +public class RemoteQueryDslConditionsTest extends SingleCacheManagerTest { + + protected final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); + + protected HotRodServer hotRodServer; + protected RemoteCacheManager remoteCacheManager; + protected RemoteCache remoteCache; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + ConfigurationBuilder builder = getConfigurationBuilder(); + + cacheManager = TestCacheManagerFactory.createCacheManager(builder); + cache = cacheManager.getCache(); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); + clientBuilder.addServer().host("127.0.0.1").port(hotRodServer.getPort()); + clientBuilder.marshaller(new ProtoStreamMarshaller()); + remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); + remoteCache = remoteCacheManager.getCache(); + + //initialize server-side serialization context + cacheManager.getGlobalComponentRegistry().getComponent(ProtobufMetadataManager.class).registerProtofile("/sample_bank_account/bank.protobin"); + + //initialize client-side serialization context + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(remoteCacheManager)); + + return cacheManager; + } + + protected ConfigurationBuilder getConfigurationBuilder() { + ConfigurationBuilder builder = hotRodCacheConfiguration(); + builder.indexing().enable() + .addProperty("default.directory_provider", getLuceneDirectoryProvider()) + .addProperty("lucene_version", "LUCENE_CURRENT"); + + return builder; + } + + public String getLuceneDirectoryProvider() { + return "ram"; + } + + @AfterMethod(alwaysRun = true) + public void release() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer); + } + + @BeforeMethod(alwaysRun = true) + protected void populateCache() throws Exception { + // create the test objects + User user1 = new User(); + user1.setId(1); + user1.setName("John"); + user1.setSurname("Doe"); + user1.setGender(User.Gender.MALE); + user1.setAge(22); + user1.setAccountIds(Arrays.asList(1, 2)); + + Address address1 = new Address(); + address1.setStreet("Main Street"); + address1.setPostCode("X1234"); + user1.setAddresses(Collections.singletonList(address1)); + + User user2 = new User(); + user2.setId(2); + user2.setName("Spider"); + user2.setSurname("Man"); + user2.setGender(User.Gender.MALE); + user2.setAccountIds(Collections.singletonList(3)); + + Address address2 = new Address(); + address2.setStreet("Old Street"); + address2.setPostCode("Y12"); + Address address3 = new Address(); + address3.setStreet("Bond Street"); + address3.setPostCode("ZZ"); + user2.setAddresses(Arrays.asList(address2, address3)); + + User user3 = new User(); + user3.setId(3); + user3.setName("Spider"); + user3.setSurname("Woman"); + user3.setGender(User.Gender.FEMALE); + user3.setAccountIds(Collections.emptyList()); + + Account account1 = new Account(); + account1.setId(1); + account1.setDescription("John Doe's first bank account"); + account1.setCreationDate(DATE_FORMAT.parse("2013-01-03")); + + Account account2 = new Account(); + account2.setId(2); + account2.setDescription("John Doe's second bank account"); + account2.setCreationDate(DATE_FORMAT.parse("2013-01-04")); + + Account account3 = new Account(); + account3.setId(3); + account3.setCreationDate(DATE_FORMAT.parse("2013-01-20")); + + Transaction transaction0 = new Transaction(); + transaction0.setId(0); + transaction0.setDescription("Birthday present"); + transaction0.setAccountId(1); + transaction0.setAmount(1800); + transaction0.setDate(DATE_FORMAT.parse("2012-09-07")); + transaction0.setDebit(false); + + Transaction transaction1 = new Transaction(); + transaction1.setId(1); + transaction1.setDescription("Feb. rent payment"); + transaction1.setAccountId(1); + transaction1.setAmount(1500); + transaction1.setDate(DATE_FORMAT.parse("2013-01-05")); + transaction1.setDebit(true); + + Transaction transaction2 = new Transaction(); + transaction2.setId(2); + transaction2.setDescription("Starbucks"); + transaction2.setAccountId(1); + transaction2.setAmount(23); + transaction2.setDate(DATE_FORMAT.parse("2013-01-09")); + transaction2.setDebit(true); + + Transaction transaction3 = new Transaction(); + transaction3.setId(3); + transaction3.setDescription("Hotel"); + transaction3.setAccountId(2); + transaction3.setAmount(45); + transaction3.setDate(DATE_FORMAT.parse("2013-02-27")); + transaction3.setDebit(true); + + Transaction transaction4 = new Transaction(); + transaction4.setId(4); + transaction4.setDescription("Last january"); + transaction4.setAccountId(2); + transaction4.setAmount(95); + transaction4.setDate(DATE_FORMAT.parse("2013-01-31")); + transaction4.setDebit(true); + + Transaction transaction5 = new Transaction(); + transaction5.setId(5); + transaction5.setDescription("Popcorn"); + transaction5.setAccountId(2); + transaction5.setAmount(5); + transaction5.setDate(DATE_FORMAT.parse("2013-01-01")); + transaction5.setDebit(true); + + // persist and index the test objects + // we put all of them in the same cache for the sake of simplicity + remoteCache.put("user_" + user1.getId(), user1); + remoteCache.put("user_" + user2.getId(), user2); + remoteCache.put("user_" + user3.getId(), user3); + remoteCache.put("account_" + account1.getId(), account1); + remoteCache.put("account_" + account2.getId(), account2); + remoteCache.put("account_" + account3.getId(), account3); + remoteCache.put("transaction_" + transaction0.getId(), transaction0); + remoteCache.put("transaction_" + transaction1.getId(), transaction1); + remoteCache.put("transaction_" + transaction2.getId(), transaction2); + remoteCache.put("transaction_" + transaction3.getId(), transaction3); + remoteCache.put("transaction_" + transaction4.getId(), transaction4); + remoteCache.put("transaction_" + transaction5.getId(), transaction5); + + SearchFactoryImplementor searchFactory = (SearchFactoryImplementor) org.infinispan.query.Search.getSearchManager(cache).getSearchFactory(); + Collection indexManagers = searchFactory.getIndexManagerHolder().getIndexManagers(); + + for(IndexManager manager : indexManagers) { + assertNotNull(manager); + assertTrue(manager.getIndexName().contains(ProtobufValueWrapper.class.getName())); + } + } + + public void testEq1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("name").eq("John") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals("John", list.get(0).getName()); + assertEquals("Doe", list.get(0).getSurname()); + } + + public void testEq() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("name").eq("Jacob") + .toBuilder().build(); + + List list = q.list(); + assertEquals(0, list.size()); + } + + public void testEqInNested1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all users in a given post code + Query q = qf.from(User.class) + .having("addresses.postCode").eq("X1234") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals("X1234", list.get(0).getAddresses().get(0).getPostCode()); + } + + public void testEqInNested2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("addresses.postCode").eq("Y12") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(2, list.get(0).getAddresses().size()); + } + + public void testLike() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all rent payments made from a given account + Query q = qf.from(Transaction.class) + .having("description").like("%rent%") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(1, list.get(0).getAccountId()); + assertEquals(1500, list.get(0).getAmount(), 0); + } + + public void testBetween1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all the transactions that happened in January 2013 + Query q = qf.from(Transaction.class) + .having("date").between(DATE_FORMAT.parse("2013-01-01").getTime(), DATE_FORMAT.parse("2013-01-31").getTime()) + .toBuilder().build(); + + List list = q.list(); + assertEquals(4, list.size()); + for (Transaction t : list) { + assertTrue(t.getDate() <= DATE_FORMAT.parse("2013-01-31").getTime()); + assertTrue(t.getDate() >= DATE_FORMAT.parse("2013-01-01").getTime()); + } + } + + public void testBetween2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all the transactions that happened in January 2013 + Query q = qf.from(Transaction.class) + .having("date").between(DATE_FORMAT.parse("2013-01-01").getTime(), DATE_FORMAT.parse("2013-01-31").getTime()).includeUpper(false) + .toBuilder().build(); + + List list = q.list(); + assertEquals(3, list.size()); + for (Transaction t : list) { + assertTrue(t.getDate() < DATE_FORMAT.parse("2013-01-31").getTime()); + assertTrue(t.getDate() >= DATE_FORMAT.parse("2013-01-01").getTime()); + } + } + + public void testBetween3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all the transactions that happened in January 2013 + Query q = qf.from(Transaction.class) + .having("date").between(DATE_FORMAT.parse("2013-01-01").getTime(), DATE_FORMAT.parse("2013-01-31").getTime()).includeLower(false) + .toBuilder().build(); + + List list = q.list(); + assertEquals(3, list.size()); + for (Transaction t : list) { + assertTrue(t.getDate() <= DATE_FORMAT.parse("2013-01-31").getTime()); + assertTrue(t.getDate() > DATE_FORMAT.parse("2013-01-01").getTime()); + } + } + + public void testGt() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all the transactions greater than a given amount + Query q = qf.from(Transaction.class) + .having("amount").gt(1500) + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertTrue(list.get(0).getAmount() > 1500); + } + + public void testGte() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(Transaction.class) + .having("amount").gte(1500) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + for (Transaction t : list) { + assertTrue(t.getAmount() >= 1500); + } + } + + public void testLt() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(Transaction.class) + .having("amount").lt(1500) + .toBuilder().build(); + + List list = q.list(); + assertEquals(4, list.size()); + for (Transaction t : list) { + assertTrue(t.getAmount() < 1500); + } + } + + public void testLte() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(Transaction.class) + .having("amount").lte(1500) + .toBuilder().build(); + + List list = q.list(); + assertEquals(5, list.size()); + for (Transaction t : list) { + assertTrue(t.getAmount() <= 1500); + } + } + + public void testAnd1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("name").eq("Spider") + .and().having("surname").eq("Man") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(2, list.get(0).getId()); + } + + public void testAnd2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("name").eq("Spider") + .and(qf.having("surname").eq("Man")) + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(2, list.get(0).getId()); + } + + public void testAnd3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("gender").eq(User.Gender.MALE) + .and().having("gender").eq(User.Gender.FEMALE) + .toBuilder().build(); + + List list = q.list(); + assertEquals(0, list.size()); + } + + public void testAnd4() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + //test for parenthesis, "and" should have higher priority + Query q = qf.from(User.class) + .having("name").eq("Spider") + .or(qf.having("name").eq("John")) + .and(qf.having("surname").eq("Man")) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + } + + public void testOr1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("surname").eq("Man") + .or().having("surname").eq("Woman") + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + for (User u : list) { + assertEquals("Spider", u.getName()); + } + } + + public void testOr2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("surname").eq("Man") + .or(qf.having("surname").eq("Woman")) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + for (User u : list) { + assertEquals("Spider", u.getName()); + } + } + + public void testOr3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("gender").eq(User.Gender.MALE) + .or().having("gender").eq(User.Gender.FEMALE) + .toBuilder().build(); + + List list = q.list(); + assertEquals(3, list.size()); + } + + public void testNot1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().having("name").eq("Spider") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals("John", list.get(0).getName()); + } + + public void testNot2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().not().having("surname").eq("Doe") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals("John", list.get(0).getName()); + } + + public void testNot3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // NOT should have higher priority than AND + Query q = qf.from(User.class) + .not().having("name").eq("John") + .and().having("surname").eq("Man") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals("Spider", list.get(0).getName()); + } + + public void testNot4() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // NOT should have higher priority than AND + Query q = qf.from(User.class) + .having("surname").eq("Man") + .and().not().having("name").eq("John") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals("Spider", list.get(0).getName()); + } + + public void testNot5() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // NOT should have higher priority than OR + Query q = qf.from(User.class) + .not().having("name").eq("Spider") + .or().having("surname").eq("Man") + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + for (User u : list) { + assertFalse("Woman".equals(u.getSurname())); + } + } + + public void testNot6() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // QueryFactory.not() test + Query q = qf.from(User.class) + .not(qf.not(qf.having("gender").eq(User.Gender.FEMALE))) + .toBuilder() + .build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertTrue(list.get(0).getSurname().equals("Woman")); + } + + public void testNot7() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("gender").eq(User.Gender.FEMALE) + .and().not(qf.having("name").eq("Spider")) + .toBuilder().build(); + + List list = q.list(); + assertTrue(list.isEmpty()); + } + + public void testEmptyQuery() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class).build(); + + List list = q.list(); + assertEquals(3, list.size()); + } + + public void testIsNull() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("addresses").isNull() + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(3, list.get(0).getId()); + } + + public void testContains1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("accountIds").contains(2) + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(1, list.get(0).getId()); + } + + public void testContains2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("accountIds").contains(42) + .toBuilder().build(); + + List list = q.list(); + assertEquals(0, list.size()); + } + + public void testContainsAll1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("accountIds").containsAll(1, 2) + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(1, list.get(0).getId()); + } + + public void testContainsAll2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("accountIds").containsAll(Collections.singleton(1)) + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(1, list.get(0).getId()); + } + + public void testContainsAll3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("accountIds").containsAll(1, 2, 3) + .toBuilder().build(); + + List list = q.list(); + assertEquals(0, list.size()); + } + + public void testContainsAll4() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("accountIds").containsAll(Collections.emptySet()) + .toBuilder().build(); + + List list = q.list(); + assertEquals(3, list.size()); + } + + public void testContainsAny1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .orderBy("id", SortOrder.ASC) + .having("accountIds").containsAny(2, 3) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertEquals(1, list.get(0).getId()); + assertEquals(2, list.get(1).getId()); + } + + public void testContainsAny2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("accountIds").containsAny(4, 5) + .toBuilder().build(); + + List list = q.list(); + assertEquals(0, list.size()); + } + + public void testContainsAny3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("accountIds").containsAny(Collections.emptySet()) + .toBuilder().build(); + + List list = q.list(); + assertEquals(3, list.size()); + } + + public void testIn1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + List ids = Arrays.asList(1, 3); + Query q = qf.from(User.class) + .having("id").in(ids) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + for (User u : list) { + assertTrue(ids.contains(u.getId())); + } + } + + public void testIn2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("id").in(4) + .toBuilder().build(); + + List list = q.list(); + assertEquals(0, list.size()); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testIn3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + qf.from(User.class).having("id").in(Collections.emptySet()); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testIn4() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Collection collection = null; + qf.from(User.class).having("id").in(collection); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testIn5() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Object[] array = null; + qf.from(User.class).having("id").in(array); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testIn6() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Object[] array = new Object[0]; + qf.from(User.class).having("id").in(array); + } + + public void testSampleDomainQuery1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all male users + Query q = qf.from(User.class) + .having("gender").eq(User.Gender.MALE) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertEquals("John", list.get(0).getName()); + assertEquals("Spider", list.get(1).getName()); + } + + public void testSampleDomainQuery2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all male users, but this time retrieved in a twisted manner + Query q = qf.from(User.class) + .not(qf.having("gender").eq(User.Gender.FEMALE)) + .and(qf.not().not(qf.having("gender").eq(User.Gender.MALE))) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertEquals("John", list.get(0).getName()); + assertEquals("Spider", list.get(1).getName()); + } + + @Test(enabled = false, description = "String literal escaping is not properly done yet, see ISPN-4045") //todo [anistor] fix disabled test + public void testStringEscape() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all transactions that have a given description. the description contains characters that need to be escaped. + Query q = qf.from(Account.class) + .having("description").eq("John Doe's first bank account") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(2, list.get(0).getId()); + } + + public void testSampleDomainQuery3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all male users + Query q = qf.from(User.class) + .having("gender").eq(User.Gender.MALE) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertEquals("John", list.get(0).getName()); + assertEquals("Spider", list.get(1).getName()); + } + + public void testSampleDomainQuery4() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all users ordered descendingly by name + Query q = qf.from(User.class) + .orderBy("name", SortOrder.DESC) + .build(); + + List list = q.list(); + assertEquals(3, list.size()); + assertEquals("Spider", list.get(0).getName()); + assertEquals("Spider", list.get(1).getName()); + assertEquals("John", list.get(2).getName()); + } + + public void testSampleDomainQuery5() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // name projection of all users ordered descendingly by name + Query q = qf.from(User.class) + .orderBy("name", SortOrder.DESC) + .setProjection("name") + .build(); + + List list = q.list(); + assertEquals(3, list.size()); + assertEquals(1, list.get(0).length); + assertEquals(1, list.get(1).length); + assertEquals(1, list.get(2).length); + assertEquals("Spider", list.get(0)[0]); + assertEquals("Spider", list.get(1)[0]); + assertEquals("John", list.get(2)[0]); + } + + public void testSampleDomainQuery6() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all users with a given name and surname + Query q = qf.from(User.class) + .having("name").eq("John") + .and().having("surname").eq("Doe") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals("John", list.get(0).getName()); + assertEquals("Doe", list.get(0).getSurname()); + } + + public void testSampleDomainQuery7() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all rent payments made from a given account + Query q = qf.from(Transaction.class) + .having("accountId").eq(1) + .and().having("description").like("%rent%") + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(1, list.get(0).getId()); + assertEquals(1, list.get(0).getAccountId()); + assertTrue(list.get(0).getDescription().contains("rent")); + } + + public void testSampleDomainQuery8() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all the transactions that happened in January 2013 + Query q = qf.from(Transaction.class) + .orderBy("date", SortOrder.ASC) + .having("date").between(DATE_FORMAT.parse("2013-01-01").getTime(), DATE_FORMAT.parse("2013-01-31").getTime()) + .toBuilder().build(); + + List list = q.list(); + assertEquals(4, list.size()); + + assertTrue(list.get(0).getDate() == DATE_FORMAT.parse("2013-01-01").getTime()); + assertTrue(list.get(1).getDate() > DATE_FORMAT.parse("2013-01-01").getTime()); + assertTrue(list.get(1).getDate() < DATE_FORMAT.parse("2013-01-31").getTime()); + assertTrue(list.get(2).getDate() < DATE_FORMAT.parse("2013-01-31").getTime()); + assertTrue(list.get(2).getDate() > DATE_FORMAT.parse("2013-01-01").getTime()); + assertTrue(list.get(3).getDate() == DATE_FORMAT.parse("2013-01-31").getTime()); + } + + public void testSampleDomainQuery9() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all the transactions that happened in January 2013, projected by date field only + Query q = qf.from(Transaction.class) + .setProjection("date") + .having("date").between(DATE_FORMAT.parse("2013-01-01").getTime(), DATE_FORMAT.parse("2013-01-31").getTime()) + .toBuilder().build(); + + List list = q.list(); + assertEquals(4, list.size()); + assertEquals(1, list.get(0).length); + assertEquals(1, list.get(1).length); + assertEquals(1, list.get(2).length); + assertEquals(1, list.get(3).length); + + for (int i = 0; i < 4; i++) { + Long d = (Long) list.get(i)[0]; + assertTrue(d <= DATE_FORMAT.parse("2013-01-31").getTime()); + assertTrue(d >= DATE_FORMAT.parse("2013-01-01").getTime()); + } + } + + public void testSampleDomainQuery10() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all the transactions for a an account having amount greater than a given amount + Query q = qf.from(Transaction.class) + .having("accountId").eq(2) + .and().having("amount").gt(40) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertTrue(list.get(0).getAmount() > 40); + assertTrue(list.get(1).getAmount() > 40); + } + + public void testSampleDomainQuery11() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("name").eq("John") + .and().having("addresses.postCode").eq("X1234") + .and(qf.having("accountIds").eq(1)) + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals("Doe", list.get(0).getSurname()); + } + + public void testSampleDomainQuery12() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all the transactions that represents credits to the account + Query q = qf.from(Transaction.class) + .having("accountId").eq(1) + .and() + .not().having("isDebit").eq(true).toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertFalse(list.get(0).isDebit()); + } + + public void testSampleDomainQuery13() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // the user that has the bank account with id 3 + Query q = qf.from(User.class) + .having("accountIds").contains(3).toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(2, list.get(0).getId()); + assertTrue(list.get(0).getAccountIds().contains(3)); + } + + public void testSampleDomainQuery14() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // the user that has all the specified bank accounts + Query q = qf.from(User.class) + .having("accountIds").containsAll(2, 1).toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(1, list.get(0).getId()); + assertTrue(list.get(0).getAccountIds().contains(1)); + assertTrue(list.get(0).getAccountIds().contains(2)); + } + + public void testSampleDomainQuery15() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // the user that has at least one of the specified accounts + Query q = qf.from(User.class) + .having("accountIds").containsAny(1, 3).toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertTrue(Arrays.asList(1, 2).contains(list.get(0).getId())); + assertTrue(Arrays.asList(1, 2).contains(list.get(1).getId())); + } + + public void testSampleDomainQuery16() throws Exception { + for (int i = 0; i < 50; i++) { + Transaction transaction = new Transaction(); + transaction.setId(50 + i); + transaction.setDescription("Expensive shoes " + i); + transaction.setAccountId(2); + transaction.setAmount(100 + i); + transaction.setDate(DATE_FORMAT.parse("2013-08-20")); + transaction.setDebit(true); + remoteCache.put("transaction_" + transaction.getId(), transaction); + } + + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // third batch of 10 transactions for a given account + Query q = qf.from(Transaction.class) + .startOffset(20).maxResults(10) + .orderBy("id", SortOrder.ASC) + .having("accountId").eq(2).and().having("description").like("Expensive%") + .toBuilder().build(); + + List list = q.list(); + assertEquals(50, q.getResultSize()); + assertEquals(10, list.size()); + for (int i = 0; i < 10; i++) { + assertEquals("Expensive shoes " + (20 + i), list.get(i).getDescription()); + } + } + + public void testSampleDomainQuery17() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all accounts for a user. first get the user by id and then get his account. + Query q1 = qf.from(User.class) + .having("id").eq(1).toBuilder().build(); + + List users = q1.list(); + Query q2 = qf.from(Account.class) + .orderBy("description", SortOrder.ASC) + .having("id").in(users.get(0).getAccountIds()).toBuilder().build(); + + List list = q2.list(); + assertEquals(2, list.size()); + assertEquals("John Doe's first bank account", list.get(0).getDescription()); + assertEquals("John Doe's second bank account", list.get(1).getDescription()); + } + + public void testSampleDomainQuery18() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + // all transactions of account with id 2 which have an amount larger than 1600 or their description contains the word 'rent' + Query q = qf.from(Transaction.class) + .having("accountId").eq(1) + .and(qf.having("amount").gt(1600) + .or().having("description").like("%rent%")).toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertEquals("Birthday present", list.get(0).getDescription()); + assertEquals("Feb. rent payment", list.get(1).getDescription()); + } + + public void testProjectionOnOptionalField() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .setProjection("id", "addresses.postCode") + .orderBy("id", SortOrder.ASC) + .build(); + + List list = q.list(); + assertEquals(3, list.size()); + assertEquals(1, list.get(0)[0]); + assertEquals("X1234", list.get(0)[1]); + assertEquals(2, list.get(1)[0]); + assertEquals("Y12", list.get(1)[1]); + assertEquals(3, list.get(2)[0]); + assertNull(list.get(2)[1]); + } + + @Test(enabled = false, description = "Nulls not correctly indexed for numeric properties, see ISPN-4046") //todo [anistor] fix disabled test + public void testNullOnIntegerField() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("age").isNull() + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + } + + public void testSampleDomainQuery19() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("addresses.postCode").in("X1234", "ZZ").toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertTrue(Arrays.asList(1, 2).contains(list.get(0).getId())); + assertTrue(Arrays.asList(1, 2).contains(list.get(1).getId())); + } + + public void testSampleDomainQuery20() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().having("addresses.postCode").in("X1234").toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertTrue(Arrays.asList(2, 3).contains(list.get(0).getId())); + assertTrue(Arrays.asList(2, 3).contains(list.get(1).getId())); + } + + public void testSampleDomainQuery21() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().having("addresses").isNull().toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertTrue(Arrays.asList(1, 2).contains(list.get(0).getId())); + assertTrue(Arrays.asList(1, 2).contains(list.get(1).getId())); + } + + public void testSampleDomainQuery22() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().having("addresses.postCode").like("%123%").toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertTrue(Arrays.asList(2, 3).contains(list.get(0).getId())); + assertTrue(Arrays.asList(2, 3).contains(list.get(1).getId())); + } + + public void testSampleDomainQuery23() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().having("id").between(1, 2) + .toBuilder().build(); + + List list = q.list(); + assertEquals(1, list.size()); + assertEquals(3, list.get(0).getId()); + } + + public void testSampleDomainQuery24() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().having("id").between(1, 2).includeLower(false) + .toBuilder().build(); + + List list = q.list(); + + assertEquals(2, list.size()); + assertTrue(Arrays.asList(1, 3).contains(list.get(0).getId())); + assertTrue(Arrays.asList(1, 3).contains(list.get(1).getId())); + } + + public void testSampleDomainQuery25() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().having("id").between(1, 2).includeUpper(false) + .toBuilder().build(); + + List list = q.list(); + assertEquals(2, list.size()); + assertTrue(Arrays.asList(2, 3).contains(list.get(0).getId())); + assertTrue(Arrays.asList(2, 3).contains(list.get(1).getId())); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testWrongQueryBuilding1() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.not().having("name").eq("John").toBuilder().build(); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testWrongQueryBuilding2() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("name").eq("John").toBuilder() + .having("surname").eq("Man").toBuilder() + .build(); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testWrongQueryBuilding3() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not().having("name").eq("John").toBuilder() + .not().having("surname").eq("Man").toBuilder() + .build(); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testWrongQueryBuilding4() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not(qf.having("name").eq("John")).toBuilder() + .not(qf.having("surname").eq("Man")).toBuilder() + .build(); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testWrongQueryBuilding5() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .not(qf.having("name").eq("John")).toBuilder() + .not(qf.having("surname").eq("Man")).toBuilder() + .build(); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testWrongQueryBuilding6() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .having("gender").eq(null) + .toBuilder().build(); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testWrongQueryBuilding7() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + FilterConditionEndContext q1 = qf.from(User.class) + .having("gender"); + + q1.eq(User.Gender.MALE); + q1.eq(User.Gender.FEMALE); + } + + public void testDefaultValue() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(Account.class).orderBy("description", SortOrder.ASC).build(); + + List list = q.list(); + assertEquals(3, list.size()); + assertEquals("Checking account", list.get(0).getDescription()); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslIterationTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslIterationTest.java new file mode 100644 index 000000000000..83465f239b2e --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryDslIterationTest.java @@ -0,0 +1,206 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.Search; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.User; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.dsl.Query; +import org.infinispan.query.dsl.QueryFactory; +import org.infinispan.query.dsl.SortOrder; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.AssertJUnit.*; + +/** + * Test for orderBy, max results, start offset and projections. + * + * @author rvansa@redhat.com + * @author anistor@redhat.com + * @since 7.0 + */ +@Test(groups = "functional", testName = "client.hotrod.query.RemoteQueryDslIterationTest") +public class RemoteQueryDslIterationTest extends SingleCacheManagerTest { + + protected HotRodServer hotRodServer; + protected RemoteCacheManager remoteCacheManager; + protected RemoteCache remoteCache; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + ConfigurationBuilder builder = getConfigurationBuilder(); + + cacheManager = TestCacheManagerFactory.createCacheManager(builder); + cache = cacheManager.getCache(); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); + clientBuilder.addServer().host("127.0.0.1").port(hotRodServer.getPort()); + clientBuilder.marshaller(new ProtoStreamMarshaller()); + remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); + remoteCache = remoteCacheManager.getCache(); + + //initialize server-side serialization context + cacheManager.getGlobalComponentRegistry().getComponent(ProtobufMetadataManager.class).registerProtofile("/sample_bank_account/bank.protobin"); + + //initialize client-side serialization context + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(remoteCacheManager)); + + return cacheManager; + } + + protected ConfigurationBuilder getConfigurationBuilder() { + ConfigurationBuilder builder = hotRodCacheConfiguration(); + builder.indexing().enable() + .addProperty("default.directory_provider", getLuceneDirectoryProvider()) + .addProperty("lucene_version", "LUCENE_CURRENT"); + + return builder; + } + + protected String getLuceneDirectoryProvider() { + return "ram"; + } + + @AfterTest + public void release() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer); + } + + @BeforeMethod(alwaysRun = true) + protected void populateCache() throws Exception { + User user1 = new User(); + user1.setId(1); + user1.setName("John"); + user1.setSurname("White"); + + User user2 = new User(); + user2.setId(2); + user2.setName("Jack"); + user2.setSurname("Black"); + + User user3 = new User(); + user3.setId(3); + user3.setName("John"); + user3.setSurname("Brown"); + + User user4 = new User(); + user4.setId(4); + user4.setName("Michael"); + user4.setSurname("Black"); + + remoteCache.put("user_" + user1.getId(), user1); + remoteCache.put("user_" + user2.getId(), user2); + remoteCache.put("user_" + user3.getId(), user3); + remoteCache.put("user_" + user4.getId(), user4); + } + + public void testOrderByAsc() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .orderBy("name", SortOrder.ASC).build(); + + assertEquals(4, q.getResultSize()); + + List list = q.list(); + assertEquals(4, list.size()); + checkNameOrder(list, true); + } + + public void testOrderByDesc() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .orderBy("surname", SortOrder.DESC).build(); + + assertEquals(4, q.getResultSize()); + + List list = q.list(); + assertEquals(4, list.size()); + checkSurnameOrder(list, false); + } + + public void testMaxResults() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .orderBy("name", SortOrder.ASC).maxResults(2).build(); + + assertEquals(4, q.getResultSize()); + + List list = q.list(); + assertEquals(2, list.size()); + checkNameOrder(list, true); + } + + public void testStartOffset() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .orderBy("name", SortOrder.ASC).startOffset(2).build(); + + assertEquals(4, q.getResultSize()); + + List list = q.list(); + assertEquals(2, list.size()); + checkNameOrder(list, true); + } + + public void testProjection() throws Exception { + QueryFactory qf = Search.getQueryFactory(remoteCache); + + Query q = qf.from(User.class) + .setProjection("id", "name").maxResults(3).build(); + + assertEquals(4, q.getResultSize()); + + List list = q.list(); + assertEquals(3, list.size()); + for (Object[] u : list) { + assertNotNull(u[1]); + assertTrue(u[0] instanceof Integer); + } + } + + private void checkNameOrder(List list, boolean isAsc) { + String prevName = null; + for (User u : list) { + assertNotNull(u.getName()); + if (prevName != null) { + int comp = u.getName().compareTo(prevName); + assertTrue(isAsc ? comp >= 0 : comp <= 0); + } + prevName = u.getName(); + } + } + + private void checkSurnameOrder(List list, boolean isAsc) { + String prevSurname = null; + for (User u : list) { + assertNotNull(u.getSurname()); + if (prevSurname != null) { + int comp = u.getSurname().compareTo(prevSurname); + assertTrue(isAsc ? comp >= 0 : comp <= 0); + } + prevSurname = u.getSurname(); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryJmxTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryJmxTest.java new file mode 100644 index 000000000000..ec2735988684 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/query/RemoteQueryJmxTest.java @@ -0,0 +1,196 @@ +package org.infinispan.client.hotrod.query; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.Search; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller; +import org.infinispan.commons.CacheException; +import org.infinispan.commons.equivalence.ByteArrayEquivalence; +import org.infinispan.commons.util.Util; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.configuration.global.GlobalConfigurationBuilder; +import org.infinispan.jmx.PerThreadMBeanServerLookup; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.protostream.sampledomain.Address; +import org.infinispan.protostream.sampledomain.User; +import org.infinispan.protostream.sampledomain.marshallers.MarshallerRegistration; +import org.infinispan.query.dsl.Query; +import org.infinispan.query.dsl.QueryFactory; +import org.infinispan.query.remote.ProtobufMetadataManager; +import org.infinispan.query.remote.ProtobufMetadataManagerMBean; +import org.infinispan.query.remote.indexing.ProtobufValueWrapper; +import org.infinispan.test.SingleCacheManagerTest; +import org.infinispan.test.fwk.CleanupAfterMethod; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterTest; +import org.testng.annotations.Test; +import org.infinispan.server.hotrod.HotRodServer; + +import javax.management.Attribute; +import javax.management.JMX; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killRemoteCacheManager; +import static org.infinispan.client.hotrod.test.HotRodClientTestingUtil.killServers; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Testing the functionality of JMX operations for the Remote Queries. + * + * @author Anna Manukyan + */ +@Test(testName = "client.hotrod.query.RemoteQueryJmxTest", groups = "functional") +@CleanupAfterMethod +public class RemoteQueryJmxTest extends SingleCacheManagerTest { + public static final String JMX_DOMAIN = ProtobufMetadataManager.class.getSimpleName(); + + public static final String TEST_CACHE_NAME = "userCache"; + + private HotRodServer hotRodServer; + private RemoteCacheManager remoteCacheManager; + private RemoteCache remoteCache; + private MBeanServer server = null; + + @Override + protected EmbeddedCacheManager createCacheManager() throws Exception { + GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder().nonClusteredDefault(); + gcb.globalJmxStatistics() + .enable() + .allowDuplicateDomains(true) + .jmxDomain(JMX_DOMAIN) + .mBeanServerLookup(new PerThreadMBeanServerLookup()); + + ConfigurationBuilder builder = new ConfigurationBuilder(); + builder.dataContainer() + .keyEquivalence(ByteArrayEquivalence.INSTANCE) + .valueEquivalence(ByteArrayEquivalence.INSTANCE) + .indexing().enable() + .indexLocalOnly(false) + .addProperty("default.directory_provider", getLuceneDirectoryProvider()) + .addProperty("lucene_version", "LUCENE_CURRENT"); + + cacheManager = TestCacheManagerFactory.createCacheManager(gcb, builder, true); + cacheManager.defineConfiguration(TEST_CACHE_NAME, builder.build()); + cache = cacheManager.getCache(TEST_CACHE_NAME); + + hotRodServer = TestHelper.startHotRodServer(cacheManager); + + org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); + clientBuilder.addServer().host("127.0.0.1").port(hotRodServer.getPort()); + clientBuilder.marshaller(new ProtoStreamMarshaller()); + remoteCacheManager = new RemoteCacheManager(clientBuilder.build()); + + remoteCache = remoteCacheManager.getCache(TEST_CACHE_NAME); + + ObjectName objName = new ObjectName(JMX_DOMAIN + ":type=RemoteQuery,name=" + + ObjectName.quote("DefaultCacheManager") + + ",component=" + ProtobufMetadataManager.OBJECT_NAME); + + byte[] descriptor = readClasspathResource("/sample_bank_account/bank.protobin"); + MBeanServer mBeanServer = PerThreadMBeanServerLookup.getThreadMBeanServer(); + ProtobufMetadataManagerMBean protobufMetadataManagerMBean = JMX.newMBeanProxy(mBeanServer, objName, ProtobufMetadataManagerMBean.class); + protobufMetadataManagerMBean.registerProtofile(descriptor); + + //initialize client-side serialization context + MarshallerRegistration.registerMarshallers(ProtoStreamMarshaller.getSerializationContext(remoteCacheManager)); + server = PerThreadMBeanServerLookup.getThreadMBeanServer(); + + return cacheManager; + } + + private byte[] readClasspathResource(String classPathResource) throws IOException { + InputStream is = getClass().getResourceAsStream(classPathResource); + try { + return Util.readStream(is); + } finally { + if (is != null) { + is.close(); + } + } + } + + protected String getLuceneDirectoryProvider() { + return "ram"; + } + + @AfterTest + public void release() { + killRemoteCacheManager(remoteCacheManager); + killServers(hotRodServer); + } + + public void testQueryStatsMBean() throws Exception { + ObjectName name = getQueryStatsObjectName(JMX_DOMAIN, TEST_CACHE_NAME); + assertTrue(server.isRegistered(name)); + assertFalse((Boolean) server.getAttribute(name, "StatisticsEnabled")); + server.setAttribute(name, new Attribute("StatisticsEnabled", true)); + assertTrue((Boolean) server.getAttribute(name, "StatisticsEnabled")); + } + + public void testEmbeddedAttributeQuery() throws Exception { + ObjectName name = getQueryStatsObjectName(JMX_DOMAIN, TEST_CACHE_NAME); + + log.tracef("StatisticsEnabled=%s", server.getAttribute(name, "StatisticsEnabled")); + + server.setAttribute(name, new Attribute("StatisticsEnabled", true)); + + remoteCache.put(1, createUser(1)); + remoteCache.put(2, createUser(2)); + + // get user back from remote cache via query and check its attributes + QueryFactory qf = Search.getQueryFactory(remoteCache); + Query query = qf.from(User.class) + .having("addresses.postCode").eq("1231").toBuilder() + .build(); + List list = query.list(); + assertNotNull(list); + assertEquals(1, list.size()); + assertEquals(User.class, list.get(0).getClass()); + assertEquals("Tom1", list.get(0).getName()); + + assertEquals(2, server.invoke(name, "getNumberOfIndexedEntities", + new Object[]{ProtobufValueWrapper.class.getCanonicalName()}, + new String[]{String.class.getCanonicalName()})); + + Set classNames = (Set) server.getAttribute(name, "IndexedClassNames"); + assertEquals(1, classNames.size()); + assertTrue("The set should contain the ProtobufValueWrapper class name.", classNames.contains(ProtobufValueWrapper.class.getCanonicalName())); + assertTrue("The query execution total time should be > 0.", (Long) server.getAttribute(name, "SearchQueryTotalTime") > 0); + assertEquals((long) 1, server.getAttribute(name, "SearchQueryExecutionCount")); + } + + private User createUser(int id) { + User user = new User(); + user.setId(id); + user.setName("Tom" + id); + user.setSurname("Cat" + id); + user.setGender(User.Gender.MALE); + user.setAccountIds(Collections.singletonList(12)); + Address address = new Address(); + address.setStreet("Dark Alley"); + address.setPostCode("123" + id); + user.setAddresses(Collections.singletonList(address)); + return user; + } + + private ObjectName getQueryStatsObjectName(String jmxDomain, String cacheName) { + String cacheManagerName = cacheManager.getCacheManagerConfiguration().globalJmxStatistics().cacheManagerName(); + try { + return new ObjectName(jmxDomain + ":type=Query,manager=" + ObjectName.quote(cacheManagerName) + + ",cache=" + ObjectName.quote(cacheName) + ",component=Statistics"); + } catch (MalformedObjectNameException e) { + throw new CacheException("Malformed object name", e); + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/AbstractRetryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/AbstractRetryTest.java new file mode 100644 index 000000000000..426b56d4f693 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/AbstractRetryTest.java @@ -0,0 +1,109 @@ +package org.infinispan.client.hotrod.retry; + +import org.infinispan.client.hotrod.HitsAwareCacheManagersTest; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.client.hotrod.impl.RemoteCacheImpl; +import org.infinispan.client.hotrod.impl.transport.tcp.RoundRobinBalancingStrategy; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.TestingUtil; +import org.infinispan.test.fwk.TestCacheManagerFactory; +import org.testng.annotations.AfterMethod; + +import java.util.Properties; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +public abstract class AbstractRetryTest extends HitsAwareCacheManagersTest { + + protected HotRodServer hotRodServer1; + protected HotRodServer hotRodServer2; + protected HotRodServer hotRodServer3; + + RemoteCacheImpl remoteCache; + protected RemoteCacheManager remoteCacheManager; + protected TcpTransportFactory tcpConnectionFactory; + protected ConfigurationBuilder config; + protected RoundRobinBalancingStrategy strategy; + + public AbstractRetryTest() { + cleanup = CleanupPhase.AFTER_METHOD; + } + + @Override + protected void assertSupportedConfig() { + } + + @Override + protected void createCacheManagers() throws Throwable { + assert cleanupAfterMethod(); + + config = hotRodCacheConfiguration(getCacheConfig()); + EmbeddedCacheManager cm1 = TestCacheManagerFactory.createClusteredCacheManager(config); + EmbeddedCacheManager cm2 = TestCacheManagerFactory.createClusteredCacheManager(config); + EmbeddedCacheManager cm3 = TestCacheManagerFactory.createClusteredCacheManager(config); + registerCacheManager(cm1); + registerCacheManager(cm2); + registerCacheManager(cm3); + + hotRodServer1 = TestHelper.startHotRodServer(manager(0)); + hrServ2CacheManager.put(getAddress(hotRodServer1), cm1); + hotRodServer2 = TestHelper.startHotRodServer(manager(1)); + hrServ2CacheManager.put(getAddress(hotRodServer2), cm2); + hotRodServer3 = TestHelper.startHotRodServer(manager(2)); + hrServ2CacheManager.put(getAddress(hotRodServer3), cm3); + + waitForClusterToForm(); + + Properties clientConfig = new Properties(); + clientConfig.put("infinispan.client.hotrod.server_list", "localhost:" + hotRodServer2.getPort()); + clientConfig.put("infinispan.client.hotrod.force_return_values", "true"); + clientConfig.put("infinispan.client.hotrod.connect_timeout", "5"); + clientConfig.put("maxActive",1); //this ensures that only one server is active at a time + + remoteCacheManager = new RemoteCacheManager(clientConfig); + remoteCache = (RemoteCacheImpl) remoteCacheManager.getCache(); + tcpConnectionFactory = (TcpTransportFactory) TestingUtil.extractField(remoteCacheManager, "transportFactory"); + strategy = (RoundRobinBalancingStrategy) tcpConnectionFactory.getBalancer(); + addInterceptors(); + + assert super.cacheManagers.size() == 3; + } + + @AfterMethod(alwaysRun = true) + @Override + protected void clearContent() throws Throwable { + // Since cleanup happens after method, + // make sure the rest of components are also cleaned up. + try { + if (remoteCache != null) remoteCache.stop(); + } finally { + try { + if (remoteCacheManager != null) remoteCacheManager.stop(); + } finally { + try { + if (hotRodServer1 != null) hotRodServer1.stop(); + } finally { + try { + if (hotRodServer2 != null) hotRodServer2.stop(); + } finally { + try { + if (hotRodServer3 != null) hotRodServer3.stop(); + } finally { + super.clearContent(); // Now stop the cache managers + } + } + } + } + } + } + + protected abstract ConfigurationBuilder getCacheConfig(); +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/DistributionRetryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/DistributionRetryTest.java new file mode 100644 index 000000000000..89dd3f0940b7 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/DistributionRetryTest.java @@ -0,0 +1,159 @@ +package org.infinispan.client.hotrod.retry; + +import org.infinispan.Cache; +import org.infinispan.affinity.KeyAffinityService; +import org.infinispan.affinity.KeyAffinityServiceFactory; +import org.infinispan.affinity.KeyGenerator; +import org.infinispan.client.hotrod.VersionedValue; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransport; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.commons.marshall.Marshaller; +import org.infinispan.marshall.core.JBossMarshaller; +import org.infinispan.remoting.transport.Address; +import org.infinispan.test.TestingUtil; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.testng.Assert.assertEquals; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test(testName = "client.hotrod.retry.DistributionRetryTest", groups = "functional") +public class DistributionRetryTest extends AbstractRetryTest { + + @Override + protected ConfigurationBuilder getCacheConfig() { + ConfigurationBuilder builder = hotRodCacheConfiguration( + getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false)); + builder.clustering().hash().numOwners(1); + return builder; + } + + public void testGet() throws Exception { + log.info("Starting actual test"); + Object key = generateKeyAndShutdownServer(); + //now make sure that next call won't fail + resetStats(); + assertEquals(remoteCache.get(key), "v"); + } + + public void testPut() throws Exception { + Object key = generateKeyAndShutdownServer(); + log.info("Here it starts"); + assertEquals(remoteCache.put(key, "v0"), "v"); + } + + public void testRemove() throws Exception { + Object key = generateKeyAndShutdownServer(); + assertEquals("v", remoteCache.remove(key)); + } + + public void testContains() throws Exception { + Object key = generateKeyAndShutdownServer(); + resetStats(); + assertEquals(true, remoteCache.containsKey(key)); + } + + public void testGetWithVersion() throws Exception { + Object key = generateKeyAndShutdownServer(); + resetStats(); + VersionedValue value = remoteCache.getVersioned(key); + assertEquals("v", value.getValue()); + } + + public void testPutIfAbsent() throws Exception { + Object key = generateKeyAndShutdownServer(); + assertEquals(null, remoteCache.putIfAbsent("noSuchKey", "someValue")); + assertEquals("someValue", remoteCache.get("noSuchKey")); + } + + public void testReplace() throws Exception { + Object key = generateKeyAndShutdownServer(); + assertEquals("v", remoteCache.replace(key, "v2")); + } + + public void testReplaceIfUnmodified() throws Exception { + Object key = generateKeyAndShutdownServer(); + assertEquals(false, remoteCache.replaceWithVersion(key, "v2", 12)); + } + + public void testRemoveIfUnmodified() throws Exception { + Object key = generateKeyAndShutdownServer(); + resetStats(); + assertEquals(false, remoteCache.removeWithVersion(key, 12)); + } + + public void testClear() throws Exception { + Object key = generateKeyAndShutdownServer(); + resetStats(); + remoteCache.clear(); + assertEquals(false, remoteCache.containsKey(key)); + } + + private Object generateKeyAndShutdownServer() throws IOException, ClassNotFoundException, InterruptedException { + resetStats(); + Cache cache = manager(1).getCache(); + ExecutorService ex = Executors.newSingleThreadExecutor(); + KeyAffinityService kaf = KeyAffinityServiceFactory.newKeyAffinityService(cache, ex, new ByteKeyGenerator(), 2, true); + Address address = cache.getAdvancedCache().getRpcManager().getTransport().getAddress(); + byte[] keyBytes = (byte[]) kaf.getKeyForAddress(address); + String key = ByteKeyGenerator.getStringObject(keyBytes); + ex.shutdownNow(); + kaf.stop(); + + remoteCache.put(key, "v"); + assertOnlyServerHit(getAddress(hotRodServer2)); + TcpTransportFactory tcpTp = (TcpTransportFactory) TestingUtil.extractField(remoteCacheManager, "transportFactory"); + + Marshaller sm = new JBossMarshaller(); + TcpTransport transport = (TcpTransport) tcpTp.getTransport(sm.objectToByteBuffer(key, 64), null); + try { + assertEquals(transport.getServerAddress(), new InetSocketAddress("localhost", hotRodServer2.getPort())); + } finally { + tcpTp.releaseTransport(transport); + } + + + log.info("About to stop Hot Rod server 2"); + hotRodServer2.stop(); + + + return key; + } + + public static class ByteKeyGenerator implements KeyGenerator { + Random r = new Random(); + @Override + public Object getKey() { + String result = String.valueOf(r.nextLong()); + Marshaller sm = new JBossMarshaller(); + try { + return sm.objectToByteBuffer(result, 64); + } catch (IOException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public static String getStringObject(byte[] bytes) { + try { + Marshaller sm = new JBossMarshaller(); + return (String) sm.objectFromByteBuffer(bytes); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/ReplicationRetryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/ReplicationRetryTest.java new file mode 100644 index 000000000000..8691a39fb708 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/ReplicationRetryTest.java @@ -0,0 +1,141 @@ +package org.infinispan.client.hotrod.retry; + +import static org.testng.Assert.assertEquals; + +import java.net.SocketAddress; +import java.util.Iterator; +import java.util.Map; + +import org.infinispan.client.hotrod.VersionedValue; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.testng.annotations.Test; + +/** + * @author Mircea.Markus@jboss.com + * @since 4.1 + */ +@Test (testName = "client.hotrod.retry.ReplicationRetryTest", groups = "functional") +public class ReplicationRetryTest extends AbstractRetryTest { + + public void testGet() { + validateSequenceAndStopServer(); + //now make sure that next call won't fail + resetStats(); + for (int i = 0; i < 100; i++) { + assert remoteCache.get("k").equals("v"); + } + } + + public void testPut() { + + validateSequenceAndStopServer(); + resetStats(); + + assertEquals(remoteCache.put("k", "v0"), "v"); + for (int i = 1; i < 100; i++) { + assertEquals("v" + (i-1), remoteCache.put("k", "v"+i)); + } + } + + public void testRemove() { + validateSequenceAndStopServer(); + resetStats(); + + assertEquals("v", remoteCache.remove("k")); + } + + public void testContains() { + validateSequenceAndStopServer(); + resetStats(); + assertEquals(true, remoteCache.containsKey("k")); + } + + public void testGetWithVersion() { + validateSequenceAndStopServer(); + resetStats(); + VersionedValue value = remoteCache.getVersioned("k"); + assertEquals("v", value.getValue()); + } + + public void testPutIfAbsent() { + validateSequenceAndStopServer(); + resetStats(); + assertEquals(null, remoteCache.putIfAbsent("noSuchKey", "someValue")); + assertEquals("someValue", remoteCache.get("noSuchKey")); + } + + public void testReplace() { + validateSequenceAndStopServer(); + resetStats(); + assertEquals("v", remoteCache.replace("k", "v2")); + } + + public void testReplaceIfUnmodified() { + validateSequenceAndStopServer(); + resetStats(); + assertEquals(false, remoteCache.replaceWithVersion("k", "v2", 12)); + } + + public void testRemoveIfUnmodified() { + validateSequenceAndStopServer(); + resetStats(); + assertEquals(false, remoteCache.removeWithVersion("k", 12)); + } + + public void testClear() { + validateSequenceAndStopServer(); + resetStats(); + remoteCache.clear(); + assertEquals(false, remoteCache.containsKey("k")); + } + + public void testBulkGet() { + validateSequenceAndStopServer(); + resetStats(); + Map map = remoteCache.getBulk(); + assertEquals(3, map.size()); + } + + private void validateSequenceAndStopServer() { + resetStats(); + assertNoHits(); + SocketAddress expectedServer = strategy.getServers()[strategy.getNextPosition()]; + assertNoHits(); + remoteCache.put("k","v"); + + assert strategy.getServers().length == 3; + assertOnlyServerHit(expectedServer); + + resetStats(); + expectedServer = strategy.getServers()[strategy.getNextPosition()]; + remoteCache.put("k2","v2"); + assertOnlyServerHit(expectedServer); + + resetStats(); + expectedServer = strategy.getServers()[strategy.getNextPosition()]; + remoteCache.put("k3","v3"); + assertOnlyServerHit(expectedServer); + + resetStats(); + expectedServer = strategy.getServers()[strategy.getNextPosition()]; + assertEquals("v", remoteCache.put("k","v")); + assertOnlyServerHit(expectedServer); + + //this would be the next server to be shutdown + expectedServer = strategy.getServers()[strategy.getNextPosition()]; + HotRodServer toStop = addr2hrServer.get(expectedServer); + toStop.stop(); + for (Iterator ecmIt = cacheManagers.iterator(); ecmIt.hasNext();) { + if (ecmIt.next().getAddress().equals(expectedServer)) ecmIt.remove(); + } + waitForClusterToForm(); + } + + @Override + protected ConfigurationBuilder getCacheConfig() { + return getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, false); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/RetryOnFailureUnitTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/RetryOnFailureUnitTest.java new file mode 100644 index 000000000000..9cf3eea815fb --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/RetryOnFailureUnitTest.java @@ -0,0 +1,106 @@ +package org.infinispan.client.hotrod.retry; + +import org.infinispan.client.hotrod.exceptions.HotRodClientException; +import org.infinispan.client.hotrod.exceptions.RemoteNodeSuspectException; +import org.infinispan.client.hotrod.exceptions.TransportException; +import org.infinispan.client.hotrod.impl.ConfigurationProperties; +import org.infinispan.client.hotrod.impl.operations.RetryOnFailureOperation; +import org.infinispan.client.hotrod.impl.transport.Transport; +import org.infinispan.client.hotrod.impl.transport.TransportFactory; +import org.mockito.Mockito; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.net.SocketAddress; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.testng.AssertJUnit.assertEquals; + +/** + * Tests the number of retries. + * + * @author Pedro Ruivo + * @since 7.0 + */ +@Test(groups = "unit", testName = "client.hotrod.retry.RetryOnFailureUnitTest") +public class RetryOnFailureUnitTest { + + public void testNoRetryOnTransportFailure() { + doRetryTest(0, true); + } + + public void testNoRetryOnExecuteFailure() { + doRetryTest(0, false); + } + + public void testSingleRetryOnTransportFailure() { + doRetryTest(1, true); + } + + public void testSingleRetryOnExecuteFailure() { + doRetryTest(1, false); + } + + public void testMultipleRetryOnTransportFailure() { + doRetryTest(ConfigurationProperties.DEFAULT_MAX_RETRIES, true); + } + + public void testMultipleRetryOnExecuteFailure() { + doRetryTest(ConfigurationProperties.DEFAULT_MAX_RETRIES, false); + } + + private void doRetryTest(int maxRetry, boolean failOnTransport) { + TransportFactory mockTransport = Mockito.mock(TransportFactory.class); + Mockito.when(mockTransport.getMaxRetries()).thenReturn(maxRetry); + MockOperation mockOperation = new MockOperation(mockTransport, failOnTransport); + try { + mockOperation.execute(); + AssertJUnit.fail("Exception expected!"); + } catch (HotRodClientException expected) { + //ignore + } + if (failOnTransport) { + assertEquals("Wrong getTransport() invocation.", maxRetry + 1, mockOperation.transportInvocationCount.get()); + assertEquals("Wrong execute() invocation.", 0, mockOperation.executeInvocationCount.get()); + } else { + assertEquals("Wrong getTransport() invocation.", maxRetry + 1, mockOperation.transportInvocationCount.get()); + assertEquals("Wrong execute() invocation.", maxRetry + 1, mockOperation.executeInvocationCount.get()); + } + } + + private class MockOperation extends RetryOnFailureOperation { + + private final AtomicInteger transportInvocationCount; + private final AtomicInteger executeInvocationCount; + private final boolean failOnTransport; + + public MockOperation(TransportFactory transportFactory, boolean failOnTransport) { + super(null, transportFactory, null, null, null); + this.failOnTransport = failOnTransport; + transportInvocationCount = new AtomicInteger(0); + executeInvocationCount = new AtomicInteger(0); + } + + @Override + protected Transport getTransport(int retryCount, Set failedServers) { + transportInvocationCount.incrementAndGet(); + if (failOnTransport) { + throw new TransportException("Induced Failure", null); + } + //we can return null since it is not used + return null; + } + + @Override + protected Void executeOperation(Transport transport) { + executeInvocationCount.incrementAndGet(); + if (!failOnTransport) { + throw new RemoteNodeSuspectException("Induced Failure", 1L, (short) 1); + } + //we can return null since it is not used + return null; + } + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/ServerFailureRetryTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/ServerFailureRetryTest.java new file mode 100644 index 000000000000..434ac57426fe --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/retry/ServerFailureRetryTest.java @@ -0,0 +1,54 @@ +package org.infinispan.client.hotrod.retry; + +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.notifications.Listener; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated; +import org.infinispan.notifications.cachelistener.event.CacheEntryEvent; +import org.infinispan.remoting.transport.jgroups.SuspectException; +import org.testng.annotations.Test; + +import java.lang.reflect.Method; + +import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration; +import static org.infinispan.test.TestingUtil.k; +import static org.infinispan.test.TestingUtil.v; + +/** + * Test different server error situations and check how clients behave under + * those circumstances. Also verify whether failover is happening accordingly. + * + * @author Galder Zamarreño + * @since 4.2 + */ +@Test(groups = "functional", testName = "client.hotrod.retry.ServerFailureRetryTest") +public class ServerFailureRetryTest extends AbstractRetryTest { + + @Override + protected ConfigurationBuilder getCacheConfig() { + return hotRodCacheConfiguration( + getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, false)); + } + + public void testRetryWithSuspectException(Method m) { + ErrorInducingListener listener = new ErrorInducingListener(); + manager(0).getCache().addListener(listener); + try { + remoteCache.put(k(m), v(m)); + } finally { + manager(0).getCache().removeListener(listener); + } + } + + @Listener + public static class ErrorInducingListener { + boolean induceError = true; + + @CacheEntryCreated + public void entryCreated(CacheEntryEvent event) throws Exception { + if (!event.isPre() && event.isOriginLocal() && induceError) { + throw new SuspectException("Simulated suspicion"); + } + } + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/stress/ClientConsistentHashPerfTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/stress/ClientConsistentHashPerfTest.java new file mode 100644 index 000000000000..7ec44604f783 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/stress/ClientConsistentHashPerfTest.java @@ -0,0 +1,63 @@ +package org.infinispan.client.hotrod.stress; + +import java.net.SocketAddress; + +import org.infinispan.client.hotrod.RemoteCache; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHash; +import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransportFactory; +import org.infinispan.client.hotrod.test.MultiHotRodServersTest; +import org.infinispan.configuration.cache.CacheMode; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.test.TestingUtil; +import org.testng.annotations.Test; + +/** + * Test the performance of ConsistentHashV1/V2. + * + * @author Dan Berindei + * @since 5.3 + */ +@Test(groups = "profiling", testName = "client.hotrod.stress.ClientConsistentHashPerfTest") +public class ClientConsistentHashPerfTest extends MultiHotRodServersTest { + + private static final int NUM_SERVERS = 64; + private static final int ITERATIONS = 10000000; + private static final int NUM_KEYS = 100000; + + @Override + protected void createCacheManagers() throws Throwable { + ConfigurationBuilder config = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false); + createHotRodServers(NUM_SERVERS, config); + } + + public void testConsistentHashPerf() throws Exception { + RemoteCacheManager rcm = client(0); + RemoteCache cache = rcm.getCache(); + // This will initialize the consistent hash + cache.put("k", "v"); + + TcpTransportFactory transportFactory = (TcpTransportFactory) TestingUtil.extractField(rcm, "transportFactory"); + ConsistentHash ch = transportFactory.getConsistentHash(); + byte[][] keys = new byte[NUM_KEYS][]; + + for (int i = 0; i < NUM_KEYS; i++) { + keys[i] = String.valueOf(i).getBytes("UTF-8"); + } + + SocketAddress aServer = null; + // warm-up + for (int i = 0; i < ITERATIONS/10; i++) { + SocketAddress server = ch.getServer(keys[i % keys.length]); + if (server != null) aServer = server; + } + + long startNanos = System.nanoTime(); + for (int i = 0; i < ITERATIONS; i++) { + SocketAddress server = ch.getServer(keys[i % keys.length]); + if (server != null) aServer = server; + } + double duration = System.nanoTime() - startNanos; + log.infof("Test took %.3f s, average CH lookup was %.3f ns", duration / 1000000000L, duration / ITERATIONS); + } +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/HotRodClientTestingUtil.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/HotRodClientTestingUtil.java new file mode 100644 index 000000000000..6be9e73a5996 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/HotRodClientTestingUtil.java @@ -0,0 +1,84 @@ +package org.infinispan.client.hotrod.test; + +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.logging.Log; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.util.logging.LogFactory; + +/** + * Utility methods for the Hot Rod client + * + * @author Galder Zamarreño + * @since 5.1 + */ +public class HotRodClientTestingUtil { + + private static final Log log = LogFactory.getLog(HotRodClientTestingUtil.class, Log.class); + + /** + * Kills a remote cache manager. + * + * @param rcm the remote cache manager instance to kill + */ + public static void killRemoteCacheManager(RemoteCacheManager rcm) { + try { + if (rcm != null) rcm.stop(); + } catch (Throwable t) { + log.warn("Error stopping remote cache manager", t); + } + } + + /** + * Kills a group of remote cache managers. + * + * @param rcm + * the remote cache manager instances to kill + */ + public static void killRemoteCacheManagers(RemoteCacheManager... rcms) { + if (rcms != null) { + for (RemoteCacheManager rcm : rcms) { + try { + if (rcm != null) + rcm.stop(); + } catch (Throwable t) { + log.warn("Error stopping remote cache manager", t); + } + } + } + + } + + /** + * Kills a group of Hot Rod servers. + * + * @param servers the group of Hot Rod servers to kill + */ + public static void killServers(HotRodServer... servers) { + if (servers != null) { + for (HotRodServer server : servers) { + try { + if (server != null) server.stop(); + } catch (Throwable t) { + log.warn("Error stopping Hot Rod server", t); + } + } + } + } + + /** + * Invoke a task using a remote cache manager. This method guarantees that + * the remote manager used in the task will be cleaned up after the task has + * completed, regardless of the task outcome. + * + * @param c task to execute + * @throws Exception if the task fails somehow + */ + public static void withRemoteCacheManager(RemoteCacheManagerCallable c) { + try { + c.call(); + } finally { + killRemoteCacheManager(c.rcm); + } + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/MultiHotRodServersTest.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/MultiHotRodServersTest.java new file mode 100644 index 000000000000..965bb165e039 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/MultiHotRodServersTest.java @@ -0,0 +1,91 @@ +package org.infinispan.client.hotrod.test; + +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.TestHelper; +import org.infinispan.configuration.cache.ConfigurationBuilder; +import org.infinispan.lifecycle.ComponentStatus; +import org.infinispan.manager.EmbeddedCacheManager; +import org.infinispan.server.hotrod.HotRodServer; +import org.infinispan.test.MultipleCacheManagersTest; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; + +import java.util.ArrayList; +import java.util.List; + +import static org.infinispan.test.TestingUtil.blockUntilCacheStatusAchieved; +import static org.infinispan.test.TestingUtil.blockUntilViewReceived; + +/** + * Base test class for Hot Rod tests. + * + * @author Galder Zamarreño + * @since 5.0 + */ +public abstract class MultiHotRodServersTest extends MultipleCacheManagersTest { + + protected List servers = new ArrayList(); + protected List clients = new ArrayList(); + + protected void createHotRodServers(int num, ConfigurationBuilder defaultBuilder) { + // Start Hot Rod servers + for (int i = 0; i < num; i++) addHotRodServer(defaultBuilder); + // Verify that default caches should be started + for (int i = 0; i < num; i++) assert manager(i).getCache() != null; + // Block until views have been received + blockUntilViewReceived(manager(0).getCache(), num); + // Verify that caches running + for (int i = 0; i < num; i++) { + blockUntilCacheStatusAchieved( + manager(i).getCache(), ComponentStatus.RUNNING, 10000); + } + + for (int i = 0; i < num; i++) { + clients.add(new RemoteCacheManager(createHotRodClientConfigurationBuilder(server(i).getPort()).build())); + } + } + + protected org.infinispan.client.hotrod.configuration.ConfigurationBuilder createHotRodClientConfigurationBuilder(int serverPort) { + org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder(); + clientBuilder.addServer() + .host("localhost") + .port(serverPort) + .pingOnStartup(false); + return clientBuilder; + } + + @AfterMethod(alwaysRun = true) + protected void clearContent() throws Throwable { + // Do not clear content to allow servers + // to stop gracefully and catch any issues there. + } + + @AfterClass(alwaysRun = true) + @Override + protected void destroy() { + // Correct order is to stop servers first + try { + for (HotRodServer server : servers) + HotRodClientTestingUtil.killServers(server); + } finally { + // And then the caches and cache managers + super.destroy(); + } + } + + private HotRodServer addHotRodServer(ConfigurationBuilder builder) { + EmbeddedCacheManager cm = addClusterEnabledCacheManager(builder); + HotRodServer server = TestHelper.startHotRodServer(cm); + servers.add(server); + return server; + } + + protected HotRodServer server(int i) { + return servers.get(i); + } + + protected RemoteCacheManager client(int i) { + return clients.get(i); + } + +} diff --git a/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/RemoteCacheManagerCallable.java b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/RemoteCacheManagerCallable.java new file mode 100644 index 000000000000..92951347c4f4 --- /dev/null +++ b/client/hotrod-client/src/test/java/org/infinispan/client/hotrod/test/RemoteCacheManagerCallable.java @@ -0,0 +1,23 @@ +package org.infinispan.client.hotrod.test; + +import org.infinispan.client.hotrod.RemoteCacheManager; + +/** + * A task that executes operations against a given remote cache manager. + * + * @author Galder Zamarreño + * @since 5.2 + */ +public class RemoteCacheManagerCallable { + + protected final RemoteCacheManager rcm; + + public RemoteCacheManagerCallable(RemoteCacheManager rcm) { + this.rcm = rcm; + } + + public void call() { + // No-op + } + +} diff --git a/core/src/main/java/org/infinispan/container/DataContainer.java b/core/src/main/java/org/infinispan/container/DataContainer.java index ec1149bac317..bb05ca9326fa 100755 --- a/core/src/main/java/org/infinispan/container/DataContainer.java +++ b/core/src/main/java/org/infinispan/container/DataContainer.java @@ -39,12 +39,10 @@ public interface DataContainer extends Iterable { * while iterating through the data container using methods like {@link #keySet()} * to avoid changing the underlying collection's order. * - * - * - * @param key key under which entry is stored + * @param k key under which entry is stored * @return entry, if it exists, or null if not */ - InternalCacheEntry peek(Object key); + InternalCacheEntry peek(Object k); /** * Puts an entry in the cache along with metadata adding information such @@ -84,13 +82,11 @@ public interface DataContainer extends Iterable { /** * Returns a set of keys in the container. When iterating through the container using this method, - * clients should never call get() method but instead peek(), in order to avoid + * clients should never call {@link #get()} method but instead {@link #peek()}, in order to avoid * changing the order of the underlying collection as a side of effect of iterating through it. * * @return a set of keys */ - //@org.jetbrains.annotations.NotNull - ///@org.jetbrains.annotations.NotNull Set keySet(); /** diff --git a/core/src/main/java/org/infinispan/container/DefaultDataContainer.java b/core/src/main/java/org/infinispan/container/DefaultDataContainer.java index 98ad3cece004..7997330d0cbb 100644 --- a/core/src/main/java/org/infinispan/container/DefaultDataContainer.java +++ b/core/src/main/java/org/infinispan/container/DefaultDataContainer.java @@ -376,7 +376,7 @@ public void executeTask(final AdvancedCacheLoader.KeyFilter filter, final ParallelIterableMap map = (ParallelIterableMap) entries; map.forEach(512, new ParallelIterableMap.KeyValueAction() { @Override - public void apply(Object key, InternalCacheEntry value) { + public void apply(Object key, InternalCacheEntry value) { if (filter.shouldLoadKey((K)key)) { action.apply((K)key, value); } diff --git a/core/src/test/java/org/infinispan/configuration/QueryableDataContainer.java b/core/src/test/java/org/infinispan/configuration/QueryableDataContainer.java index bc78e44d5e05..8b61ca99ba29 100644 --- a/core/src/test/java/org/infinispan/configuration/QueryableDataContainer.java +++ b/core/src/test/java/org/infinispan/configuration/QueryableDataContainer.java @@ -45,9 +45,9 @@ public InternalCacheEntry get(Object k) { } @Override - public InternalCacheEntry peek(Object key) { - loggedOperations.add("peek(" + key + ")" ); - return delegate.peek(key); + public InternalCacheEntry peek(Object k) { + loggedOperations.add("peek(" + k + ")" ); + return delegate.peek(k); } @Override diff --git a/core/src/test/java/org/infinispan/eviction/ManualEvictionWithSizeBasedAndConcurrentOperationsInPrimaryOwnerTest.java b/core/src/test/java/org/infinispan/eviction/ManualEvictionWithSizeBasedAndConcurrentOperationsInPrimaryOwnerTest.java index 6dce11d05713..475fef0e6d72 100644 --- a/core/src/test/java/org/infinispan/eviction/ManualEvictionWithSizeBasedAndConcurrentOperationsInPrimaryOwnerTest.java +++ b/core/src/test/java/org/infinispan/eviction/ManualEvictionWithSizeBasedAndConcurrentOperationsInPrimaryOwnerTest.java @@ -433,8 +433,8 @@ public InternalCacheEntry get(Object k) { } @Override - public InternalCacheEntry peek(Object key) { - return delegate.peek(key); + public InternalCacheEntry peek(Object k) { + return delegate.peek(k); } @Override diff --git a/jcache/src/main/java/org/infinispan/jcache/JCacheEntry.java b/jcache/src/main/java/org/infinispan/jcache/JCacheEntry.java index b882a352f240..7a6f47ce9d23 100644 --- a/jcache/src/main/java/org/infinispan/jcache/JCacheEntry.java +++ b/jcache/src/main/java/org/infinispan/jcache/JCacheEntry.java @@ -40,4 +40,3 @@ public T unwrap(Class clazz) { } } - diff --git a/maven-settings.xml b/maven-settings.xml deleted file mode 100644 index 154fd3505e19..000000000000 --- a/maven-settings.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - org.jboss.maven.plugins - - - - - - - - - - jboss-public-repository - - - jboss-public-repository-group - JBoss Public Maven Repository Group - https://repository.jboss.org/nexus/content/groups/public-jboss/ - default - - true - never - - - true - never - - - - - - jboss-public-repository-group - JBoss Public Maven Repository Group - https://repository.jboss.org/nexus/content/groups/public-jboss/ - default - - true - never - - - true - never - - - - - - - - redhat-earlyaccess-repository - - - redhat-earlyaccess-repository-group - Red Hat early access repository - http://maven.repository.redhat.com/earlyaccess/all/ - default - - true - never - - - true - never - - - - - - - - - jboss-public-repository - redhat-earlyaccess-repository - - - - diff --git a/maven-settings.xml.redhat b/maven-settings.xml.redhat index 154fd3505e19..8bd8b00d258d 100644 --- a/maven-settings.xml.redhat +++ b/maven-settings.xml.redhat @@ -6,39 +6,7 @@ org.jboss.maven.plugins - - - - - - jboss-public-repository diff --git a/off-heap/pom.xml.off-heap b/off-heap/pom.xml.off-heap new file mode 100644 index 000000000000..0fe221ea5a17 --- /dev/null +++ b/off-heap/pom.xml.off-heap @@ -0,0 +1,294 @@ + + + 4.0.0 + + + org.infinispan + infinispan-parent + 7.0.0-SNAPSHOT + parent/pom.xml + + + infinispan + + Infinispan Distribution + Builds the complete Infinispan distribution bundles + pom + + + bom + checkstyle + parent + commons + core + extended-statistics + tools + query + query-dsl + remote-query/remote-query-client + remote-query/remote-query-server + tree + lucene + lucene/lucene-directory + lucene/lucene-v4 + lucene/lucene-v3 + persistence + persistence/jdbc + persistence/remote + persistence/cli + persistence/leveldb + persistence/rest + server + server/core + server/memcached + server/hotrod + server/websocket + server/rest + client/hotrod-client + + spring + cli/cli-server + cli/cli-client + demos/gui + demos/ec2 + demos/distexec + demos/ec2-ui + demos/directory + demos/lucene-directory-demo + demos/gridfs-webdav + demos/nearcache + demos/nearcache-client + cdi/extension + as-modules + integrationtests/luceneintegration + integrationtests/as-integration + integrationtests/compatibility-mode-it + integrationtests/cdi-jcache-it + jcache + server/integration + off-heap + + + + + distribution + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + javadoc + prepare-package + + aggregate + + + true + + ${basedir}/src/javadoc/stylesheet.css + ${basedir}/src/javadoc + true + + http://docs.oracle.com/javase/6/docs/api/ + http://docs.oracle.com/javaee/5/api/ + +