/******************************************************************************* * Copyright (c) 2014, 2016 École Polytechnique de Montréal * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Geneviève Bastien - Initial API and implementation *******************************************************************************/ package org.eclipse.tracecompass.statesystem.core.tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder; import org.eclipse.tracecompass.statesystem.core.StateSystemFactory; import org.eclipse.tracecompass.statesystem.core.StateSystemUtils; import org.eclipse.tracecompass.statesystem.core.StateSystemUtils.QuarkIterator; import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend; import org.eclipse.tracecompass.statesystem.core.backend.StateHistoryBackendFactory; import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.google.common.collect.Iterators; /** * Test the {@link StateSystemUtils} class * * @author Geneviève Bastien */ public class StateSystemUtilsTest { private static final long START_TIME = 1000L; private static final @NonNull String DUMMY_STRING = "test"; private ITmfStateSystemBuilder fStateSystem; /** * Build a small test state system in memory */ @Before public void setupStateSystem() { try { IStateHistoryBackend backend = StateHistoryBackendFactory.createInMemoryBackend(DUMMY_STRING, START_TIME); fStateSystem = StateSystemFactory.newStateSystem(backend); int quark = fStateSystem.getQuarkAbsoluteAndAdd(DUMMY_STRING); fStateSystem.modifyAttribute(1200L, TmfStateValue.newValueInt(10), quark); fStateSystem.modifyAttribute(1500L, TmfStateValue.newValueInt(20), quark); fStateSystem.closeHistory(2000L); } catch (StateValueTypeException e) { fail(e.getMessage()); } } /** * Clean-up */ @After public void tearDown() { fStateSystem.dispose(); } /** * Test the {@link StateSystemUtils#queryUntilNonNullValue} method. */ @Test public void testQueryUntilNonNullValue() { ITmfStateSystem ss = fStateSystem; assertNotNull(ss); int quark; try { quark = ss.getQuarkAbsolute(DUMMY_STRING); /* Should return null if requested range is not within range */ assertNull(StateSystemUtils.queryUntilNonNullValue(ss, quark, 0, 999L)); assertNull(StateSystemUtils.queryUntilNonNullValue(ss, quark, 2001L, 5000L)); /* * Should return null if request within range, but condition is * false */ assertNull(StateSystemUtils.queryUntilNonNullValue(ss, quark, 1000L, 1199L)); /* * Should return the right interval if an interval is within range, * even if the range starts or ends outside state system range */ ITmfStateInterval interval = StateSystemUtils.queryUntilNonNullValue(ss, quark, 1000L, 1300L); assertNotNull(interval); assertEquals(ITmfStateValue.Type.INTEGER, interval.getStateValue().getType()); assertEquals(10, interval.getStateValue().unboxInt()); interval = StateSystemUtils.queryUntilNonNullValue(ss, quark, 800L, 2500L); assertNotNull(interval); assertEquals(ITmfStateValue.Type.INTEGER, interval.getStateValue().getType()); assertEquals(10, interval.getStateValue().unboxInt()); interval = StateSystemUtils.queryUntilNonNullValue(ss, quark, 1300L, 1800L); assertNotNull(interval); assertEquals(ITmfStateValue.Type.INTEGER, interval.getStateValue().getType()); assertEquals(10, interval.getStateValue().unboxInt()); interval = StateSystemUtils.queryUntilNonNullValue(ss, quark, 1500L, 1800L); assertNotNull(interval); assertEquals(ITmfStateValue.Type.INTEGER, interval.getStateValue().getType()); assertEquals(20, interval.getStateValue().unboxInt()); interval = StateSystemUtils.queryUntilNonNullValue(ss, quark, 1800L, 2500L); assertNotNull(interval); assertEquals(ITmfStateValue.Type.INTEGER, interval.getStateValue().getType()); assertEquals(20, interval.getStateValue().unboxInt()); } catch (AttributeNotFoundException e) { fail(e.getMessage()); } } /** * Test that iterator returns the correct intervals: * <ul> * <li>intervals for the correct quark</li> * <li>ordered intervals</li> * <li>intervals covering the correct time range</li> * </ul> */ @Test public void testIteratorOverQuark() { ITmfStateSystem ss = fStateSystem; assertNotNull(ss); for (int quark = 0; quark < ss.getNbAttributes(); quark++) { QuarkIterator iterator = new QuarkIterator(ss, quark, Long.MIN_VALUE); ITmfStateInterval prevInterval = null; ITmfStateInterval currInterval = null; while (iterator.hasNext()) { currInterval = iterator.next(); assertEquals(quark, currInterval.getAttribute()); if (prevInterval == null) { /* This is the first interval for this attribute */ assertEquals(currInterval.getStartTime(), ss.getStartTime()); } else { assertEquals(prevInterval.getEndTime() + 1, currInterval.getStartTime()); } prevInterval = currInterval; } assertNotNull("Iterator should have returned at least one interval", currInterval); assertEquals(ss.getCurrentEndTime(), currInterval.getEndTime()); } } /** * Test that getIteratorOverQuark returns the correct intervals for a range * included in the state system range */ @Test public void testIteratorOverQuarkSubrange() { ITmfStateSystem ss = fStateSystem; assertNotNull(ss); int quark; try { quark = ss.getQuarkAbsolute(DUMMY_STRING); QuarkIterator iterator = new QuarkIterator(ss, quark, 1800L); /* There should be one interval ranging from 1500L to 2000L */ assertTrue(iterator.hasNext()); ITmfStateInterval interval = iterator.next(); assertNotNull(interval); assertEquals(1500L, interval.getStartTime()); assertEquals(2000L, interval.getEndTime()); /* There should not be a next interval */ assertFalse(iterator.hasNext()); } catch (AttributeNotFoundException e) { fail(e.getMessage()); } } /** * With the query end > ss.end, query some intervals, then add a few * intervals to the ss such that end now becomes < ss.end and make sure * those new intervals are picked up */ @Test public void testIteratorOverQuarkAddMoreIntervals() { try { IStateHistoryBackend backend = StateHistoryBackendFactory.createInMemoryBackend(DUMMY_STRING, START_TIME); ITmfStateSystemBuilder ss = StateSystemFactory.newStateSystem(backend); int quark = ss.getQuarkAbsoluteAndAdd(DUMMY_STRING); ss.modifyAttribute(1200L, TmfStateValue.newValueInt(10), quark); ss.modifyAttribute(1500L, TmfStateValue.newValueInt(20), quark); /* We should have 2 intervals if we iterate at this point */ QuarkIterator iterator = new QuarkIterator(ss, quark, 0); assertEquals(2, Iterators.size(iterator)); /* Reset the iterator */ iterator = new QuarkIterator(ss, quark, 0); /* Add an interval, updating the ss.end time */ ss.closeHistory(2000L); /* We should have 3 intervals if we iterate at this point */ assertEquals(3, Iterators.size(iterator)); } catch (StateValueTypeException e) { fail(e.getMessage()); } } /** * Test that the reverse iterator returns the correct intervals: * <ul> * <li>intervals for the correct quark</li> * <li>ordered intervals</li> * <li>intervals covering the correct time range</li> * </ul> */ @Test public void testIteratorOverQuarkReversed() { ITmfStateSystem ss = fStateSystem; assertNotNull(ss); for (int quark = 0; quark < ss.getNbAttributes(); quark++) { QuarkIterator iterator = new QuarkIterator(ss, quark, Long.MAX_VALUE); ITmfStateInterval prevInterval = null; ITmfStateInterval currInterval = null; while (iterator.hasPrevious()) { currInterval = iterator.previous(); assertEquals(quark, currInterval.getAttribute()); if (prevInterval == null) { /* This is the first interval for this attribute */ assertEquals(currInterval.getEndTime(), ss.getCurrentEndTime()); } else { assertEquals(prevInterval.getStartTime() - 1, currInterval.getEndTime()); } prevInterval = currInterval; } assertNotNull("Iterator should have returned at least one interval", currInterval); assertEquals(ss.getStartTime(), currInterval.getStartTime()); } } }