Commit | Line | Data |
---|---|---|
03722d5b | 1 | /******************************************************************************* |
ed902a2b | 2 | * Copyright (c) 2014, 2015 École Polytechnique de Montréal |
03722d5b 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 | ||
13 | package org.eclipse.tracecompass.lttng2.kernel.core.tests.analysis.vm; | |
14 | ||
15 | import static org.junit.Assert.assertEquals; | |
16 | import static org.junit.Assert.assertNotNull; | |
17 | import static org.junit.Assert.fail; | |
18 | import static org.junit.Assume.assumeTrue; | |
19 | ||
20 | import java.util.Collection; | |
21 | import java.util.List; | |
22 | ||
23 | import org.eclipse.core.runtime.NullProgressMonitor; | |
0f7a12d3 | 24 | import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; |
03722d5b GB |
25 | import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VcpuStateValues; |
26 | import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.VmAttributes; | |
27 | import org.eclipse.tracecompass.internal.lttng2.kernel.core.analysis.vm.module.VirtualMachineCpuAnalysis; | |
03722d5b GB |
28 | import org.eclipse.tracecompass.lttng2.lttng.kernel.core.tests.shared.vm.VmTestExperiment; |
29 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; | |
30 | import org.eclipse.tracecompass.statesystem.core.StateSystemUtils; | |
31 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
32 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; | |
33 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; | |
34 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; | |
35 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
36 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; | |
37 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
38 | import org.eclipse.tracecompass.tmf.core.trace.TmfTrace; | |
39 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; | |
a6366b8b | 40 | import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment; |
03722d5b GB |
41 | import org.junit.Test; |
42 | ||
43 | import com.google.common.collect.Multimap; | |
44 | ||
45 | /** | |
46 | * Test suite for the {@link VirtualMachineCpuAnalysis} class | |
47 | * | |
48 | * @author Geneviève Bastien | |
49 | */ | |
50 | public class VirtualMachineAnalysisTest { | |
51 | ||
52 | private static void verifyStateIntervals(String testId, List<ITmfStateInterval> intervals, int[] expectedStarts, ITmfStateValue[] expectedValues) { | |
53 | int expectedCount = expectedStarts.length - 1; | |
54 | ||
55 | assertEquals(testId + ": Interval count", expectedCount, intervals.size()); | |
56 | for (int i = 0; i < expectedCount; i++) { | |
57 | ITmfStateInterval interval = intervals.get(i); | |
58 | assertEquals(testId + ": Start time of interval " + i, expectedStarts[i], interval.getStartTime()); | |
59 | long actualEnd = (i == expectedCount - 1) ? (expectedStarts[i + 1]) : (expectedStarts[i + 1]) - 1; | |
60 | assertEquals(testId + ": End time of interval " + i, actualEnd, interval.getEndTime()); | |
61 | assertEquals(testId + ": Expected value of interval " + i, expectedValues[i], interval.getStateValue()); | |
62 | } | |
63 | } | |
64 | ||
65 | private static void verifyIntervalsWithMask(String testId, Collection<ITmfStateInterval> intervals, int[] expectedStarts, int[] expectedEnds, ITmfStateValue[] expectedValues, int mask) { | |
66 | int expectedCount = expectedStarts.length - 1; | |
67 | ||
68 | assertEquals(testId + ": Interval count", expectedCount, intervals.size()); | |
69 | int i = 0; | |
70 | for (ITmfStateInterval interval : intervals) { | |
71 | assertEquals(testId + ": Start time of interval " + i, expectedStarts[i], interval.getStartTime()); | |
72 | assertEquals(testId + ": End time of interval " + i, expectedEnds[i], interval.getEndTime()); | |
73 | assertEquals(testId + ": Expected value of interval " + i, expectedValues[i].unboxInt() & mask, interval.getStateValue().unboxInt() & mask); | |
74 | i++; | |
75 | } | |
76 | } | |
77 | ||
78 | /** | |
79 | * Test the analysis execution with stub traces of a virtual machine with | |
80 | * one virtual machine and one CPU | |
81 | */ | |
82 | @Test | |
83 | public void testStubTracesOneQemuKvm() { | |
84 | ||
85 | assumeTrue(VmTestExperiment.ONE_QEMUKVM.exists()); | |
a6366b8b | 86 | TmfExperiment experiment = VmTestExperiment.ONE_QEMUKVM.getExperiment(true); |
03722d5b GB |
87 | |
88 | /* Open the traces */ | |
89 | for (ITmfTrace trace : experiment.getTraces()) { | |
90 | ((TmfTrace) trace).traceOpened(new TmfTraceOpenedSignal(this, trace, null)); | |
91 | } | |
92 | ||
93 | /* | |
94 | * TODO For now, make sure the LttngKernelAnalysis have been run for | |
95 | * each trace before running the analysis. When event request precedence | |
96 | * is implemented, we can remove this | |
97 | */ | |
98 | for (ITmfTrace trace : experiment.getTraces()) { | |
6d16f5a9 | 99 | for (KernelAnalysisModule module : TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class)) { |
03722d5b GB |
100 | module.schedule(); |
101 | module.waitForCompletion(); | |
102 | } | |
103 | } | |
104 | /* End of TODO block */ | |
105 | ||
106 | experiment.traceOpened(new TmfTraceOpenedSignal(this, experiment, null)); | |
107 | VirtualMachineCpuAnalysis module = null; | |
108 | for (VirtualMachineCpuAnalysis mod : TmfTraceUtils.getAnalysisModulesOfClass(experiment, VirtualMachineCpuAnalysis.class)) { | |
109 | module = mod; | |
110 | break; | |
111 | } | |
112 | assertNotNull(module); | |
113 | module.schedule(); | |
114 | if (!module.waitForCompletion()) { | |
115 | fail("Module did not complete properly"); | |
116 | } | |
117 | ||
118 | try { | |
119 | /* Check the state system */ | |
120 | ITmfStateSystem ss = module.getStateSystem(); | |
121 | assertNotNull(ss); | |
122 | int vmQuark; | |
123 | ||
124 | vmQuark = ss.getQuarkAbsolute(VmAttributes.VIRTUAL_MACHINES); | |
125 | ||
126 | List<Integer> guestQuarks = ss.getSubAttributes(vmQuark, false); | |
127 | assertEquals("Number of guests", 1, guestQuarks.size()); | |
128 | List<Integer> vcpuQuarks = ss.getSubAttributes(guestQuarks.get(0), false); | |
129 | assertEquals("Number of virtual CPUs", 1, vcpuQuarks.size()); | |
130 | Integer statusQuark = ss.getQuarkRelative(vcpuQuarks.get(0), VmAttributes.STATUS); | |
131 | ||
132 | /* Check the intervals for the virtual CPU */ | |
133 | List<ITmfStateInterval> intervals = StateSystemUtils.queryHistoryRange(ss, statusQuark, ss.getStartTime(), ss.getCurrentEndTime()); | |
134 | ||
135 | /* Expected interval values for the virtual CPU */ | |
136 | int[] expectedStarts = { 1, 60, 75, 95, 100, 150, 155, 195, 210, 245, 260, 295, 300, 350, 355, 375 }; | |
137 | ITmfStateValue[] expectedValues = { TmfStateValue.nullValue(), | |
138 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_UNKNOWN), | |
139 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
140 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING | VcpuStateValues.VCPU_VMM), | |
141 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING | VcpuStateValues.VCPU_VMM | VcpuStateValues.VCPU_PREEMPT), | |
142 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING | VcpuStateValues.VCPU_VMM), | |
143 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
144 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING | VcpuStateValues.VCPU_VMM), | |
145 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
146 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING | VcpuStateValues.VCPU_VMM), | |
147 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
148 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING | VcpuStateValues.VCPU_VMM), | |
149 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING | VcpuStateValues.VCPU_VMM | VcpuStateValues.VCPU_PREEMPT), | |
150 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING | VcpuStateValues.VCPU_VMM), | |
151 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING) }; | |
152 | verifyStateIntervals("Virtual CPU", intervals, expectedStarts, expectedValues); | |
153 | ||
154 | /* Check the status of the guest's threads */ | |
155 | int[] expectedStartsT130 = { 10, 35, 75, 175, 195, 225, 275, 295, 300, 350, 375 }; | |
156 | int[] expectedEndsT130 = { 34, 74, 174, 224, 209, 274, 374, 299, 349, 354, 375 }; | |
157 | ITmfStateValue[] expectedValuesT30 = { TmfStateValue.newValueInt(VcpuStateValues.VCPU_IDLE), | |
158 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
159 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_IDLE), | |
160 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
161 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT), | |
162 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_IDLE), | |
163 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
164 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT), | |
165 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT), | |
166 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT), | |
167 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING) }; | |
168 | ||
169 | int[] expectedStartsT131 = { 10, 35, 75, 95, 100, 150, 175, 225, 245, 275, 375 }; | |
170 | int[] expectedEndsT131 = { 34, 74, 174, 99, 149, 154, 224, 274, 259, 374, 375 }; | |
171 | ITmfStateValue[] expectedValuesT31 = { TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
172 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_IDLE), | |
173 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
174 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT), | |
175 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT), | |
176 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT), | |
177 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_IDLE), | |
178 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING), | |
179 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_PREEMPT), | |
180 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_IDLE), | |
181 | TmfStateValue.newValueInt(VcpuStateValues.VCPU_RUNNING) }; | |
182 | ||
183 | Multimap<Integer, ITmfStateInterval> threadIntervals = module.getUpdatedThreadIntervals(guestQuarks.get(0), ss.getStartTime(), ss.getCurrentEndTime(), 1, new NullProgressMonitor()); | |
184 | verifyIntervalsWithMask("Thread 130", threadIntervals.get(130), expectedStartsT130, expectedEndsT130, expectedValuesT30, VcpuStateValues.VCPU_PREEMPT); | |
185 | verifyIntervalsWithMask("Thread 131", threadIntervals.get(131), expectedStartsT131, expectedEndsT131, expectedValuesT31, VcpuStateValues.VCPU_PREEMPT); | |
186 | ||
187 | } catch (AttributeNotFoundException | StateSystemDisposedException e) { | |
188 | fail(e.getMessage()); | |
189 | } finally { | |
190 | experiment.dispose(); | |
191 | } | |
192 | } | |
193 | ||
194 | } |