package rocks.inspectit.server.dao.impl;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Random;
import java.util.Set;
import javax.persistence.EntityManager;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.transaction.PlatformTransactionManager;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import rocks.inspectit.server.test.AbstractTestNGLogSupport;
import rocks.inspectit.shared.all.communication.data.DatabaseAggregatedTimerData;
import rocks.inspectit.shared.all.communication.data.ParameterContentData;
import rocks.inspectit.shared.all.communication.data.TimerData;
/**
* Test of {@link TimerDataAggregator}.
*
* @author Ivan Senic
*
*/
@SuppressWarnings("PMD")
public class TimerDataAggregatorTest extends AbstractTestNGLogSupport {
/**
* {@link TimerDataAggregator} to test.
*/
private TimerDataAggregator aggregator;
@Mock
private EntityManager entityManager;
@Mock
private PlatformTransactionManager transactionManager;
/**
* Initialize.
*/
@BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
aggregator = new TimerDataAggregator(transactionManager);
aggregator.aggregationPeriod = 5l;
aggregator.cacheCleanSleepingPeriod = 10;
aggregator.maxElements = 100;
aggregator.entityManager = entityManager;
}
/**
* Tests that after maximum amount of elements is reached we move them to persist list.
*/
@Test
public void maxElementsReached() {
aggregator.maxElements = 1;
TimerData timerData1 = new TimerData(new Timestamp(System.currentTimeMillis()), 10L, 20L, 30L);
TimerData timerData2 = new TimerData(new Timestamp(System.currentTimeMillis()), 100L, 200L, 300L);
aggregator.processTimerData(timerData1);
aggregator.processTimerData(timerData2);
assertThat(aggregator.getElementCount(), is(1));
verifyZeroInteractions(entityManager);
}
/**
* Tests that if we place many time same amount of elements, maximum will not be reached.
*/
@Test
public void noMaxElementsReached() {
aggregator.maxElements = 2;
TimerData timerData1 = new TimerData(new Timestamp(System.currentTimeMillis()), 10L, 20L, 30L);
TimerData timerData2 = new TimerData(new Timestamp(System.currentTimeMillis()), 100L, 200L, 300L);
for (int i = 0; i < 100; i++) {
aggregator.processTimerData(timerData1);
aggregator.processTimerData(timerData2);
}
assertThat(aggregator.getElementCount(), is(2));
verifyZeroInteractions(entityManager);
}
/**
* Tests that persist list saving includes correct elements being saved.
*/
@Test
public void saveAllInPersistList() {
aggregator.maxElements = 1;
TimerData timerData1 = new TimerData(new Timestamp(System.currentTimeMillis()), 10L, 20L, 30L);
TimerData timerData2 = new TimerData(new Timestamp(System.currentTimeMillis()), 100L, 200L, 300L);
aggregator.processTimerData(timerData1);
aggregator.processTimerData(timerData2);
aggregator.saveAllInPersistList();
ArgumentCaptor<DatabaseAggregatedTimerData> argument = ArgumentCaptor.forClass(DatabaseAggregatedTimerData.class);
verify(entityManager, times(1)).persist(argument.capture());
assertThat(argument.getValue(), is(instanceOf(DatabaseAggregatedTimerData.class)));
assertThat(argument.getValue().getPlatformIdent(), is(timerData1.getPlatformIdent()));
assertThat(argument.getValue().getSensorTypeIdent(), is(timerData1.getSensorTypeIdent()));
assertThat(argument.getValue().getMethodIdent(), is(timerData1.getMethodIdent()));
}
/**
* Test for the validity of aggregation.
*/
@Test
public void aggregation() {
long timestampValue = new Date().getTime();
long platformIdent = new Random().nextLong();
final long count = 2;
final double min = 1;
final double max = 2;
final double average = 1.5;
final double duration = 3;
TimerData timerData = new TimerData();
timerData.setTimeStamp(new Timestamp(timestampValue));
timerData.setPlatformIdent(platformIdent);
timerData.setCount(count);
timerData.setExclusiveCount(count);
timerData.setDuration(duration);
timerData.setCpuDuration(duration);
timerData.setExclusiveDuration(duration);
timerData.calculateMin(min);
timerData.calculateCpuMin(min);
timerData.calculateExclusiveMin(min);
timerData.calculateMax(max);
timerData.calculateCpuMax(max);
timerData.calculateExclusiveMax(max);
timerData.setMethodIdent(50L);
TimerData timerData2 = new TimerData();
timerData2.setTimeStamp(new Timestamp(timestampValue * 2));
timerData2.setPlatformIdent(platformIdent);
timerData2.setCount(count);
timerData2.setExclusiveCount(count);
timerData2.setDuration(duration);
timerData2.setCpuDuration(duration);
timerData2.setExclusiveDuration(duration);
timerData2.calculateMin(min);
timerData2.calculateCpuMin(min);
timerData2.calculateExclusiveMin(min);
timerData2.calculateMax(max);
timerData2.calculateCpuMax(max);
timerData2.calculateExclusiveMax(max);
timerData2.setMethodIdent(100L);
final int elements = 1000;
for (int i = 0; i < (elements / 2); i++) {
aggregator.processTimerData(timerData);
}
for (int i = 0; i < (elements / 2); i++) {
aggregator.processTimerData(timerData2);
}
aggregator.removeAndPersistAll();
verify(entityManager, timeout(10000).times(2)).persist(argThat(new ArgumentMatcher<TimerData>() {
@Override
public boolean matches(Object argument) {
if (!DatabaseAggregatedTimerData.class.equals(argument.getClass())) {
return false;
}
TimerData timerData = (TimerData) argument;
assertThat(timerData.getCount() % count, is(equalTo(0L)));
assertThat(timerData.getMin(), is(equalTo(min)));
assertThat(timerData.getMax(), is(equalTo(max)));
assertThat(timerData.getAverage(), is(equalTo(average)));
assertThat(timerData.getDuration() / timerData.getCount(), is(equalTo(average)));
assertThat(timerData.getCpuMin(), is(equalTo(min)));
assertThat(timerData.getCpuMax(), is(equalTo(max)));
assertThat(timerData.getCpuAverage(), is(equalTo(average)));
assertThat(timerData.getCpuDuration() / timerData.getCount(), is(equalTo(average)));
assertThat(timerData.getExclusiveMin(), is(equalTo(min)));
assertThat(timerData.getExclusiveMax(), is(equalTo(max)));
assertThat(timerData.getExclusiveAverage(), is(equalTo(average)));
return true;
}
}));
}
/**
* Verify the zero interactions with setters of {@link TimerData} object passed to the
* aggregator.
*/
@SuppressWarnings("unchecked")
@Test
public void noSetterInteractions() {
TimerData timerData = mock(TimerData.class);
when(timerData.getTimeStamp()).thenReturn(new Timestamp(new Date().getTime()));
when(timerData.getPlatformIdent()).thenReturn(10L);
when(timerData.getMethodIdent()).thenReturn(20L);
aggregator.processTimerData(timerData);
verify(timerData, times(0)).setCount(anyLong());
verify(timerData, times(0)).setCpuDuration(anyDouble());
verify(timerData, times(0)).calculateCpuMax(anyDouble());
verify(timerData, times(0)).calculateCpuMin(anyDouble());
verify(timerData, times(0)).setDuration(anyDouble());
verify(timerData, times(0)).setExclusiveCount(anyLong());
verify(timerData, times(0)).setExclusiveDuration(anyDouble());
verify(timerData, times(0)).calculateExclusiveMax(anyDouble());
verify(timerData, times(0)).calculateExclusiveMin(anyDouble());
verify(timerData, times(0)).setId(anyLong());
verify(timerData, times(0)).calculateMax(anyDouble());
verify(timerData, times(0)).setMethodIdent(anyLong());
verify(timerData, times(0)).calculateMin(anyDouble());
verify(timerData, times(0)).setParameterContentData((Set<ParameterContentData>) anyObject());
verify(timerData, times(0)).setPlatformIdent(anyLong());
verify(timerData, times(0)).setSensorTypeIdent(anyLong());
verify(timerData, times(0)).setTimeStamp((Timestamp) anyObject());
verify(timerData, times(0)).setVariance(anyDouble());
}
}