blob: 280f2ec98d00e3cc205f9867cc460e2218b1adf7 [file] [log] [blame]
henrike@webrtc.orgf7795df2014-05-13 18:00:26 +00001/*
2 * Copyright 2010 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/base/gunit.h"
12#include "webrtc/base/pathutils.h"
13#include "webrtc/base/scoped_ptr.h"
14#include "webrtc/base/win32toolhelp.h"
15
16namespace rtc {
17
18typedef struct {
19 // Required to match the toolhelp api struct 'design'.
20 DWORD dwSize;
21 int a;
22 uint32 b;
23} TestData;
24
25class Win32ToolhelpTest : public testing::Test {
26 public:
27 Win32ToolhelpTest() {
28 }
29
30 HANDLE AsHandle() {
31 return reinterpret_cast<HANDLE>(this);
32 }
33
34 static Win32ToolhelpTest* AsFixture(HANDLE handle) {
35 return reinterpret_cast<Win32ToolhelpTest*>(handle);
36 }
37
38 static bool First(HANDLE handle, TestData* d) {
39 Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle);
40 // This method should be called only once for every test.
41 // If it is called more than once it return false which
42 // should break the test.
43 EXPECT_EQ(0, tst->first_called_); // Just to be safe.
44 if (tst->first_called_ > 0) {
45 return false;
46 }
47
48 *d = kTestData[0];
49 tst->index_ = 1;
50 ++(tst->first_called_);
51 return true;
52 }
53
54 static bool Next(HANDLE handle, TestData* d) {
55 Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle);
56 ++(tst->next_called_);
57
58 if (tst->index_ >= kTestDataSize) {
59 return FALSE;
60 }
61
62 *d = kTestData[tst->index_];
63 ++(tst->index_);
64 return true;
65 }
66
67 static bool Fail(HANDLE handle, TestData* d) {
68 Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle);
69 ++(tst->fail_called_);
70 return false;
71 }
72
73 static bool CloseHandle(HANDLE handle) {
74 Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle);
75 ++(tst->close_handle_called_);
76 return true;
77 }
78
79 protected:
80 virtual void SetUp() {
81 fail_called_ = 0;
82 first_called_ = 0;
83 next_called_ = 0;
84 close_handle_called_ = 0;
85 index_ = 0;
86 }
87
88 static bool AllZero(const TestData& data) {
89 return data.dwSize == 0 && data.a == 0 && data.b == 0;
90 }
91
92 static bool Equals(const TestData& expected, const TestData& actual) {
93 return expected.dwSize == actual.dwSize
94 && expected.a == actual.a
95 && expected.b == actual.b;
96 }
97
98 bool CheckCallCounters(int first, int next, int fail, int close) {
99 bool match = first_called_ == first && next_called_ == next
100 && fail_called_ == fail && close_handle_called_ == close;
101
102 if (!match) {
103 LOG(LS_ERROR) << "Expected: ("
104 << first << ", "
105 << next << ", "
106 << fail << ", "
107 << close << ")";
108
109 LOG(LS_ERROR) << "Actual: ("
110 << first_called_ << ", "
111 << next_called_ << ", "
112 << fail_called_ << ", "
113 << close_handle_called_ << ")";
114 }
115 return match;
116 }
117
118 static const int kTestDataSize = 3;
119 static const TestData kTestData[];
120 int index_;
121 int first_called_;
122 int fail_called_;
123 int next_called_;
124 int close_handle_called_;
125};
126
127const TestData Win32ToolhelpTest::kTestData[] = {
128 {1, 1, 1}, {2, 2, 2}, {3, 3, 3}
129};
130
131
132class TestTraits {
133 public:
134 typedef TestData Type;
135
136 static bool First(HANDLE handle, Type* t) {
137 return Win32ToolhelpTest::First(handle, t);
138 }
139
140 static bool Next(HANDLE handle, Type* t) {
141 return Win32ToolhelpTest::Next(handle, t);
142 }
143
144 static bool CloseHandle(HANDLE handle) {
145 return Win32ToolhelpTest::CloseHandle(handle);
146 }
147};
148
149class BadFirstTraits {
150 public:
151 typedef TestData Type;
152
153 static bool First(HANDLE handle, Type* t) {
154 return Win32ToolhelpTest::Fail(handle, t);
155 }
156
157 static bool Next(HANDLE handle, Type* t) {
158 // This should never be called.
159 ADD_FAILURE();
160 return false;
161 }
162
163 static bool CloseHandle(HANDLE handle) {
164 return Win32ToolhelpTest::CloseHandle(handle);
165 }
166};
167
168class BadNextTraits {
169 public:
170 typedef TestData Type;
171
172 static bool First(HANDLE handle, Type* t) {
173 return Win32ToolhelpTest::First(handle, t);
174 }
175
176 static bool Next(HANDLE handle, Type* t) {
177 return Win32ToolhelpTest::Fail(handle, t);
178 }
179
180 static bool CloseHandle(HANDLE handle) {
181 return Win32ToolhelpTest::CloseHandle(handle);
182 }
183};
184
185// The toolhelp in normally inherited but most of
186// these tests only excercise the methods from the
187// traits therefore I use a typedef to make the
188// test code easier to read.
189typedef rtc::ToolhelpEnumeratorBase<TestTraits> EnumeratorForTest;
190
191TEST_F(Win32ToolhelpTest, TestNextWithInvalidCtorHandle) {
192 EnumeratorForTest t(INVALID_HANDLE_VALUE);
193
194 EXPECT_FALSE(t.Next());
195 EXPECT_TRUE(CheckCallCounters(0, 0, 0, 0));
196}
197
198// Tests that Next() returns false if the first-pointer
199// function fails.
200TEST_F(Win32ToolhelpTest, TestNextFirstFails) {
201 typedef rtc::ToolhelpEnumeratorBase<BadFirstTraits> BadEnumerator;
202 rtc::scoped_ptr<BadEnumerator> t(new BadEnumerator(AsHandle()));
203
204 // If next ever fails it shall always fail.
205 EXPECT_FALSE(t->Next());
206 EXPECT_FALSE(t->Next());
207 EXPECT_FALSE(t->Next());
208 t.reset();
209 EXPECT_TRUE(CheckCallCounters(0, 0, 1, 1));
210}
211
212// Tests that Next() returns false if the next-pointer
213// function fails.
214TEST_F(Win32ToolhelpTest, TestNextNextFails) {
215 typedef rtc::ToolhelpEnumeratorBase<BadNextTraits> BadEnumerator;
216 rtc::scoped_ptr<BadEnumerator> t(new BadEnumerator(AsHandle()));
217
218 // If next ever fails it shall always fail. No more calls
219 // shall be dispatched to Next(...).
220 EXPECT_TRUE(t->Next());
221 EXPECT_FALSE(t->Next());
222 EXPECT_FALSE(t->Next());
223 t.reset();
224 EXPECT_TRUE(CheckCallCounters(1, 0, 1, 1));
225}
226
227
228// Tests that current returns an object is all zero's
229// if Next() hasn't been called.
230TEST_F(Win32ToolhelpTest, TestCurrentNextNotCalled) {
231 rtc::scoped_ptr<EnumeratorForTest> t(new EnumeratorForTest(AsHandle()));
232 EXPECT_TRUE(AllZero(t->current()));
233 t.reset();
234 EXPECT_TRUE(CheckCallCounters(0, 0, 0, 1));
235}
236
237// Tests the simple everything works path through the code.
238TEST_F(Win32ToolhelpTest, TestCurrentNextCalled) {
239 rtc::scoped_ptr<EnumeratorForTest> t(new EnumeratorForTest(AsHandle()));
240
241 EXPECT_TRUE(t->Next());
242 EXPECT_TRUE(Equals(t->current(), kTestData[0]));
243 EXPECT_TRUE(t->Next());
244 EXPECT_TRUE(Equals(t->current(), kTestData[1]));
245 EXPECT_TRUE(t->Next());
246 EXPECT_TRUE(Equals(t->current(), kTestData[2]));
247 EXPECT_FALSE(t->Next());
248 t.reset();
249 EXPECT_TRUE(CheckCallCounters(1, 3, 0, 1));
250}
251
252TEST_F(Win32ToolhelpTest, TestCurrentProcess) {
253 WCHAR buf[MAX_PATH];
254 GetModuleFileName(NULL, buf, ARRAY_SIZE(buf));
255 std::wstring name = ToUtf16(Pathname(ToUtf8(buf)).filename());
256
257 rtc::ProcessEnumerator processes;
258 bool found = false;
259 while (processes.Next()) {
260 if (!name.compare(processes.current().szExeFile)) {
261 found = true;
262 break;
263 }
264 }
265 EXPECT_TRUE(found);
266
267 rtc::ModuleEnumerator modules(processes.current().th32ProcessID);
268 found = false;
269 while (modules.Next()) {
270 if (!name.compare(modules.current().szModule)) {
271 found = true;
272 break;
273 }
274 }
275 EXPECT_TRUE(found);
276}
277
278} // namespace rtc