| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2013, 2016 École Polytechnique de Montréal |
| 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.tmf.core.tests.statesystem; |
| 11 | |
| 12 | import static org.junit.Assert.assertEquals; |
| 13 | import static org.junit.Assert.assertFalse; |
| 14 | import static org.junit.Assert.assertNotNull; |
| 15 | import static org.junit.Assert.assertNull; |
| 16 | import static org.junit.Assert.assertTrue; |
| 17 | import static org.junit.Assert.fail; |
| 18 | |
| 19 | import java.util.Map; |
| 20 | import java.util.concurrent.BrokenBarrierException; |
| 21 | import java.util.concurrent.CyclicBarrier; |
| 22 | import java.util.concurrent.TimeUnit; |
| 23 | |
| 24 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; |
| 25 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; |
| 26 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; |
| 27 | import org.eclipse.tracecompass.tmf.core.statesystem.Messages; |
| 28 | import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; |
| 29 | import org.eclipse.tracecompass.tmf.core.tests.TmfCoreTestPlugin; |
| 30 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; |
| 31 | import org.eclipse.tracecompass.tmf.tests.stubs.analysis.TestStateSystemModule; |
| 32 | import org.eclipse.tracecompass.tmf.tests.stubs.analysis.TestStateSystemProvider; |
| 33 | import org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStub; |
| 34 | import org.junit.After; |
| 35 | import org.junit.Before; |
| 36 | import org.junit.Ignore; |
| 37 | import org.junit.Rule; |
| 38 | import org.junit.Test; |
| 39 | import org.junit.rules.TestRule; |
| 40 | import org.junit.rules.Timeout; |
| 41 | |
| 42 | /** |
| 43 | * Test the {@link TmfStateSystemAnalysisModule} class |
| 44 | * |
| 45 | * @author Geneviève Bastien |
| 46 | */ |
| 47 | public class StateSystemAnalysisModuleTest { |
| 48 | |
| 49 | /** Time-out tests after 1 minute. */ |
| 50 | @Rule |
| 51 | public TestRule globalTimeout = new Timeout(1, TimeUnit.MINUTES); |
| 52 | |
| 53 | /** ID of the test state system analysis module */ |
| 54 | public static final String MODULE_SS = "org.eclipse.linuxtools.tmf.core.tests.analysis.sstest"; |
| 55 | private static final String XML_TRACE = "testfiles/stub_xml_traces/valid/analysis_dependency.xml"; |
| 56 | |
| 57 | private TestStateSystemModule fModule; |
| 58 | private ITmfTrace fTrace; |
| 59 | |
| 60 | /** |
| 61 | * Setup test trace |
| 62 | */ |
| 63 | @Before |
| 64 | public void setupTraces() { |
| 65 | TmfXmlTraceStub trace = TmfXmlTraceStub.setupTrace(TmfCoreTestPlugin.getAbsoluteFilePath(XML_TRACE)); |
| 66 | trace.traceOpened(new TmfTraceOpenedSignal(this, trace, null)); |
| 67 | fTrace = trace; |
| 68 | |
| 69 | fModule = (TestStateSystemModule) trace.getAnalysisModule(MODULE_SS); |
| 70 | } |
| 71 | |
| 72 | /** |
| 73 | * Some tests use traces, let's clean them here |
| 74 | */ |
| 75 | @After |
| 76 | public void cleanupTraces() { |
| 77 | fTrace.dispose(); |
| 78 | } |
| 79 | |
| 80 | /** |
| 81 | * Test the state system module execution and result |
| 82 | */ |
| 83 | @Test |
| 84 | public void testSsModule() { |
| 85 | ITmfStateSystem ss = fModule.getStateSystem(); |
| 86 | assertNull(ss); |
| 87 | fModule.schedule(); |
| 88 | if (fModule.waitForCompletion()) { |
| 89 | ss = fModule.getStateSystem(); |
| 90 | assertNotNull(ss); |
| 91 | } else { |
| 92 | fail("Module did not complete properly"); |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | /** |
| 97 | * Make sure that the state system is initialized after calling |
| 98 | * {@link TmfStateSystemAnalysisModule#waitForInitialization()}. |
| 99 | */ |
| 100 | @Test |
| 101 | public void testInitialization() { |
| 102 | assertNull(fModule.getStateSystem()); |
| 103 | fModule.schedule(); |
| 104 | |
| 105 | assertTrue("Initialization succeeded", fModule.waitForInitialization()); |
| 106 | assertNotNull(fModule.getStateSystem()); |
| 107 | } |
| 108 | |
| 109 | /** |
| 110 | * Test that helper returns the right properties |
| 111 | */ |
| 112 | @Test |
| 113 | public void testProperties() { |
| 114 | |
| 115 | /* The stub state system has in mem backend 2 properties */ |
| 116 | Map<String, String> properties = fModule.getProperties(); |
| 117 | assertEquals(fModule.getBackendName(), properties.get(Messages.TmfStateSystemAnalysisModule_PropertiesBackend)); |
| 118 | assertEquals(fModule.getId(), properties.get(org.eclipse.tracecompass.tmf.core.analysis.Messages.TmfAbstractAnalysisModule_LabelId)); |
| 119 | } |
| 120 | |
| 121 | private static final String CRUCIAL_EVENT = "crucialEvent"; |
| 122 | private static final String CRUCIAL_FIELD = "crucialInfo"; |
| 123 | |
| 124 | private static void setupDependentAnalysisHandler(CyclicBarrier barrier) { |
| 125 | TestStateSystemProvider.setEventHandler((ss, event) -> { |
| 126 | try { |
| 127 | /* Wait before processing the current event */ |
| 128 | barrier.await(); |
| 129 | if (event.getName().equals(CRUCIAL_EVENT)) { |
| 130 | String crucialInfo = (String) event.getContent().getField(CRUCIAL_FIELD).getValue(); |
| 131 | int quark = ss.getQuarkAbsoluteAndAdd(CRUCIAL_FIELD); |
| 132 | try { |
| 133 | ss.modifyAttribute(event.getTimestamp().toNanos(), TmfStateValue.newValueString(crucialInfo), quark); |
| 134 | } catch (Exception e) { |
| 135 | fail(e.getMessage()); |
| 136 | } |
| 137 | } |
| 138 | /* Wait before processing the next event */ |
| 139 | barrier.await(); |
| 140 | return true; |
| 141 | } catch (InterruptedException | BrokenBarrierException e1) { |
| 142 | return false; |
| 143 | } |
| 144 | |
| 145 | }); |
| 146 | } |
| 147 | |
| 148 | /** |
| 149 | * Test the {@link TmfStateSystemAnalysisModule#isQueryable(long)} method |
| 150 | */ |
| 151 | @Test |
| 152 | public void testIsQueryable() { |
| 153 | |
| 154 | CyclicBarrier barrier = new CyclicBarrier(2); |
| 155 | setupDependentAnalysisHandler(barrier); |
| 156 | |
| 157 | TestStateSystemModule module = fModule; |
| 158 | assertNotNull(module); |
| 159 | |
| 160 | /* Module is not started, it should be queriable */ |
| 161 | assertTrue(module.isQueryable(1)); |
| 162 | assertTrue(module.isQueryable(4)); |
| 163 | assertTrue(module.isQueryable(5)); |
| 164 | assertTrue(module.isQueryable(7)); |
| 165 | assertTrue(module.isQueryable(10)); |
| 166 | |
| 167 | module.schedule(); |
| 168 | |
| 169 | assertTrue(module.waitForInitialization()); |
| 170 | |
| 171 | assertFalse(module.isQueryable(1)); |
| 172 | |
| 173 | try { |
| 174 | /* 2 waits for a barrier for one event */ |
| 175 | // event 1 |
| 176 | barrier.await(); |
| 177 | barrier.await(); |
| 178 | // event 2 |
| 179 | barrier.await(); |
| 180 | assertTrue(module.isQueryable(1)); |
| 181 | assertTrue(module.isQueryable(4)); |
| 182 | assertFalse(module.isQueryable(5)); |
| 183 | barrier.await(); |
| 184 | // event 3 |
| 185 | barrier.await(); |
| 186 | assertTrue(module.isQueryable(1)); |
| 187 | assertTrue(module.isQueryable(4)); |
| 188 | assertFalse(module.isQueryable(5)); |
| 189 | barrier.await(); |
| 190 | // event 4 |
| 191 | barrier.await(); |
| 192 | assertTrue(module.isQueryable(1)); |
| 193 | assertTrue(module.isQueryable(4)); |
| 194 | assertFalse(module.isQueryable(5)); |
| 195 | barrier.await(); |
| 196 | // event 5 |
| 197 | barrier.await(); |
| 198 | assertTrue(module.isQueryable(1)); |
| 199 | assertTrue(module.isQueryable(4)); |
| 200 | assertTrue(module.isQueryable(5)); |
| 201 | assertFalse(module.isQueryable(7)); |
| 202 | barrier.await(); |
| 203 | // event 6 |
| 204 | barrier.await(); |
| 205 | assertTrue(module.isQueryable(1)); |
| 206 | assertTrue(module.isQueryable(4)); |
| 207 | assertTrue(module.isQueryable(5)); |
| 208 | assertFalse(module.isQueryable(7)); |
| 209 | barrier.await(); |
| 210 | // event 7 |
| 211 | barrier.await(); |
| 212 | assertTrue(module.isQueryable(1)); |
| 213 | assertTrue(module.isQueryable(4)); |
| 214 | assertTrue(module.isQueryable(5)); |
| 215 | assertTrue(module.isQueryable(7)); |
| 216 | assertFalse(module.isQueryable(10)); |
| 217 | barrier.await(); |
| 218 | |
| 219 | fModule.waitForCompletion(); |
| 220 | assertTrue(module.isQueryable(1)); |
| 221 | assertTrue(module.isQueryable(4)); |
| 222 | assertTrue(module.isQueryable(5)); |
| 223 | assertTrue(module.isQueryable(7)); |
| 224 | assertTrue(module.isQueryable(10)); |
| 225 | |
| 226 | // Should return true only if later than trace time |
| 227 | assertTrue(module.isQueryable(100)); |
| 228 | |
| 229 | } catch (InterruptedException | BrokenBarrierException e1) { |
| 230 | fail(e1.getMessage()); |
| 231 | fModule.cancel(); |
| 232 | } finally { |
| 233 | TestStateSystemProvider.setEventHandler(null); |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | /** |
| 238 | * Test the {@link TmfStateSystemAnalysisModule#isQueryable(long)} method |
| 239 | * when the analysis is cancelled |
| 240 | */ |
| 241 | @Ignore("Hangs very often") |
| 242 | @Test |
| 243 | public void testIsQueryableCancel() { |
| 244 | |
| 245 | TestStateSystemModule module = fModule; |
| 246 | assertNotNull(module); |
| 247 | /* Set the queue to 1 to limit the number of events buffered */ |
| 248 | module.setPerEventSignalling(true); |
| 249 | |
| 250 | /* Module is not started, it should be queriable */ |
| 251 | assertTrue(module.isQueryable(1)); |
| 252 | assertTrue(module.isQueryable(4)); |
| 253 | assertTrue(module.isQueryable(5)); |
| 254 | assertTrue(module.isQueryable(7)); |
| 255 | assertTrue(module.isQueryable(10)); |
| 256 | |
| 257 | fModule.schedule(); |
| 258 | |
| 259 | assertTrue(module.waitForInitialization()); |
| 260 | |
| 261 | assertFalse(module.isQueryable(1)); |
| 262 | |
| 263 | // Process 2 events, then cancel |
| 264 | module.signalNextEvent(); |
| 265 | module.signalNextEvent(); |
| 266 | module.cancel(); |
| 267 | module.setPerEventSignalling(false); |
| 268 | |
| 269 | fModule.waitForCompletion(); |
| 270 | assertTrue(module.isQueryable(1)); |
| 271 | assertTrue(module.isQueryable(4)); |
| 272 | assertTrue(module.isQueryable(5)); |
| 273 | assertTrue(module.isQueryable(7)); |
| 274 | assertTrue(module.isQueryable(10)); |
| 275 | } |
| 276 | } |