1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/trace_event/trace_event.h"
9 #include "base/at_exit.h"
10 #include "base/basictypes.h"
11 #include "base/files/file_util.h"
12 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/trace_event_win.h"
14 #include "base/win/event_trace_consumer.h"
15 #include "base/win/event_trace_controller.h"
16 #include "base/win/event_trace_provider.h"
17 #include "base/win/windows_version.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include <initguid.h> // NOLINT - must be last include.
23 namespace trace_event
{
28 using testing::AnyNumber
;
29 using testing::InSequence
;
32 using testing::NotNull
;
34 using base::win::EtwEventType
;
35 using base::win::EtwTraceConsumerBase
;
36 using base::win::EtwTraceController
;
37 using base::win::EtwTraceProperties
;
39 // Data for unittests traces.
40 const char kEmpty
[] = "";
41 const char kName
[] = "unittest.trace_name";
42 const char kExtra
[] = "UnittestDummyExtraString";
43 const void* kId
= kName
;
45 const wchar_t kTestSessionName
[] = L
"TraceEvent unittest session";
47 MATCHER_P(BufferStartsWith
, str
, "Buffer starts with") {
48 return memcmp(arg
, str
.c_str(), str
.length()) == 0;
51 // Duplicated from <evntrace.h> to fix link problems.
52 DEFINE_GUID( /* 68fdd900-4a3e-11d1-84f4-0000f80464e3 */
57 0x84, 0xf4, 0x00, 0x00, 0xf8, 0x04, 0x64, 0xe3);
59 class TestEventConsumer
: public EtwTraceConsumerBase
<TestEventConsumer
> {
62 EXPECT_TRUE(current_
== NULL
);
66 ~TestEventConsumer() {
67 EXPECT_TRUE(current_
== this);
71 MOCK_METHOD4(Event
, void(REFGUID event_class
,
72 EtwEventType event_type
,
76 static void ProcessEvent(EVENT_TRACE
* event
) {
77 ASSERT_TRUE(current_
!= NULL
);
78 current_
->Event(event
->Header
.Guid
,
79 event
->Header
.Class
.Type
,
85 static TestEventConsumer
* current_
;
88 TestEventConsumer
* TestEventConsumer::current_
= NULL
;
90 class TraceEventWinTest
: public testing::Test
{
95 void SetUp() override
{
96 bool is_xp
= win::GetVersion() < base::win::VERSION_VISTA
;
99 // Tear down any dangling session from an earlier failing test.
100 EtwTraceProperties ignore
;
101 EtwTraceController::Stop(kTestSessionName
, &ignore
);
104 // Resurrect and initialize the TraceLog singleton instance.
105 // On Vista and better, we need the provider registered before we
106 // start the private, in-proc session, but on XP we need the global
107 // session created and the provider enabled before we register our
109 TraceEventETWProvider
* tracelog
= NULL
;
111 TraceEventETWProvider::Resurrect();
112 tracelog
= TraceEventETWProvider::GetInstance();
113 ASSERT_TRUE(tracelog
!= NULL
);
114 ASSERT_FALSE(tracelog
->IsTracing());
117 // Create the log file.
118 ASSERT_TRUE(base::CreateTemporaryFile(&log_file_
));
120 // Create a private log session on the file.
121 EtwTraceProperties prop
;
122 ASSERT_HRESULT_SUCCEEDED(prop
.SetLoggerFileName(log_file_
.value().c_str()));
123 EVENT_TRACE_PROPERTIES
& p
= *prop
.get();
124 p
.Wnode
.ClientContext
= 1; // QPC timer accuracy.
125 p
.LogFileMode
= EVENT_TRACE_FILE_MODE_SEQUENTIAL
; // Sequential log.
127 // On Vista and later, we create a private in-process log session, because
128 // otherwise we'd need administrator privileges. Unfortunately we can't
129 // do the same on XP and better, because the semantics of a private
130 // logger session are different, and the IN_PROC flag is not supported.
132 p
.LogFileMode
|= EVENT_TRACE_PRIVATE_IN_PROC
| // In-proc for non-admin.
133 EVENT_TRACE_PRIVATE_LOGGER_MODE
; // Process-private log.
136 p
.MaximumFileSize
= 100; // 100M file size.
137 p
.FlushTimer
= 1; // 1 second flush lag.
138 ASSERT_HRESULT_SUCCEEDED(controller_
.Start(kTestSessionName
, &prop
));
140 // Enable the TraceLog provider GUID.
141 ASSERT_HRESULT_SUCCEEDED(
142 controller_
.EnableProvider(kChromeTraceProviderName
,
143 TRACE_LEVEL_INFORMATION
,
147 TraceEventETWProvider::Resurrect();
148 tracelog
= TraceEventETWProvider::GetInstance();
150 ASSERT_TRUE(tracelog
!= NULL
);
151 EXPECT_TRUE(tracelog
->IsTracing());
154 void TearDown() override
{
155 EtwTraceProperties prop
;
156 if (controller_
.session() != 0)
157 EXPECT_HRESULT_SUCCEEDED(controller_
.Stop(&prop
));
159 if (!log_file_
.value().empty())
160 base::DeleteFile(log_file_
, false);
162 // We want our singleton torn down after each test.
163 TraceLog::DeleteForTesting();
166 void ExpectEvent(REFGUID guid
,
173 // Build the trace event buffer we expect will result from this.
175 str
.sputn(name
, name_len
+ 1);
176 str
.sputn(reinterpret_cast<const char*>(&id
), sizeof(id
));
177 str
.sputn(extra
, extra_len
+ 1);
179 // And set up the expectation for the event callback.
180 EXPECT_CALL(consumer_
, Event(guid
,
182 testing::Ge(str
.str().length()),
183 BufferStartsWith(str
.str())));
186 void ExpectPlayLog() {
187 // Ignore EventTraceGuid events.
188 EXPECT_CALL(consumer_
, Event(kEventTraceGuid
, _
, _
, _
))
193 EtwTraceProperties prop
;
194 EXPECT_HRESULT_SUCCEEDED(controller_
.Flush(&prop
));
195 EXPECT_HRESULT_SUCCEEDED(controller_
.Stop(&prop
));
196 ASSERT_HRESULT_SUCCEEDED(
197 consumer_
.OpenFileSession(log_file_
.value().c_str()));
199 ASSERT_HRESULT_SUCCEEDED(consumer_
.Consume());
203 // We want our singleton torn down after each test.
204 ShadowingAtExitManager at_exit_manager_
;
205 EtwTraceController controller_
;
207 TestEventConsumer consumer_
;
213 TEST_F(TraceEventWinTest
, TraceLog
) {
216 // The events should arrive in the same sequence as the expects.
217 InSequence in_sequence
;
219 // Full argument version, passing lengths explicitly.
220 TraceEventETWProvider::Trace(kName
,
222 TRACE_EVENT_PHASE_BEGIN
,
227 ExpectEvent(kTraceEventClass32
,
228 kTraceEventTypeBegin
,
229 kName
, strlen(kName
),
231 kExtra
, strlen(kExtra
));
233 // Const char* version.
234 TraceEventETWProvider::Trace(static_cast<const char*>(kName
),
235 TRACE_EVENT_PHASE_END
,
237 static_cast<const char*>(kExtra
));
239 ExpectEvent(kTraceEventClass32
,
241 kName
, strlen(kName
),
243 kExtra
, strlen(kExtra
));
245 // std::string extra version.
246 TraceEventETWProvider::Trace(static_cast<const char*>(kName
),
247 TRACE_EVENT_PHASE_INSTANT
,
249 std::string(kExtra
));
251 ExpectEvent(kTraceEventClass32
,
252 kTraceEventTypeInstant
,
253 kName
, strlen(kName
),
255 kExtra
, strlen(kExtra
));
258 // Test for sanity on NULL inputs.
259 TraceEventETWProvider::Trace(NULL
,
261 TRACE_EVENT_PHASE_BEGIN
,
266 ExpectEvent(kTraceEventClass32
,
267 kTraceEventTypeBegin
,
272 TraceEventETWProvider::Trace(NULL
,
273 TraceEventETWProvider::kUseStrlen
,
274 TRACE_EVENT_PHASE_END
,
277 TraceEventETWProvider::kUseStrlen
);
279 ExpectEvent(kTraceEventClass32
,
288 TEST_F(TraceEventWinTest
, Macros
) {
291 // The events should arrive in the same sequence as the expects.
292 InSequence in_sequence
;
294 TRACE_EVENT_BEGIN_ETW(kName
, kId
, kExtra
);
295 ExpectEvent(kTraceEventClass32
,
296 kTraceEventTypeBegin
,
297 kName
, strlen(kName
),
299 kExtra
, strlen(kExtra
));
301 TRACE_EVENT_END_ETW(kName
, kId
, kExtra
);
302 ExpectEvent(kTraceEventClass32
,
304 kName
, strlen(kName
),
306 kExtra
, strlen(kExtra
));
308 TRACE_EVENT_INSTANT_ETW(kName
, kId
, kExtra
);
309 ExpectEvent(kTraceEventClass32
,
310 kTraceEventTypeInstant
,
311 kName
, strlen(kName
),
313 kExtra
, strlen(kExtra
));
318 } // namespace trace_event