1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.segmentstore
.core
.tests
;
12 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
13 import static org
.junit
.Assert
.assertEquals
;
14 import static org
.junit
.Assert
.assertFalse
;
15 import static org
.junit
.Assert
.assertTrue
;
17 import java
.util
.ArrayList
;
18 import java
.util
.Arrays
;
19 import java
.util
.Collection
;
20 import java
.util
.Collections
;
21 import java
.util
.Comparator
;
22 import java
.util
.Iterator
;
23 import java
.util
.LinkedList
;
24 import java
.util
.List
;
26 import org
.eclipse
.jdt
.annotation
.NonNull
;
27 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
28 import org
.eclipse
.tracecompass
.datastore
.core
.interval
.IHTIntervalReader
;
29 import org
.eclipse
.tracecompass
.datastore
.core
.serialization
.ISafeByteBufferWriter
;
30 import org
.eclipse
.tracecompass
.datastore
.core
.serialization
.SafeByteBufferFactory
;
31 import org
.eclipse
.tracecompass
.internal
.provisional
.segmentstore
.core
.ISegment2
;
32 import org
.eclipse
.tracecompass
.segmentstore
.core
.BasicSegment
;
33 import org
.eclipse
.tracecompass
.segmentstore
.core
.ISegment
;
34 import org
.eclipse
.tracecompass
.segmentstore
.core
.ISegmentStore
;
35 import org
.eclipse
.tracecompass
.segmentstore
.core
.SegmentComparators
;
36 import org
.junit
.After
;
37 import org
.junit
.Before
;
38 import org
.junit
.Test
;
40 import com
.google
.common
.collect
.ImmutableList
;
41 import com
.google
.common
.collect
.Iterables
;
42 import com
.google
.common
.collect
.Lists
;
45 * Unit tests for intersecting elements in an SegmentStore
47 * Originally the TreeMapStoreTest, copied for this internal implementation. The
48 * test was barely changed as it tests the interface and not the internals.
50 * @author Matthew Khouzam
52 public abstract class AbstractTestSegmentStore
{
57 protected final ISegmentStore
<@NonNull TestSegment
> fSegmentStore
;
60 * Get the segment store to test
62 * @return the segment store
64 protected abstract ISegmentStore
<@NonNull TestSegment
> getSegmentStore();
67 * Get the segment store to test with initial data
72 * @return the segment store
74 protected abstract ISegmentStore
<@NonNull TestSegment
> getSegmentStore(@NonNull TestSegment
@NonNull [] data
);
76 private static final @NonNull TestSegment SEGMENT_2_6
= new TestSegment(2, 6, "test");
77 private static final @NonNull TestSegment SEGMENT_4_6
= new TestSegment(4, 6, "test2");
78 private static final @NonNull TestSegment SEGMENT_4_8
= new TestSegment(4, 8, "test3");
79 private static final @NonNull TestSegment SEGMENT_6_8
= new TestSegment(6, 8, "test");
80 private static final @NonNull TestSegment SEGMENT_10_14
= new TestSegment(10, 14, "test");
82 * A sample segment list
84 protected static final List
<@NonNull TestSegment
> SEGMENTS
= ImmutableList
.of(SEGMENT_2_6
, SEGMENT_4_6
, SEGMENT_4_8
, SEGMENT_6_8
, SEGMENT_10_14
);
85 private static final List
<@NonNull TestSegment
> REVERSE_SEGMENTS
= Lists
.reverse(SEGMENTS
);
88 * A test type of segment that can be serialized with the safe buffers. It
89 * has an extra payload
91 * @author Geneviève Bastien
93 protected static final class TestSegment
implements ISegment2
{
96 * The reader for this class
98 public static final @NonNull IHTIntervalReader
<@NonNull TestSegment
> DESERIALISER
= buffer
-> new TestSegment(buffer
.getLong(), buffer
.getLong(), buffer
.getString());
103 private static final long serialVersionUID
= -2242452053089575887L;
105 private final long fStart
;
106 private final long fEnd
;
107 private final @NonNull String fPayload
;
113 * Start of this segment
115 * End of this segment
119 public TestSegment(long start
, long end
, @NonNull String payload
) {
126 public long getStart() {
131 public long getEnd() {
136 * Get the payload of this segment
138 * @return The payload
140 public String
getPayload() {
145 public int getSizeOnDisk() {
146 return 2 * Long
.BYTES
+ SafeByteBufferFactory
.getStringSizeInBuffer(fPayload
);
150 public void writeSegment(@NonNull ISafeByteBufferWriter buffer
) {
151 buffer
.putLong(fStart
);
152 buffer
.putLong(fEnd
);
153 buffer
.putString(fPayload
);
161 public AbstractTestSegmentStore() {
163 fSegmentStore
= getSegmentStore();
167 * Asserts that 2 segments are equal. Some backend may not return exactly
168 * the same type of segment so the main assert will be false, but the
169 * segments are in fact identical
172 * The expected segment
176 protected void assertSegmentsEqual(ISegment expected
, ISegment actual
) {
177 assertEquals(expected
, actual
);
181 * Initialize data (test vector) that will be tested
184 public void setup() {
185 for (TestSegment segment
: SEGMENTS
) {
186 fSegmentStore
.add(segment
);
191 * Dispose of the segment store
194 public void teardown() {
195 fSegmentStore
.dispose();
199 * Testing method size()
202 public void testSize() {
203 assertEquals(SEGMENTS
.size(), fSegmentStore
.size());
207 * Testing isEmpty() method
210 public void testIsEmpty() {
211 assertFalse(fSegmentStore
.isEmpty());
212 fSegmentStore
.clear();
213 assertTrue(fSegmentStore
.isEmpty());
217 * Testing adding a collection with the addAll method
220 public void testAddAll() {
221 assertFalse(fSegmentStore
.isEmpty());
222 fSegmentStore
.clear();
223 assertTrue(fSegmentStore
.isEmpty());
224 fSegmentStore
.addAll(SEGMENTS
);
225 assertTrue(fSegmentStore
.containsAll(SEGMENTS
));
229 * Testing "copy" constructor
232 public void testAddAllConstructor() {
233 ISegmentStore
<@NonNull TestSegment
> other
= getSegmentStore(fSegmentStore
.toArray(new TestSegment
[fSegmentStore
.size()]));
234 assertTrue(fSegmentStore
.containsAll(other
));
235 assertTrue(other
.containsAll(fSegmentStore
));
239 * Testing "copy" constructor out of order
242 public void testAddAllConstructorOutOfOrder() {
243 ISegmentStore
<@NonNull TestSegment
> other
= getSegmentStore(REVERSE_SEGMENTS
.toArray(new TestSegment
[fSegmentStore
.size()]));
244 assertTrue(fSegmentStore
.containsAll(other
));
245 assertTrue(other
.containsAll(fSegmentStore
));
249 * Testing adding an out of order collection with the addAll method
252 public void testAddAllOutOfOrder() {
253 assertFalse(fSegmentStore
.isEmpty());
254 fSegmentStore
.clear();
255 assertTrue(fSegmentStore
.isEmpty());
256 fSegmentStore
.addAll(REVERSE_SEGMENTS
);
257 assertTrue(fSegmentStore
.containsAll(SEGMENTS
));
261 * Test the contains() method.
264 public void testContains() {
265 ISegment otherSegment
= new BasicSegment(0, 20);
267 assertTrue(fSegmentStore
.contains(SEGMENT_2_6
));
268 assertTrue(fSegmentStore
.contains(SEGMENT_4_8
));
269 assertFalse(fSegmentStore
.contains(otherSegment
));
273 * Test containsAll() method
275 public void testContainsAll() {
276 ISegmentStore
<@NonNull TestSegment
> store
= getSegmentStore();
278 store
.add(SEGMENT_2_6
);
279 assertTrue(store
.containsAll(Collections
.emptyList()));
280 assertTrue(store
.containsAll(Collections
.singleton(SEGMENT_2_6
)));
281 assertFalse(store
.containsAll(Collections
.singleton(SEGMENT_4_6
)));
285 * Test the toArray() method.
288 public void testToObjectArray() {
289 Object
[] array
= fSegmentStore
.toArray();
291 assertEquals(SEGMENTS
.size(), array
.length
);
292 assertTrue(Arrays
.asList(array
).containsAll(SEGMENTS
));
296 * Test the toArray(T[]) method.
299 public void testToSpecificArray() {
300 ISegment
[] array
= fSegmentStore
.toArray(new ISegment
[0]);
302 assertEquals(SEGMENTS
.size(), array
.length
);
303 assertTrue(Arrays
.asList(array
).containsAll(SEGMENTS
));
307 * Test the toArray(T[]) method with a subtype of ISegment.
310 public void testToSpecifyArraySubtype() {
311 ISegmentStore
<@NonNull TestSegment
> tms2
= getSegmentStore();
312 TestSegment otherSegment
= new TestSegment(2, 6, "test");
313 tms2
.add(otherSegment
);
314 TestSegment
[] array
= tms2
.toArray(new TestSegment
[0]);
316 assertEquals(1, array
.length
);
317 assertTrue(Arrays
.asList(array
).contains(otherSegment
));
323 * Test the iteration order of the complete segment store.
326 public void testIterationOrder() {
328 for (ISegment segment
: fSegmentStore
) {
329 assertSegmentsEqual(SEGMENTS
.get(i
++), segment
);
334 * Test the iteration order when the elements are not inserted in sorted
338 public void testIterationOrderNonSortedInsertion() {
339 /* Prepare the segment store, we don't use the 'fixture' in this test */
340 ISegmentStore
<@NonNull TestSegment
> store
= getSegmentStore();
341 for (TestSegment segment
: REVERSE_SEGMENTS
) {
342 store
.add(checkNotNull(segment
));
346 * Test each element one by one, the iteration order should follow the
347 * start times, not the insertion order.
350 for (TestSegment segment
: store
) {
351 assertSegmentsEqual(SEGMENTS
.get(i
++), segment
);
354 /* Manually dispose our own store */
360 * {@link ISegmentStore#getIntersectingElements(long start, long end)}
363 public void testGetIntersectingElementsRange() {
365 Iterable
<TestSegment
> intersectingElements
;
368 * Range that does not include any segment
370 intersectingElements
= fSegmentStore
.getIntersectingElements(16, 20);
371 assertEquals(0, Iterables
.size(intersectingElements
));
374 * Range start time : Before first segment start time Range end time :
375 * After last segment end time
377 intersectingElements
= fSegmentStore
.getIntersectingElements(1, 15);
378 assertEquals(5, Iterables
.size(intersectingElements
));
381 * Range start time : On first segment start time Range end time : On
382 * last segment end time
384 intersectingElements
= fSegmentStore
.getIntersectingElements(2, 14);
385 assertEquals(5, Iterables
.size(intersectingElements
));
388 * Range start time : After one segment start time Range end time :
389 * Before one segment end time
391 intersectingElements
= fSegmentStore
.getIntersectingElements(11, 13);
392 assertEquals(1, Iterables
.size(intersectingElements
));
393 assertSegmentsEqual(SEGMENT_10_14
, Iterables
.getOnlyElement(intersectingElements
));
396 * Range start time : On one segment start time Range end time : On one
399 intersectingElements
= fSegmentStore
.getIntersectingElements(10, 14);
400 assertEquals(1, Iterables
.size(intersectingElements
));
401 assertSegmentsEqual(SEGMENT_10_14
, Iterables
.getOnlyElement(intersectingElements
));
404 * Range start time : On last segment end time Range end time : After
405 * last segment end time
407 intersectingElements
= fSegmentStore
.getIntersectingElements(14, 18);
408 assertEquals(1, Iterables
.size(intersectingElements
));
409 assertSegmentsEqual(SEGMENT_10_14
, Iterables
.getOnlyElement(intersectingElements
));
412 * Range start time : Before first segment start time Range end time :
413 * On first segment start time
415 intersectingElements
= fSegmentStore
.getIntersectingElements(1, 2);
416 assertEquals(1, Iterables
.size(intersectingElements
));
417 assertSegmentsEqual(SEGMENT_2_6
, Iterables
.getOnlyElement(intersectingElements
));
421 * Testing method {@link ISegmentStore#getIntersectingElements(long time)}
424 public void testGetIntersectingElementsTime() {
426 Iterable
<TestSegment
> intersectingElements
;
429 * Time between segment start time and end time
431 intersectingElements
= fSegmentStore
.getIntersectingElements(3);
432 assertEquals(1, Iterables
.size(intersectingElements
));
433 assertSegmentsEqual(SEGMENT_2_6
, Iterables
.getOnlyElement(intersectingElements
));
436 * Time on segment start time
438 intersectingElements
= fSegmentStore
.getIntersectingElements(2);
439 assertEquals(1, Iterables
.size(intersectingElements
));
440 assertSegmentsEqual(SEGMENT_2_6
, Iterables
.getOnlyElement(intersectingElements
));
443 * Time on segment end time
445 intersectingElements
= fSegmentStore
.getIntersectingElements(14);
446 assertEquals(1, Iterables
.size(intersectingElements
));
447 assertSegmentsEqual(SEGMENT_10_14
, Iterables
.getOnlyElement(intersectingElements
));
450 * Time overlapping many segments
452 intersectingElements
= fSegmentStore
.getIntersectingElements(6);
453 assertEquals(4, Iterables
.size(intersectingElements
));
456 * Time between segments
458 intersectingElements
= fSegmentStore
.getIntersectingElements(9);
459 assertEquals(0, Iterables
.size(intersectingElements
));
462 * Time before all segment start time
464 intersectingElements
= fSegmentStore
.getIntersectingElements(1);
465 assertEquals(0, Iterables
.size(intersectingElements
));
468 * Time after all segment end time
470 intersectingElements
= fSegmentStore
.getIntersectingElements(15);
471 assertEquals(0, Iterables
.size(intersectingElements
));
475 * Testing method {@link ISegmentStore#dispose()}
478 public void testDispose() {
479 ISegmentStore
<@NonNull TestSegment
> store
= getSegmentStore();
480 store
.add(SEGMENT_2_6
);
482 assertEquals(0, store
.size());
486 * Test iterating over a store being built.
491 public void testIterator() {
492 Collection
<@NonNull TestSegment
> beforeExpected
= ImmutableList
.of(SEGMENT_2_6
);
493 Collection
<@NonNull TestSegment
> afterExpected
= ImmutableList
.of(SEGMENT_2_6
, SEGMENT_4_8
);
494 Collection
<@NonNull TestSegment
> lastExpected
= ImmutableList
.of(SEGMENT_2_6
, SEGMENT_4_8
, SEGMENT_6_8
);
495 Collection
<@NonNull TestSegment
> fixture
= new ArrayList
<>();
496 ISegmentStore
<@NonNull TestSegment
> store
= getSegmentStore();
498 // Add one segment to the segment store and iterate
499 store
.add(SEGMENT_2_6
);
500 for (TestSegment item
: store
) {
503 assertEquals(beforeExpected
, fixture
);
505 // Add a second segment to the store and iterate
507 store
.add(SEGMENT_4_8
);
508 for (TestSegment item
: store
) {
511 assertEquals(afterExpected
, fixture
);
515 Iterator
<@NonNull TestSegment
> iter
= store
.iterator();
517 // Add a third segment to the store and iterate
518 store
.add(SEGMENT_6_8
);
519 Iterator
<@NonNull TestSegment
> iter2
= store
.iterator();
522 // Make sure the first iterator take has at least 2 elements (depends on
523 // implementation) and the second has 3 elements
524 while (iter
.hasNext()) {
525 fixture
.add(iter
.next());
527 assertTrue(fixture
.size() >= 2);
529 while (iter2
.hasNext()) {
530 fixture
.add(iter2
.next());
532 assertEquals(lastExpected
, fixture
);
536 * Test to check ordered iterators
539 public void testSortedIterator() {
540 List
<@NonNull Comparator
<ISegment
>> comparators
= new LinkedList
<>();
541 comparators
.add(SegmentComparators
.INTERVAL_END_COMPARATOR
);
542 comparators
.add(NonNullUtils
.checkNotNull(SegmentComparators
.INTERVAL_END_COMPARATOR
.reversed()));
543 comparators
.add(SegmentComparators
.INTERVAL_START_COMPARATOR
);
544 comparators
.add(NonNullUtils
.checkNotNull(SegmentComparators
.INTERVAL_START_COMPARATOR
.reversed()));
545 comparators
.add(SegmentComparators
.INTERVAL_LENGTH_COMPARATOR
);
546 comparators
.add(NonNullUtils
.checkNotNull(SegmentComparators
.INTERVAL_LENGTH_COMPARATOR
.reversed()));
548 Iterable
<TestSegment
> iterable
;
549 for (Comparator
<ISegment
> comparator
: comparators
) {
550 iterable
= fSegmentStore
.iterator(comparator
);
551 verifySortedIterable(iterable
, 5, comparator
);
552 iterable
= fSegmentStore
.getIntersectingElements(5, comparator
);
553 verifySortedIterable(iterable
, 3, comparator
);
554 iterable
= fSegmentStore
.getIntersectingElements(7, 14, comparator
);
555 verifySortedIterable(iterable
, 3, comparator
);
559 private static void verifySortedIterable(Iterable
<TestSegment
> iterable
, int expectedSize
, Comparator
<ISegment
> comparator
) {
561 assertEquals(expectedSize
, Iterables
.size(iterable
));
562 Iterator
<TestSegment
> iterator
= iterable
.iterator();
564 ISegment prev
, current
= iterator
.next();
565 while (iterator
.hasNext()) {
567 current
= iterator
.next();
568 assertTrue(comparator
.compare(prev
, current
) <= 0);
573 * Test retainAll() contract
575 @Test(expected
= UnsupportedOperationException
.class)
576 public void testRetainAll() {
577 ISegmentStore
<@NonNull TestSegment
> store
= getSegmentStore();
579 store
.add(SEGMENT_2_6
);
580 store
.retainAll(Collections
.emptyList());
584 * Test remove() contract
586 @Test(expected
= UnsupportedOperationException
.class)
587 public void testRemove() {
588 ISegmentStore
<@NonNull TestSegment
> store
= getSegmentStore();
590 store
.add(SEGMENT_2_6
);
591 store
.remove(SEGMENT_2_6
);
595 * Test removeAll() contract
597 @Test(expected
= UnsupportedOperationException
.class)
598 public void testRemoveAll() {
599 ISegmentStore
<@NonNull TestSegment
> store
= getSegmentStore();
601 store
.add(SEGMENT_2_6
);
602 store
.removeAll(Collections
.emptyList());