f678b700e4ff6699b4eb17f7d0d6389e9f057a1c
[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, EfficiOS Inc. 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.junit.Test;
31
32 import com.google.common.collect.ImmutableList;
33
34 /**
35 * Abstract class to test implementations of the {@link IStateHistoryBackend}
36 * interface.
37 *
38 * @author Patrick Tasse
39 * @author Alexandre Montplaisir
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
274 try {
275 IStateHistoryBackend backend = getBackendForBuilding(startTime);
276 assertNotNull(backend);
277
278 /* Int interval */
279 backend.insertPastState(startTime, startTime + timeStep, intQuark, INT_VAL1);
280 ITmfStateInterval interval = backend.doSingularQuery(startTime, intQuark);
281
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());
285
286 /* Long interval */
287 backend.insertPastState(startTime, startTime + timeStep, longQuark, LONG_VAL1);
288 interval = backend.doSingularQuery(startTime, longQuark);
289
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());
293
294 /* Double interval */
295 backend.insertPastState(startTime, startTime + timeStep, doubleQuark, DOUBLE_VAL1);
296 interval = backend.doSingularQuery(startTime, doubleQuark);
297
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());
301
302 /* String interval */
303 backend.insertPastState(startTime, startTime + timeStep, strQuark, STR_VAL1);
304 interval = backend.doSingularQuery(startTime, strQuark);
305
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());
309
310 /*
311 * Add other intervals for the int quark and query at different
312 * times
313 */
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);
316
317 interval = backend.doSingularQuery(startTime + timeStep, intQuark);
318 assertEquals("Int interval value", INT_VAL1, interval.getStateValue());
319
320 interval = backend.doSingularQuery(startTime + timeStep + 1, intQuark);
321 assertEquals("Int interval value", INT_VAL2, interval.getStateValue());
322
323 interval = backend.doSingularQuery(startTime + (2 * timeStep), intQuark);
324 assertEquals("Int interval value", INT_VAL2, interval.getStateValue());
325
326 interval = backend.doSingularQuery(startTime + (2 * timeStep) + 1, intQuark);
327 assertEquals("Int interval value", INT_VAL1, interval.getStateValue());
328
329 } catch (TimeRangeException | StateSystemDisposedException | IOException | AttributeNotFoundException e) {
330 fail(e.getMessage());
331 }
332 }
333
334 /**
335 * Test querying various state value types after the state system has been
336 * built and finished
337 */
338 @Test
339 public void testBuildNowQueryLaterStateValues() {
340 /* Test specific data initialization */
341 long startTime = 10;
342 long timeStep = 5;
343 int intQuark = 0;
344 int longQuark = 1;
345 int doubleQuark = 2;
346 int strQuark = 3;
347 int nbAttribs = 4;
348
349 try {
350 IStateHistoryBackend backend = getBackendForBuilding(startTime);
351 assertNotNull(backend);
352
353 long firstEnd = startTime + timeStep;
354 long nextStart = firstEnd + 1;
355 long endTime = nextStart + timeStep;
356
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)));
365
366 backend.finishedBuilding(endTime);
367
368 /* Make sure the end time corresponds to the backend end time */
369 assertEquals(endTime, backend.getEndTime());
370
371 IStateHistoryBackend backendQuery = getBackendForQuerying(backend);
372
373 /* Verify start and end times */
374 assertEquals("Backend start time", startTime, backendQuery.getStartTime());
375 assertEquals("Backend end time", endTime, backendQuery.getEndTime());
376
377 List<@Nullable ITmfStateInterval> intervals = prepareIntervalList(nbAttribs);
378
379 /* Do a full query at start and verify the values */
380 backendQuery.doQuery(intervals, startTime);
381
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());
394
395 /* Do a full query at the end and verify the values */
396 backendQuery.doQuery(intervals, endTime);
397
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());
410
411 } catch (TimeRangeException | IOException | StateSystemDisposedException e) {
412 fail(e.getMessage());
413 }
414 }
415 }
This page took 0.042137 seconds and 5 git commands to generate.