Commit | Line | Data |
---|---|---|
50a47aa6 | 1 | /******************************************************************************* |
ed902a2b | 2 | * Copyright (c) 2014, 2015 École Polytechnique de Montréal |
50a47aa6 GB |
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 | * Contributors: | |
10 | * Geneviève Bastien - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
0f7a12d3 | 13 | package org.eclipse.tracecompass.analysis.os.linux.core.tests.kernel; |
50a47aa6 | 14 | |
e363eae1 | 15 | import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
50a47aa6 GB |
16 | import static org.junit.Assert.assertEquals; |
17 | import static org.junit.Assert.assertNotNull; | |
18 | import static org.junit.Assert.assertNull; | |
19 | import static org.junit.Assert.assertTrue; | |
50a47aa6 GB |
20 | |
21 | import java.io.File; | |
22 | import java.util.Collection; | |
3fef638d | 23 | import java.util.Collections; |
50a47aa6 | 24 | import java.util.List; |
3fef638d | 25 | import java.util.Set; |
50a47aa6 | 26 | |
50a47aa6 | 27 | import org.eclipse.core.runtime.IProgressMonitor; |
50a47aa6 GB |
28 | import org.eclipse.core.runtime.NullProgressMonitor; |
29 | import org.eclipse.jdt.annotation.NonNull; | |
0f7a12d3 AM |
30 | import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; |
31 | import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelThreadInformationProvider; | |
32 | import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues; | |
0783ea52 GB |
33 | import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.LinuxTestCase; |
34 | import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.kernel.KernelAnalysisTestFactory; | |
50a47aa6 GB |
35 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; |
36 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; | |
37 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
38 | import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; | |
50a47aa6 GB |
39 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; |
40 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
41 | import org.eclipse.tracecompass.tmf.core.trace.TmfTrace; | |
42 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; | |
43 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; | |
50a47aa6 GB |
44 | import org.junit.After; |
45 | import org.junit.Before; | |
46 | import org.junit.Test; | |
47 | ||
c8f45ad2 MK |
48 | import com.google.common.collect.ImmutableSet; |
49 | ||
50a47aa6 | 50 | /** |
6d16f5a9 | 51 | * Test analysis-specific methods for the {@link KernelAnalysisModule} class. |
50a47aa6 GB |
52 | * |
53 | * @author Geneviève Bastien | |
54 | */ | |
e363eae1 | 55 | public class KernelThreadInformationProviderTest { |
50a47aa6 | 56 | |
0783ea52 | 57 | private static final @NonNull LinuxTestCase KERNEL_TEST_CASE = KernelAnalysisTestFactory.KERNEL_SCHED; |
e363eae1 | 58 | |
50a47aa6 | 59 | private ITmfTrace fTrace; |
6d16f5a9 | 60 | private KernelAnalysisModule fModule; |
50a47aa6 GB |
61 | |
62 | private static void deleteSuppFiles(ITmfTrace trace) { | |
63 | /* Remove supplementary files */ | |
64 | File suppDir = new File(TmfTraceManager.getSupplementaryFileDir(trace)); | |
65 | for (File file : suppDir.listFiles()) { | |
66 | file.delete(); | |
67 | } | |
68 | } | |
69 | ||
70 | /** | |
71 | * Setup the trace for the tests | |
72 | */ | |
73 | @Before | |
74 | public void setUp() { | |
0783ea52 | 75 | ITmfTrace trace = KERNEL_TEST_CASE.getKernelTrace(); |
1d83ed07 AM |
76 | deleteSuppFiles(trace); |
77 | ((TmfTrace) trace).traceOpened(new TmfTraceOpenedSignal(this, trace, null)); | |
50a47aa6 | 78 | IAnalysisModule module = null; |
6d16f5a9 | 79 | for (IAnalysisModule mod : TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class)) { |
50a47aa6 GB |
80 | module = mod; |
81 | } | |
82 | assertNotNull(module); | |
83 | module.schedule(); | |
84 | module.waitForCompletion(); | |
6d16f5a9 | 85 | fModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, KernelAnalysisModule.class, KernelAnalysisModule.ID); |
1d83ed07 | 86 | fTrace = trace; |
50a47aa6 GB |
87 | } |
88 | ||
89 | /** | |
90 | * Clean up | |
91 | */ | |
92 | @After | |
93 | public void tearDown() { | |
94 | deleteSuppFiles(fTrace); | |
95 | fTrace.dispose(); | |
96 | } | |
97 | ||
98 | /** | |
99 | * Test the | |
6d16f5a9 | 100 | * {@link KernelThreadInformationProvider#getThreadIds(KernelAnalysisModule)} |
50a47aa6 GB |
101 | * method |
102 | */ | |
103 | @Test | |
104 | public void testGetThreadQuarks() { | |
6d16f5a9 | 105 | KernelAnalysisModule module = checkNotNull(fModule); |
e363eae1 | 106 | Collection<Integer> threadIds = KernelThreadInformationProvider.getThreadIds(module); |
c8f45ad2 | 107 | assertEquals(ImmutableSet.<Integer>of(10,11,20,21,30,100), threadIds); |
50a47aa6 GB |
108 | } |
109 | ||
110 | /** | |
111 | * Test the | |
6d16f5a9 | 112 | * {@link KernelThreadInformationProvider#getThreadOnCpu(KernelAnalysisModule, long, long)} |
50a47aa6 GB |
113 | * method |
114 | */ | |
115 | @Test | |
116 | public void testGetThreadOnCpu() { | |
6d16f5a9 | 117 | KernelAnalysisModule module = checkNotNull(fModule); |
50a47aa6 GB |
118 | |
119 | /* Check with invalid timestamps */ | |
e363eae1 | 120 | Integer tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, -1); |
50a47aa6 GB |
121 | assertNull(tid); |
122 | ||
c422f500 | 123 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 90); |
50a47aa6 GB |
124 | assertNull(tid); |
125 | ||
126 | /* Check with invalid cpus */ | |
e363eae1 | 127 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 2, 20); |
50a47aa6 GB |
128 | assertNull(tid); |
129 | ||
e363eae1 | 130 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, -1, 20); |
50a47aa6 GB |
131 | assertNull(tid); |
132 | ||
133 | /* Check valid values */ | |
e363eae1 | 134 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 4); |
50a47aa6 GB |
135 | assertNull(tid); |
136 | ||
e363eae1 | 137 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 15); |
50a47aa6 GB |
138 | assertNull(tid); |
139 | ||
e363eae1 | 140 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 15); |
50a47aa6 GB |
141 | assertEquals(Integer.valueOf(11), tid); |
142 | ||
e363eae1 | 143 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 29); |
50a47aa6 GB |
144 | assertEquals(Integer.valueOf(20), tid); |
145 | ||
e363eae1 | 146 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 30); |
50a47aa6 GB |
147 | assertEquals(Integer.valueOf(21), tid); |
148 | ||
e363eae1 | 149 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 59); |
50a47aa6 GB |
150 | assertEquals(Integer.valueOf(11), tid); |
151 | ||
e363eae1 | 152 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 59); |
50a47aa6 GB |
153 | assertEquals(Integer.valueOf(30), tid); |
154 | ||
e363eae1 | 155 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 60); |
50a47aa6 GB |
156 | assertEquals(Integer.valueOf(11), tid); |
157 | ||
e363eae1 | 158 | tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 60); |
50a47aa6 GB |
159 | assertEquals(Integer.valueOf(21), tid); |
160 | ||
161 | } | |
162 | ||
3fef638d AM |
163 | /** |
164 | * Test the {@link KernelThreadInformationProvider#getThreadsOfCpus} method. | |
165 | */ | |
166 | @Test | |
167 | public void testGetThreadsOfCpus() { | |
168 | KernelAnalysisModule module = checkNotNull(fModule); | |
169 | final long start = 45L; | |
170 | final long end = 65L; | |
171 | ||
172 | /* | |
173 | * The test trace considers all scheduled out processes to remain in the | |
174 | * "wait for cpu" state. In this particular case, the util method means | |
175 | * "has ever run on CPU X". | |
176 | */ | |
177 | ||
178 | Set<Integer> tids = KernelThreadInformationProvider.getThreadsOfCpus(module, Collections.singleton(0L), start, end); | |
179 | assertNotNull(tids); | |
180 | /* | |
181 | * Only threads 11 and 100 should be present, due to the sched_switch at | |
182 | * t=35. | |
183 | */ | |
184 | assertEquals(ImmutableSet.of(11, 100), tids); | |
185 | ||
186 | tids = KernelThreadInformationProvider.getThreadsOfCpus(module, Collections.singleton(1L), start, end); | |
187 | assertNotNull(tids); | |
188 | /* Only threads 10, 20, 21, 30 get scheduled on CPU 1. */ | |
189 | assertEquals(ImmutableSet.of(10, 20, 21, 30), tids); | |
190 | } | |
191 | ||
192 | /** | |
193 | * Test the {@link KernelThreadInformationProvider#getActiveThreadsForRange} | |
194 | * method. | |
195 | */ | |
196 | @Test | |
197 | public void testIsThreadActiveRange() { | |
198 | KernelAnalysisModule module = checkNotNull(fModule); | |
199 | final long start = 45L; | |
200 | final long end = 65L; | |
201 | ||
202 | /* Thread 30 should be active in the range */ | |
203 | Set<Integer> tids = KernelThreadInformationProvider.getActiveThreadsForRange(module, start, end); | |
204 | assertNotNull(tids); | |
205 | assertTrue(tids.contains(30)); | |
206 | ||
207 | // TODO Check for non-active states too. Unfortunately the test trace | |
208 | // wrongly considers all processes to be in a active (value=5) state all | |
209 | // the time. | |
210 | } | |
211 | ||
50a47aa6 GB |
212 | /** |
213 | * Test the | |
6d16f5a9 | 214 | * {@link KernelThreadInformationProvider#getParentPid(KernelAnalysisModule, Integer, long)} |
50a47aa6 GB |
215 | * method |
216 | */ | |
217 | @Test | |
218 | public void testGetPpid() { | |
6d16f5a9 | 219 | KernelAnalysisModule module = checkNotNull(fModule); |
50a47aa6 GB |
220 | |
221 | /* Check with invalid timestamps */ | |
e363eae1 | 222 | Integer ppid = KernelThreadInformationProvider.getParentPid(module, 11, -1); |
50a47aa6 GB |
223 | assertNull(ppid); |
224 | ||
c422f500 | 225 | ppid = KernelThreadInformationProvider.getParentPid(module, 11, 90); |
50a47aa6 GB |
226 | assertNull(ppid); |
227 | ||
228 | /* Check with invalid cpus */ | |
e363eae1 | 229 | ppid = KernelThreadInformationProvider.getParentPid(module, -4, 20); |
50a47aa6 GB |
230 | assertNull(ppid); |
231 | ||
e363eae1 | 232 | ppid = KernelThreadInformationProvider.getParentPid(module, 12, 20); |
50a47aa6 GB |
233 | assertNull(ppid); |
234 | ||
235 | /* Check values with no parent */ | |
e363eae1 | 236 | ppid = KernelThreadInformationProvider.getParentPid(module, 10, 20); |
50a47aa6 GB |
237 | assertEquals(Integer.valueOf(0), ppid); |
238 | ||
e363eae1 | 239 | ppid = KernelThreadInformationProvider.getParentPid(module, 30, 60); |
50a47aa6 GB |
240 | assertEquals(Integer.valueOf(0), ppid); |
241 | ||
242 | /* Check parent determined at statedump */ | |
e363eae1 | 243 | ppid = KernelThreadInformationProvider.getParentPid(module, 11, 4); |
50a47aa6 GB |
244 | assertNull(ppid); |
245 | ||
e363eae1 | 246 | ppid = KernelThreadInformationProvider.getParentPid(module, 11, 5); |
50a47aa6 GB |
247 | assertEquals(Integer.valueOf(10), ppid); |
248 | ||
249 | /* Check parent after process fork */ | |
e363eae1 | 250 | ppid = KernelThreadInformationProvider.getParentPid(module, 21, 25); |
50a47aa6 GB |
251 | assertEquals(Integer.valueOf(20), ppid); |
252 | ||
e363eae1 | 253 | ppid = KernelThreadInformationProvider.getParentPid(module, 21, 70); |
50a47aa6 GB |
254 | assertEquals(Integer.valueOf(20), ppid); |
255 | ||
256 | } | |
257 | ||
258 | /** | |
6d16f5a9 | 259 | * Test the {@link KernelThreadInformationProvider#getExecutableName(KernelAnalysisModule, Integer)} method |
50a47aa6 GB |
260 | */ |
261 | @Test | |
262 | public void testGetExecutableName() { | |
6d16f5a9 | 263 | KernelAnalysisModule module = checkNotNull(fModule); |
e363eae1 | 264 | |
50a47aa6 | 265 | /* Check with invalid threads */ |
e363eae1 | 266 | String execName = KernelThreadInformationProvider.getExecutableName(module, 101); |
50a47aa6 GB |
267 | assertNull(execName); |
268 | ||
e363eae1 | 269 | execName = KernelThreadInformationProvider.getExecutableName(module, -2); |
50a47aa6 GB |
270 | assertNull(execName); |
271 | ||
272 | /* Check valid value */ | |
e363eae1 | 273 | execName = KernelThreadInformationProvider.getExecutableName(module, 20); |
50a47aa6 GB |
274 | assertEquals("proc20", execName); |
275 | ||
276 | /* Check valid value with process name change in history */ | |
e363eae1 | 277 | execName = KernelThreadInformationProvider.getExecutableName(module, 21); |
50a47aa6 GB |
278 | assertEquals("proc21", execName); |
279 | ||
280 | } | |
281 | ||
282 | private static void testIntervals(String info, List<ITmfStateInterval> intervals, ITmfStateValue[] values) { | |
283 | assertEquals(info + " interval count", values.length, intervals.size()); | |
284 | for (int i = 0; i < values.length; i++) { | |
285 | assertEquals(info + " interval " + i, values[i], intervals.get(i).getStateValue()); | |
286 | } | |
287 | } | |
288 | ||
289 | /** | |
290 | * Test the | |
6d16f5a9 | 291 | * {@link KernelThreadInformationProvider#getStatusIntervalsForThread(KernelAnalysisModule, Integer, long, long, long, IProgressMonitor)} |
50a47aa6 GB |
292 | * method |
293 | */ | |
294 | @Test | |
295 | public void testGetStatusIntervalsForThread() { | |
6d16f5a9 | 296 | KernelAnalysisModule module = checkNotNull(fModule); |
50a47aa6 GB |
297 | |
298 | IProgressMonitor monitor = new NullProgressMonitor(); | |
299 | Integer process21 = 21; | |
300 | Integer process20 = 20; | |
301 | ||
302 | /* Check invalid time ranges */ | |
e363eae1 | 303 | List<ITmfStateInterval> intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, -15, -5, 3, monitor); |
50a47aa6 GB |
304 | assertTrue(intervals.isEmpty()); |
305 | ||
c422f500 | 306 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, 90, 1500000000L, 50, monitor); |
50a47aa6 GB |
307 | assertTrue(intervals.isEmpty()); |
308 | ||
309 | /* Check invalid quarks */ | |
e363eae1 | 310 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, -1, 0, 70L, 3, monitor); |
50a47aa6 GB |
311 | assertTrue(intervals.isEmpty()); |
312 | ||
e363eae1 | 313 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, 0, 0, 70L, 3, monitor); |
50a47aa6 GB |
314 | assertTrue(intervals.isEmpty()); |
315 | ||
316 | /* Check different time ranges and resolutions */ | |
317 | ITmfStateValue[] values = { TmfStateValue.nullValue(), StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE, | |
2e3a31c4 FG |
318 | StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE, StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE, |
319 | StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE }; | |
e363eae1 | 320 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, 0, 70L, 3, monitor); |
50a47aa6 GB |
321 | testIntervals("tid 21 [0,70,3]", intervals, values); |
322 | ||
2e3a31c4 FG |
323 | ITmfStateValue[] values2 = { TmfStateValue.nullValue(), StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE, |
324 | StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE }; | |
e363eae1 | 325 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, 1, 70L, 30, monitor); |
50a47aa6 GB |
326 | testIntervals("tid 21 [0,70,30]", intervals, values2); |
327 | ||
328 | ITmfStateValue[] values3 = { StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE, | |
2e3a31c4 | 329 | StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE }; |
e363eae1 | 330 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, 25, 50L, 3, monitor); |
50a47aa6 GB |
331 | testIntervals("tid 21 [25,50,3]", intervals, values3); |
332 | ||
a810c240 | 333 | ITmfStateValue[] values4 = { TmfStateValue.nullValue(), StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE, |
50a47aa6 | 334 | StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE, StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE }; |
e363eae1 | 335 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process20, 0, 70L, 3, monitor); |
50a47aa6 GB |
336 | testIntervals("tid 20 [0,70,3]", intervals, values4); |
337 | ||
338 | ITmfStateValue[] values5 = { TmfStateValue.nullValue(), StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE }; | |
e363eae1 | 339 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process20, 1, 70L, 30, monitor); |
50a47aa6 GB |
340 | testIntervals("tid 20 [0,70,30]", intervals, values5); |
341 | ||
342 | ITmfStateValue[] values6 = { StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE, | |
343 | StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE }; | |
e363eae1 | 344 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process20, 25, 50L, 3, monitor); |
50a47aa6 GB |
345 | testIntervals("tid 20 [25,50,3]", intervals, values6); |
346 | ||
c422f500 MK |
347 | ITmfStateValue[] values7 = { StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE }; |
348 | intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process20, 80L, 85L, 3, monitor); | |
349 | testIntervals("tid 20 [80,85,3]", intervals, values7); | |
350 | ||
50a47aa6 GB |
351 | } |
352 | ||
353 | } |