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/debug/trace_event.h"
9 #include "base/at_exit.h"
10 #include "base/basictypes.h"
11 #include "base/file_util.h"
12 #include "base/debug/trace_event.h"
13 #include "base/debug/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.
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
{
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(file_util::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());
155 EtwTraceProperties prop
;
156 if (controller_
.session() != 0)
157 EXPECT_HRESULT_SUCCEEDED(controller_
.Stop(&prop
));
159 if (!log_file_
.value().empty())
160 file_util::Delete(log_file_
, false);
163 void ExpectEvent(REFGUID guid
,
170 // Build the trace event buffer we expect will result from this.
172 str
.sputn(name
, name_len
+ 1);
173 str
.sputn(reinterpret_cast<const char*>(&id
), sizeof(id
));
174 str
.sputn(extra
, extra_len
+ 1);
176 // And set up the expectation for the event callback.
177 EXPECT_CALL(consumer_
, Event(guid
,
179 testing::Ge(str
.str().length()),
180 BufferStartsWith(str
.str())));
183 void ExpectPlayLog() {
184 // Ignore EventTraceGuid events.
185 EXPECT_CALL(consumer_
, Event(kEventTraceGuid
, _
, _
, _
))
190 EtwTraceProperties prop
;
191 EXPECT_HRESULT_SUCCEEDED(controller_
.Flush(&prop
));
192 EXPECT_HRESULT_SUCCEEDED(controller_
.Stop(&prop
));
193 ASSERT_HRESULT_SUCCEEDED(
194 consumer_
.OpenFileSession(log_file_
.value().c_str()));
196 ASSERT_HRESULT_SUCCEEDED(consumer_
.Consume());
200 // We want our singleton torn down after each test.
201 ShadowingAtExitManager at_exit_manager_
;
202 EtwTraceController controller_
;
204 TestEventConsumer consumer_
;
210 TEST_F(TraceEventWinTest
, TraceLog
) {
213 // The events should arrive in the same sequence as the expects.
214 InSequence in_sequence
;
216 // Full argument version, passing lengths explicitly.
217 TraceEventETWProvider::Trace(kName
,
219 TRACE_EVENT_PHASE_BEGIN
,
224 ExpectEvent(kTraceEventClass32
,
225 kTraceEventTypeBegin
,
226 kName
, strlen(kName
),
228 kExtra
, strlen(kExtra
));
230 // Const char* version.
231 TraceEventETWProvider::Trace(static_cast<const char*>(kName
),
232 TRACE_EVENT_PHASE_END
,
234 static_cast<const char*>(kExtra
));
236 ExpectEvent(kTraceEventClass32
,
238 kName
, strlen(kName
),
240 kExtra
, strlen(kExtra
));
242 // std::string extra version.
243 TraceEventETWProvider::Trace(static_cast<const char*>(kName
),
244 TRACE_EVENT_PHASE_INSTANT
,
246 std::string(kExtra
));
248 ExpectEvent(kTraceEventClass32
,
249 kTraceEventTypeInstant
,
250 kName
, strlen(kName
),
252 kExtra
, strlen(kExtra
));
255 // Test for sanity on NULL inputs.
256 TraceEventETWProvider::Trace(NULL
,
258 TRACE_EVENT_PHASE_BEGIN
,
263 ExpectEvent(kTraceEventClass32
,
264 kTraceEventTypeBegin
,
269 TraceEventETWProvider::Trace(NULL
,
271 TRACE_EVENT_PHASE_END
,
276 ExpectEvent(kTraceEventClass32
,
285 TEST_F(TraceEventWinTest
, Macros
) {
288 // The events should arrive in the same sequence as the expects.
289 InSequence in_sequence
;
291 TRACE_EVENT_BEGIN_ETW(kName
, kId
, kExtra
);
292 ExpectEvent(kTraceEventClass32
,
293 kTraceEventTypeBegin
,
294 kName
, strlen(kName
),
296 kExtra
, strlen(kExtra
));
298 TRACE_EVENT_END_ETW(kName
, kId
, kExtra
);
299 ExpectEvent(kTraceEventClass32
,
301 kName
, strlen(kName
),
303 kExtra
, strlen(kExtra
));
305 TRACE_EVENT_INSTANT_ETW(kName
, kId
, kExtra
);
306 ExpectEvent(kTraceEventClass32
,
307 kTraceEventTypeInstant
,
308 kName
, strlen(kName
),
310 kExtra
, strlen(kExtra
));