Commit | Line | Data |
---|---|---|
96811390 | 1 | /******************************************************************************* |
ed902a2b | 2 | * Copyright (c) 2014, 2015 École Polytechnique de Montréal |
96811390 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 | ||
e363eae1 | 13 | package org.eclipse.tracecompass.analysis.os.linux.core.tests.cpuusage; |
96811390 GB |
14 | |
15 | import static org.junit.Assert.assertEquals; | |
16 | import static org.junit.Assert.assertNotNull; | |
17 | import static org.junit.Assert.assertNull; | |
18 | import static org.junit.Assert.assertTrue; | |
19 | import static org.junit.Assert.fail; | |
20 | ||
21 | import java.io.File; | |
405a6506 | 22 | import java.util.ArrayList; |
17a3454d | 23 | import java.util.Collections; |
96811390 GB |
24 | import java.util.HashMap; |
25 | import java.util.List; | |
26 | import java.util.Map; | |
52c97b87 GB |
27 | import java.util.Set; |
28 | import java.util.stream.Collectors; | |
29 | import java.util.stream.StreamSupport; | |
96811390 GB |
30 | |
31 | import org.eclipse.core.runtime.IPath; | |
32 | import org.eclipse.core.runtime.IStatus; | |
405a6506 | 33 | import org.eclipse.jdt.annotation.NonNull; |
e363eae1 | 34 | import org.eclipse.tracecompass.analysis.os.linux.core.cpuusage.KernelCpuUsageAnalysis; |
0f7a12d3 | 35 | import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; |
e363eae1 | 36 | import org.eclipse.tracecompass.analysis.os.linux.core.tests.Activator; |
698fde87 | 37 | import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.trace.TmfXmlKernelTraceStub; |
52c97b87 GB |
38 | import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout; |
39 | import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace; | |
f69045e2 | 40 | import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; |
96811390 GB |
41 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; |
42 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
96811390 | 43 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; |
405a6506 GB |
44 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; |
45 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
405a6506 | 46 | import org.eclipse.tracecompass.statesystem.core.tests.shared.utils.StateIntervalStub; |
698fde87 | 47 | import org.eclipse.tracecompass.statesystem.core.tests.shared.utils.StateSystemTestUtils; |
96811390 GB |
48 | import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; |
49 | import org.eclipse.tracecompass.tmf.core.event.TmfEvent; | |
50 | import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException; | |
51 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; | |
52 | import org.eclipse.tracecompass.tmf.core.tests.shared.TmfTestHelper; | |
53 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
54 | import org.eclipse.tracecompass.tmf.core.trace.TmfTrace; | |
55 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; | |
56 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; | |
96811390 GB |
57 | import org.junit.After; |
58 | import org.junit.Before; | |
59 | import org.junit.Test; | |
60 | ||
17a3454d MK |
61 | import com.google.common.collect.ImmutableSet; |
62 | ||
96811390 | 63 | /** |
e363eae1 | 64 | * Test suite for the {@link KernelCpuUsageAnalysis} class |
96811390 GB |
65 | * |
66 | * @author Geneviève Bastien | |
67 | */ | |
68 | public class CpuUsageStateProviderTest { | |
69 | ||
70 | private static final String CPU_USAGE_FILE = "testfiles/cpu_analysis.xml"; | |
e363eae1 | 71 | |
52c97b87 | 72 | private IKernelTrace fTrace; |
e363eae1 | 73 | private KernelCpuUsageAnalysis fModule; |
96811390 GB |
74 | |
75 | private static void deleteSuppFiles(ITmfTrace trace) { | |
76 | /* Remove supplementary files */ | |
77 | File suppDir = new File(TmfTraceManager.getSupplementaryFileDir(trace)); | |
78 | for (File file : suppDir.listFiles()) { | |
79 | file.delete(); | |
80 | } | |
81 | } | |
82 | ||
83 | /** | |
84 | * Setup the trace for the tests | |
85 | */ | |
86 | @Before | |
87 | public void setUp() { | |
52c97b87 | 88 | IKernelTrace trace = new TmfXmlKernelTraceStub(); |
96811390 | 89 | IPath filePath = Activator.getAbsoluteFilePath(CPU_USAGE_FILE); |
1d83ed07 | 90 | IStatus status = trace.validate(null, filePath.toOSString()); |
96811390 GB |
91 | if (!status.isOK()) { |
92 | fail(status.getException().getMessage()); | |
93 | } | |
94 | try { | |
1d83ed07 | 95 | trace.initTrace(null, filePath.toOSString(), TmfEvent.class); |
96811390 GB |
96 | } catch (TmfTraceException e) { |
97 | fail(e.getMessage()); | |
98 | } | |
1d83ed07 AM |
99 | deleteSuppFiles(trace); |
100 | ((TmfTrace) trace).traceOpened(new TmfTraceOpenedSignal(this, trace, null)); | |
96811390 GB |
101 | /* |
102 | * FIXME: Make sure this analysis is finished before running the CPU | |
103 | * analysis. This block can be removed once analysis dependency and | |
104 | * request precedence is implemented | |
105 | */ | |
106 | IAnalysisModule module = null; | |
6d16f5a9 | 107 | for (IAnalysisModule mod : TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class)) { |
96811390 GB |
108 | module = mod; |
109 | } | |
110 | assertNotNull(module); | |
111 | module.schedule(); | |
112 | module.waitForCompletion(); | |
113 | /* End of the FIXME block */ | |
e363eae1 | 114 | |
1d83ed07 | 115 | fModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, KernelCpuUsageAnalysis.class, KernelCpuUsageAnalysis.ID); |
96811390 | 116 | assertNotNull(fModule); |
1d83ed07 | 117 | fTrace = trace; |
96811390 GB |
118 | } |
119 | ||
120 | /** | |
121 | * Clean up | |
122 | */ | |
123 | @After | |
124 | public void tearDown() { | |
125 | deleteSuppFiles(fTrace); | |
126 | fTrace.dispose(); | |
127 | } | |
128 | ||
129 | /** | |
130 | * Test that the analysis executes without problems | |
131 | */ | |
132 | @Test | |
133 | public void testAnalysisExecution() { | |
134 | /* Make sure the analysis hasn't run yet */ | |
135 | assertNull(fModule.getStateSystem()); | |
136 | ||
137 | /* Execute the analysis */ | |
138 | assertTrue(TmfTestHelper.executeAnalysis(fModule)); | |
139 | assertNotNull(fModule.getStateSystem()); | |
140 | } | |
141 | ||
142 | /** | |
143 | * Test that the state system is returned with the expected results | |
144 | */ | |
145 | @Test | |
146 | public void testReturnedStateSystem() { | |
147 | fModule.schedule(); | |
148 | fModule.waitForCompletion(); | |
149 | ITmfStateSystem ss = fModule.getStateSystem(); | |
150 | assertNotNull(ss); | |
151 | assertEquals(1L, ss.getStartTime()); | |
152 | assertEquals(25L, ss.getCurrentEndTime()); | |
153 | ||
154 | try { | |
155 | int cpusQuark = ss.getQuarkAbsolute(Attributes.CPUS); | |
156 | ||
157 | /* | |
158 | * There should be 2 CPU entries: 0 and 1 and 3 process entries | |
159 | * under each | |
160 | */ | |
161 | List<Integer> cpuQuarks = ss.getSubAttributes(cpusQuark, false); | |
162 | assertEquals(2, cpuQuarks.size()); | |
163 | for (Integer cpuQuark : cpuQuarks) { | |
164 | assertEquals(3, ss.getSubAttributes(cpuQuark, false).size()); | |
165 | } | |
166 | ||
405a6506 GB |
167 | /* Test the intervals of proc2 on CPU 0 */ |
168 | List<@NonNull ITmfStateInterval> intervals = new ArrayList<>(); | |
169 | intervals.add(new StateIntervalStub(1, 19, TmfStateValue.nullValue())); | |
170 | intervals.add(new StateIntervalStub(20, 25, TmfStateValue.newValueLong(19L))); | |
171 | StateSystemTestUtils.testIntervalForAttributes(ss, intervals, Attributes.CPUS, "0", "2"); | |
172 | ||
173 | /* Test the intervals of proc 4 CPU 1 */ | |
174 | intervals.clear(); | |
175 | intervals.add(new StateIntervalStub(1, 4, TmfStateValue.nullValue())); | |
176 | intervals.add(new StateIntervalStub(5, 14, TmfStateValue.newValueLong(3L))); | |
177 | intervals.add(new StateIntervalStub(15, 25, TmfStateValue.newValueLong(8L))); | |
178 | StateSystemTestUtils.testIntervalForAttributes(ss, intervals, Attributes.CPUS, "1", "4"); | |
179 | ||
180 | /* Test the intervals of proc 3 on both CPUs */ | |
181 | intervals.clear(); | |
182 | intervals.add(new StateIntervalStub(1, 24, TmfStateValue.nullValue())); | |
183 | intervals.add(new StateIntervalStub(25, 25, TmfStateValue.newValueLong(5L))); | |
184 | StateSystemTestUtils.testIntervalForAttributes(ss, intervals, Attributes.CPUS, "0", "3"); | |
185 | ||
186 | intervals.clear(); | |
187 | intervals.add(new StateIntervalStub(1, 1, TmfStateValue.nullValue())); | |
188 | intervals.add(new StateIntervalStub(2, 9, TmfStateValue.newValueLong(1L))); | |
189 | intervals.add(new StateIntervalStub(10, 25, TmfStateValue.newValueLong(6L))); | |
190 | StateSystemTestUtils.testIntervalForAttributes(ss, intervals, Attributes.CPUS, "1", "3"); | |
96811390 GB |
191 | |
192 | /* | |
193 | * Query at the end and make sure all processes on all CPU have the | |
194 | * expected values | |
195 | */ | |
405a6506 GB |
196 | Map<@NonNull String @NonNull [], @NonNull ITmfStateValue> map = new HashMap<>(); |
197 | map.put(StateSystemTestUtils.makeAttribute(Attributes.CPUS, "0", "1"), TmfStateValue.newValueLong(0L)); | |
198 | map.put(StateSystemTestUtils.makeAttribute(Attributes.CPUS, "0", "2"), TmfStateValue.newValueLong(19L)); | |
199 | map.put(StateSystemTestUtils.makeAttribute(Attributes.CPUS, "0", "3"), TmfStateValue.newValueLong(5L)); | |
200 | map.put(StateSystemTestUtils.makeAttribute(Attributes.CPUS, "1", "1"), TmfStateValue.newValueLong(5L)); | |
201 | map.put(StateSystemTestUtils.makeAttribute(Attributes.CPUS, "1", "3"), TmfStateValue.newValueLong(6L)); | |
202 | map.put(StateSystemTestUtils.makeAttribute(Attributes.CPUS, "1", "4"), TmfStateValue.newValueLong(8L)); | |
203 | StateSystemTestUtils.testValuesAtTime(ss, 25L, map); | |
204 | ||
205 | } catch (AttributeNotFoundException e) { | |
96811390 GB |
206 | fail(e.getMessage()); |
207 | } | |
208 | } | |
209 | ||
210 | /** | |
17a3454d MK |
211 | * Test the |
212 | * {@link KernelCpuUsageAnalysis#getCpuUsageInRange(java.util.Set, long, long)} | |
96811390 | 213 | * method. |
17a3454d MK |
214 | * <p> |
215 | * TODO: extend! | |
96811390 GB |
216 | */ |
217 | @Test | |
218 | public void testUsageInRange() { | |
219 | fModule.schedule(); | |
220 | fModule.waitForCompletion(); | |
221 | ||
222 | /* This range should query the total range */ | |
223 | Map<String, Long> expected = new HashMap<>(); | |
224 | expected.put("0/1", 0L); | |
225 | expected.put("0/2", 19L); | |
226 | expected.put("0/3", 5L); | |
227 | expected.put("1/1", 5L); | |
228 | expected.put("1/3", 6L); | |
229 | expected.put("1/4", 13L); | |
230 | expected.put("total", 48L); | |
231 | expected.put("total/1", 5L); | |
232 | expected.put("total/2", 19L); | |
233 | expected.put("total/3", 11L); | |
234 | expected.put("total/4", 13L); | |
235 | expected.put("0", 24L); | |
236 | expected.put("1", 24L); | |
17a3454d | 237 | Map<String, Long> resultMap = fModule.getCpuUsageInRange(Collections.EMPTY_SET, 0L, 30L); |
96811390 GB |
238 | assertEquals(expected, resultMap); |
239 | ||
240 | /* Verify a range when a process runs at the start */ | |
241 | expected.clear(); | |
242 | expected.put("0/1", 0L); | |
243 | expected.put("0/2", 0L); | |
244 | expected.put("0/3", 3L); | |
245 | expected.put("1/1", 0L); | |
246 | expected.put("1/3", 0L); | |
247 | expected.put("1/4", 3L); | |
248 | expected.put("total", 6L); | |
249 | expected.put("total/1", 0L); | |
250 | expected.put("total/2", 0L); | |
251 | expected.put("total/3", 3L); | |
252 | expected.put("total/4", 3L); | |
253 | expected.put("0", 3L); | |
254 | expected.put("1", 3L); | |
17a3454d | 255 | resultMap = fModule.getCpuUsageInRange(Collections.EMPTY_SET, 22L, 25L); |
96811390 GB |
256 | assertEquals(expected, resultMap); |
257 | ||
258 | /* Verify a range when a process runs at the end */ | |
259 | expected.clear(); | |
260 | expected.put("0/1", 0L); | |
261 | expected.put("0/2", 3L); | |
262 | expected.put("0/3", 0L); | |
263 | expected.put("1/1", 0L); | |
264 | expected.put("1/3", 1L); | |
265 | expected.put("1/4", 2L); | |
266 | expected.put("total", 6L); | |
267 | expected.put("total/1", 0L); | |
268 | expected.put("total/2", 3L); | |
269 | expected.put("total/3", 1L); | |
270 | expected.put("total/4", 2L); | |
271 | expected.put("0", 3L); | |
272 | expected.put("1", 3L); | |
17a3454d | 273 | resultMap = fModule.getCpuUsageInRange(Collections.EMPTY_SET, 1L, 4L); |
96811390 GB |
274 | assertEquals(expected, resultMap); |
275 | ||
276 | /* Verify a range when a process runs at start and at the end */ | |
277 | expected.clear(); | |
278 | expected.put("0/1", 0L); | |
279 | expected.put("0/2", 9L); | |
280 | expected.put("0/3", 0L); | |
281 | expected.put("1/1", 0L); | |
282 | expected.put("1/3", 5L); | |
283 | expected.put("1/4", 4L); | |
284 | expected.put("total", 18L); | |
285 | expected.put("total/1", 0L); | |
286 | expected.put("total/2", 9L); | |
287 | expected.put("total/3", 5L); | |
288 | expected.put("total/4", 4L); | |
289 | expected.put("0", 9L); | |
290 | expected.put("1", 9L); | |
17a3454d MK |
291 | resultMap = fModule.getCpuUsageInRange(Collections.EMPTY_SET, 4L, 13L); |
292 | assertEquals(expected, resultMap); | |
293 | } | |
294 | ||
295 | /** | |
296 | * Tests the cpu usage for a cpu subset within a range | |
297 | */ | |
298 | @Test | |
299 | public void testInRangeWithCpuSubset() { | |
300 | ||
301 | fModule.schedule(); | |
302 | fModule.waitForCompletion(); | |
303 | ||
304 | /* Verify a range when a process runs at start and at the end */ | |
305 | Map<String, Long> expected = new HashMap<>(); | |
306 | expected.put("0/1", 0L); | |
307 | expected.put("0/2", 9L); | |
308 | expected.put("0/3", 0L); | |
309 | expected.put("total/1", 0L); | |
310 | expected.put("total/2", 9L); | |
311 | expected.put("total/3", 0L); | |
312 | expected.put("0", 9L); | |
313 | expected.put("total", 9L); | |
314 | Map<String, Long> resultMap = fModule.getCpuUsageInRange(Collections.<@NonNull Integer> singleton(0), 4L, 13L); | |
315 | assertEquals(expected, resultMap); | |
316 | ||
317 | /* Verify a range when a process runs at start and at the end */ | |
318 | expected.clear(); | |
319 | expected.put("1/1", 0L); | |
320 | expected.put("1/3", 5L); | |
321 | expected.put("1/4", 4L); | |
322 | expected.put("total/1", 0L); | |
323 | expected.put("total/3", 5L); | |
324 | expected.put("total/4", 4L); | |
325 | expected.put("1", 9L); | |
326 | expected.put("total", 9L); | |
52c97b87 | 327 | resultMap = fModule.getCpuUsageInRange(ImmutableSet.of(1, 2), 4L, 13L); |
96811390 GB |
328 | assertEquals(expected, resultMap); |
329 | ||
330 | } | |
52c97b87 GB |
331 | |
332 | /** | |
333 | * Test the requirements of the analysis module | |
334 | */ | |
335 | @Test | |
336 | public void testRequirements() { | |
337 | IKernelTrace trace = fTrace; | |
338 | assertNotNull(trace); | |
339 | IKernelAnalysisEventLayout layout = trace.getKernelEventLayout(); | |
340 | Set<String> expected = ImmutableSet.of(layout.eventSchedSwitch()); | |
341 | ||
342 | Set<String> actual = StreamSupport.stream(fModule.getAnalysisRequirements().spliterator(), false) | |
343 | .flatMap(req -> req.getValues().stream()) | |
344 | .collect(Collectors.toSet()); | |
345 | ||
346 | assertEquals(expected, actual); | |
347 | } | |
96811390 | 348 | } |