blob: 32432ff2b6a22c81516ec798e3475033b370c688 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.segmentstore.core.tests.htStore;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import java.util.Iterator;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.internal.provisional.datastore.core.historytree.AbstractHistoryTree;
import org.eclipse.tracecompass.internal.provisional.datastore.core.historytree.overlapping.AbstractOverlappingHistoryTreeTestBase;
import org.eclipse.tracecompass.internal.segmentstore.core.segmentHistoryTree.SegmentHistoryTree;
import org.eclipse.tracecompass.internal.segmentstore.core.segmentHistoryTree.SegmentTreeNode;
import org.eclipse.tracecompass.segmentstore.core.BasicSegment;
import org.eclipse.tracecompass.segmentstore.core.tests.historytree.SegmentHistoryTreeStub;
import org.junit.Test;
import com.google.common.collect.Iterators;
/**
* Test the segment history tree itself, using a stub history tree with stub
* nodes
*
* @author Geneviève Bastien
*/
@NonNullByDefault
public class SegmentHistoryTreeTest extends AbstractOverlappingHistoryTreeTestBase<BasicSegment, SegmentTreeNode<BasicSegment>> {
private static final BasicSegment DEFAULT_OBJECT = new BasicSegment(0, 0);
@Override
protected SegmentHistoryTreeStub<BasicSegment> createHistoryTree(@NonNull File stateHistoryFile, int blockSize, int maxChildren, int providerVersion, long treeStart)
throws IOException {
return new SegmentHistoryTreeStub<>(stateHistoryFile,
blockSize,
maxChildren,
providerVersion,
treeStart,
BasicSegment.BASIC_SEGMENT_READ_FACTORY);
}
@Override
protected SegmentHistoryTreeStub<BasicSegment> createHistoryTree(@NonNull File existingStateFile, int expectedProviderVersion) throws IOException {
return new SegmentHistoryTreeStub<>(existingStateFile, expectedProviderVersion,
BasicSegment.BASIC_SEGMENT_READ_FACTORY);
}
@Override
protected BasicSegment createInterval(long start, long end) {
return new BasicSegment(start, end);
}
@Override
protected long fillValues(@NonNull AbstractHistoryTree<@NonNull BasicSegment, SegmentTreeNode<@NonNull BasicSegment>> ht, int fillSize, long start) {
int nbValues = fillSize / DEFAULT_OBJECT.getSizeOnDisk();
for (int i = 0; i < nbValues; i++) {
ht.insert(createInterval(start + i, start + i + 1));
}
return start + nbValues;
}
/**
* Test the {@link SegmentHistoryTree#isEmpty()} method
*/
@Test
public void testIsEmpty() {
long start = 10L;
SegmentHistoryTreeStub<BasicSegment> oht = (SegmentHistoryTreeStub<BasicSegment>) setupSmallTree(3, start);
assertTrue(oht.isEmpty());
// Add one element, the tree should not be empty anymore
oht.insert(createInterval(start, start + 1));
assertFalse(oht.isEmpty());
/* Fill a first node */
SegmentTreeNode<BasicSegment> node = oht.getLatestLeaf();
long time = fillValues(oht, node.getNodeFreeSpace(), start);
/*
* Add an element that will create a sibling and a root node, the root
* node should be empty but not the tree
*/
oht.insert(createInterval(time, time + 1));
assertFalse(oht.isEmpty());
}
/**
* Test the {@link SegmentHistoryTree#size()} method
*
* @throws IOException
* Exceptions during the test
*/
@Test
public void testSizeAndIterator() throws IOException {
long start = 10L;
SegmentHistoryTreeStub<BasicSegment> oht = (SegmentHistoryTreeStub<BasicSegment>) setupSmallTree(3, start);
int nbSegments = 0;
assertEquals(nbSegments, oht.size());
// Add one element, the tree have one element
oht.insert(createInterval(start, start + 1));
nbSegments++;
assertEquals(nbSegments, oht.size());
/* Fill a first node */
SegmentTreeNode<BasicSegment> node = oht.getLatestLeaf();
nbSegments += node.getNodeFreeSpace() / DEFAULT_OBJECT.getSizeOnDisk();
long time = fillValues(oht, node.getNodeFreeSpace(), start);
assertEquals(nbSegments, oht.size());
/*
* Add an element that will create a sibling and a root node, the root
* node should be empty but not the tree
*/
oht.insert(createInterval(time, time + 1));
nbSegments++;
// Add some intervals that will go in the top node
oht.insert(createInterval(start, time));
oht.insert(createInterval(start, start + 10));
nbSegments += 2;
assertEquals(nbSegments, oht.size());
/*
* Fill the latest node
*/
node = oht.getLatestLeaf();
nbSegments += node.getNodeFreeSpace() / DEFAULT_OBJECT.getSizeOnDisk();
time = fillValues(oht, node.getNodeFreeSpace(), start);
assertEquals(nbSegments, oht.size());
// Close the tree
oht.closeTree(oht.getTreeEnd());
// Create a reader history tree
oht = (SegmentHistoryTreeStub<BasicSegment>) createHistoryTreeReader();
assertEquals(nbSegments, oht.size());
// Test the iterator on that tree
Iterator<BasicSegment> iterator = oht.iterator();
assertNotNull(iterator);
int count = Iterators.size(iterator);
assertEquals(nbSegments, count);
// Test the intersecting elements
Iterable<BasicSegment> intersectingElements = oht.getIntersectingElements(start, time);
count = 0;
// While doing this iterator, count the number of segments of a smaller
// time range, it will be needed later
long rangeStart = (long) (start + (time - start) * 0.4);
long rangeEnd = (long) (time - (time - start) * 0.4);
int nbInRange = 0;
for (BasicSegment segment : intersectingElements) {
count++;
if (segment.getStart() <= rangeEnd && rangeStart <= segment.getEnd()) {
nbInRange++;
}
}
assertEquals(nbSegments, count);
// Test intersecting elements for a time range
count = Iterators.size(oht.getIntersectingElements(rangeStart, rangeEnd).iterator());
assertEquals(nbInRange, count);
// Test intersecting elements with start time ordering
Comparator<BasicSegment> cmp = NonNullUtils.checkNotNull(Comparator.comparing(BasicSegment::getStart));
assertSortedIteration(oht, rangeStart, rangeEnd, cmp, nbInRange);
// Test intersecting elements with end time ordering
cmp = NonNullUtils.checkNotNull(Comparator.comparing(BasicSegment::getEnd));
assertSortedIteration(oht, rangeStart, rangeEnd, cmp, nbInRange);
// Test intersecting elements with duration ordering
cmp = NonNullUtils.checkNotNull(Comparator.comparing(BasicSegment::getLength));
assertSortedIteration(oht, rangeStart, rangeEnd, cmp, nbInRange);
}
private static void assertSortedIteration(SegmentHistoryTreeStub<@NonNull BasicSegment> oht, long rangeStart, long rangeEnd, Comparator<@NonNull BasicSegment> cmp, int nbInRange) {
int count = 0;
BasicSegment prev = DEFAULT_OBJECT;
for (BasicSegment segment : oht.getIntersectingElements(rangeStart, rangeEnd, cmp)) {
count++;
assertTrue("Segment comparison at " + count, cmp.compare(prev, segment) <= 0);
}
assertEquals(nbInRange, count);
}
}