1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson, EfficiOS Inc. 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 Alexandre Montplaisir
40 * @author Geneviève Bastien
42 public abstract class StateHistoryBackendTestBase
{
44 /* Some state values of each type */
45 private static final ITmfStateValue INT_VAL1
= TmfStateValue
.newValueInt(-42);
46 private static final ITmfStateValue INT_VAL2
= TmfStateValue
.newValueInt(675893);
47 private static final ITmfStateValue LONG_VAL1
= TmfStateValue
.newValueLong(-78L);
48 private static final ITmfStateValue LONG_VAL2
= TmfStateValue
.newValueLong(2234L);
49 private static final ITmfStateValue DOUBLE_VAL1
= TmfStateValue
.newValueDouble(-9.87);
50 private static final ITmfStateValue DOUBLE_VAL2
= TmfStateValue
.newValueDouble(50324.131643);
51 private static final ITmfStateValue STR_VAL1
= TmfStateValue
.newValueString("A string");
52 private static final ITmfStateValue STR_VAL2
= TmfStateValue
.newValueString("Another éèstr");
55 * Gets the backend to be used for building.
58 * The start time of the history
60 * @return The backend to be used for building.
62 * if an exception occurs
64 protected abstract IStateHistoryBackend
getBackendForBuilding(long startTime
) throws IOException
;
67 * Gets the backend to be used for querying. The default implementation
68 * returns the backend that was used for building.
70 * Only the returned backend should be used after calling this method. The
71 * one sent in parameter might have been disposed.
74 * The backend that was used for building
75 * @return The backend to be used for querying.
77 * if an exception occurs
79 @SuppressWarnings("unused")
80 protected IStateHistoryBackend
getBackendForQuerying(IStateHistoryBackend backend
) throws IOException
{
85 * Prepares a backend to be used in tests. The specified intervals will be
86 * inserted in the backend, and then the backend will be closed.
89 * The start time of the history
91 * The end time at which to close the history
93 * The intervals to insert in the history backend
94 * @return The backend to be used for querying.
96 protected final @Nullable IStateHistoryBackend
prepareBackend(long startTime
, long endTime
,
97 List
<ITmfStateInterval
> intervals
) {
100 IStateHistoryBackend backend
= getBackendForBuilding(startTime
);
101 insertIntervals(backend
, intervals
);
102 backend
.finishedBuilding(Math
.max(endTime
, backend
.getEndTime()));
103 return getBackendForQuerying(backend
);
104 } catch (IOException e
) {
105 fail(e
.getMessage());
111 * Insert the specified intervals in the provided backend.
114 * The backend to be used
116 * The intervals to insert in the history backend
118 protected static void insertIntervals(IStateHistoryBackend backend
, List
<ITmfStateInterval
> intervals
) {
119 for (ITmfStateInterval interval
: intervals
) {
120 backend
.insertPastState(interval
.getStartTime(), interval
.getEndTime(), interval
.getAttribute(), interval
.getStateValue());
125 * Initializes a list for the number of attributes in the backend and
126 * associates a null value for each
129 * The number of attributes in the backend
130 * @return A list of null values for each attribute
132 private static List
<@Nullable ITmfStateInterval
> prepareIntervalList(int nbAttrib
) {
133 List
<@Nullable ITmfStateInterval
> intervals
= new ArrayList
<>(nbAttrib
);
134 for (int i
= 0; i
< nbAttrib
; i
++) {
141 * Test the integrity of a backend by first building the backend with the
142 * specified intervals, closing it, and then querying at every single
143 * timestamp, making sure that all returned intervals intersect with the
144 * query time. The backend start and end time will be checked.
146 * If <code>allowNull</code> is false, the specified intervals must cover
147 * the full range for all attributes. The method will make sure that no null
148 * intervals are returned.
151 * The start time of the history
153 * The end time of the history
155 * The number of attributes
157 * The list of intervals to insert
159 * True if null intervals are allowed, false otherwise
160 * @return The backend to be used for querying.
162 protected final IStateHistoryBackend
buildAndQueryFullRange(long startTime
, long endTime
, int nbAttr
, List
<ITmfStateInterval
> intervals
, boolean allowNull
) {
164 final IStateHistoryBackend backend
= prepareBackend(startTime
, endTime
, intervals
);
165 assertNotNull(backend
);
169 * Query at every valid time stamp, making sure only the expected
170 * intervals are returned.
172 for (long t
= backend
.getStartTime(); t
<= backend
.getEndTime(); t
++) {
173 List
<@Nullable ITmfStateInterval
> stateInfo
= prepareIntervalList(nbAttr
);
174 backend
.doQuery(stateInfo
, t
);
175 for (int attr
= 0; attr
< stateInfo
.size(); attr
++) {
176 ITmfStateInterval interval
= stateInfo
.get(attr
);
178 assertTrue("null interval at t=" + t
+ " for attr=" + attr
, interval
!= null);
180 if (interval
!= null) {
181 assertTrue(interval
+ " does not intersect t=" + t
, interval
.intersects(t
));
186 assertEquals(startTime
, backend
.getStartTime());
187 assertEquals(endTime
, backend
.getEndTime());
188 } catch (StateSystemDisposedException e
) {
189 fail(e
.getMessage());
195 * Test the full query method by filling a small backend with intervals
196 * placed in a "stair-like" fashion, like this:
206 * and then querying at every single timestamp, making sure all, and only,
207 * the expected intervals are returned.
210 public void testCascadingIntervals() {
211 final int nbAttr
= 10;
212 final long duration
= 10;
213 final long startTime
= 0;
214 final long endTime
= 1000;
216 List
<ITmfStateInterval
> intervals
= new ArrayList
<>();
217 for (long t
= startTime
+ 1; t
<= endTime
+ duration
; t
++) {
218 intervals
.add(new TmfStateInterval(
219 Math
.max(startTime
, t
- duration
),
220 Math
.min(endTime
, t
- 1),
222 TmfStateValue
.newValueLong(t
)));
225 buildAndQueryFullRange(startTime
, endTime
, nbAttr
, intervals
, false);
229 * Test the full query method by filling a small backend with intervals that
230 * take the full time range, like this:
240 * and then querying at every single timestamp, making sure all, and only,
241 * the expected intervals are returned.
244 public void testFullIntervals() {
245 final int nbAttr
= 1000;
246 final long startTime
= 0;
247 final long endTime
= 1000;
249 List
<ITmfStateInterval
> intervals
= new ArrayList
<>();
250 for (int attr
= 0; attr
< nbAttr
; attr
++) {
251 intervals
.add(new TmfStateInterval(
255 TmfStateValue
.newValueLong(attr
)));
258 buildAndQueryFullRange(startTime
, endTime
, nbAttr
, intervals
, false);
262 * Test inserting values of different types and querying them right after
265 public void testInsertQueryStateValues() {
266 /* Test specific data initialization */
275 IStateHistoryBackend backend
= getBackendForBuilding(startTime
);
276 assertNotNull(backend
);
279 backend
.insertPastState(startTime
, startTime
+ timeStep
, intQuark
, INT_VAL1
);
280 ITmfStateInterval interval
= backend
.doSingularQuery(startTime
, intQuark
);
282 assertEquals("Int interval start time", startTime
, interval
.getStartTime());
283 assertEquals("Int interval end time", startTime
+ timeStep
, interval
.getEndTime());
284 assertEquals("Int interval value", INT_VAL1
, interval
.getStateValue());
287 backend
.insertPastState(startTime
, startTime
+ timeStep
, longQuark
, LONG_VAL1
);
288 interval
= backend
.doSingularQuery(startTime
, longQuark
);
290 assertEquals("Long interval start time", startTime
, interval
.getStartTime());
291 assertEquals("Long interval end time", startTime
+ timeStep
, interval
.getEndTime());
292 assertEquals("Long interval value", LONG_VAL1
, interval
.getStateValue());
294 /* Double interval */
295 backend
.insertPastState(startTime
, startTime
+ timeStep
, doubleQuark
, DOUBLE_VAL1
);
296 interval
= backend
.doSingularQuery(startTime
, doubleQuark
);
298 assertEquals("Double interval start time", startTime
, interval
.getStartTime());
299 assertEquals("Double interval end time", startTime
+ timeStep
, interval
.getEndTime());
300 assertEquals("Double interval value", DOUBLE_VAL1
, interval
.getStateValue());
302 /* String interval */
303 backend
.insertPastState(startTime
, startTime
+ timeStep
, strQuark
, STR_VAL1
);
304 interval
= backend
.doSingularQuery(startTime
, strQuark
);
306 assertEquals("String interval start time", startTime
, interval
.getStartTime());
307 assertEquals("String interval end time", startTime
+ timeStep
, interval
.getEndTime());
308 assertEquals("String interval value", STR_VAL1
, interval
.getStateValue());
311 * Add other intervals for the int quark and query at different
314 backend
.insertPastState(startTime
+ timeStep
+ 1, startTime
+ (2 * timeStep
), intQuark
, INT_VAL2
);
315 backend
.insertPastState(startTime
+ (2 * timeStep
) + 1, startTime
+ (3 * timeStep
), intQuark
, INT_VAL1
);
317 interval
= backend
.doSingularQuery(startTime
+ timeStep
, intQuark
);
318 assertEquals("Int interval value", INT_VAL1
, interval
.getStateValue());
320 interval
= backend
.doSingularQuery(startTime
+ timeStep
+ 1, intQuark
);
321 assertEquals("Int interval value", INT_VAL2
, interval
.getStateValue());
323 interval
= backend
.doSingularQuery(startTime
+ (2 * timeStep
), intQuark
);
324 assertEquals("Int interval value", INT_VAL2
, interval
.getStateValue());
326 interval
= backend
.doSingularQuery(startTime
+ (2 * timeStep
) + 1, intQuark
);
327 assertEquals("Int interval value", INT_VAL1
, interval
.getStateValue());
329 } catch (TimeRangeException
| StateSystemDisposedException
| IOException
| AttributeNotFoundException e
) {
330 fail(e
.getMessage());
335 * Test querying various state value types after the state system has been
339 public void testBuildNowQueryLaterStateValues() {
340 /* Test specific data initialization */
350 IStateHistoryBackend backend
= getBackendForBuilding(startTime
);
351 assertNotNull(backend
);
353 long firstEnd
= startTime
+ timeStep
;
354 long nextStart
= firstEnd
+ 1;
355 long endTime
= nextStart
+ timeStep
;
357 insertIntervals(backend
, ImmutableList
.of(new TmfStateInterval(startTime
, startTime
+ timeStep
, intQuark
, INT_VAL1
),
358 new TmfStateInterval(startTime
, startTime
+ timeStep
, longQuark
, LONG_VAL1
),
359 new TmfStateInterval(startTime
, startTime
+ timeStep
, doubleQuark
, DOUBLE_VAL1
),
360 new TmfStateInterval(startTime
, startTime
+ timeStep
, strQuark
, STR_VAL1
),
361 new TmfStateInterval(nextStart
, endTime
, intQuark
, INT_VAL2
),
362 new TmfStateInterval(nextStart
, endTime
, longQuark
, LONG_VAL2
),
363 new TmfStateInterval(nextStart
, endTime
, doubleQuark
, DOUBLE_VAL2
),
364 new TmfStateInterval(nextStart
, endTime
, strQuark
, STR_VAL2
)));
366 backend
.finishedBuilding(endTime
);
368 /* Make sure the end time corresponds to the backend end time */
369 assertEquals(endTime
, backend
.getEndTime());
371 IStateHistoryBackend backendQuery
= getBackendForQuerying(backend
);
373 /* Verify start and end times */
374 assertEquals("Backend start time", startTime
, backendQuery
.getStartTime());
375 assertEquals("Backend end time", endTime
, backendQuery
.getEndTime());
377 List
<@Nullable ITmfStateInterval
> intervals
= prepareIntervalList(nbAttribs
);
379 /* Do a full query at start and verify the values */
380 backendQuery
.doQuery(intervals
, startTime
);
382 ITmfStateInterval interval
= intervals
.get(intQuark
);
383 assertNotNull(interval
);
384 assertEquals("Int value after read", INT_VAL1
, interval
.getStateValue());
385 interval
= intervals
.get(longQuark
);
386 assertNotNull(interval
);
387 assertEquals("Long value after read", LONG_VAL1
, interval
.getStateValue());
388 interval
= intervals
.get(doubleQuark
);
389 assertNotNull(interval
);
390 assertEquals("Double value after read", DOUBLE_VAL1
, interval
.getStateValue());
391 interval
= intervals
.get(strQuark
);
392 assertNotNull(interval
);
393 assertEquals("String value after read", STR_VAL1
, interval
.getStateValue());
395 /* Do a full query at the end and verify the values */
396 backendQuery
.doQuery(intervals
, endTime
);
398 interval
= intervals
.get(intQuark
);
399 assertNotNull(interval
);
400 assertEquals("Int value after read", INT_VAL2
, interval
.getStateValue());
401 interval
= intervals
.get(longQuark
);
402 assertNotNull(interval
);
403 assertEquals("Long value after read", LONG_VAL2
, interval
.getStateValue());
404 interval
= intervals
.get(doubleQuark
);
405 assertNotNull(interval
);
406 assertEquals("Double value after read", DOUBLE_VAL2
, interval
.getStateValue());
407 interval
= intervals
.get(strQuark
);
408 assertNotNull(interval
);
409 assertEquals("String value after read", STR_VAL2
, interval
.getStateValue());
411 } catch (TimeRangeException
| IOException
| StateSystemDisposedException e
) {
412 fail(e
.getMessage());