| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2012 Ericsson |
| 3 | * Copyright (c) 2010, 2011 École Polytechnique de Montréal |
| 4 | * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> |
| 5 | * |
| 6 | * All rights reserved. This program and the accompanying materials are |
| 7 | * made available under the terms of the Eclipse Public License v1.0 which |
| 8 | * accompanies this distribution, and is available at |
| 9 | * http://www.eclipse.org/legal/epl-v10.html |
| 10 | * |
| 11 | *******************************************************************************/ |
| 12 | |
| 13 | package org.eclipse.linuxtools.lttng2.kernel.core.tests.stateprovider; |
| 14 | |
| 15 | import static org.junit.Assert.assertEquals; |
| 16 | import static org.junit.Assert.assertNotNull; |
| 17 | import static org.junit.Assert.assertTrue; |
| 18 | |
| 19 | import java.io.File; |
| 20 | import java.util.List; |
| 21 | |
| 22 | import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes; |
| 23 | import org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider.CtfKernelStateInput; |
| 24 | import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException; |
| 25 | import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException; |
| 26 | import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException; |
| 27 | import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException; |
| 28 | import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException; |
| 29 | import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; |
| 30 | import org.eclipse.linuxtools.tmf.core.statesystem.IStateChangeInput; |
| 31 | import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem; |
| 32 | import org.eclipse.linuxtools.tmf.core.statesystem.StateSystemManager; |
| 33 | import org.junit.AfterClass; |
| 34 | import org.junit.BeforeClass; |
| 35 | import org.junit.Test; |
| 36 | |
| 37 | /** |
| 38 | * Unit tests for the StateHistorySystem, which uses a full (non-partial) |
| 39 | * history and the non-threaded CTF kernel handler. |
| 40 | * |
| 41 | * @author alexmont |
| 42 | * |
| 43 | */ |
| 44 | @SuppressWarnings({"nls", "javadoc"}) |
| 45 | public class StateSystemFullHistoryTest { |
| 46 | |
| 47 | static File stateFile; |
| 48 | static File stateFileBenchmark; |
| 49 | |
| 50 | static IStateChangeInput input; |
| 51 | static ITmfStateSystem ssq; |
| 52 | |
| 53 | /* Offset in the trace + start time of the trace */ |
| 54 | private final static long interestingTimestamp1 = 18670067372290L + 1331649577946812237L; |
| 55 | |
| 56 | protected static String getTestFileName() { |
| 57 | return "/tmp/statefile.ht"; //$NON-NLS-1$ |
| 58 | } |
| 59 | |
| 60 | @BeforeClass |
| 61 | public static void initialize() { |
| 62 | stateFile = new File(getTestFileName()); |
| 63 | stateFileBenchmark = new File(getTestFileName() + ".benchmark"); //$NON-NLS-1$ |
| 64 | try { |
| 65 | input = new CtfKernelStateInput(CtfTestFiles.getTestTrace()); |
| 66 | ssq = StateSystemManager.loadStateHistory(stateFile, input, true); |
| 67 | } catch (Exception e) { |
| 68 | e.printStackTrace(); |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | @AfterClass |
| 73 | public static void cleanup() { |
| 74 | boolean ret1, ret2; |
| 75 | ret1 = stateFile.delete(); |
| 76 | ret2 = stateFileBenchmark.delete(); |
| 77 | if ( !(ret1 && ret2) ) { |
| 78 | System.err.println("Error cleaning up during unit testing, " + //$NON-NLS-1$ |
| 79 | "you might have leftovers state history files in /tmp"); //$NON-NLS-1$ |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Rebuild independently so we can benchmark it. Too bad JUnit doesn't allow |
| 85 | * us to @Test the @BeforeClass... |
| 86 | * |
| 87 | * @throws IOException |
| 88 | * @throws TmfTraceException |
| 89 | */ |
| 90 | @Test |
| 91 | public void testBuild() throws TmfTraceException { |
| 92 | IStateChangeInput input2; |
| 93 | ITmfStateSystem ssb2; |
| 94 | |
| 95 | input2 = new CtfKernelStateInput(CtfTestFiles.getTestTrace()); |
| 96 | ssb2 = StateSystemManager.loadStateHistory(stateFileBenchmark, input2, true); |
| 97 | |
| 98 | assertEquals(CtfTestFiles.startTime, ssb2.getStartTime()); |
| 99 | assertEquals(CtfTestFiles.endTime, ssb2.getCurrentEndTime()); |
| 100 | } |
| 101 | |
| 102 | @Test |
| 103 | public void testOpenExistingStateFile() throws TmfTraceException { |
| 104 | ITmfStateSystem ssb2; |
| 105 | |
| 106 | /* 'newStateFile' should have already been created */ |
| 107 | ssb2 = StateSystemManager.loadStateHistory(stateFile, null, true); |
| 108 | |
| 109 | assertNotNull(ssb2); |
| 110 | assertEquals(CtfTestFiles.startTime, ssb2.getStartTime()); |
| 111 | assertEquals(CtfTestFiles.endTime, ssb2.getCurrentEndTime()); |
| 112 | } |
| 113 | |
| 114 | @Test |
| 115 | public void testFullQuery1() throws StateValueTypeException, |
| 116 | AttributeNotFoundException, TimeRangeException, |
| 117 | StateSystemDisposedException { |
| 118 | |
| 119 | List<ITmfStateInterval> list; |
| 120 | ITmfStateInterval interval; |
| 121 | int quark, valueInt; |
| 122 | String valueStr; |
| 123 | |
| 124 | list = ssq.queryFullState(interestingTimestamp1); |
| 125 | |
| 126 | quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 127 | interval = list.get(quark); |
| 128 | valueInt = interval.getStateValue().unboxInt(); |
| 129 | assertEquals(1397, valueInt); |
| 130 | |
| 131 | quark = ssq.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME); |
| 132 | interval = list.get(quark); |
| 133 | valueStr = interval.getStateValue().unboxStr(); |
| 134 | assertEquals("gdbus", valueStr); |
| 135 | |
| 136 | quark = ssq.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.SYSTEM_CALL); |
| 137 | interval = list.get(quark); |
| 138 | valueStr = interval.getStateValue().unboxStr(); |
| 139 | assertTrue(valueStr.equals("sys_poll")); |
| 140 | } |
| 141 | |
| 142 | @Test |
| 143 | public void testFullQuery2() { |
| 144 | // |
| 145 | } |
| 146 | |
| 147 | @Test |
| 148 | public void testFullQuery3() { |
| 149 | // |
| 150 | } |
| 151 | |
| 152 | @Test |
| 153 | public void testSingleQuery1() throws AttributeNotFoundException, |
| 154 | TimeRangeException, StateValueTypeException, |
| 155 | StateSystemDisposedException { |
| 156 | |
| 157 | long timestamp = interestingTimestamp1; |
| 158 | int quark; |
| 159 | ITmfStateInterval interval; |
| 160 | String valueStr; |
| 161 | |
| 162 | quark = ssq.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME); |
| 163 | interval = ssq.querySingleState(timestamp, quark); |
| 164 | valueStr = interval.getStateValue().unboxStr(); |
| 165 | assertEquals("gdbus", valueStr); |
| 166 | } |
| 167 | |
| 168 | @Test |
| 169 | public void testSingleQuery2() { |
| 170 | // |
| 171 | } |
| 172 | |
| 173 | @Test |
| 174 | public void testSingleQuery3() { |
| 175 | // |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Test a range query (with no resolution parameter, so all intervals) |
| 180 | */ |
| 181 | @Test |
| 182 | public void testRangeQuery1() throws AttributeNotFoundException, |
| 183 | TimeRangeException, StateValueTypeException, |
| 184 | StateSystemDisposedException { |
| 185 | |
| 186 | long time1 = interestingTimestamp1; |
| 187 | long time2 = time1 + 1L * CtfTestFiles.NANOSECS_PER_SEC; |
| 188 | int quark; |
| 189 | List<ITmfStateInterval> intervals; |
| 190 | |
| 191 | quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 192 | intervals = ssq.queryHistoryRange(quark, time1, time2); |
| 193 | assertEquals(487, intervals.size()); /* Number of context switches! */ |
| 194 | assertEquals(1685, intervals.get(100).getStateValue().unboxInt()); |
| 195 | assertEquals(1331668248427681372L, intervals.get(205).getEndTime()); |
| 196 | } |
| 197 | |
| 198 | /** |
| 199 | * Range query, but with a t2 far off the end of the trace. |
| 200 | * The result should still be valid. |
| 201 | */ |
| 202 | @Test |
| 203 | public void testRangeQuery2() throws TimeRangeException, |
| 204 | AttributeNotFoundException, StateSystemDisposedException { |
| 205 | |
| 206 | List<ITmfStateInterval> intervals; |
| 207 | |
| 208 | int quark = ssq.getQuarkAbsolute(Attributes.RESOURCES, Attributes.IRQS, "1"); |
| 209 | long ts1 = ssq.getStartTime(); /* start of the trace */ |
| 210 | long ts2 = CtfTestFiles.startTime + 20L * CtfTestFiles.NANOSECS_PER_SEC; /* invalid, but ignored */ |
| 211 | |
| 212 | intervals = ssq.queryHistoryRange(quark, ts1, ts2); |
| 213 | |
| 214 | /* Activity of IRQ 1 over the whole trace */ |
| 215 | assertEquals(65, intervals.size()); |
| 216 | } |
| 217 | |
| 218 | /** |
| 219 | * Test a range query with a resolution |
| 220 | */ |
| 221 | @Test |
| 222 | public void testRangeQuery3() throws AttributeNotFoundException, |
| 223 | TimeRangeException, StateValueTypeException, |
| 224 | StateSystemDisposedException { |
| 225 | |
| 226 | long time1 = interestingTimestamp1; |
| 227 | long time2 = time1 + 1L * CtfTestFiles.NANOSECS_PER_SEC; |
| 228 | long resolution = 1000000; /* One query every millisecond */ |
| 229 | int quark; |
| 230 | List<ITmfStateInterval> intervals; |
| 231 | |
| 232 | quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 233 | intervals = ssq.queryHistoryRange(quark, time1, time2, resolution, null); |
| 234 | assertEquals(126, intervals.size()); /* Number of context switches! */ |
| 235 | assertEquals(1452, intervals.get(50).getStateValue().unboxInt()); |
| 236 | assertEquals(1331668248815698779L, intervals.get(100).getEndTime()); |
| 237 | } |
| 238 | |
| 239 | /** |
| 240 | * Ask for a time range outside of the trace's range |
| 241 | */ |
| 242 | @Test(expected = TimeRangeException.class) |
| 243 | public void testFullQueryInvalidTime1() throws TimeRangeException, |
| 244 | StateSystemDisposedException { |
| 245 | long ts = CtfTestFiles.startTime + 20L * CtfTestFiles.NANOSECS_PER_SEC; |
| 246 | ssq.queryFullState(ts); |
| 247 | } |
| 248 | |
| 249 | @Test(expected = TimeRangeException.class) |
| 250 | public void testFullQueryInvalidTime2() throws TimeRangeException, |
| 251 | StateSystemDisposedException { |
| 252 | long ts = CtfTestFiles.startTime - 20L * CtfTestFiles.NANOSECS_PER_SEC; |
| 253 | ssq.queryFullState(ts); |
| 254 | } |
| 255 | |
| 256 | @Test(expected = TimeRangeException.class) |
| 257 | public void testSingleQueryInvalidTime1() |
| 258 | throws AttributeNotFoundException, TimeRangeException, |
| 259 | StateSystemDisposedException { |
| 260 | |
| 261 | int quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 262 | long ts = CtfTestFiles.startTime + 20L * CtfTestFiles.NANOSECS_PER_SEC; |
| 263 | ssq.querySingleState(ts, quark); |
| 264 | } |
| 265 | |
| 266 | @Test(expected = TimeRangeException.class) |
| 267 | public void testSingleQueryInvalidTime2() |
| 268 | throws AttributeNotFoundException, TimeRangeException, |
| 269 | StateSystemDisposedException { |
| 270 | |
| 271 | int quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 272 | long ts = CtfTestFiles.startTime - 20L * CtfTestFiles.NANOSECS_PER_SEC; |
| 273 | ssq.querySingleState(ts, quark); |
| 274 | } |
| 275 | |
| 276 | @Test(expected = TimeRangeException.class) |
| 277 | public void testRangeQueryInvalidTime1() throws AttributeNotFoundException, |
| 278 | TimeRangeException, StateSystemDisposedException { |
| 279 | |
| 280 | int quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 281 | long ts1 = CtfTestFiles.startTime - 20L * CtfTestFiles.NANOSECS_PER_SEC; /* invalid */ |
| 282 | long ts2 = CtfTestFiles.startTime + 1L * CtfTestFiles.NANOSECS_PER_SEC; /* valid */ |
| 283 | |
| 284 | ssq.queryHistoryRange(quark, ts1, ts2); |
| 285 | } |
| 286 | |
| 287 | @Test(expected = TimeRangeException.class) |
| 288 | public void testRangeQueryInvalidTime2() throws TimeRangeException, |
| 289 | AttributeNotFoundException, StateSystemDisposedException { |
| 290 | |
| 291 | int quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 292 | long ts1 = CtfTestFiles.startTime - 1L * CtfTestFiles.NANOSECS_PER_SEC; /* invalid */ |
| 293 | long ts2 = CtfTestFiles.startTime + 20L * CtfTestFiles.NANOSECS_PER_SEC; /* invalid */ |
| 294 | |
| 295 | ssq.queryHistoryRange(quark, ts1, ts2); |
| 296 | } |
| 297 | |
| 298 | /** |
| 299 | * Ask for a non-existing attribute |
| 300 | * |
| 301 | * @throws AttributeNotFoundException |
| 302 | */ |
| 303 | @Test(expected = AttributeNotFoundException.class) |
| 304 | public void testQueryInvalidAttribute() throws AttributeNotFoundException { |
| 305 | |
| 306 | ssq.getQuarkAbsolute("There", "is", "no", "cow", "level"); |
| 307 | } |
| 308 | |
| 309 | /** |
| 310 | * Query but with the wrong State Value type |
| 311 | */ |
| 312 | @Test(expected = StateValueTypeException.class) |
| 313 | public void testQueryInvalidValuetype1() throws StateValueTypeException, |
| 314 | AttributeNotFoundException, TimeRangeException, |
| 315 | StateSystemDisposedException { |
| 316 | List<ITmfStateInterval> list; |
| 317 | ITmfStateInterval interval; |
| 318 | int quark; |
| 319 | |
| 320 | list = ssq.queryFullState(interestingTimestamp1); |
| 321 | quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 322 | interval = list.get(quark); |
| 323 | |
| 324 | /* This is supposed to be an int value */ |
| 325 | interval.getStateValue().unboxStr(); |
| 326 | } |
| 327 | |
| 328 | @Test(expected = StateValueTypeException.class) |
| 329 | public void testQueryInvalidValuetype2() throws StateValueTypeException, |
| 330 | AttributeNotFoundException, TimeRangeException, |
| 331 | StateSystemDisposedException { |
| 332 | List<ITmfStateInterval> list; |
| 333 | ITmfStateInterval interval; |
| 334 | int quark; |
| 335 | |
| 336 | list = ssq.queryFullState(interestingTimestamp1); |
| 337 | quark = ssq.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME); |
| 338 | interval = list.get(quark); |
| 339 | |
| 340 | /* This is supposed to be a String value */ |
| 341 | interval.getStateValue().unboxInt(); |
| 342 | } |
| 343 | |
| 344 | @Test |
| 345 | public void testFullAttributeName() throws AttributeNotFoundException { |
| 346 | int quark = ssq.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
| 347 | String name = ssq.getFullAttributePath(quark); |
| 348 | assertEquals(name, "CPUs/0/Current_thread"); |
| 349 | } |
| 350 | |
| 351 | @Test |
| 352 | public void testGetQuarks_begin() { |
| 353 | List<Integer> list = ssq.getQuarks("*", "1577", Attributes.EXEC_NAME); |
| 354 | |
| 355 | assertEquals(1, list.size()); |
| 356 | } |
| 357 | |
| 358 | @Test |
| 359 | public void testGetQuarks_middle() { |
| 360 | List<Integer> list = ssq.getQuarks(Attributes.THREADS, "*", Attributes.EXEC_NAME); |
| 361 | |
| 362 | /* Number of different kernel threads in the trace */ |
| 363 | assertEquals(168, list.size()); |
| 364 | } |
| 365 | |
| 366 | @Test |
| 367 | public void testGetQuarks_end() { |
| 368 | List<Integer> list = ssq.getQuarks(Attributes.THREADS, "1577", "*"); |
| 369 | |
| 370 | /* There should be 4 sub-attributes for each Thread node */ |
| 371 | assertEquals(4, list.size()); |
| 372 | } |
| 373 | } |