1 /*******************************************************************************
2 * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir
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 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.lttng2
.kernel
.core
.tests
.synchronization
;
12 import static org
.junit
.Assert
.assertEquals
;
13 import static org
.junit
.Assert
.assertNotNull
;
14 import static org
.junit
.Assert
.fail
;
16 import java
.util
.Objects
;
17 import java
.util
.concurrent
.TimeUnit
;
18 import java
.util
.function
.Predicate
;
20 import org
.eclipse
.jdt
.annotation
.NonNull
;
21 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.KernelAnalysisModule
;
22 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.KernelThreadInformationProvider
;
23 import org
.eclipse
.tracecompass
.lttng2
.kernel
.core
.trace
.LttngKernelTrace
;
24 import org
.eclipse
.tracecompass
.testtraces
.ctf
.CtfTestTrace
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfTraceException
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.experiment
.TmfExperiment
;
34 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.event
.CtfTmfEvent
;
35 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.tests
.shared
.CtfTmfTestTraceUtils
;
36 import org
.junit
.After
;
37 import org
.junit
.Before
;
38 import org
.junit
.Rule
;
39 import org
.junit
.Test
;
40 import org
.junit
.rules
.TestRule
;
41 import org
.junit
.rules
.Timeout
;
44 * Test that synchronization between LTTng UST and kernel traces is done
47 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=484620
49 * @author Alexandre Montplaisir
51 public class UstKernelSyncTest
{
53 /** Time-out tests after 60 seconds */
54 @Rule public TestRule globalTimeout
= new Timeout(60, TimeUnit
.SECONDS
);
56 private static final @NonNull CtfTestTrace KERNEL_TRACE
= CtfTestTrace
.CONTEXT_SWITCHES_KERNEL
;
57 private static final @NonNull CtfTestTrace UST_TRACE
= CtfTestTrace
.CONTEXT_SWITCHES_UST
;
59 private TmfExperiment fExperiment
;
60 private ITmfTrace fKernelTrace
;
61 private ITmfTrace fUstTrace
;
62 private KernelAnalysisModule fKernelModule
;
69 ITmfTrace ustTrace
= CtfTmfTestTraceUtils
.getTrace(UST_TRACE
);
72 * We need to initialize the kernel trace to the "LttngKernelTrace"
73 * type ourselves, so the kernel analysis can run on it.
75 String kernelTracePath
= CtfTmfTestTraceUtils
.getTrace(KERNEL_TRACE
).getPath();
76 ITmfTrace kernelTrace
= new LttngKernelTrace();
79 kernelTrace
.initTrace(null, kernelTracePath
, CtfTmfEvent
.class);
80 } catch (TmfTraceException e
) {
84 TmfExperiment experiment
= new TmfExperiment(CtfTmfEvent
.class,
86 new ITmfTrace
[] { ustTrace
, kernelTrace
},
87 TmfExperiment
.DEFAULT_INDEX_PAGE_SIZE
,
90 /* Simulate experiment being opened */
91 // We have to "open" the sub-traces too, or their analyses are
92 // never initialized. Is that on purpose?
93 TmfSignalManager
.dispatchSignal(new TmfTraceOpenedSignal(this, ustTrace
, null));
94 TmfSignalManager
.dispatchSignal(new TmfTraceOpenedSignal(this, kernelTrace
, null));
95 TmfSignalManager
.dispatchSignal(new TmfTraceOpenedSignal(this, experiment
, null));
96 TmfSignalManager
.dispatchSignal(new TmfTraceSelectedSignal(this, experiment
));
98 KernelAnalysisModule module
= TmfTraceUtils
.getAnalysisModuleOfClass(experiment
,
99 KernelAnalysisModule
.class, KernelAnalysisModule
.ID
);
100 assertNotNull(module
);
101 module
.waitForCompletion();
103 fExperiment
= experiment
;
104 fKernelTrace
= kernelTrace
;
105 fUstTrace
= ustTrace
;
106 fKernelModule
= module
;
113 public void tearDown() {
114 if (fExperiment
!= null) {
115 fExperiment
.dispose();
117 if (fKernelTrace
!= null) {
118 fKernelTrace
.dispose();
121 CtfTmfTestTraceUtils
.dispose(KERNEL_TRACE
);
122 CtfTmfTestTraceUtils
.dispose(UST_TRACE
);
126 * Test that the TID given by the kernel analysis matches the one from the
127 * UST event's context for a given UST event that was known to fail.
129 * Reproduces the specific example that was pointed out in bug 484620.
132 public void testOneEvent() {
133 TmfExperiment experiment
= fExperiment
;
134 ITmfTrace ustTrace
= fUstTrace
;
135 KernelAnalysisModule module
= fKernelModule
;
136 assertNotNull(experiment
);
137 assertNotNull(ustTrace
);
138 assertNotNull(module
);
140 Predicate
<@NonNull ITmfEvent
> eventFinder
= event
-> {
141 Long addr
= event
.getContent().getFieldValue(Long
.class, "addr");
142 Long cs
= event
.getContent().getFieldValue(Long
.class, "call_site");
143 Long ctxVtid
= event
.getContent().getFieldValue(Long
.class, "context._vtid");
145 if (addr
== null || cs
== null || ctxVtid
== null) {
149 return Objects
.equals(event
.getType().getName(), "lttng_ust_cyg_profile:func_entry") &&
150 Objects
.equals(Long
.toHexString(addr
), "804af97") &&
151 Objects
.equals(Long
.toHexString(cs
), "804ab03") &&
152 Objects
.equals(ctxVtid
.longValue(), 594L);
155 /* The event we're looking for is the second event matching the predicate */
156 CtfTmfEvent ustEvent
= (CtfTmfEvent
) TmfTraceUtils
.getNextEventMatching(experiment
, 0, eventFinder
, null);
157 assertNotNull(ustEvent
);
158 long rank
= experiment
.seekEvent(ustEvent
.getTimestamp()).getRank() + 1;
159 ustEvent
= (CtfTmfEvent
) TmfTraceUtils
.getNextEventMatching(experiment
, rank
, eventFinder
, null);
160 assertNotNull(ustEvent
);
162 assertEquals(ustTrace
, ustEvent
.getTrace());
164 Integer tidFromKernel
= KernelThreadInformationProvider
.getThreadOnCpu(module
,
165 ustEvent
.getCPU(), ustEvent
.getTimestamp().toNanos());
167 assertNotNull(tidFromKernel
);
168 assertEquals(594, tidFromKernel
.intValue());
172 * Test going through the whole UST trace, making sure the VTID context of
173 * each event corresponds to the TID given by the kernel analysis at the
177 public void testWholeUstTrace() {
178 TmfExperiment experiment
= fExperiment
;
179 ITmfTrace ustTrace
= fUstTrace
;
180 KernelAnalysisModule module
= fKernelModule
;
181 assertNotNull(experiment
);
182 assertNotNull(ustTrace
);
183 assertNotNull(module
);
185 ITmfContext context
= ustTrace
.seekEvent(0L);
186 CtfTmfEvent ustEvent
= (CtfTmfEvent
) ustTrace
.getNext(context
);
188 while (ustEvent
!= null) {
189 Long ustVtid
= ustEvent
.getContent().getFieldValue(Long
.class, "context._vtid");
190 /* All events in the trace should have that context */
191 assertNotNull(ustVtid
);
193 long ts
= ustEvent
.getTimestamp().toNanos();
194 long cpu
= ustEvent
.getCPU();
195 Integer kernelTid
= KernelThreadInformationProvider
.getThreadOnCpu(module
, cpu
, ts
);
196 assertNotNull(kernelTid
);
198 assertEquals("Wrong TID for trace event " + ustEvent
.toString(), ustVtid
.longValue(), kernelTid
.longValue());
200 ustEvent
= (CtfTmfEvent
) ustTrace
.getNext(context
);
204 /* Make sure we've read all expected events */
205 assertEquals(UST_TRACE
.getNbEvents(), count
);