package rocks.inspectit.shared.cs.indexing.impl;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.comparesEqualTo;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import rocks.inspectit.shared.all.communication.DefaultData;
import rocks.inspectit.shared.all.communication.MethodSensorData;
import rocks.inspectit.shared.all.communication.data.InvocationSequenceData;
import rocks.inspectit.shared.all.communication.data.SqlStatementData;
import rocks.inspectit.shared.all.communication.data.TimerData;
import rocks.inspectit.shared.cs.indexing.indexer.impl.MethodIdentIndexer;
import rocks.inspectit.shared.cs.indexing.indexer.impl.ObjectTypeIndexer;
import rocks.inspectit.shared.cs.indexing.indexer.impl.PlatformIdentIndexer;
import rocks.inspectit.shared.cs.indexing.indexer.impl.SensorTypeIdentIndexer;
import rocks.inspectit.shared.cs.indexing.indexer.impl.TimestampIndexer;
import rocks.inspectit.shared.cs.indexing.storage.IStorageDescriptor;
import rocks.inspectit.shared.cs.indexing.storage.IStorageTreeComponent;
import rocks.inspectit.shared.cs.indexing.storage.impl.ArrayBasedStorageLeaf;
import rocks.inspectit.shared.cs.indexing.storage.impl.CombinedStorageBranch;
import rocks.inspectit.shared.cs.indexing.storage.impl.LeafWithNoDescriptors;
import rocks.inspectit.shared.cs.indexing.storage.impl.StorageBranch;
import rocks.inspectit.shared.cs.indexing.storage.impl.StorageBranchIndexer;
import rocks.inspectit.shared.cs.indexing.storage.impl.StorageDescriptor;
import rocks.inspectit.shared.cs.indexing.storage.impl.StorageIndexQuery;
/**
* Test for checking the {@link IStorageTreeComponent}s.
*
* @author Ivan Senic
*
*/
public class StorageIndexingTest {
/**
* {@link StorageIndexQuery}.
*/
private StorageIndexQuery storageIndexQuery;
/**
* The forkJoinPool which starts the forks
*/
private ForkJoinPool forkJoinPool = new ForkJoinPool();
/**
* Initializes the index query.
*/
@BeforeMethod
public void initMethod() {
storageIndexQuery = new StorageIndexQuery();
}
/**
* Test tree with empty query. All elements should be returned.
*
* @throws IndexingException
* If {@link IndexingException} occurs.
*/
@Test
public void emptyQueryTest() throws IndexingException {
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(new StorageBranchIndexer<>(new ObjectTypeIndexer<>(), false));
DefaultData defaultData = mock(DefaultData.class);
when(defaultData.getId()).thenReturn(1L);
IStorageDescriptor storageDescriptor1 = rootBranch.put(defaultData);
storageDescriptor1.setPositionAndSize(0, 1);
SqlStatementData defaultData2 = mock(SqlStatementData.class);
when(defaultData2.getId()).thenReturn(2L);
IStorageDescriptor storageDescriptor2 = rootBranch.put(defaultData2);
storageDescriptor2.setPositionAndSize(2, 1);
List<IStorageDescriptor> results = rootBranch.query(storageIndexQuery);
assertThat(results.size(), is(equalTo(2)));
// Test for forkJoinPool
List<IStorageDescriptor> resultsForkJoin = rootBranch.query(storageIndexQuery, forkJoinPool);
assertThat(resultsForkJoin.size(), is(equalTo(2)));
}
/**
* Test that putting one element will return the same {@link IStorageDescriptor} as when get is
* executed..
*
* @throws IndexingException
* If {@link IndexingException} occurs.
*/
@Test
public void putAndGetInvocation() throws IndexingException {
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(new StorageBranchIndexer<>(new ObjectTypeIndexer<>(), false));
InvocationSequenceData invocationSequenceData = new InvocationSequenceData();
invocationSequenceData.setId(1L);
IStorageDescriptor storageDescriptor = rootBranch.put(invocationSequenceData);
assertThat(storageDescriptor, comparesEqualTo(rootBranch.get(invocationSequenceData)));
}
/**
* Test that the get on the {@link LeafWithNoDescriptors} will throw an exception if invoked.
*
* @throws IndexingException
* If {@link IndexingException} occurs.
*/
@Test(expectedExceptions = { UnsupportedOperationException.class })
public void putAndGetElement() throws IndexingException {
IStorageTreeComponent<DefaultData> rootBranch = new LeafWithNoDescriptors<>();
DefaultData defaultData = mock(DefaultData.class);
when(defaultData.getId()).thenReturn(1L);
rootBranch.put(defaultData);
rootBranch.get(defaultData);
}
/**
* Test tree with query that holds only platform ident.
*
* @throws IndexingException
* If {@link IndexingException} occurs.
*/
@Test
public void queryBranchWithPlatformIdent() throws IndexingException {
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(new StorageBranchIndexer<>(new PlatformIdentIndexer<>(), false));
DefaultData defaultData1 = mock(DefaultData.class);
when(defaultData1.getId()).thenReturn(1L);
when(defaultData1.getPlatformIdent()).thenReturn(10L);
IStorageDescriptor storageDescriptor1 = rootBranch.put(defaultData1);
storageDescriptor1.setPositionAndSize(0L, 100L);
DefaultData defaultData2 = mock(DefaultData.class);
when(defaultData2.getId()).thenReturn(2L);
when(defaultData2.getPlatformIdent()).thenReturn(20L);
IStorageDescriptor storageDescriptor2 = rootBranch.put(defaultData2);
storageDescriptor2.setPositionAndSize(0L, 200L);
storageIndexQuery.setPlatformIdent(10L);
List<IStorageDescriptor> results = rootBranch.query(storageIndexQuery);
assertThat(results.size(), is(equalTo(1)));
for (IStorageDescriptor result : results) {
assertThat(result.getSize(), is(equalTo(100L)));
}
// Test for forkJoinPool
List<IStorageDescriptor> resultsForkJoin = rootBranch.query(storageIndexQuery, forkJoinPool);
assertThat(resultsForkJoin.size(), is(equalTo(1)));
for (IStorageDescriptor result : resultsForkJoin) {
assertThat(result.getSize(), is(equalTo(100L)));
}
}
/**
* Test tree with query that holds only method ident.
*
* @throws IndexingException
* If {@link IndexingException} occurs.
*/
@Test
public void queryBranchWithMethodIdent() throws IndexingException {
IStorageTreeComponent<MethodSensorData> rootBranch = new StorageBranch<>(new StorageBranchIndexer<>(new MethodIdentIndexer<MethodSensorData>(), false));
MethodSensorData defaultData1 = mock(MethodSensorData.class);
when(defaultData1.getId()).thenReturn(1L);
when(defaultData1.getMethodIdent()).thenReturn(10L);
IStorageDescriptor storageDescriptor1 = rootBranch.put(defaultData1);
storageDescriptor1.setPositionAndSize(0L, 100L);
MethodSensorData defaultData2 = mock(MethodSensorData.class);
when(defaultData2.getId()).thenReturn(2L);
when(defaultData2.getMethodIdent()).thenReturn(20L);
IStorageDescriptor storageDescriptor2 = rootBranch.put(defaultData2);
storageDescriptor2.setPositionAndSize(0L, 200L);
storageIndexQuery.setMethodIdent(10L);
List<IStorageDescriptor> results = rootBranch.query(storageIndexQuery);
assertThat(results.size(), is(equalTo(1)));
for (IStorageDescriptor result : results) {
assertThat(result.getSize(), is(equalTo(100L)));
}
// Test for forkJoinPool
List<IStorageDescriptor> resultsForkJoin = rootBranch.query(storageIndexQuery, forkJoinPool);
assertThat(resultsForkJoin.size(), is(equalTo(1)));
for (IStorageDescriptor result : resultsForkJoin) {
assertThat(result.getSize(), is(equalTo(100L)));
}
}
/**
* Test tree with query that holds only object type.
*
* @throws IndexingException
* If {@link IndexingException} occurs.
*/
@Test
public void queryBranchWithObjectType() throws IndexingException {
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(new StorageBranchIndexer<>(new ObjectTypeIndexer<>(), false));
TimerData defaultData1 = mock(TimerData.class);
when(defaultData1.getId()).thenReturn(1L);
IStorageDescriptor storageDescriptor1 = rootBranch.put(defaultData1);
storageDescriptor1.setPositionAndSize(0L, 100L);
SqlStatementData defaultData2 = mock(SqlStatementData.class);
when(defaultData2.getId()).thenReturn(2L);
IStorageDescriptor storageDescriptor2 = rootBranch.put(defaultData2);
storageDescriptor2.setPositionAndSize(0L, 200L);
List<Class<?>> searchedClasses = new ArrayList<>();
searchedClasses.add(defaultData1.getClass());
storageIndexQuery.setObjectClasses(searchedClasses);
List<IStorageDescriptor> results = rootBranch.query(storageIndexQuery);
assertThat(results.size(), is(equalTo(1)));
for (IStorageDescriptor result : results) {
assertThat(result.getSize(), is(equalTo(100L)));
}
// Test for forkJoinPool
List<IStorageDescriptor> resultsForkJoin = rootBranch.query(storageIndexQuery, forkJoinPool);
assertThat(resultsForkJoin.size(), is(equalTo(1)));
for (IStorageDescriptor result : resultsForkJoin) {
assertThat(result.getSize(), is(equalTo(100L)));
}
}
/**
* Test tree with query that holds only time interval.
*
* @throws IndexingException
* If {@link IndexingException} occurs.
*/
@Test
public void queryBranchWithTimestampInterval() throws IndexingException {
Timestamp minusHour = new Timestamp(new Date().getTime() + (20 * 60 * 1000));
Timestamp plusHour = new Timestamp(new Date().getTime() + (25 * 60 * 1000));
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(new StorageBranchIndexer<>(new TimestampIndexer<>(), false));
DefaultData defaultData1 = mock(DefaultData.class);
when(defaultData1.getId()).thenReturn(1L);
when(defaultData1.getTimeStamp()).thenReturn(new Timestamp(new Date().getTime()));
IStorageDescriptor storageDescriptor1 = rootBranch.put(defaultData1);
storageDescriptor1.setPositionAndSize(0L, 100L);
DefaultData defaultData2 = mock(DefaultData.class);
when(defaultData2.getId()).thenReturn(2L);
when(defaultData2.getTimeStamp()).thenReturn(plusHour);
IStorageDescriptor storageDescriptor2 = rootBranch.put(defaultData2);
storageDescriptor2.setPositionAndSize(0L, 200L);
storageIndexQuery.setFromDate(minusHour);
storageIndexQuery.setToDate(plusHour);
List<IStorageDescriptor> results = rootBranch.query(storageIndexQuery);
assertThat(results.size(), is(equalTo(1)));
for (IStorageDescriptor result : results) {
assertThat(result.getSize(), is(equalTo(200L)));
}
// Test for forkJoinPool
List<IStorageDescriptor> resultsForkJoin = rootBranch.query(storageIndexQuery, forkJoinPool);
assertThat(resultsForkJoin.size(), is(equalTo(1)));
for (IStorageDescriptor result : resultsForkJoin) {
assertThat(result.getSize(), is(equalTo(200L)));
}
}
/**
* Test tree with query that holds platform ident and sensor ident in different levels.
*
* @throws IndexingException
* If {@link IndexingException} occurs.
*/
@Test
public void queryDifferentLevels() throws IndexingException {
StorageBranchIndexer<DefaultData> sensorTypeIndexer = new StorageBranchIndexer<>(new SensorTypeIdentIndexer<>(), false);
StorageBranchIndexer<DefaultData> objectTypeIndexer = new StorageBranchIndexer<>(new ObjectTypeIndexer<>(), sensorTypeIndexer, false);
StorageBranchIndexer<DefaultData> platformTypeIndexer = new StorageBranchIndexer<>(new PlatformIdentIndexer<>(), objectTypeIndexer, false);
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(platformTypeIndexer);
TimerData defaultData1 = mock(TimerData.class);
when(defaultData1.getId()).thenReturn(1L);
when(defaultData1.getPlatformIdent()).thenReturn(10L);
when(defaultData1.getSensorTypeIdent()).thenReturn(10L);
IStorageDescriptor storageDescriptor1 = rootBranch.put(defaultData1);
storageDescriptor1.setPositionAndSize(0L, 100L);
SqlStatementData defaultData2 = mock(SqlStatementData.class);
when(defaultData2.getId()).thenReturn(2L);
when(defaultData2.getPlatformIdent()).thenReturn(10L);
when(defaultData2.getSensorTypeIdent()).thenReturn(20L);
IStorageDescriptor storageDescriptor2 = rootBranch.put(defaultData2);
storageDescriptor2.setPositionAndSize(0L, 200L);
storageIndexQuery.setPlatformIdent(10L);
List<IStorageDescriptor> results = rootBranch.query(storageIndexQuery);
assertThat(results.size(), is(equalTo(2)));
long totalSize = 0;
for (IStorageDescriptor result : results) {
totalSize += result.getSize();
}
assertThat(totalSize, is(equalTo(300L)));
storageIndexQuery.setPlatformIdent(10L);
storageIndexQuery.setSensorTypeIdent(10L);
results = rootBranch.query(storageIndexQuery);
assertThat(results.size(), is(equalTo(1)));
for (IStorageDescriptor result : results) {
assertThat(result.getSize(), is(equalTo(100L)));
}
}
/**
* Same Test as queryDifferentLevels() except with ForkJoin
*
* @throws IndexingException
*/
@Test
public void queryDifferentLevelsForkJoin() throws IndexingException {
StorageBranchIndexer<DefaultData> sensorTypeIndexer = new StorageBranchIndexer<>(new SensorTypeIdentIndexer<>(), false);
StorageBranchIndexer<DefaultData> objectTypeIndexer = new StorageBranchIndexer<>(new ObjectTypeIndexer<>(), sensorTypeIndexer, false);
StorageBranchIndexer<DefaultData> platformTypeIndexer = new StorageBranchIndexer<>(new PlatformIdentIndexer<>(), objectTypeIndexer, false);
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(platformTypeIndexer);
TimerData defaultData1 = mock(TimerData.class);
when(defaultData1.getId()).thenReturn(1L);
when(defaultData1.getPlatformIdent()).thenReturn(10L);
when(defaultData1.getSensorTypeIdent()).thenReturn(10L);
IStorageDescriptor storageDescriptor1 = rootBranch.put(defaultData1);
storageDescriptor1.setPositionAndSize(0L, 100L);
SqlStatementData defaultData2 = mock(SqlStatementData.class);
when(defaultData2.getId()).thenReturn(2L);
when(defaultData2.getPlatformIdent()).thenReturn(10L);
when(defaultData2.getSensorTypeIdent()).thenReturn(20L);
IStorageDescriptor storageDescriptor2 = rootBranch.put(defaultData2);
storageDescriptor2.setPositionAndSize(0L, 200L);
storageIndexQuery.setPlatformIdent(10L);
List<IStorageDescriptor> results = rootBranch.query(storageIndexQuery, forkJoinPool);
assertThat(results.size(), is(equalTo(2)));
long totalSize = 0;
for (IStorageDescriptor result : results) {
totalSize += result.getSize();
}
assertThat(totalSize, is(equalTo(300L)));
storageIndexQuery.setPlatformIdent(10L);
storageIndexQuery.setSensorTypeIdent(10L);
results = rootBranch.query(storageIndexQuery, forkJoinPool);
assertThat(results.size(), is(equalTo(1)));
for (IStorageDescriptor result : results) {
assertThat(result.getSize(), is(equalTo(100L)));
}
}
/**
* Tests that the indexing the same element in the {@link ArrayBasedStorageLeaf} will thrown a
* exception.
*
* @throws IndexingException
* {@link IndexingException}
*/
@Test(expectedExceptions = { IndexingException.class })
public void indexSameElement() throws IndexingException {
ArrayBasedStorageLeaf<DefaultData> arrayBasedStorageLeaf = new ArrayBasedStorageLeaf<>();
DefaultData defaultData = mock(DefaultData.class);
when(defaultData.getId()).thenReturn(1L);
arrayBasedStorageLeaf.put(defaultData);
arrayBasedStorageLeaf.put(defaultData);
}
/**
* Test the removing of the element in the {@link ArrayBasedStorageLeaf}.
*
* @throws IndexingException
* {@link IndexingException}
*/
@Test
public void removeElement() throws IndexingException {
ArrayBasedStorageLeaf<DefaultData> arrayBasedStorageLeaf = new ArrayBasedStorageLeaf<>();
DefaultData defaultData = mock(DefaultData.class);
when(defaultData.getId()).thenReturn(1L);
arrayBasedStorageLeaf.put(defaultData);
assertThat(arrayBasedStorageLeaf.getAndRemove(defaultData), is(notNullValue()));
assertThat(arrayBasedStorageLeaf.get(defaultData), is(nullValue()));
assertThat(arrayBasedStorageLeaf.query(storageIndexQuery), is(empty()));
// Test for forkJoinPool
assertThat(arrayBasedStorageLeaf.query(storageIndexQuery, forkJoinPool), is(empty()));
}
/**
* Test the removing of the element in the {@link ArrayBasedStorageLeaf} when the leaf is full
* of elements.
*
* @throws IndexingException
* {@link IndexingException}
*/
@Test
public void removeElementFromFullLeaf() throws IndexingException {
ArrayBasedStorageLeaf<DefaultData> arrayBasedStorageLeaf = new ArrayBasedStorageLeaf<>();
DefaultData defaultData = mock(DefaultData.class);
long i = 1L;
long totalSize = 0L;
int entries = 100;
while (i <= entries) {
when(defaultData.getId()).thenReturn(i);
IStorageDescriptor storageDescriptor = arrayBasedStorageLeaf.put(defaultData);
storageDescriptor.setPositionAndSize(totalSize, i);
totalSize += i;
i++;
}
long removeId = 50L;
when(defaultData.getId()).thenReturn(removeId);
assertThat(arrayBasedStorageLeaf.getAndRemove(defaultData), is(notNullValue()));
assertThat(arrayBasedStorageLeaf.get(defaultData), is(nullValue()));
List<IStorageDescriptor> results = arrayBasedStorageLeaf.query(storageIndexQuery);
assertThat(results.size(), is(equalTo(entries - 1)));
for (IStorageDescriptor storageDescriptor : results) {
assertThat(storageDescriptor.getSize(), is(not(equalTo(removeId))));
}
// Test for forkJoinPool
List<IStorageDescriptor> resultsForkJoin = arrayBasedStorageLeaf.query(storageIndexQuery, forkJoinPool);
assertThat(resultsForkJoin.size(), is(equalTo(entries - 1)));
for (IStorageDescriptor storageDescriptor : resultsForkJoin) {
assertThat(storageDescriptor.getSize(), is(not(equalTo(removeId))));
}
}
/**
* Tests that the total returned size of the leaf with no descriptors will be the same as the
* amount given.
*
* @throws IndexingException
* {@link IndexingException}
*/
@Test
public void totalSizeOfBoundedDescriptor() throws IndexingException {
LeafWithNoDescriptors<DefaultData> leafWithNoDescriptors = new LeafWithNoDescriptors<>();
DefaultData defaultData = mock(DefaultData.class);
long i = 1L;
int entries = 100;
long totalSize = 0L;
while (i <= entries) {
when(defaultData.getId()).thenReturn(i);
IStorageDescriptor storageDescriptor = leafWithNoDescriptors.put(defaultData);
storageDescriptor.setPositionAndSize(totalSize, i);
totalSize += i;
i++;
}
List<IStorageDescriptor> results = leafWithNoDescriptors.query(storageIndexQuery);
long totalReturnedSize = 0;
for (IStorageDescriptor storageDescriptor : results) {
totalReturnedSize += storageDescriptor.getSize();
}
assertThat(totalReturnedSize, is(equalTo(totalSize)));
// Test for forkJoinPool
List<IStorageDescriptor> resultsForkJoin = leafWithNoDescriptors.query(storageIndexQuery, forkJoinPool);
totalReturnedSize = 0;
for (IStorageDescriptor storageDescriptor : resultsForkJoin) {
totalReturnedSize += storageDescriptor.getSize();
}
assertThat(totalReturnedSize, is(equalTo(totalSize)));
}
/**
* Confirm {@link IndexingException} will be reaised when key can not be generated for element.
*
* @throws IndexingException
*/
@Test(expectedExceptions = { IndexingException.class })
public void putWithNoKey() throws IndexingException {
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(new StorageBranchIndexer<>(new TimestampIndexer<>(), false));
InvocationSequenceData invocation = mock(InvocationSequenceData.class);
when(invocation.getId()).thenReturn(1L);
rootBranch.put(invocation);
}
/**
* Test that get will work even when branch can not generate key for the element if ID is
* correctly set.
*
* @throws IndexingException
*/
@Test
public void getWithNoKey() throws IndexingException {
IStorageTreeComponent<DefaultData> rootBranch = new StorageBranch<>(new StorageBranchIndexer<>(new TimestampIndexer<>(), false));
InvocationSequenceData invocation = mock(InvocationSequenceData.class);
when(invocation.getId()).thenReturn(1L);
when(invocation.getTimeStamp()).thenReturn(new Timestamp(new Date().getTime()));
IStorageDescriptor storageDescriptor = rootBranch.put(invocation);
when(invocation.getTimeStamp()).thenReturn(null);
// test get
assertThat(rootBranch.get(invocation), is(equalTo(storageDescriptor)));
// then get and remove
assertThat(rootBranch.getAndRemove(invocation), is(equalTo(storageDescriptor)));
// confirm it is removed
assertThat(rootBranch.get(invocation), is(nullValue()));
}
/**
* Test that tests the functionality of {@link CombinedStorageQueryTask}
*/
@SuppressWarnings("unchecked")
@Test
public void queryCombinedStorageBranch() {
List<IStorageDescriptor> testResultList = new ArrayList<>();
testResultList.add(new StorageDescriptor());
testResultList.add(new StorageDescriptor());
CombinedStorageQueryTestTask<DefaultData> testTask = new CombinedStorageQueryTestTask<>(testResultList);
StorageBranch<DefaultData> mockedBranch1 = mock(StorageBranch.class);
when(mockedBranch1.getTaskForForkJoinQuery(storageIndexQuery)).thenReturn(testTask);
StorageBranch<DefaultData> mockedBranch2 = mock(StorageBranch.class);
when(mockedBranch2.getTaskForForkJoinQuery(storageIndexQuery)).thenReturn(testTask);
ArrayList<IStorageTreeComponent<DefaultData>> branches = new ArrayList<>();
branches.add(mockedBranch1);
branches.add(mockedBranch2);
IStorageTreeComponent<DefaultData> rootCombinedStoreBranch = new CombinedStorageBranch<>(branches);
List<IStorageDescriptor> results = rootCombinedStoreBranch.query(storageIndexQuery, forkJoinPool);
assertThat(results.size(), is(equalTo(4)));
}
}