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