• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 controller.
6 
7 #include <objbase.h>
8 #include <initguid.h>
9 
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/logging.h"
14 #include "base/process/process.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/sys_info.h"
17 #include "base/win/event_trace_controller.h"
18 #include "base/win/event_trace_provider.h"
19 #include "base/win/scoped_handle.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace base {
23 namespace win {
24 
25 namespace {
26 
27 DEFINE_GUID(kGuidNull,
28     0x0000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0);
29 
30 const ULONG kTestProviderFlags = 0xCAFEBABE;
31 
32 class TestingProvider: public EtwTraceProvider {
33  public:
TestingProvider(const GUID & provider_name)34   explicit TestingProvider(const GUID& provider_name)
35       : EtwTraceProvider(provider_name) {
36     callback_event_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
37   }
38 
WaitForCallback()39   void WaitForCallback() {
40     ::WaitForSingleObject(callback_event_.Get(), INFINITE);
41     ::ResetEvent(callback_event_.Get());
42   }
43 
44  private:
OnEventsEnabled()45   virtual void OnEventsEnabled() {
46     ::SetEvent(callback_event_.Get());
47   }
PostEventsDisabled()48   virtual void PostEventsDisabled() {
49     ::SetEvent(callback_event_.Get());
50   }
51 
52   ScopedHandle callback_event_;
53 
54   DISALLOW_COPY_AND_ASSIGN(TestingProvider);
55 };
56 
57 }  // namespace
58 
TEST(EtwTracePropertiesTest,Initialization)59 TEST(EtwTracePropertiesTest, Initialization) {
60   EtwTraceProperties prop;
61 
62   EVENT_TRACE_PROPERTIES* p = prop.get();
63   EXPECT_NE(0u, p->Wnode.BufferSize);
64   EXPECT_EQ(0u, p->Wnode.ProviderId);
65   EXPECT_EQ(0u, p->Wnode.HistoricalContext);
66 
67   EXPECT_TRUE(kGuidNull == p->Wnode.Guid);
68   EXPECT_EQ(0, p->Wnode.ClientContext);
69   EXPECT_EQ(WNODE_FLAG_TRACED_GUID, p->Wnode.Flags);
70 
71   EXPECT_EQ(0, p->BufferSize);
72   EXPECT_EQ(0, p->MinimumBuffers);
73   EXPECT_EQ(0, p->MaximumBuffers);
74   EXPECT_EQ(0, p->MaximumFileSize);
75   EXPECT_EQ(0, p->LogFileMode);
76   EXPECT_EQ(0, p->FlushTimer);
77   EXPECT_EQ(0, p->EnableFlags);
78   EXPECT_EQ(0, p->AgeLimit);
79 
80   EXPECT_EQ(0, p->NumberOfBuffers);
81   EXPECT_EQ(0, p->FreeBuffers);
82   EXPECT_EQ(0, p->EventsLost);
83   EXPECT_EQ(0, p->BuffersWritten);
84   EXPECT_EQ(0, p->LogBuffersLost);
85   EXPECT_EQ(0, p->RealTimeBuffersLost);
86   EXPECT_EQ(0, p->LoggerThreadId);
87   EXPECT_NE(0u, p->LogFileNameOffset);
88   EXPECT_NE(0u, p->LoggerNameOffset);
89 }
90 
TEST(EtwTracePropertiesTest,Strings)91 TEST(EtwTracePropertiesTest, Strings) {
92   EtwTraceProperties prop;
93 
94   ASSERT_STREQ(L"", prop.GetLoggerFileName());
95   ASSERT_STREQ(L"", prop.GetLoggerName());
96 
97   std::wstring name(1023, L'A');
98   ASSERT_HRESULT_SUCCEEDED(prop.SetLoggerFileName(name.c_str()));
99   ASSERT_HRESULT_SUCCEEDED(prop.SetLoggerName(name.c_str()));
100   ASSERT_STREQ(name.c_str(), prop.GetLoggerFileName());
101   ASSERT_STREQ(name.c_str(), prop.GetLoggerName());
102 
103   std::wstring name2(1024, L'A');
104   ASSERT_HRESULT_FAILED(prop.SetLoggerFileName(name2.c_str()));
105   ASSERT_HRESULT_FAILED(prop.SetLoggerName(name2.c_str()));
106 }
107 
108 namespace {
109 
110 class EtwTraceControllerTest : public testing::Test {
111  public:
EtwTraceControllerTest()112   EtwTraceControllerTest()
113       : session_name_(
114             StringPrintf(L"TestSession-%d", Process::Current().pid())) {
115   }
116 
SetUp()117   virtual void SetUp() {
118     EtwTraceProperties ignore;
119     EtwTraceController::Stop(session_name_.c_str(), &ignore);
120 
121     // Allocate a new provider name GUID for each test.
122     ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
123   }
124 
TearDown()125   virtual void TearDown() {
126     EtwTraceProperties prop;
127     EtwTraceController::Stop(session_name_.c_str(), &prop);
128   }
129 
130  protected:
131   GUID test_provider_;
132   std::wstring session_name_;
133 };
134 
135 }  // namespace
136 
TEST_F(EtwTraceControllerTest,Initialize)137 TEST_F(EtwTraceControllerTest, Initialize) {
138   EtwTraceController controller;
139 
140   EXPECT_EQ(NULL, controller.session());
141   EXPECT_STREQ(L"", controller.session_name());
142 }
143 
144 
TEST_F(EtwTraceControllerTest,StartRealTimeSession)145 TEST_F(EtwTraceControllerTest, StartRealTimeSession) {
146   EtwTraceController controller;
147 
148   HRESULT hr = controller.StartRealtimeSession(session_name_.c_str(),
149                                                100 * 1024);
150   if (hr == E_ACCESSDENIED) {
151     VLOG(1) << "You must be an administrator to run this test on Vista";
152     return;
153   }
154 
155   EXPECT_TRUE(NULL != controller.session());
156   EXPECT_STREQ(session_name_.c_str(), controller.session_name());
157 
158   EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
159   EXPECT_EQ(NULL, controller.session());
160   EXPECT_STREQ(L"", controller.session_name());
161 }
162 
TEST_F(EtwTraceControllerTest,StartFileSession)163 TEST_F(EtwTraceControllerTest, StartFileSession) {
164   ScopedTempDir temp_dir;
165   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
166   FilePath temp;
167   ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp));
168 
169   EtwTraceController controller;
170   HRESULT hr = controller.StartFileSession(session_name_.c_str(),
171                                            temp.value().c_str());
172   if (hr == E_ACCESSDENIED) {
173     VLOG(1) << "You must be an administrator to run this test on Vista";
174     base::DeleteFile(temp, false);
175     return;
176   }
177 
178   EXPECT_TRUE(NULL != controller.session());
179   EXPECT_STREQ(session_name_.c_str(), controller.session_name());
180 
181   EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
182   EXPECT_EQ(NULL, controller.session());
183   EXPECT_STREQ(L"", controller.session_name());
184   base::DeleteFile(temp, false);
185 }
186 
TEST_F(EtwTraceControllerTest,EnableDisable)187 TEST_F(EtwTraceControllerTest, EnableDisable) {
188   TestingProvider provider(test_provider_);
189 
190   EXPECT_EQ(ERROR_SUCCESS, provider.Register());
191   EXPECT_EQ(NULL, provider.session_handle());
192 
193   EtwTraceController controller;
194   HRESULT hr = controller.StartRealtimeSession(session_name_.c_str(),
195                                                100 * 1024);
196   if (hr == E_ACCESSDENIED) {
197     VLOG(1) << "You must be an administrator to run this test on Vista";
198     return;
199   }
200 
201   EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(test_provider_,
202                            TRACE_LEVEL_VERBOSE, kTestProviderFlags));
203 
204   provider.WaitForCallback();
205 
206   EXPECT_EQ(TRACE_LEVEL_VERBOSE, provider.enable_level());
207   EXPECT_EQ(kTestProviderFlags, provider.enable_flags());
208 
209   EXPECT_HRESULT_SUCCEEDED(controller.DisableProvider(test_provider_));
210 
211   provider.WaitForCallback();
212 
213   EXPECT_EQ(0, provider.enable_level());
214   EXPECT_EQ(0, provider.enable_flags());
215 
216   EXPECT_EQ(ERROR_SUCCESS, provider.Unregister());
217 
218   // Enable the provider again, before registering.
219   EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(test_provider_,
220                            TRACE_LEVEL_VERBOSE, kTestProviderFlags));
221 
222   // Register the provider again, the settings above
223   // should take immediate effect.
224   EXPECT_EQ(ERROR_SUCCESS, provider.Register());
225 
226   EXPECT_EQ(TRACE_LEVEL_VERBOSE, provider.enable_level());
227   EXPECT_EQ(kTestProviderFlags, provider.enable_flags());
228 
229   EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
230 
231   provider.WaitForCallback();
232 
233   // Session should have wound down.
234   EXPECT_EQ(0, provider.enable_level());
235   EXPECT_EQ(0, provider.enable_flags());
236 }
237 
238 }  // namespace win
239 }  // namespace base
240