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))); } }