ss: Add support for custom state values
[deliverable/tracecompass.git] / statesystem / org.eclipse.tracecompass.statesystem.core.tests / src / org / eclipse / tracecompass / statesystem / core / tests / backend / StateHistoryBackendTestBase.java
1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson and others
3 *
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 *******************************************************************************/
9
10 package org.eclipse.tracecompass.statesystem.core.tests.backend;
11
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;
16
17 import java.io.IOException;
18 import java.util.ArrayList;
19 import java.util.List;
20
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.eclipse.tracecompass.statesystem.core.tests.stubs.statevalues.CustomStateValueStub;
31 import org.junit.Test;
32
33 import com.google.common.collect.ImmutableList;
34
35 /**
36 * Abstract class to test implementations of the {@link IStateHistoryBackend}
37 * interface.
38 *
39 * @author Patrick Tasse
40 * @author Geneviève Bastien
41 */
42 public abstract class StateHistoryBackendTestBase {
43
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");
53
54 /**
55 * Gets the backend to be used for building.
56 *
57 * @param startTime
58 * The start time of the history
59 *
60 * @return The backend to be used for building.
61 * @throws IOException
62 * if an exception occurs
63 */
64 protected abstract IStateHistoryBackend getBackendForBuilding(long startTime) throws IOException;
65
66 /**
67 * Gets the backend to be used for querying. The default implementation
68 * returns the backend that was used for building.
69 * <p>
70 * Only the returned backend should be used after calling this method. The
71 * one sent in parameter might have been disposed.
72 *
73 * @param backend
74 * The backend that was used for building
75 * @return The backend to be used for querying.
76 * @throws IOException
77 * if an exception occurs
78 */
79 @SuppressWarnings("unused")
80 protected IStateHistoryBackend getBackendForQuerying(IStateHistoryBackend backend) throws IOException {
81 return backend;
82 }
83
84 /**
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.
87 *
88 * @param startTime
89 * The start time of the history
90 * @param endTime
91 * The end time at which to close the history
92 * @param intervals
93 * The intervals to insert in the history backend
94 * @return The backend to be used for querying.
95 */
96 protected final @Nullable IStateHistoryBackend prepareBackend(long startTime, long endTime,
97 List<ITmfStateInterval> intervals) {
98
99 try {
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());
106 return null;
107 }
108 }
109
110 /**
111 * Insert the specified intervals in the provided backend.
112 *
113 * @param backend
114 * The backend to be used
115 * @param intervals
116 * The intervals to insert in the history backend
117 */
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());
121 }
122 }
123
124 /**
125 * Initializes a list for the number of attributes in the backend and
126 * associates a null value for each
127 *
128 * @param nbAttrib
129 * The number of attributes in the backend
130 * @return A list of null values for each attribute
131 */
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++) {
135 intervals.add(null);
136 }
137 return intervals;
138 }
139
140 /**
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.
145 * <p>
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.
149 *
150 * @param startTime
151 * The start time of the history
152 * @param endTime
153 * The end time of the history
154 * @param nbAttr
155 * The number of attributes
156 * @param intervals
157 * The list of intervals to insert
158 * @param allowNull
159 * True if null intervals are allowed, false otherwise
160 * @return The backend to be used for querying.
161 */
162 protected final IStateHistoryBackend buildAndQueryFullRange(long startTime, long endTime, int nbAttr, List<ITmfStateInterval> intervals, boolean allowNull) {
163
164 final IStateHistoryBackend backend = prepareBackend(startTime, endTime, intervals);
165 assertNotNull(backend);
166
167 try {
168 /*
169 * Query at every valid time stamp, making sure only the expected
170 * intervals are returned.
171 */
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);
177 if (!allowNull) {
178 assertTrue("null interval at t=" + t + " for attr=" + attr, interval != null);
179 }
180 if (interval != null) {
181 assertTrue(interval + " does not intersect t=" + t, interval.intersects(t));
182 }
183 }
184 }
185
186 assertEquals(startTime, backend.getStartTime());
187 assertEquals(endTime, backend.getEndTime());
188 } catch (StateSystemDisposedException e) {
189 fail(e.getMessage());
190 }
191 return backend;
192 }
193
194 /**
195 * Test the full query method by filling a small backend with intervals
196 * placed in a "stair-like" fashion, like this:
197 *
198 * <pre>
199 * |x----x----x---x|
200 * |xx----x----x--x|
201 * |x-x----x----x-x|
202 * |x--x----x----xx|
203 * | ... |
204 * </pre>
205 *
206 * and then querying at every single timestamp, making sure all, and only,
207 * the expected intervals are returned.
208 */
209 @Test
210 public void testCascadingIntervals() {
211 final int nbAttr = 10;
212 final long duration = 10;
213 final long startTime = 0;
214 final long endTime = 1000;
215
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),
221 (int) t % nbAttr,
222 TmfStateValue.newValueLong(t)));
223 }
224
225 buildAndQueryFullRange(startTime, endTime, nbAttr, intervals, false);
226 }
227
228 /**
229 * Test the full query method by filling a small backend with intervals that
230 * take the full time range, like this:
231 *
232 * <pre>
233 * |x-------------x|
234 * |x-------------x|
235 * |x-------------x|
236 * |x-------------x|
237 * | ... |
238 * </pre>
239 *
240 * and then querying at every single timestamp, making sure all, and only,
241 * the expected intervals are returned.
242 */
243 @Test
244 public void testFullIntervals() {
245 final int nbAttr = 1000;
246 final long startTime = 0;
247 final long endTime = 1000;
248
249 List<ITmfStateInterval> intervals = new ArrayList<>();
250 for (int attr = 0; attr < nbAttr; attr++) {
251 intervals.add(new TmfStateInterval(
252 startTime,
253 endTime,
254 attr,
255 TmfStateValue.newValueLong(attr)));
256 }
257
258 buildAndQueryFullRange(startTime, endTime, nbAttr, intervals, false);
259 }
260
261 /**
262 * Test inserting values of different types and querying them right after
263 */
264 @Test
265 public void testInsertQueryStateValues() {
266 /* Test specific data initialization */
267 long startTime = 10;
268 long timeStep = 5;
269 int intQuark = 0;
270 int longQuark = 1;
271 int doubleQuark = 2;
272 int strQuark = 3;
273 int customQuark = 4;
274 /* Register custom factory and create a custom state value */
275 CustomStateValueStub.registerFactory();
276 ITmfStateValue customVal = new CustomStateValueStub(10, "a string");
277
278 try {
279 IStateHistoryBackend backend = getBackendForBuilding(startTime);
280 assertNotNull(backend);
281
282 /* Int interval */
283 backend.insertPastState(startTime, startTime + timeStep, intQuark, INT_VAL1);
284 ITmfStateInterval interval = backend.doSingularQuery(startTime, intQuark);
285
286 assertEquals("Int interval start time", startTime, interval.getStartTime());
287 assertEquals("Int interval end time", startTime + timeStep, interval.getEndTime());
288 assertEquals("Int interval value", INT_VAL1, interval.getStateValue());
289
290 /* Long interval */
291 backend.insertPastState(startTime, startTime + timeStep, longQuark, LONG_VAL1);
292 interval = backend.doSingularQuery(startTime, longQuark);
293
294 assertEquals("Long interval start time", startTime, interval.getStartTime());
295 assertEquals("Long interval end time", startTime + timeStep, interval.getEndTime());
296 assertEquals("Long interval value", LONG_VAL1, interval.getStateValue());
297
298 /* Double interval */
299 backend.insertPastState(startTime, startTime + timeStep, doubleQuark, DOUBLE_VAL1);
300 interval = backend.doSingularQuery(startTime, doubleQuark);
301
302 assertEquals("Double interval start time", startTime, interval.getStartTime());
303 assertEquals("Double interval end time", startTime + timeStep, interval.getEndTime());
304 assertEquals("Double interval value", DOUBLE_VAL1, interval.getStateValue());
305
306 /* String interval */
307 backend.insertPastState(startTime, startTime + timeStep, strQuark, STR_VAL1);
308 interval = backend.doSingularQuery(startTime, strQuark);
309
310 assertEquals("String interval start time", startTime, interval.getStartTime());
311 assertEquals("String interval end time", startTime + timeStep, interval.getEndTime());
312 assertEquals("String interval value", STR_VAL1, interval.getStateValue());
313
314 /* Custom state values */
315 backend.insertPastState(startTime, startTime + timeStep, customQuark, customVal);
316 interval = backend.doSingularQuery(startTime, customQuark);
317
318 assertEquals("Custom interval start time", startTime, interval.getStartTime());
319 assertEquals("Custom interval end time", startTime + timeStep, interval.getEndTime());
320 assertEquals("Custom interval value", customVal, interval.getStateValue());
321
322 /*
323 * Add other intervals for the int quark and query at different
324 * times
325 */
326 backend.insertPastState(startTime + timeStep + 1, startTime + (2 * timeStep), intQuark, INT_VAL2);
327 backend.insertPastState(startTime + (2 * timeStep) + 1, startTime + (3 * timeStep), intQuark, INT_VAL1);
328
329 interval = backend.doSingularQuery(startTime + timeStep, intQuark);
330 assertEquals("Int interval value", INT_VAL1, interval.getStateValue());
331
332 interval = backend.doSingularQuery(startTime + timeStep + 1, intQuark);
333 assertEquals("Int interval value", INT_VAL2, interval.getStateValue());
334
335 interval = backend.doSingularQuery(startTime + (2 * timeStep), intQuark);
336 assertEquals("Int interval value", INT_VAL2, interval.getStateValue());
337
338 interval = backend.doSingularQuery(startTime + (2 * timeStep) + 1, intQuark);
339 assertEquals("Int interval value", INT_VAL1, interval.getStateValue());
340
341 } catch (TimeRangeException | StateSystemDisposedException | IOException | AttributeNotFoundException e) {
342 fail(e.getMessage());
343 }
344 }
345
346 /**
347 * Test querying various state value types after the state system has been
348 * built and finished
349 */
350 @Test
351 public void testBuildNowQueryLaterStateValues() {
352 /* Test specific data initialization */
353 long startTime = 10;
354 long timeStep = 5;
355 int intQuark = 0;
356 int longQuark = 1;
357 int doubleQuark = 2;
358 int strQuark = 3;
359 int customQuark = 4;
360 int nbAttribs = 5;
361 /* Register custom factory and create custom state values */
362 CustomStateValueStub.registerFactory();
363 ITmfStateValue customVal = new CustomStateValueStub(10, "a string");
364 ITmfStateValue customVal2 = new CustomStateValueStub(Short.MAX_VALUE, "another string");
365
366 try {
367 IStateHistoryBackend backend = getBackendForBuilding(startTime);
368 assertNotNull(backend);
369
370 long firstEnd = startTime + timeStep;
371 long nextStart = firstEnd + 1;
372 long endTime = nextStart + timeStep;
373
374 insertIntervals(backend, ImmutableList.of(new TmfStateInterval(startTime, startTime + timeStep, intQuark, INT_VAL1),
375 new TmfStateInterval(startTime, startTime + timeStep, longQuark, LONG_VAL1),
376 new TmfStateInterval(startTime, startTime + timeStep, doubleQuark, DOUBLE_VAL1),
377 new TmfStateInterval(startTime, startTime + timeStep, strQuark, STR_VAL1),
378 new TmfStateInterval(startTime, startTime + timeStep, customQuark, customVal),
379 new TmfStateInterval(nextStart, endTime, intQuark, INT_VAL2),
380 new TmfStateInterval(nextStart, endTime, longQuark, LONG_VAL2),
381 new TmfStateInterval(nextStart, endTime, doubleQuark, DOUBLE_VAL2),
382 new TmfStateInterval(nextStart, endTime, strQuark, STR_VAL2),
383 new TmfStateInterval(nextStart, endTime, customQuark, customVal2)));
384
385 backend.finishedBuilding(endTime);
386
387 /* Make sure the end time corresponds to the backend end time */
388 assertEquals(endTime, backend.getEndTime());
389
390 IStateHistoryBackend backendQuery = getBackendForQuerying(backend);
391
392 /* Verify start and end times */
393 assertEquals("Backend start time", startTime, backendQuery.getStartTime());
394 assertEquals("Backend end time", endTime, backendQuery.getEndTime());
395
396 List<@Nullable ITmfStateInterval> intervals = prepareIntervalList(nbAttribs);
397
398 /* Do a full query at start and verify the values */
399 backendQuery.doQuery(intervals, startTime);
400
401 ITmfStateInterval interval = intervals.get(intQuark);
402 assertNotNull(interval);
403 assertEquals("Int value after read", INT_VAL1, interval.getStateValue());
404 interval = intervals.get(longQuark);
405 assertNotNull(interval);
406 assertEquals("Long value after read", LONG_VAL1, interval.getStateValue());
407 interval = intervals.get(doubleQuark);
408 assertNotNull(interval);
409 assertEquals("Double value after read", DOUBLE_VAL1, interval.getStateValue());
410 interval = intervals.get(strQuark);
411 assertNotNull(interval);
412 assertEquals("String value after read", STR_VAL1, interval.getStateValue());
413 /* Custom */
414 interval = intervals.get(customQuark);
415 assertNotNull(interval);
416 assertEquals("String value after read", customVal, interval.getStateValue());
417
418 /* Do a full query at the end and verify the values */
419 backendQuery.doQuery(intervals, endTime);
420
421 interval = intervals.get(intQuark);
422 assertNotNull(interval);
423 assertEquals("Int value after read", INT_VAL2, interval.getStateValue());
424 interval = intervals.get(longQuark);
425 assertNotNull(interval);
426 assertEquals("Long value after read", LONG_VAL2, interval.getStateValue());
427 interval = intervals.get(doubleQuark);
428 assertNotNull(interval);
429 assertEquals("Double value after read", DOUBLE_VAL2, interval.getStateValue());
430 interval = intervals.get(strQuark);
431 assertNotNull(interval);
432 assertEquals("String value after read", STR_VAL2, interval.getStateValue());
433 /* Custom */
434 interval = intervals.get(customQuark);
435 assertNotNull(interval);
436 assertEquals("String value after read", customVal2, interval.getStateValue());
437
438 } catch (TimeRangeException | IOException | StateSystemDisposedException e) {
439 fail(e.getMessage());
440 }
441 }
442 }
This page took 0.059393 seconds and 5 git commands to generate.