/*******************************************************************************
* Copyright (c) 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.tracecompass.segmentstore.core.tests;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.segmentstore.core.BasicSegment;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
import org.eclipse.tracecompass.segmentstore.core.SegmentComparators;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
* Unit tests for intersecting elements in an SegmentStore
*
* Originally the TreeMapStoreTest, copied for this internal implementation. The
* test was barely changed as it tests the interface and not the internals.
*
* @author Matthew Khouzam
*/
public abstract class AbstractTestSegmentStore {
/**
* The segment store
*/
protected ISegmentStore<@NonNull ISegment> fSegmentStore;
/**
* Get the segment store to test
*
* @return the segment store
*/
protected abstract ISegmentStore<@NonNull ISegment> getSegmentStore();
/**
* Get the segment store to test with initial data
*
* @param data
* the data
*
* @return the segment store
*/
protected abstract ISegmentStore<@NonNull ISegment> getSegmentStore(@NonNull ISegment @NonNull [] data);
private static final @NonNull ISegment SEGMENT_2_6 = new BasicSegment(2, 6);
private static final @NonNull ISegment SEGMENT_4_6 = new BasicSegment(4, 6);
private static final @NonNull ISegment SEGMENT_4_8 = new BasicSegment(4, 8);
private static final @NonNull ISegment SEGMENT_6_8 = new BasicSegment(6, 8);
private static final @NonNull ISegment SEGMENT_10_14 = new BasicSegment(10, 14);
/**
* A sample segment list
*/
protected static final List<@NonNull ISegment> SEGMENTS = ImmutableList.of(SEGMENT_2_6, SEGMENT_4_6, SEGMENT_4_8, SEGMENT_6_8, SEGMENT_10_14);
private static final List<@NonNull ISegment> REVERSE_SEGMENTS = Lists.reverse(SEGMENTS);
/**
* Constructor
*/
public AbstractTestSegmentStore() {
super();
}
/**
* Initialize data (test vector) that will be tested
*/
@Before
public void setup() {
fSegmentStore = getSegmentStore();
for (ISegment segment : SEGMENTS) {
fSegmentStore.add(segment);
}
}
/**
* Dispose of the segment store
*/
@After
public void teardown() {
fSegmentStore.dispose();
}
/**
* Testing method size()
*/
@Test
public void testSize() {
assertEquals(SEGMENTS.size(), fSegmentStore.size());
}
/**
* Testing isEmpty() method
*/
@Test
public void testIsEmpty() {
assertFalse(fSegmentStore.isEmpty());
fSegmentStore.clear();
assertTrue(fSegmentStore.isEmpty());
}
/**
* Testing adding a collection with the addAll method
*/
@Test
public void testAddAll() {
assertFalse(fSegmentStore.isEmpty());
fSegmentStore.clear();
assertTrue(fSegmentStore.isEmpty());
fSegmentStore.addAll(SEGMENTS);
assertTrue(fSegmentStore.containsAll(SEGMENTS));
}
/**
* Testing "copy" constructor
*/
@Test
public void testAddAllConstructor() {
@SuppressWarnings("null")
ISegmentStore<@NonNull ISegment> other = getSegmentStore(fSegmentStore.toArray(new ISegment[fSegmentStore.size()]));
assertTrue(fSegmentStore.containsAll(other));
assertTrue(other.containsAll(fSegmentStore));
}
/**
* Testing "copy" constructor out of order
*/
@Test
public void testAddAllConstructorOutOfOrder() {
@SuppressWarnings("null")
ISegmentStore<@NonNull ISegment> other = getSegmentStore(REVERSE_SEGMENTS.toArray(new ISegment[fSegmentStore.size()]));
assertTrue(fSegmentStore.containsAll(other));
assertTrue(other.containsAll(fSegmentStore));
}
/**
* Testing adding an out of order collection with the addAll method
*/
@Test
public void testAddAllOutOfOrder() {
assertFalse(fSegmentStore.isEmpty());
fSegmentStore.clear();
assertTrue(fSegmentStore.isEmpty());
fSegmentStore.addAll(REVERSE_SEGMENTS);
assertTrue(fSegmentStore.containsAll(SEGMENTS));
}
/**
* Test the contains() method.
*/
@Test
public void testContains() {
ISegment otherSegment = new BasicSegment(0, 20);
assertTrue(fSegmentStore.contains(SEGMENT_2_6));
assertTrue(fSegmentStore.contains(SEGMENT_4_8));
assertFalse(fSegmentStore.contains(otherSegment));
}
/**
* Test containsAll() method
*/
public void testContainsAll() {
ISegmentStore<@NonNull ISegment> store = getSegmentStore();
store.add(SEGMENT_2_6);
assertTrue(store.containsAll(Collections.emptyList()));
assertTrue(store.containsAll(Collections.singleton(SEGMENT_2_6)));
assertFalse(store.containsAll(Collections.singleton(SEGMENT_4_6)));
}
/**
* Test the toArray() method.
*/
@Test
public void testToObjectArray() {
Object[] array = fSegmentStore.toArray();
assertEquals(SEGMENTS.size(), array.length);
assertTrue(Arrays.asList(array).containsAll(SEGMENTS));
}
/**
* Test the toArray(T[]) method.
*/
@Test
public void testToSpecificArray() {
ISegment[] array = fSegmentStore.toArray(new ISegment[0]);
assertEquals(SEGMENTS.size(), array.length);
assertTrue(Arrays.asList(array).containsAll(SEGMENTS));
}
/**
* Test the toArray(T[]) method with a subtype of ISegment.
*/
@Test
public void testToSpecifyArraySubtype() {
ISegmentStore<@NonNull ISegment> tms2 = getSegmentStore();
BasicSegment otherSegment = new BasicSegment(2, 6);
tms2.add(otherSegment);
BasicSegment[] array = tms2.toArray(new BasicSegment[0]);
assertEquals(1, array.length);
assertTrue(Arrays.asList(array).contains(otherSegment));
tms2.dispose();
}
/**
* Test the iteration order of the complete segment store.
*/
@Test
public void testIterationOrder() {
int i = 0;
for (ISegment segment : fSegmentStore) {
assertEquals(SEGMENTS.get(i++), segment);
}
}
/**
* Test the iteration order when the elements are not inserted in sorted
* order.
*/
@Test
public void testIterationOrderNonSortedInsertion() {
/* Prepare the segment store, we don't use the 'fixture' in this test */
ISegmentStore<@NonNull ISegment> store = getSegmentStore();
for (ISegment segment : REVERSE_SEGMENTS) {
store.add(checkNotNull(segment));
}
/*
* Test each element one by one, the iteration order should follow the
* start times, not the insertion order.
*/
int i = 0;
for (ISegment segment : store) {
assertEquals(SEGMENTS.get(i++), segment);
}
/* Manually dispose our own store */
store.dispose();
}
/**
* Testing method
* {@link ISegmentStore#getIntersectingElements(long start, long end)}
*/
@Test
public void testGetIntersectingElementsRange() {
Iterable<ISegment> intersectingElements;
/*
* Range that does not include any segment
*/
intersectingElements = fSegmentStore.getIntersectingElements(16, 20);
assertEquals(0, Iterables.size(intersectingElements));
/*
* Range start time : Before first segment start time Range end time :
* After last segment end time
*/
intersectingElements = fSegmentStore.getIntersectingElements(1, 15);
assertEquals(5, Iterables.size(intersectingElements));
/*
* Range start time : On first segment start time Range end time : On
* last segment end time
*/
intersectingElements = fSegmentStore.getIntersectingElements(2, 14);
assertEquals(5, Iterables.size(intersectingElements));
/*
* Range start time : After one segment start time Range end time :
* Before one segment end time
*/
intersectingElements = fSegmentStore.getIntersectingElements(11, 13);
assertEquals(1, Iterables.size(intersectingElements));
assertEquals(SEGMENT_10_14, Iterables.getOnlyElement(intersectingElements));
/*
* Range start time : On one segment start time Range end time : On one
* segment end time
*/
intersectingElements = fSegmentStore.getIntersectingElements(10, 14);
assertEquals(1, Iterables.size(intersectingElements));
assertEquals(SEGMENT_10_14, Iterables.getOnlyElement(intersectingElements));
/*
* Range start time : On last segment end time Range end time : After
* last segment end time
*/
intersectingElements = fSegmentStore.getIntersectingElements(14, 18);
assertEquals(1, Iterables.size(intersectingElements));
assertEquals(SEGMENT_10_14, Iterables.getOnlyElement(intersectingElements));
/*
* Range start time : Before first segment start time Range end time :
* On first segment start time
*/
intersectingElements = fSegmentStore.getIntersectingElements(1, 2);
assertEquals(1, Iterables.size(intersectingElements));
assertEquals(SEGMENT_2_6, Iterables.getOnlyElement(intersectingElements));
}
/**
* Testing method {@link ISegmentStore#getIntersectingElements(long time)}
*/
@Test
public void testGetIntersectingElementsTime() {
Iterable<ISegment> intersectingElements;
/*
* Time between segment start time and end time
*/
intersectingElements = fSegmentStore.getIntersectingElements(3);
assertEquals(1, Iterables.size(intersectingElements));
assertEquals(SEGMENT_2_6, Iterables.getOnlyElement(intersectingElements));
/*
* Time on segment start time
*/
intersectingElements = fSegmentStore.getIntersectingElements(2);
assertEquals(1, Iterables.size(intersectingElements));
assertEquals(SEGMENT_2_6, Iterables.getOnlyElement(intersectingElements));
/*
* Time on segment end time
*/
intersectingElements = fSegmentStore.getIntersectingElements(14);
assertEquals(1, Iterables.size(intersectingElements));
assertEquals(SEGMENT_10_14, Iterables.getOnlyElement(intersectingElements));
/*
* Time overlapping many segments
*/
intersectingElements = fSegmentStore.getIntersectingElements(6);
assertEquals(4, Iterables.size(intersectingElements));
/*
* Time between segments
*/
intersectingElements = fSegmentStore.getIntersectingElements(9);
assertEquals(0, Iterables.size(intersectingElements));
/*
* Time before all segment start time
*/
intersectingElements = fSegmentStore.getIntersectingElements(1);
assertEquals(0, Iterables.size(intersectingElements));
/*
* Time after all segment end time
*/
intersectingElements = fSegmentStore.getIntersectingElements(15);
assertEquals(0, Iterables.size(intersectingElements));
}
/**
* Testing method {@link ISegmentStore#dispose()}
*/
@Test
public void testDispose() {
ISegmentStore<@NonNull ISegment> store = getSegmentStore();
store.add(SEGMENT_2_6);
store.dispose();
assertEquals(0, store.size());
}
/**
* Test iterating over a store being built.
*
* bug 500607
*/
@Test
public void testIterator() {
Collection<@NonNull ISegment> beforeExpected = ImmutableList.of(SEGMENT_2_6);
Collection<@NonNull ISegment> afterExpected = ImmutableList.of(SEGMENT_2_6, SEGMENT_4_8);
Collection<@NonNull ISegment> lastExpected = ImmutableList.of(SEGMENT_2_6, SEGMENT_4_8, SEGMENT_6_8);
Collection<@NonNull ISegment> fixture = new ArrayList<>();
ISegmentStore<@NonNull ISegment> store = getSegmentStore();
// Add one segment to the segment store and iterate
store.add(SEGMENT_2_6);
for (ISegment item : store) {
fixture.add(item);
}
assertEquals(beforeExpected, fixture);
// Add a second segment to the store and iterate
fixture.clear();
store.add(SEGMENT_4_8);
for (ISegment item : store) {
fixture.add(item);
}
assertEquals(afterExpected, fixture);
fixture.clear();
// Take an iterator
Iterator<@NonNull ISegment> iter = store.iterator();
// Add a third segment to the store and iterate
store.add(SEGMENT_6_8);
Iterator<@NonNull ISegment> iter2 = store.iterator();
fixture.clear();
// Make sure the first iterator take has only 2 elements and the second
// has 3 elements
while (iter.hasNext()) {
fixture.add(iter.next());
}
assertEquals(afterExpected, fixture);
fixture.clear();
while (iter2.hasNext()) {
fixture.add(iter2.next());
}
assertEquals(lastExpected, fixture);
}
/**
* Test to check ordered iterators
*/
@Test
public void testSortedIterator() {
List<@NonNull Comparator<ISegment>> comparators = new LinkedList<>();
comparators.add(SegmentComparators.INTERVAL_END_COMPARATOR);
comparators.add(NonNullUtils.checkNotNull(SegmentComparators.INTERVAL_END_COMPARATOR.reversed()));
comparators.add(SegmentComparators.INTERVAL_START_COMPARATOR);
comparators.add(NonNullUtils.checkNotNull(SegmentComparators.INTERVAL_START_COMPARATOR.reversed()));
comparators.add(SegmentComparators.INTERVAL_LENGTH_COMPARATOR);
comparators.add(NonNullUtils.checkNotNull(SegmentComparators.INTERVAL_LENGTH_COMPARATOR.reversed()));
Iterable<ISegment> iterable;
for (Comparator<ISegment> comparator : comparators) {
iterable = fSegmentStore.iterator(comparator);
verifySortedIterable(iterable, 5, comparator);
iterable = fSegmentStore.getIntersectingElements(5, comparator);
verifySortedIterable(iterable, 3, comparator);
iterable = fSegmentStore.getIntersectingElements(7, 14, comparator);
verifySortedIterable(iterable, 3, comparator);
}
}
private static void verifySortedIterable(Iterable<ISegment> iterable, int expectedSize, Comparator<ISegment> comparator) {
// check its size
assertEquals(expectedSize, Iterables.size(iterable));
Iterator<ISegment> iterator = iterable.iterator();
// check the order
ISegment prev, current = iterator.next();
while (iterator.hasNext()) {
prev = current;
current = iterator.next();
assertTrue(comparator.compare(prev, current) <= 0);
}
}
/**
* Test retainAll() contract
*/
@Test(expected = UnsupportedOperationException.class)
public void testRetainAll() {
ISegmentStore<@NonNull ISegment> store = getSegmentStore();
store.add(SEGMENT_2_6);
store.retainAll(Collections.emptyList());
}
/**
* Test remove() contract
*/
@Test(expected = UnsupportedOperationException.class)
public void testRemove() {
ISegmentStore<@NonNull ISegment> store = getSegmentStore();
store.add(SEGMENT_2_6);
store.remove(SEGMENT_2_6);
}
/**
* Test removeAll() contract
*/
@Test(expected = UnsupportedOperationException.class)
public void testRemoveAll() {
ISegmentStore<@NonNull ISegment> store = getSegmentStore();
store.add(SEGMENT_2_6);
store.removeAll(Collections.emptyList());
}
}