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