package org.cache2k.ee.impl;
/*
* #%L
* cache2k server side
* %%
* Copyright (C) 2000 - 2017 headissue GmbH, Munich
* %%
* 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.
* #L%
*/
import org.cache2k.Cache;
import org.cache2k.Cache2kBuilder;
import org.cache2k.CacheManager;
import static org.junit.Assert.*;
import org.cache2k.core.CacheManagerImpl;
import org.cache2k.core.util.Log;
import org.cache2k.testing.category.FastTests;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* Simple test to check that the support and the management object appear
* and disappear.
*
* @author Jens Wilke; created: 2014-10-10
*/
@Category(FastTests.class)
public class JmxSupportTest {
private static final MBeanServerConnection server = ManagementFactory.getPlatformMBeanServer();
private ObjectName objectName;
@Test
public void testManagerPresent() throws Exception {
String _name = getClass().getName() + ".testManagerPresent";
CacheManager m = CacheManager.getInstance(_name);
MBeanInfo i = getCacheManagerInfo(_name);
assertEquals(ManagerMXBeanImpl.class.getName(), i.getClassName());
m.close();
}
@Test
public void emptyCacheManager_healthOkay() throws Exception {
String _name = getClass().getName() + ".emptyCacheManager_healthOkay";
CacheManager m = CacheManager.getInstance(_name);
MBeanInfo i = getCacheManagerInfo(_name);
assertEquals(ManagerMXBeanImpl.class.getName(), i.getClassName());
String _health = (String) server.getAttribute(getCacheManagerObjectName(_name), "HealthStatus");
assertEquals("ok", _health);
m.close();
}
/**
* Construct three caches with multiple issues and check the health string of the manager JMX.
*/
@Test
public void multipleWarnings() throws Exception {
final String _MANAGER_NAME = getClass().getName() + ".multipleWarnings";
final String _CACHE_NAME_BAD_HASHING = "cacheWithBadHashing";
final String _CACHE_NAME_KEY_MUTATION = "cacheWithKeyMutation";
final String _CACHE_NAME_MULTIPLE_ISSUES = "cacheWithMultipleIssues";
final String _SUPPRESS1 = "org.cache2k.Cache/" + _MANAGER_NAME + ":" + _CACHE_NAME_KEY_MUTATION;
final String _SUPPRESS2 = "org.cache2k.Cache/" + _MANAGER_NAME + ":" + _CACHE_NAME_MULTIPLE_ISSUES;
Log.registerSuppression(_SUPPRESS1, new Log.SuppressionCounter());
Log.registerSuppression(_SUPPRESS2, new Log.SuppressionCounter());
CacheManager m = CacheManager.getInstance(_MANAGER_NAME);
Cache _cacheWithBadHashing = Cache2kBuilder.of(Object.class, Object.class)
.manager(m)
.name(_CACHE_NAME_BAD_HASHING)
.eternal(true)
.build();
Cache _cacheWithKeyMutation = Cache2kBuilder.of(Object.class, Object.class)
.manager(m)
.name(_CACHE_NAME_KEY_MUTATION)
.eternal(true)
.entryCapacity(50)
.build();
Cache _cacheWithMultipleIssues = Cache2kBuilder.of(Object.class, Object.class)
.manager(m)
.name(_CACHE_NAME_MULTIPLE_ISSUES)
.entryCapacity(50)
.eternal(true)
.build();
for (int i = 0; i < 9; i++) {
_cacheWithBadHashing.put(new KeyForMutation(), 1);
}
for (int i = 0; i < 100; i++) {
_cacheWithMultipleIssues.put(new KeyForMutation(), 1);
}
for (int i = 0; i < 100; i++) {
KeyForMutation v = new KeyForMutation();
_cacheWithKeyMutation.put(v, 1);
_cacheWithMultipleIssues.put(v, 1);
v.value = 1;
}
String _health = (String) server.getAttribute(getCacheManagerObjectName(_MANAGER_NAME), "HealthStatus");
assertEquals(
"FAILURE: [cacheWithKeyMutation] hash quality is 0 (threshold: 5); " +
"FAILURE: [cacheWithMultipleIssues] hash quality is 0 (threshold: 5); " +
"WARNING: [cacheWithBadHashing] hash quality is 7 (threshold: 20); " +
"WARNING: [cacheWithKeyMutation] key mutation detected; " +
"WARNING: [cacheWithMultipleIssues] key mutation detected", _health);
Log.deregisterSuppression(_SUPPRESS1);
Log.deregisterSuppression(_SUPPRESS2);
m.close();
}
private static class KeyForMutation {
int value = 0;
public int hashCode() { return value; }
}
static MBeanInfo getCacheManagerInfo(String _name) throws Exception {
ObjectName on = getCacheManagerObjectName(_name);
return server.getMBeanInfo(on);
}
private static ObjectName getCacheManagerObjectName(final String _name) throws MalformedObjectNameException {
if (needsQuoting(_name)) {
return new ObjectName("org.cache2k:type=CacheManager,name=\"" + _name + "\"");
} else {
return new ObjectName("org.cache2k:type=CacheManager,name=" + _name);
}
}
private static boolean needsQuoting(String _name) {
return _name.contains(",");
}
@Test(expected = InstanceNotFoundException.class)
public void testManagerDestroyed() throws Exception {
String _name = getClass().getName() + ".testManagerDestroyed";
CacheManager m = CacheManager.getInstance(_name);
MBeanInfo i = getCacheManagerInfo(_name);
assertEquals(ManagerMXBeanImpl.class.getName(), i.getClassName());
m.close();
getCacheManagerInfo(_name);
}
@Test
public void managerClear_noCache() throws Exception {
String _name = getClass().getName() + ".managerClear_noCache";
CacheManager m = CacheManager.getInstance(_name);
server.invoke(getCacheManagerObjectName(_name), "clear", new Object[0], new String[0]);
m.close();
}
@Test
public void managerAttributes() throws Exception {
String _name = getClass().getName() + ".managerAttributes";
CacheManager m = CacheManager.getInstance(_name);
objectName = getCacheManagerObjectName(_name);
checkAttribute("Version", ((CacheManagerImpl) m).getVersion());
checkAttribute("BuildNumber", ((CacheManagerImpl) m).getBuildNumber());
m.close();
}
@Test
public void testCacheCreated() throws Exception {
String _name = getClass().getName() + ".testCacheCreated";
Cache c = Cache2kBuilder.of(Object.class, Object.class)
.name(_name)
.eternal(true)
.build();
MBeanInfo i = getCacheInfo(_name);
assertEquals(CacheMXBeanImpl.class.getName(), i.getClassName());
c.close();
}
@Test
public void testInitialProperties() throws Exception {
Date _beforeCreateion = new Date();
String _name = getClass().getName() + ".testInitialProperties";
Cache c = new Cache2kBuilder<Long, List<Collection<Long>>> () {}
.name(_name)
.eternal(true)
.build();
objectName = constructCacheObjectName(_name);
checkAttribute("KeyType", "Long");
checkAttribute("ValueType", "java.util.List<java.util.Collection<Long>>");
checkAttribute("Size", 0L);
checkAttribute("EntryCapacity", 2000L);
checkAttribute("InsertCount", 0L);
checkAttribute("MissCount", 0L);
checkAttribute("RefreshCount", 0L);
checkAttribute("RefreshFailedCount", 0L);
checkAttribute("RefreshedHitCount", 0L);
checkAttribute("ExpiredCount", 0L);
checkAttribute("EvictedCount", 0L);
checkAttribute("PutCount", 0L);
checkAttribute("RemoveCount", 0L);
checkAttribute("ClearedEntriesCount", 0L);
checkAttribute("ClearCount", 0L);
checkAttribute("KeyMutationCount", 0L);
checkAttribute("LoadExceptionCount", 0L);
checkAttribute("SuppressedLoadExceptionCount", 0L);
checkAttribute("HitRate", 0.0);
checkAttribute("HashQuality", 100);
checkAttribute("MillisPerLoad", 0.0);
checkAttribute("TotalLoadMillis", 0L);
checkAttribute("Implementation", "HeapCache");
checkAttribute("ClearedTime", null);
checkAttribute("Alert", 0);
assertTrue("reasonable CreatedTime", ((Date) retrieve("CreatedTime")).compareTo(_beforeCreateion) >= 0);
assertTrue("reasonable InfoCreatedTime", ((Date) retrieve("InfoCreatedTime")).compareTo(_beforeCreateion) >= 0);
assertTrue("reasonable InfoCreatedDeltaMillis", ((Integer) retrieve("InfoCreatedDeltaMillis")) >= 0);
assertTrue("reasonable EvictionStatistics", retrieve("EvictionStatistics").toString().contains("impl="));
assertTrue("reasonable IntegrityDescriptor", retrieve("IntegrityDescriptor").toString().startsWith("0."));
c.close();
}
@Test
public void testDisabled() throws Exception {
String _name = getClass().getName() + ".testInitialProperties";
Cache c = new Cache2kBuilder<Long, List<Collection<Long>>> () {}
.name(_name)
.disableStatistics(true)
.eternal(true)
.build();
objectName = constructCacheObjectName(_name);
try {
retrieve("Alert");
fail("exception expected");
} catch (InstanceNotFoundException ex) {
}
c.close();
}
private void checkAttribute(String _name, Object _expected) throws Exception {
Object v = retrieve(_name);
assertEquals("Value of attribute '" + _name + "'", _expected, v);
}
private Object retrieve(final String _name) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException {
return server.getAttribute(objectName, _name);
}
static MBeanInfo getCacheInfo(String _name) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName on = constructCacheObjectName(_name);
return mbs.getMBeanInfo(on);
}
static ObjectName constructCacheObjectName(final String _name) throws MalformedObjectNameException {
if (needsQuoting(_name)) {
return new ObjectName("org.cache2k:type=Cache,manager=default,name=\"" + _name + "\"");
} else {
return new ObjectName("org.cache2k:type=Cache,manager=default,name=" + _name);
}
}
@Test(expected = InstanceNotFoundException.class)
public void testCacheDestroyed() throws Exception {
String _name = getClass().getName() + ".testCacheDestroyed";
Cache c = Cache2kBuilder.of(Object.class, Object.class)
.name(_name)
.eternal(true)
.build();
MBeanInfo i = getCacheInfo(_name);
assertEquals(CacheMXBeanImpl.class.getName(), i.getClassName());
c.close();
getCacheInfo(_name);
}
}