Tweak/Wontfix a few tests that we could care less about.
[chromium-blink-merge.git] / base / event_trace_consumer_win_unittest.cc
blob9fcc4a61f36498ee209bf610caaee29d7c7d1046
1 // Copyright (c) 2009 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"
17 #include <initguid.h> // NOLINT - has to be last
19 namespace {
21 typedef std::list<EVENT_TRACE> EventQueue;
23 class TestConsumer: public EtwTraceConsumerBase<TestConsumer> {
24 public:
25 TestConsumer() {
26 sank_event_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
27 ClearQueue();
30 ~TestConsumer() {
31 ClearQueue();
32 sank_event_.Close();
35 void ClearQueue() {
36 EventQueue::const_iterator it(events_.begin()), end(events_.end());
38 for (; it != end; ++it) {
39 delete [] it->MofData;
42 events_.clear();
45 static void EnqueueEvent(EVENT_TRACE* event) {
46 events_.push_back(*event);
47 EVENT_TRACE& back = events_.back();
49 if (NULL != event->MofData && 0 != event->MofLength) {
50 back.MofData = new char[event->MofLength];
51 memcpy(back.MofData, event->MofData, event->MofLength);
55 static void ProcessEvent(EVENT_TRACE* event) {
56 EnqueueEvent(event);
57 ::SetEvent(sank_event_.Get());
60 static ScopedHandle sank_event_;
61 static EventQueue events_;
63 private:
64 DISALLOW_COPY_AND_ASSIGN(TestConsumer);
67 ScopedHandle TestConsumer::sank_event_;
68 EventQueue TestConsumer::events_;
70 const wchar_t* const kTestSessionName = L"TestLogSession";
72 class EtwTraceConsumerBaseTest: public testing::Test {
73 public:
74 virtual void SetUp() {
75 EtwTraceController::Stop(kTestSessionName, NULL);
79 } // namespace
81 TEST_F(EtwTraceConsumerBaseTest, Initialize) {
82 TestConsumer consumer_;
85 TEST_F(EtwTraceConsumerBaseTest, OpenRealtimeSucceedsWhenNoSession) {
86 TestConsumer consumer_;
88 ASSERT_HRESULT_SUCCEEDED(consumer_.OpenRealtimeSession(kTestSessionName));
91 TEST_F(EtwTraceConsumerBaseTest, ConsumerImmediateFailureWhenNoSession) {
92 TestConsumer consumer_;
94 ASSERT_HRESULT_SUCCEEDED(consumer_.OpenRealtimeSession(kTestSessionName));
95 ASSERT_HRESULT_FAILED(consumer_.Consume());
98 namespace {
100 class EtwTraceConsumerRealtimeTest: public testing::Test {
101 public:
102 virtual void SetUp() {
103 ASSERT_HRESULT_SUCCEEDED(consumer_.OpenRealtimeSession(kTestSessionName));
106 virtual void TearDown() {
107 consumer_.Close();
110 DWORD ConsumerThread() {
111 ::SetEvent(consumer_ready_.Get());
113 HRESULT hr = consumer_.Consume();
114 return hr;
117 static DWORD WINAPI ConsumerThreadMainProc(void* arg) {
118 return reinterpret_cast<EtwTraceConsumerRealtimeTest*>(arg)->
119 ConsumerThread();
122 HRESULT StartConsumerThread() {
123 consumer_ready_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
124 EXPECT_TRUE(consumer_ready_ != NULL);
125 consumer_thread_.Set(::CreateThread(NULL, 0, ConsumerThreadMainProc,
126 this, 0, NULL));
127 if (NULL == consumer_thread_.Get())
128 return HRESULT_FROM_WIN32(::GetLastError());
130 HRESULT hr = S_OK;
131 HANDLE events[] = { consumer_ready_, consumer_thread_ };
132 DWORD result = ::WaitForMultipleObjects(arraysize(events), events,
133 FALSE, INFINITE);
134 switch (result) {
135 case WAIT_OBJECT_0:
136 // The event was set, the consumer_ is ready.
137 return S_OK;
138 case WAIT_OBJECT_0 + 1: {
139 // The thread finished. This may race with the event, so check
140 // explicitly for the event here, before concluding there's trouble.
141 if (WAIT_OBJECT_0 == ::WaitForSingleObject(consumer_ready_, 0))
142 return S_OK;
143 DWORD exit_code = 0;
144 if (::GetExitCodeThread(consumer_thread_, &exit_code))
145 return exit_code;
146 else
147 return HRESULT_FROM_WIN32(::GetLastError());
148 break;
150 default:
151 return E_UNEXPECTED;
152 break;
155 return hr;
158 // Waits for consumer_ thread to exit, and returns its exit code.
159 HRESULT JoinConsumerThread() {
160 if (WAIT_OBJECT_0 != ::WaitForSingleObject(consumer_thread_, INFINITE))
161 return HRESULT_FROM_WIN32(::GetLastError());
163 DWORD exit_code = 0;
164 if (::GetExitCodeThread(consumer_thread_, &exit_code))
165 return exit_code;
167 return HRESULT_FROM_WIN32(::GetLastError());
170 TestConsumer consumer_;
171 ScopedHandle consumer_ready_;
172 ScopedHandle consumer_thread_;
174 } // namespace
176 TEST_F(EtwTraceConsumerRealtimeTest, ConsumerReturnsWhenSessionClosed) {
177 EtwTraceController controller;
179 HRESULT hr = controller.StartRealtimeSession(kTestSessionName, 100 * 1024);
180 if (hr == E_ACCESSDENIED) {
181 LOG(INFO) << "You must be an administrator to run this test on Vista";
182 return;
185 // Start the consumer_.
186 ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
188 // Wait around for the consumer_ thread a bit.
189 ASSERT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(consumer_thread_, 50));
191 ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
193 // The consumer_ returns success on session stop.
194 ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
197 namespace {
199 // {036B8F65-8DF3-46e4-ABFC-6985C43D59BA}
200 DEFINE_GUID(kTestProvider,
201 0x36b8f65, 0x8df3, 0x46e4, 0xab, 0xfc, 0x69, 0x85, 0xc4, 0x3d, 0x59, 0xba);
203 // {57E47923-A549-476f-86CA-503D57F59E62}
204 DEFINE_GUID(kTestEventType,
205 0x57e47923, 0xa549, 0x476f, 0x86, 0xca, 0x50, 0x3d, 0x57, 0xf5, 0x9e, 0x62);
207 } // namespace
209 TEST_F(EtwTraceConsumerRealtimeTest, ConsumeEvent) {
210 EtwTraceController controller;
211 HRESULT hr = controller.StartRealtimeSession(kTestSessionName, 100 * 1024);
212 if (hr == E_ACCESSDENIED) {
213 LOG(INFO) << "You must be an administrator to run this test on Vista";
214 return;
217 ASSERT_HRESULT_SUCCEEDED(controller.EnableProvider(kTestProvider,
218 TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
220 EtwTraceProvider provider(kTestProvider);
221 ASSERT_EQ(ERROR_SUCCESS, provider.Register());
223 // Start the consumer_.
224 ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
226 ASSERT_EQ(0, TestConsumer::events_.size());
228 EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
229 EXPECT_EQ(ERROR_SUCCESS, provider.Log(&event.header));
231 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(TestConsumer::sank_event_,
232 INFINITE));
233 ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
234 ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
235 ASSERT_NE(0, TestConsumer::events_.size());
238 namespace {
240 // We run events through a file session to assert that
241 // the content comes through.
242 class EtwTraceConsumerDataTest: public testing::Test {
243 public:
244 EtwTraceConsumerDataTest() {
247 virtual void SetUp() {
248 EtwTraceController::Stop(kTestSessionName, NULL);
249 // Construct a temp file name.
250 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_));
253 virtual void TearDown() {
254 EXPECT_TRUE(file_util::Delete(temp_file_, false));
255 EtwTraceController::Stop(kTestSessionName, NULL);
258 HRESULT LogEventToTempSession(PEVENT_TRACE_HEADER header) {
259 EtwTraceController controller;
261 // Set up a file session.
262 HRESULT hr = controller.StartFileSession(kTestSessionName,
263 temp_file_.value().c_str());
264 if (FAILED(hr))
265 return hr;
267 // Enable our provider.
268 EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(kTestProvider,
269 TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
271 EtwTraceProvider provider(kTestProvider);
272 // Then register our provider, means we get a session handle immediately.
273 EXPECT_EQ(ERROR_SUCCESS, provider.Register());
274 // Trace the event, it goes to the temp file.
275 EXPECT_EQ(ERROR_SUCCESS, provider.Log(header));
276 EXPECT_HRESULT_SUCCEEDED(controller.DisableProvider(kTestProvider));
277 EXPECT_HRESULT_SUCCEEDED(provider.Unregister());
278 EXPECT_HRESULT_SUCCEEDED(controller.Flush(NULL));
279 EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
281 return S_OK;
284 HRESULT ConsumeEventFromTempSession() {
285 // Now consume the event(s).
286 TestConsumer consumer_;
287 HRESULT hr = consumer_.OpenFileSession(temp_file_.value().c_str());
288 if (SUCCEEDED(hr))
289 hr = consumer_.Consume();
290 consumer_.Close();
291 // And nab the result.
292 events_.swap(TestConsumer::events_);
293 return hr;
296 HRESULT RoundTripEvent(PEVENT_TRACE_HEADER header, PEVENT_TRACE* trace) {
297 file_util::Delete(temp_file_, false);
299 HRESULT hr = LogEventToTempSession(header);
300 if (SUCCEEDED(hr))
301 hr = ConsumeEventFromTempSession();
303 if (FAILED(hr))
304 return hr;
306 // We should now have the event in the queue.
307 if (events_.empty())
308 return E_FAIL;
310 *trace = &events_.back();
311 return S_OK;
314 EventQueue events_;
315 FilePath temp_file_;
318 } // namespace
321 TEST_F(EtwTraceConsumerDataTest, RoundTrip) {
322 EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
324 static const char kData[] = "This is but test data";
325 event.fields[0].DataPtr = reinterpret_cast<ULONG64>(kData);
326 event.fields[0].Length = sizeof(kData);
328 PEVENT_TRACE trace = NULL;
329 HRESULT hr = RoundTripEvent(&event.header, &trace);
330 if (hr == E_ACCESSDENIED) {
331 LOG(INFO) << "You must be an administrator to run this test on Vista";
332 return;
334 ASSERT_TRUE(NULL != trace);
335 ASSERT_EQ(sizeof(kData), trace->MofLength);
336 ASSERT_STREQ(kData, reinterpret_cast<const char*>(trace->MofData));