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

Side by Side Diff: base/win/event_trace_consumer_unittest.cc

Issue 1446363003: Deleted OS_WIN and all Windows specific files from base. (Closed) Base URL: https://github.com/domokit/mojo.git@base_tests
Patch Set: Created 5 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
« no previous file with comments | « base/win/event_trace_consumer.h ('k') | base/win/event_trace_controller.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) 2012 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/win/event_trace_consumer.h"
7
8 #include <list>
9
10 #include <objbase.h>
11
12 #include "base/basictypes.h"
13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/logging.h"
17 #include "base/process/process_handle.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/win/event_trace_controller.h"
20 #include "base/win/event_trace_provider.h"
21 #include "base/win/scoped_handle.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 #include <initguid.h> // NOLINT - has to be last
25
26 namespace base {
27 namespace win {
28
29 namespace {
30
31 typedef std::list<EVENT_TRACE> EventQueue;
32
33 class TestConsumer: public EtwTraceConsumerBase<TestConsumer> {
34 public:
35 TestConsumer() {
36 sank_event_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
37 ClearQueue();
38 }
39
40 ~TestConsumer() {
41 ClearQueue();
42 sank_event_.Close();
43 }
44
45 void ClearQueue() {
46 for (EventQueue::const_iterator it(events_.begin()), end(events_.end());
47 it != end; ++it) {
48 delete[] reinterpret_cast<char*>(it->MofData);
49 }
50
51 events_.clear();
52 }
53
54 static void EnqueueEvent(EVENT_TRACE* event) {
55 events_.push_back(*event);
56 EVENT_TRACE& back = events_.back();
57
58 if (event->MofData != NULL && event->MofLength != 0) {
59 back.MofData = new char[event->MofLength];
60 memcpy(back.MofData, event->MofData, event->MofLength);
61 }
62 }
63
64 static void ProcessEvent(EVENT_TRACE* event) {
65 EnqueueEvent(event);
66 ::SetEvent(sank_event_.Get());
67 }
68
69 static ScopedHandle sank_event_;
70 static EventQueue events_;
71
72 private:
73 DISALLOW_COPY_AND_ASSIGN(TestConsumer);
74 };
75
76 ScopedHandle TestConsumer::sank_event_;
77 EventQueue TestConsumer::events_;
78
79 class EtwTraceConsumerBaseTest: public testing::Test {
80 public:
81 EtwTraceConsumerBaseTest()
82 : session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
83 }
84
85 void SetUp() override {
86 // Cleanup any potentially dangling sessions.
87 EtwTraceProperties ignore;
88 EtwTraceController::Stop(session_name_.c_str(), &ignore);
89
90 // Allocate a new GUID for each provider test.
91 ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
92 }
93
94 void TearDown() override {
95 // Cleanup any potentially dangling sessions.
96 EtwTraceProperties ignore;
97 EtwTraceController::Stop(session_name_.c_str(), &ignore);
98 }
99
100 protected:
101 GUID test_provider_;
102 std::wstring session_name_;
103 };
104
105 } // namespace
106
107 TEST_F(EtwTraceConsumerBaseTest, Initialize) {
108 TestConsumer consumer_;
109 }
110
111 TEST_F(EtwTraceConsumerBaseTest, OpenRealtimeSucceedsWhenNoSession) {
112 TestConsumer consumer_;
113 ASSERT_HRESULT_SUCCEEDED(
114 consumer_.OpenRealtimeSession(session_name_.c_str()));
115 }
116
117 TEST_F(EtwTraceConsumerBaseTest, ConsumerImmediateFailureWhenNoSession) {
118 TestConsumer consumer_;
119 ASSERT_HRESULT_SUCCEEDED(
120 consumer_.OpenRealtimeSession(session_name_.c_str()));
121 ASSERT_HRESULT_FAILED(consumer_.Consume());
122 }
123
124 namespace {
125
126 class EtwTraceConsumerRealtimeTest: public EtwTraceConsumerBaseTest {
127 public:
128 void SetUp() override {
129 EtwTraceConsumerBaseTest::SetUp();
130 ASSERT_HRESULT_SUCCEEDED(
131 consumer_.OpenRealtimeSession(session_name_.c_str()));
132 }
133
134 void TearDown() override {
135 consumer_.Close();
136 EtwTraceConsumerBaseTest::TearDown();
137 }
138
139 DWORD ConsumerThread() {
140 ::SetEvent(consumer_ready_.Get());
141 return consumer_.Consume();
142 }
143
144 static DWORD WINAPI ConsumerThreadMainProc(void* arg) {
145 return reinterpret_cast<EtwTraceConsumerRealtimeTest*>(arg)->
146 ConsumerThread();
147 }
148
149 HRESULT StartConsumerThread() {
150 consumer_ready_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
151 EXPECT_TRUE(consumer_ready_.IsValid());
152 consumer_thread_.Set(::CreateThread(NULL, 0, ConsumerThreadMainProc, this,
153 0, NULL));
154 if (consumer_thread_.Get() == NULL)
155 return HRESULT_FROM_WIN32(::GetLastError());
156
157 HANDLE events[] = { consumer_ready_.Get(), consumer_thread_.Get() };
158 DWORD result = ::WaitForMultipleObjects(arraysize(events), events,
159 FALSE, INFINITE);
160 switch (result) {
161 case WAIT_OBJECT_0:
162 // The event was set, the consumer_ is ready.
163 return S_OK;
164 case WAIT_OBJECT_0 + 1: {
165 // The thread finished. This may race with the event, so check
166 // explicitly for the event here, before concluding there's trouble.
167 if (::WaitForSingleObject(consumer_ready_.Get(), 0) == WAIT_OBJECT_0)
168 return S_OK;
169 DWORD exit_code = 0;
170 if (::GetExitCodeThread(consumer_thread_.Get(), &exit_code))
171 return exit_code;
172 return HRESULT_FROM_WIN32(::GetLastError());
173 }
174 default:
175 return E_UNEXPECTED;
176 }
177 }
178
179 // Waits for consumer_ thread to exit, and returns its exit code.
180 HRESULT JoinConsumerThread() {
181 if (::WaitForSingleObject(consumer_thread_.Get(), INFINITE) !=
182 WAIT_OBJECT_0) {
183 return HRESULT_FROM_WIN32(::GetLastError());
184 }
185
186 DWORD exit_code = 0;
187 if (::GetExitCodeThread(consumer_thread_.Get(), &exit_code))
188 return exit_code;
189
190 return HRESULT_FROM_WIN32(::GetLastError());
191 }
192
193 TestConsumer consumer_;
194 ScopedHandle consumer_ready_;
195 ScopedHandle consumer_thread_;
196 };
197
198 } // namespace
199
200 TEST_F(EtwTraceConsumerRealtimeTest, ConsumerReturnsWhenSessionClosed) {
201 EtwTraceController controller;
202 if (controller.StartRealtimeSession(session_name_.c_str(), 100 * 1024) ==
203 E_ACCESSDENIED) {
204 VLOG(1) << "You must be an administrator to run this test on Vista";
205 return;
206 }
207
208 // Start the consumer_.
209 ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
210
211 // Wait around for the consumer_ thread a bit.
212 ASSERT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(consumer_thread_.Get(), 50));
213 ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
214
215 // The consumer_ returns success on session stop.
216 ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
217 }
218
219 namespace {
220
221 // {57E47923-A549-476f-86CA-503D57F59E62}
222 DEFINE_GUID(
223 kTestEventType,
224 0x57e47923, 0xa549, 0x476f, 0x86, 0xca, 0x50, 0x3d, 0x57, 0xf5, 0x9e, 0x62);
225
226 } // namespace
227
228 TEST_F(EtwTraceConsumerRealtimeTest, ConsumeEvent) {
229 EtwTraceController controller;
230 if (controller.StartRealtimeSession(session_name_.c_str(), 100 * 1024) ==
231 E_ACCESSDENIED) {
232 VLOG(1) << "You must be an administrator to run this test on Vista";
233 return;
234 }
235
236 ASSERT_HRESULT_SUCCEEDED(controller.EnableProvider(
237 test_provider_, TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
238
239 EtwTraceProvider provider(test_provider_);
240 ASSERT_EQ(ERROR_SUCCESS, provider.Register());
241
242 // Start the consumer_.
243 ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
244 ASSERT_EQ(0, TestConsumer::events_.size());
245
246 EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
247 EXPECT_EQ(ERROR_SUCCESS, provider.Log(&event.header));
248 EXPECT_EQ(WAIT_OBJECT_0,
249 ::WaitForSingleObject(TestConsumer::sank_event_.Get(), INFINITE));
250 ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
251 ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
252 ASSERT_NE(0u, TestConsumer::events_.size());
253 }
254
255 namespace {
256
257 // We run events through a file session to assert that
258 // the content comes through.
259 class EtwTraceConsumerDataTest: public EtwTraceConsumerBaseTest {
260 public:
261 EtwTraceConsumerDataTest() {
262 }
263
264 void SetUp() override {
265 EtwTraceConsumerBaseTest::SetUp();
266
267 EtwTraceProperties prop;
268 EtwTraceController::Stop(session_name_.c_str(), &prop);
269
270 // Create a temp dir for this test.
271 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
272 // Construct a temp file name in our dir.
273 temp_file_ = temp_dir_.path().Append(L"test.etl");
274 }
275
276 void TearDown() override {
277 EXPECT_TRUE(base::DeleteFile(temp_file_, false));
278
279 EtwTraceConsumerBaseTest::TearDown();
280 }
281
282 HRESULT LogEventToTempSession(PEVENT_TRACE_HEADER header) {
283 EtwTraceController controller;
284
285 // Set up a file session.
286 HRESULT hr = controller.StartFileSession(session_name_.c_str(),
287 temp_file_.value().c_str());
288 if (FAILED(hr))
289 return hr;
290
291 // Enable our provider.
292 EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(
293 test_provider_, TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
294
295 EtwTraceProvider provider(test_provider_);
296 // Then register our provider, means we get a session handle immediately.
297 EXPECT_EQ(ERROR_SUCCESS, provider.Register());
298 // Trace the event, it goes to the temp file.
299 EXPECT_EQ(ERROR_SUCCESS, provider.Log(header));
300 EXPECT_HRESULT_SUCCEEDED(controller.DisableProvider(test_provider_));
301 EXPECT_HRESULT_SUCCEEDED(provider.Unregister());
302 EXPECT_HRESULT_SUCCEEDED(controller.Flush(NULL));
303 EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
304
305 return S_OK;
306 }
307
308 HRESULT ConsumeEventFromTempSession() {
309 // Now consume the event(s).
310 TestConsumer consumer_;
311 HRESULT hr = consumer_.OpenFileSession(temp_file_.value().c_str());
312 if (SUCCEEDED(hr))
313 hr = consumer_.Consume();
314 consumer_.Close();
315 // And nab the result.
316 events_.swap(TestConsumer::events_);
317 return hr;
318 }
319
320 HRESULT RoundTripEvent(PEVENT_TRACE_HEADER header, PEVENT_TRACE* trace) {
321 base::DeleteFile(temp_file_, false);
322
323 HRESULT hr = LogEventToTempSession(header);
324 if (SUCCEEDED(hr))
325 hr = ConsumeEventFromTempSession();
326
327 if (FAILED(hr))
328 return hr;
329
330 // We should now have the event in the queue.
331 if (events_.empty())
332 return E_FAIL;
333
334 *trace = &events_.back();
335 return S_OK;
336 }
337
338 EventQueue events_;
339 ScopedTempDir temp_dir_;
340 FilePath temp_file_;
341 };
342
343 } // namespace
344
345
346 TEST_F(EtwTraceConsumerDataTest, RoundTrip) {
347 EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
348
349 static const char kData[] = "This is but test data";
350 event.fields[0].DataPtr = reinterpret_cast<ULONG64>(kData);
351 event.fields[0].Length = sizeof(kData);
352
353 PEVENT_TRACE trace = NULL;
354 HRESULT hr = RoundTripEvent(&event.header, &trace);
355 if (hr == E_ACCESSDENIED) {
356 VLOG(1) << "You must be an administrator to run this test on Vista";
357 return;
358 }
359 ASSERT_HRESULT_SUCCEEDED(hr) << "RoundTripEvent failed";
360 ASSERT_TRUE(trace != NULL);
361 ASSERT_EQ(sizeof(kData), trace->MofLength);
362 ASSERT_STREQ(kData, reinterpret_cast<const char*>(trace->MofData));
363 }
364
365 } // namespace win
366 } // namespace base
OLDNEW
« no previous file with comments | « base/win/event_trace_consumer.h ('k') | base/win/event_trace_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698