/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.cache.instance;
import com.hazelcast.cache.CacheNotExistsException;
import com.hazelcast.cache.HazelcastCacheManager;
import com.hazelcast.cache.HazelcastCachingProvider;
import com.hazelcast.cache.ICache;
import com.hazelcast.cache.impl.HazelcastServerCachingProvider;
import com.hazelcast.cache.impl.ICacheService;
import com.hazelcast.config.CacheConfig;
import com.hazelcast.config.CacheSimpleConfig;
import com.hazelcast.config.Config;
import com.hazelcast.core.HazelcastException;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.HazelcastInstanceNotActiveException;
import com.hazelcast.core.ICacheManager;
import com.hazelcast.core.IMap;
import com.hazelcast.instance.HazelcastInstanceCacheManager;
import com.hazelcast.instance.HazelcastInstanceImpl;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.TestHazelcastInstanceFactory;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.spi.CachingProvider;
import java.net.URI;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelTest.class})
public class CacheThroughHazelcastInstanceTest extends HazelcastTestSupport {
private static final String CACHE_NAME = "MyCache";
@Rule
public ExpectedException thrown = ExpectedException.none();
protected Config createConfig() {
return new Config();
}
protected CacheSimpleConfig createCacheSimpleConfig(String cacheName) {
CacheSimpleConfig cacheSimpleConfig = new CacheSimpleConfig();
cacheSimpleConfig.setName(cacheName);
return cacheSimpleConfig;
}
protected CacheConfig createCacheConfig(String cacheName) {
return new CacheConfig(cacheName);
}
protected CachingProvider createCachingProvider(HazelcastInstance instance) {
return HazelcastServerCachingProvider.createCachingProvider(instance);
}
protected HazelcastInstance createInstance() {
TestHazelcastInstanceFactory instanceFactory = createHazelcastInstanceFactory();
return instanceFactory.newHazelcastInstance();
}
protected HazelcastInstance createInstance(Config config) {
TestHazelcastInstanceFactory instanceFactory = createHazelcastInstanceFactory();
return instanceFactory.newHazelcastInstance(config);
}
protected void shutdownOwnerInstance(HazelcastInstance instance) {
instance.shutdown();
}
protected Class<? extends Exception> getInstanceNotActiveExceptionType() {
return HazelcastInstanceNotActiveException.class;
}
@Test
public void getCache_whenThereIsNoCacheConfig_thenFail() {
thrown.expect(CacheNotExistsException.class);
whenThereIsNoCacheConfig_thenFail(true);
}
@Test
public void getDistributedObject_whenThereIsNoCacheConfig_thenFail() {
thrown.expect(CacheNotExistsException.class);
whenThereIsNoCacheConfig_thenFail(false);
}
private void whenThereIsNoCacheConfig_thenFail(boolean getCache) {
HazelcastInstance instance = createInstance();
retrieveCache(instance, getCache);
}
@Test
public void getCache_whenJCacheLibIsNotAvailable_thenFail() {
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
try {
ClassLoader classLoader = new NonJCacheAwareClassLoader();
Config config = createConfig();
config.setClassLoader(classLoader);
Thread.currentThread().setContextClassLoader(classLoader);
HazelcastInstance instance = createInstance(config);
thrown.expect(IllegalStateException.class);
retrieveCache(instance, true);
} finally {
Thread.currentThread().setContextClassLoader(tccl);
}
}
@Test
public void whenJCacheLibIsNotAvailable_thenOtherServicesWorks() {
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
try {
ClassLoader classLoader = new NonJCacheAwareClassLoader();
Config config = createConfig();
config.setClassLoader(classLoader);
Thread.currentThread().setContextClassLoader(classLoader);
HazelcastInstance instance = createInstance(config);
IMap<Integer, String> map = instance.getMap(randomName());
map.put(1, "Value-1");
assertEquals("Value-1", map.get(1));
} finally {
Thread.currentThread().setContextClassLoader(tccl);
}
}
@Test
public void getCache_whenThereIsCacheConfigAndDefinedInConfig_thenRetrieveCacheSucceeds() {
whenThereIsCacheConfigAndDefinedInConfig_thenRetrieveCacheSucceeds(true);
}
@Test
public void getDistributedObject_whenThereIsCacheConfigAndDefinedInConfig_thenRetrieveCacheSucceeds() {
whenThereIsCacheConfigAndDefinedInConfig_thenRetrieveCacheSucceeds(false);
}
private void whenThereIsCacheConfigAndDefinedInConfig_thenRetrieveCacheSucceeds(boolean getCache) {
Config config = createConfig();
config.addCacheConfig(createCacheSimpleConfig(CACHE_NAME));
HazelcastInstance instance = createInstance(config);
Cache cache = retrieveCache(instance, getCache);
assertNotNull(cache);
}
@Test
public void getCache_whenThereIsCacheConfigAndCreatedByCacheManager_thenReturnsSameCache() {
whenThereIsCacheConfigAndCreatedByCacheManager_thenReturnsSameCache(true);
}
@Test
public void getDistributedObject_whenThereIsCacheConfigAndCreatedByCacheManager_thenReturnsSameCache() {
whenThereIsCacheConfigAndCreatedByCacheManager_thenReturnsSameCache(false);
}
private void whenThereIsCacheConfigAndCreatedByCacheManager_thenReturnsSameCache(boolean getCache) {
HazelcastInstance instance = createInstance();
CachingProvider cachingProvider = createCachingProvider(instance);
CacheManager cacheManager = cachingProvider.getCacheManager();
Cache cache1 = cacheManager.createCache(CACHE_NAME, createCacheConfig(CACHE_NAME));
assertNotNull(cache1);
Cache cache2 = retrieveCache(instance, getCache);
assertNotNull(cache2);
// verify that they are same cache instance
assertTrue(cache1 == cache2);
}
@Test
public void getCache_whenThereIsCacheConfigWithURIandCreatedByCacheManager_thenReturnsSameCache() throws Exception {
whenThereIsCacheConfigWithURIandCreatedByCacheManager_thenReturnsSameCache(true);
}
@Test
public void getDistributedObject_whenThereIsCacheConfigWithURIandCreatedByCacheManager_thenReturnsSameCache()
throws Exception {
whenThereIsCacheConfigWithURIandCreatedByCacheManager_thenReturnsSameCache(false);
}
private void whenThereIsCacheConfigWithURIandCreatedByCacheManager_thenReturnsSameCache(boolean getCache) throws Exception {
HazelcastInstance instance = createInstance();
CachingProvider cachingProvider = createCachingProvider(instance);
Properties properties = HazelcastCachingProvider.propertiesByInstanceItself(instance);
CacheManager cacheManager = cachingProvider.getCacheManager(new URI("MY-URI"), null, properties);
Cache cache1 = cacheManager.createCache(CACHE_NAME, createCacheConfig(CACHE_NAME));
assertNotNull(cache1);
Cache cache2 = retrieveCache(instance, "MY-URI/" + CACHE_NAME, getCache);
assertNotNull(cache2);
// verify that they are same cache instance
assertTrue(cache1 == cache2);
}
@Test
public void getCache_whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByCacheManager_thenFail()
throws Exception {
thrown.expect(CacheNotExistsException.class);
whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByCacheManager_thenFail(true);
}
@Test
public void getDistributedObject_whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByCacheManager_thenFail()
throws Exception {
thrown.expect(CacheNotExistsException.class);
whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByCacheManager_thenFail(false);
}
private void whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByCacheManager_thenFail(boolean getCache)
throws Exception {
HazelcastInstance instance = createInstance();
CachingProvider cachingProvider = createCachingProvider(instance);
Properties properties = HazelcastCachingProvider.propertiesByInstanceItself(instance);
CacheManager cacheManager = cachingProvider.getCacheManager(new URI("MY-URI"), null, properties);
Cache cache1 = cacheManager.createCache(CACHE_NAME, createCacheConfig(CACHE_NAME));
assertNotNull(cache1);
retrieveCache(instance, getCache);
}
@Test
public void getCache_whenThereIsCacheConfigAndCreatedByInstance_thenReturnSameCache() {
whenThereIsCacheConfigAndCreatedByInstance_thenReturnSameCache(true);
}
@Test
public void getDistributedObject_whenThereIsCacheConfigAndCreatedByInstance_thenReturnSameCache() {
whenThereIsCacheConfigAndCreatedByInstance_thenReturnSameCache(false);
}
private void whenThereIsCacheConfigAndCreatedByInstance_thenReturnSameCache(boolean getCache) {
Config config = createConfig();
config.addCacheConfig(createCacheSimpleConfig(CACHE_NAME));
HazelcastInstance instance = createInstance(config);
Cache cache1 = retrieveCache(instance, getCache);
assertNotNull(cache1);
CachingProvider cachingProvider = createCachingProvider(instance);
CacheManager cacheManager = cachingProvider.getCacheManager();
Cache cache2 = cacheManager.getCache(CACHE_NAME);
assertNotNull(cache2);
// verify that they are same cache instance
assertTrue(cache1 == cache2);
}
@Test
public void getCache_whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByInstance_thenReturnDifferentCache()
throws Exception {
whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByInstance_thenReturnDifferentCache(true);
}
@Test
public void getDistributedObject_whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByInstance_thenReturnDifferentCache()
throws Exception {
whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByInstance_thenReturnDifferentCache(false);
}
private void whenThereIsCacheConfigWithSameNameButDifferentFullNameAndCreatedByInstance_thenReturnDifferentCache(
boolean getCache) throws Exception {
Config config = createConfig();
config.addCacheConfig(createCacheSimpleConfig(CACHE_NAME));
HazelcastInstance instance = createInstance(config);
Cache cache1 = retrieveCache(instance, getCache);
assertNotNull(cache1);
CachingProvider cachingProvider = createCachingProvider(instance);
Properties properties = HazelcastCachingProvider.propertiesByInstanceItself(instance);
CacheManager cacheManager = cachingProvider.getCacheManager(new URI("MY-URI"), null, properties);
Cache cache2 = cacheManager.getCache(CACHE_NAME);
assertNotNull(cache2);
assertNotEquals(cache1, cache2);
}
@Test
public void getCache_whenOwnerInstanceIsShutdown_thenOperateOnCacheFails() {
whenOwnerInstanceIsShutdown_thenOperateOnCacheFails(true);
}
@Test
public void getDistributedObject_whenOwnerInstanceIsShutdown_thenOperateOnCacheFails() {
whenOwnerInstanceIsShutdown_thenOperateOnCacheFails(false);
}
private void whenOwnerInstanceIsShutdown_thenOperateOnCacheFails(boolean getCache) {
Config config = createConfig();
config.addCacheConfig(createCacheSimpleConfig(CACHE_NAME));
HazelcastInstance instance = createInstance(config);
Cache<Integer, Integer> cache = retrieveCache(instance, getCache);
assertNotNull(cache);
cache.put(1, 1);
shutdownOwnerInstance(instance);
try {
cache.put(2, 2);
fail("Operation on cache must fails because owner instance is not active!");
} catch (Throwable t) {
Class<? extends Exception> expectedExceptionType = getInstanceNotActiveExceptionType();
Class<? extends Throwable> actualExceptionType = t.getClass();
if (!expectedExceptionType.isAssignableFrom(actualExceptionType)) {
fail("Expected exception type: " + expectedExceptionType
+ ", but actual exception type: " + actualExceptionType);
}
}
}
@Test
public void getCache_whenCacheIsDestroyed_thenCacheIsRemovedFromDistributedObject() {
getCache_whenCacheIsDestroyed_thenCacheIsRemovedFromDistributedObject(true);
}
@Test
public void getDistributedObject_getCache_whenCacheIsDestroyed_thenCacheIsRemovedFromDistributedObject() {
getCache_whenCacheIsDestroyed_thenCacheIsRemovedFromDistributedObject(false);
}
private void getCache_whenCacheIsDestroyed_thenCacheIsRemovedFromDistributedObject(boolean getCache) {
Config config = createConfig();
config.addCacheConfig(createCacheSimpleConfig(CACHE_NAME));
HazelcastInstance instance = createInstance(config);
ICache cache = retrieveCache(instance, getCache);
assertNotNull(cache);
assertContains(instance.getDistributedObjects(), cache);
cache.destroy();
assertNotContains(instance.getDistributedObjects(), cache);
}
@Test
public void getCache_whenOtherHazelcastExceptionIsThrown_thenFail() {
// when one attempts to getCache but a HazelcastException other than ServiceNotFoundException is thrown
HazelcastInstanceImpl hzInstanceImpl = mock(HazelcastInstanceImpl.class);
when(hzInstanceImpl.getDistributedObject(anyString(), anyString()))
.thenThrow(new HazelcastException("mock hz exception"));
// then the thrown HazelcastException is rethrown by getCache
ICacheManager hzCacheManager = new HazelcastInstanceCacheManager(hzInstanceImpl);
thrown.expect(HazelcastException.class);
hzCacheManager.getCache("any-cache");
}
private static ICache<Integer, Integer> retrieveCache(HazelcastInstance instance, boolean getCache) {
return retrieveCache(instance, CACHE_NAME, getCache);
}
@SuppressWarnings("unchecked")
private static ICache<Integer, Integer> retrieveCache(HazelcastInstance instance, String cacheName, boolean getCache) {
return getCache
? instance.getCacheManager().getCache(cacheName)
: (ICache) instance.getDistributedObject(ICacheService.SERVICE_NAME,
HazelcastCacheManager.CACHE_MANAGER_PREFIX + cacheName);
}
private static class NonJCacheAwareClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.startsWith("javax.cache.")) {
throw new ClassNotFoundException("Couldn't load class " + name + ". Because JCache is disabled!");
}
return super.loadClass(name);
}
}
}