/atlassian-plugins-core/src/test/java/com/atlassian/plugin/jmx/TestAbstractJmxBridge.java
Java | 279 lines | 205 code | 60 blank | 14 comment | 0 complexity | f6c4e0a0d359f02a1512c7ca5315e19f MD5 | raw file
- package com.atlassian.plugin.jmx;
- import org.hamcrest.Matchers;
- import org.junit.Before;
- import org.junit.Rule;
- import org.junit.Test;
- import org.junit.rules.ExpectedException;
- import javax.management.InstanceNotFoundException;
- import javax.management.MBeanServer;
- import javax.management.ObjectName;
- import javax.management.RuntimeMBeanException;
- import java.lang.management.ManagementFactory;
- import java.util.concurrent.atomic.AtomicInteger;
- import static org.hamcrest.MatcherAssert.assertThat;
- import static org.hamcrest.Matchers.containsString;
- import static org.hamcrest.Matchers.instanceOf;
- import static org.hamcrest.Matchers.is;
- public class TestAbstractJmxBridge {
- private static final boolean NONDEFAULT_BOOLEAN = true;
- private static final char NONDEFAULT_CHAR = 'A';
- private static final byte NONDEFAULT_BYTE = 1;
- private static final short NONDEFAULT_SHORT = 2;
- private static final int NONDEFAULT_INT = 3;
- private static final long NONDEFAULT_LONG = 4;
- private static final float NONDEFAULT_FLOAT = 5;
- private static final double NONDEFAULT_DOUBLE = 6;
- private static final String NONDEFAULT_STRING = "B";
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
- @SuppressWarnings("UnusedDeclaration")
- public interface SampleMXBean {
- boolean getBoolean();
- char getChar();
- byte getByte();
- short getShort();
- int getInt();
- long getLong();
- float getFloat();
- double getDouble();
- String getString();
- void operation();
- String concat(String left, String right);
- }
- /**
- * Test class for abstract {@link AbstractJmxBridge}.
- * <p/>
- * As well as a test class, this serves as an example for the idiomatic usage {@link AbstractJmxBridge}.
- */
- private static class SampleJmxBridge extends AbstractJmxBridge<SampleMXBean> implements SampleMXBean {
- /**
- * Counter for uniqueifying jmx object names.
- */
- private static final AtomicInteger nextJmxInstance = new AtomicInteger();
- private int operationCount;
- public SampleJmxBridge() {
- super(JmxUtil.objectName(nextJmxInstance, "Sample"), SampleMXBean.class);
- }
- @Override
- protected SampleMXBean getMXBean() {
- return this;
- }
- public int getOperationCount() {
- return operationCount;
- }
- @Override
- public boolean getBoolean() {
- return NONDEFAULT_BOOLEAN;
- }
- @Override
- public char getChar() {
- return NONDEFAULT_CHAR;
- }
- @Override
- public byte getByte() {
- return NONDEFAULT_BYTE;
- }
- @Override
- public short getShort() {
- return NONDEFAULT_SHORT;
- }
- @Override
- public int getInt() {
- return NONDEFAULT_INT;
- }
- @Override
- public long getLong() {
- return NONDEFAULT_LONG;
- }
- @Override
- public float getFloat() {
- return NONDEFAULT_FLOAT;
- }
- @Override
- public double getDouble() {
- return NONDEFAULT_DOUBLE;
- }
- @Override
- public String getString() {
- return NONDEFAULT_STRING;
- }
- @Override
- public void operation() {
- ++operationCount;
- }
- @Override
- public String concat(final String left, final String right) {
- return left + right;
- }
- }
- private SampleJmxBridge sampleJmxBridge;
- private MBeanServer platformMBeanServer;
- @Before
- public void setUp() throws Exception {
- sampleJmxBridge = new SampleJmxBridge();
- platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
- }
- @Test
- public void getObjectNameMentionsType() {
- final ObjectName objectName = sampleJmxBridge.getObjectName();
- assertThat(objectName.toString(), containsString("Sample"));
- }
- @Test
- public void notExposedToJmxBeforeRegister() throws Exception {
- final ObjectName objectName = sampleJmxBridge.getObjectName();
- expectedException.expect(InstanceNotFoundException.class);
- expectedException.expectMessage(objectName.toString());
- platformMBeanServer.invoke(objectName, "operation", new Object[0], new String[0]);
- }
- @Test
- public void registerExposesToJmx() throws Exception {
- final ObjectName objectName = sampleJmxBridge.getObjectName();
- sampleJmxBridge.register();
- final int before = sampleJmxBridge.getOperationCount();
- platformMBeanServer.invoke(objectName, "operation", new Object[0], new String[0]);
- assertThat(sampleJmxBridge.getOperationCount(), is(before + 1));
- }
- @Test
- public void primitiveTypesAreReturnedBoxed() throws Exception {
- // Originally the proxy had some special case code around primitives, so i'm leaving these tests here as they not costly
- final ObjectName objectName = sampleJmxBridge.getObjectName();
- sampleJmxBridge.register();
- final Object aBoolean = platformMBeanServer.getAttribute(objectName, "Boolean");
- assertThat(aBoolean, instanceOf(Boolean.class));
- assertThat((Boolean) aBoolean, is(NONDEFAULT_BOOLEAN));
- final Object aChar = platformMBeanServer.getAttribute(objectName, "Char");
- assertThat(aChar, instanceOf(Character.class));
- assertThat((Character) aChar, is(NONDEFAULT_CHAR));
- final Object aByte = platformMBeanServer.getAttribute(objectName, "Byte");
- assertThat(aByte, instanceOf(Byte.class));
- assertThat((Byte) aByte, is(NONDEFAULT_BYTE));
- final Object aShort = platformMBeanServer.getAttribute(objectName, "Short");
- assertThat(aShort, instanceOf(Short.class));
- assertThat((Short) aShort, is(NONDEFAULT_SHORT));
- final Object anInt = platformMBeanServer.getAttribute(objectName, "Int");
- assertThat(anInt, instanceOf(Integer.class));
- assertThat((Integer) anInt, is(NONDEFAULT_INT));
- final Object aLong = platformMBeanServer.getAttribute(objectName, "Long");
- assertThat(aLong, instanceOf(Long.class));
- assertThat((Long) aLong, is(NONDEFAULT_LONG));
- final Object aFloat = platformMBeanServer.getAttribute(objectName, "Float");
- assertThat(aFloat, instanceOf(Float.class));
- assertThat((Float) aFloat, is(NONDEFAULT_FLOAT));
- final Object aDouble = platformMBeanServer.getAttribute(objectName, "Double");
- assertThat(aDouble, instanceOf(Double.class));
- assertThat((Double) aDouble, is(NONDEFAULT_DOUBLE));
- final Object aString = platformMBeanServer.getAttribute(objectName, "String");
- assertThat(aString, instanceOf(String.class));
- assertThat((String) aString, is(NONDEFAULT_STRING));
- }
- @Test
- public void parametersArePassedCorrectly() throws Exception {
- final ObjectName objectName = sampleJmxBridge.getObjectName();
- sampleJmxBridge.register();
- final Object[] params = {"left", "right"};
- final String[] signature = new String[]{String.class.getName(), String.class.getName()};
- final Object result = platformMBeanServer.invoke(objectName, "concat", params, signature);
- assertThat(result, instanceOf(String.class));
- assertThat((String) result, is("leftright"));
- }
- @Test
- public void notExposedToJmxAfterUnregister() throws Exception {
- final ObjectName objectName = sampleJmxBridge.getObjectName();
- sampleJmxBridge.register();
- sampleJmxBridge.unregister();
- expectedException.expect(InstanceNotFoundException.class);
- expectedException.expectMessage(objectName.toString());
- platformMBeanServer.invoke(objectName, "operation", new Object[0], new String[0]);
- }
- @Test
- public void throwsIllegalStateExceptionIfReferenceIsCleared() throws Exception {
- // This is as close to testing the garbage collection can be easily managed
- final ObjectName objectName = sampleJmxBridge.getObjectName();
- // registerInternal is just register but exposing state we can use to fake garbage collection.
- final AbstractJmxBridge.WeakMXBeanInvocationHandler<SampleMXBean> invocationHandler = sampleJmxBridge.registerInternal();
- // Quick check that registerInternal works as expected to validate the test
- final Object aString = platformMBeanServer.getAttribute(objectName, "String");
- assertThat(aString, instanceOf(String.class));
- assertThat((String) aString, is(NONDEFAULT_STRING));
- invocationHandler.getImplementationReference().clear();
- expectedException.expect(RuntimeMBeanException.class);
- expectedException.expectCause(Matchers.<Throwable>instanceOf(IllegalStateException.class));
- expectedException.expectMessage(objectName.toString());
- platformMBeanServer.invoke(objectName, "operation", new Object[0], new String[0]);
- }
- @Test
- public void usageAfterReferenceClearsCausesUnregister() throws Exception {
- final ObjectName objectName = sampleJmxBridge.getObjectName();
- final AbstractJmxBridge.WeakMXBeanInvocationHandler<SampleMXBean> invocationHandler = sampleJmxBridge.registerInternal();
- invocationHandler.getImplementationReference().clear();
- try {
- platformMBeanServer.invoke(objectName, "operation", new Object[0], new String[0]);
- } catch (RuntimeMBeanException ermb) {
- // Expected
- }
- // Note that this is the same exception shape as use before registration
- expectedException.expect(InstanceNotFoundException.class);
- expectedException.expectMessage(objectName.toString());
- platformMBeanServer.invoke(objectName, "operation", new Object[0], new String[0]);
- }
- }