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