1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson and others
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
.statesystem
.core
.tests
.backend
;
12 import static org
.junit
.Assert
.assertEquals
;
13 import static org
.junit
.Assert
.assertNotNull
;
14 import static org
.junit
.Assert
.assertTrue
;
15 import static org
.junit
.Assert
.fail
;
17 import java
.io
.IOException
;
18 import java
.util
.ArrayList
;
19 import java
.util
.List
;
21 import org
.eclipse
.jdt
.annotation
.Nullable
;
22 import org
.eclipse
.tracecompass
.statesystem
.core
.backend
.IStateHistoryBackend
;
23 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
24 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.TmfStateInterval
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
29 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
30 import org
.junit
.Test
;
32 import com
.google
.common
.collect
.ImmutableList
;
35 * Abstract class to test implementations of the {@link IStateHistoryBackend}
38 * @author Patrick Tasse
39 * @author Geneviève Bastien
41 public abstract class StateHistoryBackendTestBase
{
43 /* Some state values of each type */
44 private static final ITmfStateValue INT_VAL1
= TmfStateValue
.newValueInt(-42);
45 private static final ITmfStateValue INT_VAL2
= TmfStateValue
.newValueInt(675893);
46 private static final ITmfStateValue LONG_VAL1
= TmfStateValue
.newValueLong(-78L);
47 private static final ITmfStateValue LONG_VAL2
= TmfStateValue
.newValueLong(2234L);
48 private static final ITmfStateValue DOUBLE_VAL1
= TmfStateValue
.newValueDouble(-9.87);
49 private static final ITmfStateValue DOUBLE_VAL2
= TmfStateValue
.newValueDouble(50324.131643);
50 private static final ITmfStateValue STR_VAL1
= TmfStateValue
.newValueString("A string");
51 private static final ITmfStateValue STR_VAL2
= TmfStateValue
.newValueString("Another éèstr");
54 * Gets the backend to be used for building.
57 * The start time of the history
59 * @return The backend to be used for building.
61 * if an exception occurs
63 protected abstract IStateHistoryBackend
getBackendForBuilding(long startTime
) throws IOException
;
66 * Gets the backend to be used for querying. The default implementation
67 * returns the backend that was used for building.
69 * Only the returned backend should be used after calling this method. The
70 * one sent in parameter might have been disposed.
73 * The backend that was used for building
74 * @return The backend to be used for querying.
76 * if an exception occurs
78 @SuppressWarnings("unused")
79 protected IStateHistoryBackend
getBackendForQuerying(IStateHistoryBackend backend
) throws IOException
{
84 * Prepares a backend to be used in tests. The specified intervals will be
85 * inserted in the backend, and then the backend will be closed.
88 * The start time of the history
90 * The end time at which to close the history
92 * The intervals to insert in the history backend
93 * @return The backend to be used for querying.
95 protected final @Nullable IStateHistoryBackend
prepareBackend(long startTime
, long endTime
,
96 List
<ITmfStateInterval
> intervals
) {
99 IStateHistoryBackend backend
= getBackendForBuilding(startTime
);
100 insertIntervals(backend
, intervals
);
101 backend
.finishedBuilding(Math
.max(endTime
, backend
.getEndTime()));
102 return getBackendForQuerying(backend
);
103 } catch (IOException e
) {
104 fail(e
.getMessage());
110 * Insert the specified intervals in the provided backend.
113 * The backend to be used
115 * The intervals to insert in the history backend
117 protected static void insertIntervals(IStateHistoryBackend backend
, List
<ITmfStateInterval
> intervals
) {
118 for (ITmfStateInterval interval
: intervals
) {
119 backend
.insertPastState(interval
.getStartTime(), interval
.getEndTime(), interval
.getAttribute(), interval
.getStateValue());
124 * Initializes a list for the number of attributes in the backend and
125 * associates a null value for each
128 * The number of attributes in the backend
129 * @return A list of null values for each attribute
131 private static List
<@Nullable ITmfStateInterval
> prepareIntervalList(int nbAttrib
) {
132 List
<@Nullable ITmfStateInterval
> intervals
= new ArrayList
<>(nbAttrib
);
133 for (int i
= 0; i
< nbAttrib
; i
++) {
140 * Test the integrity of a backend by first building the backend with the
141 * specified intervals, closing it, and then querying at every single
142 * timestamp, making sure that all returned intervals intersect with the
143 * query time. The backend start and end time will be checked.
145 * If <code>allowNull</code> is false, the specified intervals must cover
146 * the full range for all attributes. The method will make sure that no null
147 * intervals are returned.
150 * The start time of the history
152 * The end time of the history
154 * The number of attributes
156 * The list of intervals to insert
158 * True if null intervals are allowed, false otherwise
159 * @return The backend to be used for querying.
161 protected final IStateHistoryBackend
buildAndQueryFullRange(long startTime
, long endTime
, int nbAttr
, List
<ITmfStateInterval
> intervals
, boolean allowNull
) {
163 final IStateHistoryBackend backend
= prepareBackend(startTime
, endTime
, intervals
);
164 assertNotNull(backend
);
168 * Query at every valid time stamp, making sure only the expected
169 * intervals are returned.
171 for (long t
= backend
.getStartTime(); t
<= backend
.getEndTime(); t
++) {
172 List
<@Nullable ITmfStateInterval
> stateInfo
= prepareIntervalList(nbAttr
);
173 backend
.doQuery(stateInfo
, t
);
174 for (int attr
= 0; attr
< stateInfo
.size(); attr
++) {
175 ITmfStateInterval interval
= stateInfo
.get(attr
);
177 assertTrue("null interval at t=" + t
+ " for attr=" + attr
, interval
!= null);
179 if (interval
!= null) {
180 assertTrue(interval
+ " does not intersect t=" + t
, interval
.intersects(t
));
185 assertEquals(startTime
, backend
.getStartTime());
186 assertEquals(endTime
, backend
.getEndTime());
187 } catch (StateSystemDisposedException e
) {
188 fail(e
.getMessage());
194 * Test the full query method by filling a small backend with intervals
195 * placed in a "stair-like" fashion, like this:
205 * and then querying at every single timestamp, making sure all, and only,
206 * the expected intervals are returned.
209 public void testCascadingIntervals() {
210 final int nbAttr
= 10;
211 final long duration
= 10;
212 final long startTime
= 0;
213 final long endTime
= 1000;
215 List
<ITmfStateInterval
> intervals
= new ArrayList
<>();
216 for (long t
= startTime
+ 1; t
<= endTime
+ duration
; t
++) {
217 intervals
.add(new TmfStateInterval(
218 Math
.max(startTime
, t
- duration
),
219 Math
.min(endTime
, t
- 1),
221 TmfStateValue
.newValueLong(t
)));
224 buildAndQueryFullRange(startTime
, endTime
, nbAttr
, intervals
, false);
228 * Test the full query method by filling a small backend with intervals that
229 * take the full time range, like this:
239 * and then querying at every single timestamp, making sure all, and only,
240 * the expected intervals are returned.
243 public void testFullIntervals() {
244 final int nbAttr
= 1000;
245 final long startTime
= 0;
246 final long endTime
= 1000;
248 List
<ITmfStateInterval
> intervals
= new ArrayList
<>();
249 for (int attr
= 0; attr
< nbAttr
; attr
++) {
250 intervals
.add(new TmfStateInterval(
254 TmfStateValue
.newValueLong(attr
)));
257 buildAndQueryFullRange(startTime
, endTime
, nbAttr
, intervals
, false);
261 * Test inserting values of different types and querying them right after
264 public void testInsertQueryStateValues() {
265 /* Test specific data initialization */
274 IStateHistoryBackend backend
= getBackendForBuilding(startTime
);
275 assertNotNull(backend
);
278 backend
.insertPastState(startTime
, startTime
+ timeStep
, intQuark
, INT_VAL1
);
279 ITmfStateInterval interval
= backend
.doSingularQuery(startTime
, intQuark
);
281 assertEquals("Int interval start time", startTime
, interval
.getStartTime());
282 assertEquals("Int interval end time", startTime
+ timeStep
, interval
.getEndTime());
283 assertEquals("Int interval value", INT_VAL1
, interval
.getStateValue());
286 backend
.insertPastState(startTime
, startTime
+ timeStep
, longQuark
, LONG_VAL1
);
287 interval
= backend
.doSingularQuery(startTime
, longQuark
);
289 assertEquals("Long interval start time", startTime
, interval
.getStartTime());
290 assertEquals("Long interval end time", startTime
+ timeStep
, interval
.getEndTime());
291 assertEquals("Long interval value", LONG_VAL1
, interval
.getStateValue());
293 /* Double interval */
294 backend
.insertPastState(startTime
, startTime
+ timeStep
, doubleQuark
, DOUBLE_VAL1
);
295 interval
= backend
.doSingularQuery(startTime
, doubleQuark
);
297 assertEquals("Double interval start time", startTime
, interval
.getStartTime());
298 assertEquals("Double interval end time", startTime
+ timeStep
, interval
.getEndTime());
299 assertEquals("Double interval value", DOUBLE_VAL1
, interval
.getStateValue());
301 /* String interval */
302 backend
.insertPastState(startTime
, startTime
+ timeStep
, strQuark
, STR_VAL1
);
303 interval
= backend
.doSingularQuery(startTime
, strQuark
);
305 assertEquals("String interval start time", startTime
, interval
.getStartTime());
306 assertEquals("String interval end time", startTime
+ timeStep
, interval
.getEndTime());
307 assertEquals("String interval value", STR_VAL1
, interval
.getStateValue());
310 * Add other intervals for the int quark and query at different
313 backend
.insertPastState(startTime
+ timeStep
+ 1, startTime
+ (2 * timeStep
), intQuark
, INT_VAL2
);
314 backend
.insertPastState(startTime
+ (2 * timeStep
) + 1, startTime
+ (3 * timeStep
), intQuark
, INT_VAL1
);
316 interval
= backend
.doSingularQuery(startTime
+ timeStep
, intQuark
);
317 assertEquals("Int interval value", INT_VAL1
, interval
.getStateValue());
319 interval
= backend
.doSingularQuery(startTime
+ timeStep
+ 1, intQuark
);
320 assertEquals("Int interval value", INT_VAL2
, interval
.getStateValue());
322 interval
= backend
.doSingularQuery(startTime
+ (2 * timeStep
), intQuark
);
323 assertEquals("Int interval value", INT_VAL2
, interval
.getStateValue());
325 interval
= backend
.doSingularQuery(startTime
+ (2 * timeStep
) + 1, intQuark
);
326 assertEquals("Int interval value", INT_VAL1
, interval
.getStateValue());
328 } catch (TimeRangeException
| StateSystemDisposedException
| IOException
| AttributeNotFoundException e
) {
329 fail(e
.getMessage());
334 * Test querying various state value types after the state system has been
338 public void testBuildNowQueryLaterStateValues() {
339 /* Test specific data initialization */
349 IStateHistoryBackend backend
= getBackendForBuilding(startTime
);
350 assertNotNull(backend
);
352 long firstEnd
= startTime
+ timeStep
;
353 long nextStart
= firstEnd
+ 1;
354 long endTime
= nextStart
+ timeStep
;
356 insertIntervals(backend
, ImmutableList
.of(new TmfStateInterval(startTime
, startTime
+ timeStep
, intQuark
, INT_VAL1
),
357 new TmfStateInterval(startTime
, startTime
+ timeStep
, longQuark
, LONG_VAL1
),
358 new TmfStateInterval(startTime
, startTime
+ timeStep
, doubleQuark
, DOUBLE_VAL1
),
359 new TmfStateInterval(startTime
, startTime
+ timeStep
, strQuark
, STR_VAL1
),
360 new TmfStateInterval(nextStart
, endTime
, intQuark
, INT_VAL2
),
361 new TmfStateInterval(nextStart
, endTime
, longQuark
, LONG_VAL2
),
362 new TmfStateInterval(nextStart
, endTime
, doubleQuark
, DOUBLE_VAL2
),
363 new TmfStateInterval(nextStart
, endTime
, strQuark
, STR_VAL2
)));
365 backend
.finishedBuilding(endTime
);
367 /* Make sure the end time corresponds to the backend end time */
368 assertEquals(endTime
, backend
.getEndTime());
370 IStateHistoryBackend backendQuery
= getBackendForQuerying(backend
);
372 /* Verify start and end times */
373 assertEquals("Backend start time", startTime
, backendQuery
.getStartTime());
374 assertEquals("Backend end time", endTime
, backendQuery
.getEndTime());
376 List
<@Nullable ITmfStateInterval
> intervals
= prepareIntervalList(nbAttribs
);
378 /* Do a full query at start and verify the values */
379 backendQuery
.doQuery(intervals
, startTime
);
381 ITmfStateInterval interval
= intervals
.get(intQuark
);
382 assertNotNull(interval
);
383 assertEquals("Int value after read", INT_VAL1
, interval
.getStateValue());
384 interval
= intervals
.get(longQuark
);
385 assertNotNull(interval
);
386 assertEquals("Long value after read", LONG_VAL1
, interval
.getStateValue());
387 interval
= intervals
.get(doubleQuark
);
388 assertNotNull(interval
);
389 assertEquals("Double value after read", DOUBLE_VAL1
, interval
.getStateValue());
390 interval
= intervals
.get(strQuark
);
391 assertNotNull(interval
);
392 assertEquals("String value after read", STR_VAL1
, interval
.getStateValue());
394 /* Do a full query at the end and verify the values */
395 backendQuery
.doQuery(intervals
, endTime
);
397 interval
= intervals
.get(intQuark
);
398 assertNotNull(interval
);
399 assertEquals("Int value after read", INT_VAL2
, interval
.getStateValue());
400 interval
= intervals
.get(longQuark
);
401 assertNotNull(interval
);
402 assertEquals("Long value after read", LONG_VAL2
, interval
.getStateValue());
403 interval
= intervals
.get(doubleQuark
);
404 assertNotNull(interval
);
405 assertEquals("Double value after read", DOUBLE_VAL2
, interval
.getStateValue());
406 interval
= intervals
.get(strQuark
);
407 assertNotNull(interval
);
408 assertEquals("String value after read", STR_VAL2
, interval
.getStateValue());
410 } catch (TimeRangeException
| IOException
| StateSystemDisposedException e
) {
411 fail(e
.getMessage());