Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: base/event_trace_consumer_win_unittest.cc

Issue 4517004: Move Windows-specific Event Tracing for Windows implementation to base/win. ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Fixed another ETW user in Chrome Frame Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/event_trace_consumer_win.h ('k') | base/event_trace_controller_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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.
4 //
5 // Unit tests for event trace consumer_ base class.
6 #include "base/event_trace_consumer_win.h"
7 #include <list>
8 #include "base/basictypes.h"
9 #include "base/event_trace_controller_win.h"
10 #include "base/event_trace_provider_win.h"
11 #include "base/file_path.h"
12 #include "base/file_util.h"
13 #include "base/logging.h"
14 #include "base/scoped_handle.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 #include <initguid.h> // NOLINT - has to be last
18
19 namespace {
20
21 typedef std::list<EVENT_TRACE> EventQueue;
22
23 class TestConsumer: public EtwTraceConsumerBase<TestConsumer> {
24 public:
25 TestConsumer() {
26 sank_event_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
27 ClearQueue();
28 }
29
30 ~TestConsumer() {
31 ClearQueue();
32 sank_event_.Close();
33 }
34
35 void ClearQueue() {
36 EventQueue::const_iterator it(events_.begin()), end(events_.end());
37
38 for (; it != end; ++it) {
39 delete [] it->MofData;
40 }
41
42 events_.clear();
43 }
44
45 static void EnqueueEvent(EVENT_TRACE* event) {
46 events_.push_back(*event);
47 EVENT_TRACE& back = events_.back();
48
49 if (NULL != event->MofData && 0 != event->MofLength) {
50 back.MofData = new char[event->MofLength];
51 memcpy(back.MofData, event->MofData, event->MofLength);
52 }
53 }
54
55 static void ProcessEvent(EVENT_TRACE* event) {
56 EnqueueEvent(event);
57 ::SetEvent(sank_event_.Get());
58 }
59
60 static ScopedHandle sank_event_;
61 static EventQueue events_;
62
63 private:
64 DISALLOW_COPY_AND_ASSIGN(TestConsumer);
65 };
66
67 ScopedHandle TestConsumer::sank_event_;
68 EventQueue TestConsumer::events_;
69
70 const wchar_t* const kTestSessionName = L"TestLogSession";
71
72 class EtwTraceConsumerBaseTest: public testing::Test {
73 public:
74 virtual void SetUp() {
75 EtwTraceProperties ignore;
76 EtwTraceController::Stop(kTestSessionName, &ignore);
77 }
78 };
79
80 } // namespace
81
82 TEST_F(EtwTraceConsumerBaseTest, Initialize) {
83 TestConsumer consumer_;
84 }
85
86 TEST_F(EtwTraceConsumerBaseTest, OpenRealtimeSucceedsWhenNoSession) {
87 TestConsumer consumer_;
88
89 ASSERT_HRESULT_SUCCEEDED(consumer_.OpenRealtimeSession(kTestSessionName));
90 }
91
92 TEST_F(EtwTraceConsumerBaseTest, ConsumerImmediateFailureWhenNoSession) {
93 TestConsumer consumer_;
94
95 ASSERT_HRESULT_SUCCEEDED(consumer_.OpenRealtimeSession(kTestSessionName));
96 ASSERT_HRESULT_FAILED(consumer_.Consume());
97 }
98
99 namespace {
100
101 class EtwTraceConsumerRealtimeTest: public testing::Test {
102 public:
103 virtual void SetUp() {
104 ASSERT_HRESULT_SUCCEEDED(consumer_.OpenRealtimeSession(kTestSessionName));
105 }
106
107 virtual void TearDown() {
108 consumer_.Close();
109 }
110
111 DWORD ConsumerThread() {
112 ::SetEvent(consumer_ready_.Get());
113
114 HRESULT hr = consumer_.Consume();
115 return hr;
116 }
117
118 static DWORD WINAPI ConsumerThreadMainProc(void* arg) {
119 return reinterpret_cast<EtwTraceConsumerRealtimeTest*>(arg)->
120 ConsumerThread();
121 }
122
123 HRESULT StartConsumerThread() {
124 consumer_ready_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
125 EXPECT_TRUE(consumer_ready_ != NULL);
126 consumer_thread_.Set(::CreateThread(NULL, 0, ConsumerThreadMainProc,
127 this, 0, NULL));
128 if (NULL == consumer_thread_.Get())
129 return HRESULT_FROM_WIN32(::GetLastError());
130
131 HRESULT hr = S_OK;
132 HANDLE events[] = { consumer_ready_, consumer_thread_ };
133 DWORD result = ::WaitForMultipleObjects(arraysize(events), events,
134 FALSE, INFINITE);
135 switch (result) {
136 case WAIT_OBJECT_0:
137 // The event was set, the consumer_ is ready.
138 return S_OK;
139 case WAIT_OBJECT_0 + 1: {
140 // The thread finished. This may race with the event, so check
141 // explicitly for the event here, before concluding there's trouble.
142 if (WAIT_OBJECT_0 == ::WaitForSingleObject(consumer_ready_, 0))
143 return S_OK;
144 DWORD exit_code = 0;
145 if (::GetExitCodeThread(consumer_thread_, &exit_code))
146 return exit_code;
147 else
148 return HRESULT_FROM_WIN32(::GetLastError());
149 break;
150 }
151 default:
152 return E_UNEXPECTED;
153 break;
154 }
155
156 return hr;
157 }
158
159 // Waits for consumer_ thread to exit, and returns its exit code.
160 HRESULT JoinConsumerThread() {
161 if (WAIT_OBJECT_0 != ::WaitForSingleObject(consumer_thread_, INFINITE))
162 return HRESULT_FROM_WIN32(::GetLastError());
163
164 DWORD exit_code = 0;
165 if (::GetExitCodeThread(consumer_thread_, &exit_code))
166 return exit_code;
167
168 return HRESULT_FROM_WIN32(::GetLastError());
169 }
170
171 TestConsumer consumer_;
172 ScopedHandle consumer_ready_;
173 ScopedHandle consumer_thread_;
174 };
175 } // namespace
176
177 TEST_F(EtwTraceConsumerRealtimeTest, ConsumerReturnsWhenSessionClosed) {
178 EtwTraceController controller;
179
180 HRESULT hr = controller.StartRealtimeSession(kTestSessionName, 100 * 1024);
181 if (hr == E_ACCESSDENIED) {
182 VLOG(1) << "You must be an administrator to run this test on Vista";
183 return;
184 }
185
186 // Start the consumer_.
187 ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
188
189 // Wait around for the consumer_ thread a bit.
190 ASSERT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(consumer_thread_, 50));
191
192 ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
193
194 // The consumer_ returns success on session stop.
195 ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
196 }
197
198 namespace {
199
200 // {036B8F65-8DF3-46e4-ABFC-6985C43D59BA}
201 DEFINE_GUID(kTestProvider,
202 0x36b8f65, 0x8df3, 0x46e4, 0xab, 0xfc, 0x69, 0x85, 0xc4, 0x3d, 0x59, 0xba);
203
204 // {57E47923-A549-476f-86CA-503D57F59E62}
205 DEFINE_GUID(kTestEventType,
206 0x57e47923, 0xa549, 0x476f, 0x86, 0xca, 0x50, 0x3d, 0x57, 0xf5, 0x9e, 0x62);
207
208 } // namespace
209
210 TEST_F(EtwTraceConsumerRealtimeTest, ConsumeEvent) {
211 EtwTraceController controller;
212 HRESULT hr = controller.StartRealtimeSession(kTestSessionName, 100 * 1024);
213 if (hr == E_ACCESSDENIED) {
214 VLOG(1) << "You must be an administrator to run this test on Vista";
215 return;
216 }
217
218 ASSERT_HRESULT_SUCCEEDED(controller.EnableProvider(kTestProvider,
219 TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
220
221 EtwTraceProvider provider(kTestProvider);
222 ASSERT_EQ(ERROR_SUCCESS, provider.Register());
223
224 // Start the consumer_.
225 ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
226
227 ASSERT_EQ(0, TestConsumer::events_.size());
228
229 EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
230 EXPECT_EQ(ERROR_SUCCESS, provider.Log(&event.header));
231
232 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(TestConsumer::sank_event_,
233 INFINITE));
234 ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
235 ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
236 ASSERT_NE(0u, TestConsumer::events_.size());
237 }
238
239 namespace {
240
241 // We run events through a file session to assert that
242 // the content comes through.
243 class EtwTraceConsumerDataTest: public testing::Test {
244 public:
245 EtwTraceConsumerDataTest() {
246 }
247
248 virtual void SetUp() {
249 EtwTraceProperties prop;
250 EtwTraceController::Stop(kTestSessionName, &prop);
251 // Construct a temp file name.
252 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_));
253 }
254
255 virtual void TearDown() {
256 EXPECT_TRUE(file_util::Delete(temp_file_, false));
257 EtwTraceProperties ignore;
258 EtwTraceController::Stop(kTestSessionName, &ignore);
259 }
260
261 HRESULT LogEventToTempSession(PEVENT_TRACE_HEADER header) {
262 EtwTraceController controller;
263
264 // Set up a file session.
265 HRESULT hr = controller.StartFileSession(kTestSessionName,
266 temp_file_.value().c_str());
267 if (FAILED(hr))
268 return hr;
269
270 // Enable our provider.
271 EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(kTestProvider,
272 TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
273
274 EtwTraceProvider provider(kTestProvider);
275 // Then register our provider, means we get a session handle immediately.
276 EXPECT_EQ(ERROR_SUCCESS, provider.Register());
277 // Trace the event, it goes to the temp file.
278 EXPECT_EQ(ERROR_SUCCESS, provider.Log(header));
279 EXPECT_HRESULT_SUCCEEDED(controller.DisableProvider(kTestProvider));
280 EXPECT_HRESULT_SUCCEEDED(provider.Unregister());
281 EXPECT_HRESULT_SUCCEEDED(controller.Flush(NULL));
282 EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
283
284 return S_OK;
285 }
286
287 HRESULT ConsumeEventFromTempSession() {
288 // Now consume the event(s).
289 TestConsumer consumer_;
290 HRESULT hr = consumer_.OpenFileSession(temp_file_.value().c_str());
291 if (SUCCEEDED(hr))
292 hr = consumer_.Consume();
293 consumer_.Close();
294 // And nab the result.
295 events_.swap(TestConsumer::events_);
296 return hr;
297 }
298
299 HRESULT RoundTripEvent(PEVENT_TRACE_HEADER header, PEVENT_TRACE* trace) {
300 file_util::Delete(temp_file_, false);
301
302 HRESULT hr = LogEventToTempSession(header);
303 if (SUCCEEDED(hr))
304 hr = ConsumeEventFromTempSession();
305
306 if (FAILED(hr))
307 return hr;
308
309 // We should now have the event in the queue.
310 if (events_.empty())
311 return E_FAIL;
312
313 *trace = &events_.back();
314 return S_OK;
315 }
316
317 EventQueue events_;
318 FilePath temp_file_;
319 };
320
321 } // namespace
322
323
324 TEST_F(EtwTraceConsumerDataTest, RoundTrip) {
325 EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
326
327 static const char kData[] = "This is but test data";
328 event.fields[0].DataPtr = reinterpret_cast<ULONG64>(kData);
329 event.fields[0].Length = sizeof(kData);
330
331 PEVENT_TRACE trace = NULL;
332 HRESULT hr = RoundTripEvent(&event.header, &trace);
333 if (hr == E_ACCESSDENIED) {
334 VLOG(1) << "You must be an administrator to run this test on Vista";
335 return;
336 }
337 ASSERT_TRUE(NULL != trace);
338 ASSERT_EQ(sizeof(kData), trace->MofLength);
339 ASSERT_STREQ(kData, reinterpret_cast<const char*>(trace->MofData));
340 }
OLDNEW
« no previous file with comments | « base/event_trace_consumer_win.h ('k') | base/event_trace_controller_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698