package com.epam.wilma.safeguard.monitor;
/*==========================================================================
Copyright 2013-2017 EPAM Systems
This file is part of Wilma.
Wilma is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Wilma is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Wilma. If not, see <http://www.gnu.org/licenses/>.
===========================================================================*/
import com.epam.wilma.core.safeguard.SafeguardController;
import com.epam.wilma.domain.exception.SystemException;
import com.epam.wilma.safeguard.configuration.SafeguardConfigurationAccess;
import com.epam.wilma.safeguard.configuration.domain.PropertyDTO;
import com.epam.wilma.safeguard.configuration.domain.QueueSizeProvider;
import com.epam.wilma.safeguard.configuration.domain.SafeguardLimits;
import com.epam.wilma.safeguard.monitor.helper.JmxConnectionBuilder;
import com.epam.wilma.safeguard.monitor.helper.JmxObjectNameProvider;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.internal.util.reflection.Whitebox;
import org.slf4j.Logger;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
* Provides tests for the class {@link JmsQueueMonitorTask}.
* @author Marton_Sereg
*
*/
public class JmsQueueMonitorTaskTest {
@InjectMocks
private JmsQueueMonitorTask underTest;
@Mock
private JmxConnectionBuilder jmxConnectionBuilder;
@Mock
private JmxObjectNameProvider jmxObjectNameProvider;
@Mock
private MBeanServerConnection mBeanServerConnection;
@Mock
private ObjectName responseQueue;
@Mock
private ObjectName loggerQueue;
@Mock
private ObjectName dlqQueue;
@Mock
private ObjectName amqObject;
@Mock
private Logger logger;
@Mock
private SafeguardController safeguardController;
@Mock
private SafeguardConfigurationAccess configurationAccess;
@Mock
private PropertyDTO propertyDTO;
@Mock
private QueueSizeProvider queueSizeProvider;
@BeforeMethod
public void setUp() {
MockitoAnnotations.initMocks(this);
Whitebox.setInternalState(underTest, "logger", logger);
given(configurationAccess.getProperties()).willReturn(propertyDTO);
given(propertyDTO.getSafeguardLimits()).willReturn(new SafeguardLimits(new Long(100), new Long(60), new Long(200), new Long(80), "1099"));
}
@Test
public final void testRunShouldSwitchOnlyFIOffWhenFIOffLimitExceededButMWOffLimitNotExceeded() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(12));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(91));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(logger).info("Due to High load, FI decompression is turned OFF.");
verify(logger, never()).info("Due to High load, Message Logging is turned OFF.");
verify(logger, never()).info("Due to Normal load, Message Logging is restored.");
verify(logger, never()).info("Due to Normal load, FI decompression is restored.");
}
@Test
public final void testRunShouldSwitchFIAndMWOffWhenFIAndMwOffLimitExceeded() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(12));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(191));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(logger).info("Due to High load, FI decompression is turned OFF.");
verify(logger).info("Due to High load, Message Logging is turned OFF.");
verify(logger, never()).info("Due to Normal load, Message Logging is restored.");
verify(logger, never()).info("Due to Normal load, FI decompression is restored.");
}
@Test
public final void testRunShouldNotSwitchOffAnythingWhenLimitsAreNotExceeded() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(12));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(11));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(logger, never()).info("Due to High load, FI decompression is turned OFF.");
verify(logger, never()).info("Due to High load, Message Logging is turned OFF.");
verify(logger, never()).info("Due to Normal load, Message Logging is restored.");
verify(logger, never()).info("Due to Normal load, FI decompression is restored.");
}
@Test
public final void testRunShouldntSwitchOnAnythingWhenQueueSizeDidntDropBelowAnyLimit() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", false);
Whitebox.setInternalState(underTest, "messageWritingEnabled", false);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(12));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(111));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(logger, never()).info("Due to High load, FI decompression is turned OFF.");
verify(logger, never()).info("Due to High load, Message Logging is turned OFF.");
verify(logger, never()).info("Due to Normal load, Message Logging is restored.");
verify(logger, never()).info("Due to Normal load, FI decompression is restored.");
}
@Test
public final void testRunShouldSwitchMWOnWhenQueueSizeDroppedBelowMWLimit() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", false);
Whitebox.setInternalState(underTest, "messageWritingEnabled", false);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(12));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(58));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(logger, never()).info("Due to High load, FI decompression is turned OFF.");
verify(logger, never()).info("Due to High load, Message Logging is turned OFF.");
verify(logger).info("Due to Normal load, Message Logging is restored.");
verify(logger, never()).info("Due to Normal load, FI decompression is restored.");
}
@Test
public final void testRunShouldSwitchMWAndFIOnWhenQueueSizeDroppedBelowFILimit() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", false);
Whitebox.setInternalState(underTest, "messageWritingEnabled", false);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(2));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(3));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(logger, never()).info("Due to High load, FI decompression is turned OFF.");
verify(logger, never()).info("Due to High load, Message Logging is turned OFF.");
verify(logger).info("Due to Normal load, Message Logging is restored.");
verify(logger).info("Due to Normal load, FI decompression is restored.");
}
@Test(expectedExceptions = SystemException.class)
public final void testRunShouldThrowExceptionWhenQueueSizeCannotBeRetrieved() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willThrow(new AttributeNotFoundException());
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(91));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN exception is thrown
}
@Test(expectedExceptions = SystemException.class)
public final void testRunShouldThrowExceptionWhenMemoryUsageCannotBeRetrieved() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(2));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(91));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willThrow(new AttributeNotFoundException());
// WHEN
underTest.run();
// THEN exception is thrown
}
@Test
public final void testRunShouldInitConnectionWhenLoggerQueueIsNull() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "loggerQueue", null);
QueueSizeProvider queueSizeProvider = new QueueSizeProvider();
Whitebox.setInternalState(underTest, "queueSizeProvider", queueSizeProvider);
givenJmxConnectionBuilder();
// WHEN
underTest.run();
// THEN
verifyConnectionBuilder();
}
@Test
public final void testRunShouldInitConnectionWhenResponseQueueIsNull() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "responseQueue", null);
QueueSizeProvider queueSizeProvider = new QueueSizeProvider();
Whitebox.setInternalState(underTest, "queueSizeProvider", queueSizeProvider);
givenJmxConnectionBuilder();
// WHEN
underTest.run();
// THEN
verifyConnectionBuilder();
}
@Test
public final void testRunShouldInitConnectionWhenMBeanServerConnectionIsNull() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "mBeanServerConnection", null);
QueueSizeProvider queueSizeProvider = new QueueSizeProvider();
Whitebox.setInternalState(underTest, "queueSizeProvider", queueSizeProvider);
givenJmxConnectionBuilder();
// WHEN
underTest.run();
// THEN
verifyConnectionBuilder();
}
@Test
public final void testRunShouldInitConnectionWhenAmqObjectIsNull() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "amqObject", null);
QueueSizeProvider queueSizeProvider = new QueueSizeProvider();
Whitebox.setInternalState(underTest, "queueSizeProvider", queueSizeProvider);
givenJmxConnectionBuilder();
// WHEN
underTest.run();
// THEN
verifyConnectionBuilder();
}
@Test
public final void testRunShouldSetQueueSizesIntoQueueSizeProvider() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(12));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(91));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(queueSizeProvider).setResponseQueueSize(new Long(12));
verify(queueSizeProvider).setLoggerQueueSize(new Long(91));
}
@Test
public final void testRunShouldSaveQueueSizesIntoQueueSizeProvider() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
QueueSizeProvider queueSizeProvider = new QueueSizeProvider();
Whitebox.setInternalState(underTest, "queueSizeProvider", queueSizeProvider);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(12));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(91));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
long loggerQueueSize = ((QueueSizeProvider) Whitebox.getInternalState(underTest, "queueSizeProvider")).getLoggerQueueSize();
Assert.assertEquals(loggerQueueSize, 91);
long responseQueueSize = ((QueueSizeProvider) Whitebox.getInternalState(underTest, "queueSizeProvider")).getResponseQueueSize();
Assert.assertEquals(responseQueueSize, 12);
}
@Test
public final void testRunShouldPurgeDlqQueue() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
QueueSizeProvider queueSizeProvider = new QueueSizeProvider();
Whitebox.setInternalState(underTest, "queueSizeProvider", queueSizeProvider);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(1));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(mBeanServerConnection).invoke(dlqQueue, "purge", null, null);
}
@Test
public final void testRunShouldRestartAmqWhenAmqMemoryIsFull() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
QueueSizeProvider queueSizeProvider = new QueueSizeProvider();
Whitebox.setInternalState(underTest, "queueSizeProvider", queueSizeProvider);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(1));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(JmsQueueMonitorTask.MAX_AMQ_MEMORY_USAGE + 1));
// WHEN
underTest.run();
// THEN
verify(mBeanServerConnection).invoke(amqObject, "restart", null, null);
}
@Test
public final void testRunShouldRestartAmqWhenTotalQueueSizeIsTooBig() throws Exception {
// GIVEN
Whitebox.setInternalState(underTest, "fIDecompressionEnabled", true);
Whitebox.setInternalState(underTest, "messageWritingEnabled", true);
QueueSizeProvider queueSizeProvider = new QueueSizeProvider();
Whitebox.setInternalState(underTest, "queueSizeProvider", queueSizeProvider);
Long queueSizeIsTooBig = JmsQueueMonitorTask.MAX_MULTIPLIER_OF_MESSAGE_OFF_LIMIT * propertyDTO.getSafeguardLimits().getMwOffLimit() + 1;
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(queueSizeIsTooBig);
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
// WHEN
underTest.run();
// THEN
verify(mBeanServerConnection).invoke(amqObject, "restart", null, null);
}
private void givenJmxConnectionBuilder() throws Exception {
given(jmxConnectionBuilder.buildMBeanServerConnection(JmsQueueMonitorTask.JMX_SERVICE_PRE_URL
+ "1099" + JmsQueueMonitorTask.JMX_SERVICE_POST_URL)).willReturn(mBeanServerConnection);
given(jmxObjectNameProvider.getObjectName(JmsQueueMonitorTask.RESPONSE_QUEUE_OBJECT_NAME)).willReturn(responseQueue);
given(jmxObjectNameProvider.getObjectName(JmsQueueMonitorTask.LOGGER_QUEUE_OBJECT_NAME)).willReturn(loggerQueue);
given(jmxObjectNameProvider.getObjectName(JmsQueueMonitorTask.DLQ_QUEUE_OBJECT_NAME)).willReturn(dlqQueue);
given(jmxObjectNameProvider.getObjectName(JmsQueueMonitorTask.AMQ_OBJECT_NAME)).willReturn(amqObject);
given(mBeanServerConnection.getAttribute(responseQueue, "QueueSize")).willReturn(new Long(2));
given(mBeanServerConnection.getAttribute(loggerQueue, "QueueSize")).willReturn(new Long(3));
given(mBeanServerConnection.getAttribute(dlqQueue, "QueueSize")).willReturn(new Long(0));
given(mBeanServerConnection.getAttribute(amqObject, "MemoryPercentUsage")).willReturn(new Integer(0));
}
private void verifyConnectionBuilder() {
verify(jmxConnectionBuilder).buildMBeanServerConnection(JmsQueueMonitorTask.JMX_SERVICE_PRE_URL + "1099" + JmsQueueMonitorTask.JMX_SERVICE_POST_URL);
verify(jmxObjectNameProvider).getObjectName(JmsQueueMonitorTask.RESPONSE_QUEUE_OBJECT_NAME);
verify(jmxObjectNameProvider).getObjectName(JmsQueueMonitorTask.LOGGER_QUEUE_OBJECT_NAME);
verify(jmxObjectNameProvider).getObjectName(JmsQueueMonitorTask.DLQ_QUEUE_OBJECT_NAME);
verify(jmxObjectNameProvider).getObjectName(JmsQueueMonitorTask.AMQ_OBJECT_NAME);
}
}