blob: e740345978c7dd2ecf85e4ee9de1f9cf34bb65cf [file] [log] [blame]
henrike@webrtc.org0e118e72013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2010, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/base/gunit.h"
29#include "talk/base/pathutils.h"
30#include "talk/base/scoped_ptr.h"
31#include "talk/base/win32toolhelp.h"
32
33namespace talk_base {
34
35typedef struct {
36 // Required to match the toolhelp api struct 'design'.
37 DWORD dwSize;
38 int a;
39 uint32 b;
40} TestData;
41
42class Win32ToolhelpTest : public testing::Test {
43 public:
44 Win32ToolhelpTest() {
45 }
46
47 HANDLE AsHandle() {
48 return reinterpret_cast<HANDLE>(this);
49 }
50
51 static Win32ToolhelpTest* AsFixture(HANDLE handle) {
52 return reinterpret_cast<Win32ToolhelpTest*>(handle);
53 }
54
55 static bool First(HANDLE handle, TestData* d) {
56 Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle);
57 // This method should be called only once for every test.
58 // If it is called more than once it return false which
59 // should break the test.
60 EXPECT_EQ(0, tst->first_called_); // Just to be safe.
61 if (tst->first_called_ > 0) {
62 return false;
63 }
64
65 *d = kTestData[0];
66 tst->index_ = 1;
67 ++(tst->first_called_);
68 return true;
69 }
70
71 static bool Next(HANDLE handle, TestData* d) {
72 Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle);
73 ++(tst->next_called_);
74
75 if (tst->index_ >= kTestDataSize) {
76 return FALSE;
77 }
78
79 *d = kTestData[tst->index_];
80 ++(tst->index_);
81 return true;
82 }
83
84 static bool Fail(HANDLE handle, TestData* d) {
85 Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle);
86 ++(tst->fail_called_);
87 return false;
88 }
89
90 static bool CloseHandle(HANDLE handle) {
91 Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle);
92 ++(tst->close_handle_called_);
93 return true;
94 }
95
96 protected:
97 virtual void SetUp() {
98 fail_called_ = 0;
99 first_called_ = 0;
100 next_called_ = 0;
101 close_handle_called_ = 0;
102 index_ = 0;
103 }
104
105 static bool AllZero(const TestData& data) {
106 return data.dwSize == 0 && data.a == 0 && data.b == 0;
107 }
108
109 static bool Equals(const TestData& expected, const TestData& actual) {
110 return expected.dwSize == actual.dwSize
111 && expected.a == actual.a
112 && expected.b == actual.b;
113 }
114
115 bool CheckCallCounters(int first, int next, int fail, int close) {
116 bool match = first_called_ == first && next_called_ == next
117 && fail_called_ == fail && close_handle_called_ == close;
118
119 if (!match) {
120 LOG(LS_ERROR) << "Expected: ("
121 << first << ", "
122 << next << ", "
123 << fail << ", "
124 << close << ")";
125
126 LOG(LS_ERROR) << "Actual: ("
127 << first_called_ << ", "
128 << next_called_ << ", "
129 << fail_called_ << ", "
130 << close_handle_called_ << ")";
131 }
132 return match;
133 }
134
135 static const int kTestDataSize = 3;
136 static const TestData kTestData[];
137 int index_;
138 int first_called_;
139 int fail_called_;
140 int next_called_;
141 int close_handle_called_;
142};
143
144const TestData Win32ToolhelpTest::kTestData[] = {
145 {1, 1, 1}, {2, 2, 2}, {3, 3, 3}
146};
147
148
149class TestTraits {
150 public:
151 typedef TestData Type;
152
153 static bool First(HANDLE handle, Type* t) {
154 return Win32ToolhelpTest::First(handle, t);
155 }
156
157 static bool Next(HANDLE handle, Type* t) {
158 return Win32ToolhelpTest::Next(handle, t);
159 }
160
161 static bool CloseHandle(HANDLE handle) {
162 return Win32ToolhelpTest::CloseHandle(handle);
163 }
164};
165
166class BadFirstTraits {
167 public:
168 typedef TestData Type;
169
170 static bool First(HANDLE handle, Type* t) {
171 return Win32ToolhelpTest::Fail(handle, t);
172 }
173
174 static bool Next(HANDLE handle, Type* t) {
175 // This should never be called.
176 ADD_FAILURE();
177 return false;
178 }
179
180 static bool CloseHandle(HANDLE handle) {
181 return Win32ToolhelpTest::CloseHandle(handle);
182 }
183};
184
185class BadNextTraits {
186 public:
187 typedef TestData Type;
188
189 static bool First(HANDLE handle, Type* t) {
190 return Win32ToolhelpTest::First(handle, t);
191 }
192
193 static bool Next(HANDLE handle, Type* t) {
194 return Win32ToolhelpTest::Fail(handle, t);
195 }
196
197 static bool CloseHandle(HANDLE handle) {
198 return Win32ToolhelpTest::CloseHandle(handle);
199 }
200};
201
202// The toolhelp in normally inherited but most of
203// these tests only excercise the methods from the
204// traits therefore I use a typedef to make the
205// test code easier to read.
206typedef talk_base::ToolhelpEnumeratorBase<TestTraits> EnumeratorForTest;
207
208TEST_F(Win32ToolhelpTest, TestNextWithInvalidCtorHandle) {
209 EnumeratorForTest t(INVALID_HANDLE_VALUE);
210
211 EXPECT_FALSE(t.Next());
212 EXPECT_TRUE(CheckCallCounters(0, 0, 0, 0));
213}
214
215// Tests that Next() returns false if the first-pointer
216// function fails.
217TEST_F(Win32ToolhelpTest, TestNextFirstFails) {
218 typedef talk_base::ToolhelpEnumeratorBase<BadFirstTraits> BadEnumerator;
219 talk_base::scoped_ptr<BadEnumerator> t(new BadEnumerator(AsHandle()));
220
221 // If next ever fails it shall always fail.
222 EXPECT_FALSE(t->Next());
223 EXPECT_FALSE(t->Next());
224 EXPECT_FALSE(t->Next());
225 t.reset();
226 EXPECT_TRUE(CheckCallCounters(0, 0, 1, 1));
227}
228
229// Tests that Next() returns false if the next-pointer
230// function fails.
231TEST_F(Win32ToolhelpTest, TestNextNextFails) {
232 typedef talk_base::ToolhelpEnumeratorBase<BadNextTraits> BadEnumerator;
233 talk_base::scoped_ptr<BadEnumerator> t(new BadEnumerator(AsHandle()));
234
235 // If next ever fails it shall always fail. No more calls
236 // shall be dispatched to Next(...).
237 EXPECT_TRUE(t->Next());
238 EXPECT_FALSE(t->Next());
239 EXPECT_FALSE(t->Next());
240 t.reset();
241 EXPECT_TRUE(CheckCallCounters(1, 0, 1, 1));
242}
243
244
245// Tests that current returns an object is all zero's
246// if Next() hasn't been called.
247TEST_F(Win32ToolhelpTest, TestCurrentNextNotCalled) {
248 talk_base::scoped_ptr<EnumeratorForTest> t(new EnumeratorForTest(AsHandle()));
249 EXPECT_TRUE(AllZero(t->current()));
250 t.reset();
251 EXPECT_TRUE(CheckCallCounters(0, 0, 0, 1));
252}
253
254// Tests the simple everything works path through the code.
255TEST_F(Win32ToolhelpTest, TestCurrentNextCalled) {
256 talk_base::scoped_ptr<EnumeratorForTest> t(new EnumeratorForTest(AsHandle()));
257
258 EXPECT_TRUE(t->Next());
259 EXPECT_TRUE(Equals(t->current(), kTestData[0]));
260 EXPECT_TRUE(t->Next());
261 EXPECT_TRUE(Equals(t->current(), kTestData[1]));
262 EXPECT_TRUE(t->Next());
263 EXPECT_TRUE(Equals(t->current(), kTestData[2]));
264 EXPECT_FALSE(t->Next());
265 t.reset();
266 EXPECT_TRUE(CheckCallCounters(1, 3, 0, 1));
267}
268
269TEST_F(Win32ToolhelpTest, TestCurrentProcess) {
henrike@webrtc.org0e118e72013-07-10 00:45:36 +0000270 WCHAR buf[MAX_PATH];
271 GetModuleFileName(NULL, buf, ARRAY_SIZE(buf));
272 std::wstring name = ToUtf16(Pathname(ToUtf8(buf)).filename());
273
274 talk_base::ProcessEnumerator processes;
275 bool found = false;
276 while (processes.Next()) {
277 if (!name.compare(processes.current().szExeFile)) {
278 found = true;
279 break;
280 }
281 }
282 EXPECT_TRUE(found);
283
284 talk_base::ModuleEnumerator modules(processes.current().th32ProcessID);
285 found = false;
286 while (modules.Next()) {
287 if (!name.compare(modules.current().szModule)) {
288 found = true;
289 break;
290 }
291 }
292 EXPECT_TRUE(found);
293}
294
295} // namespace talk_base