Home | History | Annotate | Download | only in base
      1 /*
      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 
     16 namespace rtc {
     17 
     18 typedef struct {
     19   // Required to match the toolhelp api struct 'design'.
     20   DWORD dwSize;
     21   int a;
     22   uint32 b;
     23 } TestData;
     24 
     25 class 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 
    127 const TestData Win32ToolhelpTest::kTestData[] = {
    128   {1, 1, 1}, {2, 2, 2}, {3, 3, 3}
    129 };
    130 
    131 
    132 class 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 
    149 class 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 
    168 class 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.
    189 typedef rtc::ToolhelpEnumeratorBase<TestTraits> EnumeratorForTest;
    190 
    191 TEST_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.
    200 TEST_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.
    214 TEST_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.
    230 TEST_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.
    238 TEST_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 
    252 TEST_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
    279