/* * Copyright 2014, The Sporting Exchange Limited * * 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.betfair.cougar.util.monitors; import com.betfair.cougar.CougarUtilTestCase; import com.betfair.cougar.util.monitors.JMXMonitor.IsHealthyExpression; import com.betfair.tornjak.monitor.Monitor; import com.betfair.tornjak.monitor.MonitorRegistry; import com.betfair.tornjak.monitor.Status; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import javax.management.MBeanServer; import javax.management.ObjectName; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; public class JMXMonitorTest extends CougarUtilTestCase { private MonitorRegistry registry; private MBeanServer mBeanServer; private Logger logger; private Logger oldLogger; public JMXMonitorTest() { super(JMXMonitor.class); } @Before public void setUp() { registry = mock(MonitorRegistry.class); mBeanServer = mock(MBeanServer.class); logger = mock(Logger.class); oldLogger = JMXMonitor.setLogger(logger); } @After public void tearDown() { JMXMonitor.setLogger(oldLogger); } private static final IsHealthyExpression notHealthy = new IsHealthyExpression() { public boolean evaluate(Object value) { return false; } }; private static final IsHealthyExpression isHealthy = new IsHealthyExpression() { public boolean evaluate(Object value) { return true; } }; @Test public void testJMXMonitorBadFailState() throws Exception{ try { JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=ClassLoading", "Verbose", "false", false, Status.OK); fail(); } catch (IllegalArgumentException e) { // good } } private void verifyZeroWarnInteractions() { verify(logger, times(0)).warn(anyString(), anyObject()); verify(logger, times(0)).warn(anyString(), anyObject(), anyObject()); verify(logger, times(0)).warn(anyString(), any(Object[].class)); verify(logger, times(0)).warn(anyString()); verify(logger, times(0)).warn(anyString(), any(Throwable.class)); } @Test public void testJMXMonitorOK() throws Exception{ when(mBeanServer.isRegistered(any(ObjectName.class))).thenReturn(true); when(mBeanServer.getAttribute(any(ObjectName.class), anyString())).thenReturn("false"); JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=ClassLoading", "Verbose", "false", false); assertEquals(Status.OK, jxm.getStatus()); verify(logger, times(1)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString()); verifyZeroWarnInteractions(); verify(registry, times(1)).addMonitor(any(Monitor.class)); } @Test public void testJMXMonitorFail_NotInMBeanServer() throws Exception{ JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=ClassLoading", "Verbose", "false", false); assertEquals(Status.FAIL, jxm.getStatus()); verify(logger, times(1)).debug(anyString(), anyObject()); // verify(logger, times(1)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString()); verifyZeroWarnInteractions(); verify(registry, times(1)).addMonitor(any(Monitor.class)); } @Test public void testJMXMonitorIgnoreOK() throws Exception{ when(mBeanServer.isRegistered(any(ObjectName.class))).thenReturn(false); JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=NON_EXISTENT", "Verbose", "true", true); assertEquals(Status.OK, jxm.getStatus()); verify(logger, times(1)).debug(anyString(), anyObject()); verify(logger, times(1)).info(anyString()); verifyZeroWarnInteractions(); verify(registry, times(1)).addMonitor(any(Monitor.class)); } @Test public void testJMXMonitorFail() throws Exception{ when(mBeanServer.isRegistered(any(ObjectName.class))).thenReturn(true); JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=ClassLoading", "Verbose", "true", false); assertEquals(Status.FAIL, jxm.getStatus()); verify(logger, times(1)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString()); verifyZeroWarnInteractions(); verify(registry, times(1)).addMonitor(any(Monitor.class)); } @Test public void testJMXMonitorWarning() throws Exception{ when(mBeanServer.isRegistered(any(ObjectName.class))).thenReturn(true); JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=ClassLoading", "Verbose", "true", false, Status.WARN); assertEquals(Status.WARN, jxm.getStatus()); verify(logger, times(1)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString()); verifyZeroWarnInteractions(); verify(registry, times(1)).addMonitor(any(Monitor.class)); } @Test public void testJMXMonitorIgnoreFail() throws Exception{ when(mBeanServer.isRegistered(any(ObjectName.class))).thenReturn(true); JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=NON_EXISTENT", "Verbose", "true", false); assertEquals(Status.FAIL, jxm.getStatus()); verify(logger, times(1)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString()); verifyZeroWarnInteractions(); verify(registry, times(1)).addMonitor(any(Monitor.class)); } @Test public void testJMXMonitorExpressionEvaluation() throws Exception{ IsHealthyExpression expression = new IsHealthyExpression() { @Override public boolean evaluate(Object value) { return false; } }; when(mBeanServer.isRegistered(any(ObjectName.class))).thenReturn(true); JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=NON_EXISTENT", "Verbose", expression, false, Status.WARN); assertEquals(Status.WARN, jxm.getStatus()); verify(logger, times(1)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString()); verifyZeroWarnInteractions(); verify(registry, times(1)).addMonitor(any(Monitor.class)); } @Test public void testJMXMonitorMultiFail() throws Exception{ final IsHealthyExpression healthy = mock(IsHealthyExpression.class); final IsHealthyExpression unhealthy = mock(IsHealthyExpression.class); when(healthy.evaluate(anyString())).thenReturn(true); when(unhealthy.evaluate(anyString())).thenReturn(false); when(mBeanServer.isRegistered(any(ObjectName.class))).thenReturn(true); JMXMonitor jxm = new JMXMonitor(registry, mBeanServer, "java.lang:type=ClassLoading", "Verbose", "true", false); assertEquals(Status.FAIL, jxm.getStatus()); verify(logger, times(1)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString()); verify(logger, times(1)).warn(anyString(), anyString(), anyString(), anyString()); // Check it doesn't log each time a failure occurs jxm.getStatus(); jxm.getStatus(); verify(logger, times(3)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString()); verify(logger, times(0)).info(anyString(), anyString(), anyString(), anyString()); verify(logger, times(1)).warn(anyString(), anyString(), anyString(), anyString()); // Put it back into an OK state Field f = jxm.getClass().getDeclaredField("isHealthyExpression"); f.setAccessible(true); f.set(jxm, isHealthy); assertEquals(Status.OK, jxm.getStatus()); verify(logger, times(4)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString(), anyString(), anyString()); verify(logger, times(1)).warn(anyString(), anyString(), anyString(), anyString()); // And back to failure. f.set(jxm, notHealthy); assertEquals(Status.FAIL, jxm.getStatus()); verify(logger, times(5)).debug(anyString(), anyObject(), anyObject()); verify(logger, times(1)).info(anyString(), anyString(), anyString()); verify(logger, times(2)).warn(anyString(), anyString(), anyString(), anyString()); verify(registry, times(1)).addMonitor(any(Monitor.class)); } }