diff options
Diffstat (limited to 'chromium/third_party/webrtc/base/win32toolhelp_unittest.cc')
-rw-r--r-- | chromium/third_party/webrtc/base/win32toolhelp_unittest.cc | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/chromium/third_party/webrtc/base/win32toolhelp_unittest.cc b/chromium/third_party/webrtc/base/win32toolhelp_unittest.cc new file mode 100644 index 00000000000..280f2ec98d0 --- /dev/null +++ b/chromium/third_party/webrtc/base/win32toolhelp_unittest.cc @@ -0,0 +1,278 @@ +/* + * Copyright 2010 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/base/gunit.h" +#include "webrtc/base/pathutils.h" +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/base/win32toolhelp.h" + +namespace rtc { + +typedef struct { + // Required to match the toolhelp api struct 'design'. + DWORD dwSize; + int a; + uint32 b; +} TestData; + +class Win32ToolhelpTest : public testing::Test { + public: + Win32ToolhelpTest() { + } + + HANDLE AsHandle() { + return reinterpret_cast<HANDLE>(this); + } + + static Win32ToolhelpTest* AsFixture(HANDLE handle) { + return reinterpret_cast<Win32ToolhelpTest*>(handle); + } + + static bool First(HANDLE handle, TestData* d) { + Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle); + // This method should be called only once for every test. + // If it is called more than once it return false which + // should break the test. + EXPECT_EQ(0, tst->first_called_); // Just to be safe. + if (tst->first_called_ > 0) { + return false; + } + + *d = kTestData[0]; + tst->index_ = 1; + ++(tst->first_called_); + return true; + } + + static bool Next(HANDLE handle, TestData* d) { + Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle); + ++(tst->next_called_); + + if (tst->index_ >= kTestDataSize) { + return FALSE; + } + + *d = kTestData[tst->index_]; + ++(tst->index_); + return true; + } + + static bool Fail(HANDLE handle, TestData* d) { + Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle); + ++(tst->fail_called_); + return false; + } + + static bool CloseHandle(HANDLE handle) { + Win32ToolhelpTest* tst = Win32ToolhelpTest::AsFixture(handle); + ++(tst->close_handle_called_); + return true; + } + + protected: + virtual void SetUp() { + fail_called_ = 0; + first_called_ = 0; + next_called_ = 0; + close_handle_called_ = 0; + index_ = 0; + } + + static bool AllZero(const TestData& data) { + return data.dwSize == 0 && data.a == 0 && data.b == 0; + } + + static bool Equals(const TestData& expected, const TestData& actual) { + return expected.dwSize == actual.dwSize + && expected.a == actual.a + && expected.b == actual.b; + } + + bool CheckCallCounters(int first, int next, int fail, int close) { + bool match = first_called_ == first && next_called_ == next + && fail_called_ == fail && close_handle_called_ == close; + + if (!match) { + LOG(LS_ERROR) << "Expected: (" + << first << ", " + << next << ", " + << fail << ", " + << close << ")"; + + LOG(LS_ERROR) << "Actual: (" + << first_called_ << ", " + << next_called_ << ", " + << fail_called_ << ", " + << close_handle_called_ << ")"; + } + return match; + } + + static const int kTestDataSize = 3; + static const TestData kTestData[]; + int index_; + int first_called_; + int fail_called_; + int next_called_; + int close_handle_called_; +}; + +const TestData Win32ToolhelpTest::kTestData[] = { + {1, 1, 1}, {2, 2, 2}, {3, 3, 3} +}; + + +class TestTraits { + public: + typedef TestData Type; + + static bool First(HANDLE handle, Type* t) { + return Win32ToolhelpTest::First(handle, t); + } + + static bool Next(HANDLE handle, Type* t) { + return Win32ToolhelpTest::Next(handle, t); + } + + static bool CloseHandle(HANDLE handle) { + return Win32ToolhelpTest::CloseHandle(handle); + } +}; + +class BadFirstTraits { + public: + typedef TestData Type; + + static bool First(HANDLE handle, Type* t) { + return Win32ToolhelpTest::Fail(handle, t); + } + + static bool Next(HANDLE handle, Type* t) { + // This should never be called. + ADD_FAILURE(); + return false; + } + + static bool CloseHandle(HANDLE handle) { + return Win32ToolhelpTest::CloseHandle(handle); + } +}; + +class BadNextTraits { + public: + typedef TestData Type; + + static bool First(HANDLE handle, Type* t) { + return Win32ToolhelpTest::First(handle, t); + } + + static bool Next(HANDLE handle, Type* t) { + return Win32ToolhelpTest::Fail(handle, t); + } + + static bool CloseHandle(HANDLE handle) { + return Win32ToolhelpTest::CloseHandle(handle); + } +}; + +// The toolhelp in normally inherited but most of +// these tests only excercise the methods from the +// traits therefore I use a typedef to make the +// test code easier to read. +typedef rtc::ToolhelpEnumeratorBase<TestTraits> EnumeratorForTest; + +TEST_F(Win32ToolhelpTest, TestNextWithInvalidCtorHandle) { + EnumeratorForTest t(INVALID_HANDLE_VALUE); + + EXPECT_FALSE(t.Next()); + EXPECT_TRUE(CheckCallCounters(0, 0, 0, 0)); +} + +// Tests that Next() returns false if the first-pointer +// function fails. +TEST_F(Win32ToolhelpTest, TestNextFirstFails) { + typedef rtc::ToolhelpEnumeratorBase<BadFirstTraits> BadEnumerator; + rtc::scoped_ptr<BadEnumerator> t(new BadEnumerator(AsHandle())); + + // If next ever fails it shall always fail. + EXPECT_FALSE(t->Next()); + EXPECT_FALSE(t->Next()); + EXPECT_FALSE(t->Next()); + t.reset(); + EXPECT_TRUE(CheckCallCounters(0, 0, 1, 1)); +} + +// Tests that Next() returns false if the next-pointer +// function fails. +TEST_F(Win32ToolhelpTest, TestNextNextFails) { + typedef rtc::ToolhelpEnumeratorBase<BadNextTraits> BadEnumerator; + rtc::scoped_ptr<BadEnumerator> t(new BadEnumerator(AsHandle())); + + // If next ever fails it shall always fail. No more calls + // shall be dispatched to Next(...). + EXPECT_TRUE(t->Next()); + EXPECT_FALSE(t->Next()); + EXPECT_FALSE(t->Next()); + t.reset(); + EXPECT_TRUE(CheckCallCounters(1, 0, 1, 1)); +} + + +// Tests that current returns an object is all zero's +// if Next() hasn't been called. +TEST_F(Win32ToolhelpTest, TestCurrentNextNotCalled) { + rtc::scoped_ptr<EnumeratorForTest> t(new EnumeratorForTest(AsHandle())); + EXPECT_TRUE(AllZero(t->current())); + t.reset(); + EXPECT_TRUE(CheckCallCounters(0, 0, 0, 1)); +} + +// Tests the simple everything works path through the code. +TEST_F(Win32ToolhelpTest, TestCurrentNextCalled) { + rtc::scoped_ptr<EnumeratorForTest> t(new EnumeratorForTest(AsHandle())); + + EXPECT_TRUE(t->Next()); + EXPECT_TRUE(Equals(t->current(), kTestData[0])); + EXPECT_TRUE(t->Next()); + EXPECT_TRUE(Equals(t->current(), kTestData[1])); + EXPECT_TRUE(t->Next()); + EXPECT_TRUE(Equals(t->current(), kTestData[2])); + EXPECT_FALSE(t->Next()); + t.reset(); + EXPECT_TRUE(CheckCallCounters(1, 3, 0, 1)); +} + +TEST_F(Win32ToolhelpTest, TestCurrentProcess) { + WCHAR buf[MAX_PATH]; + GetModuleFileName(NULL, buf, ARRAY_SIZE(buf)); + std::wstring name = ToUtf16(Pathname(ToUtf8(buf)).filename()); + + rtc::ProcessEnumerator processes; + bool found = false; + while (processes.Next()) { + if (!name.compare(processes.current().szExeFile)) { + found = true; + break; + } + } + EXPECT_TRUE(found); + + rtc::ModuleEnumerator modules(processes.current().th32ProcessID); + found = false; + while (modules.Next()) { + if (!name.compare(modules.current().szModule)) { + found = true; + break; + } + } + EXPECT_TRUE(found); +} + +} // namespace rtc |