Coverage for /Syzygy/agent/asan/timed_try_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
99.0%97980.C++test

Line-by-line coverage:

   1    :  // Copyright 2014 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/agent/asan/timed_try.h"
  16    :  
  17    :  #include "base/synchronization/condition_variable.h"
  18    :  #include "base/synchronization/lock.h"
  19    :  #include "base/threading/simple_thread.h"
  20    :  #include "base/time/time.h"
  21    :  #include "gtest/gtest.h"
  22    :  #include "syzygy/agent/asan/heaps/win_heap.h"
  23    :  #include "syzygy/common/recursive_lock.h"
  24    :  
  25    :  namespace agent {
  26    :  namespace asan {
  27    :  
  28    :  namespace {
  29    :  
  30    :  // An adapater for allowing a base::Lock to be used in the unittest.
  31    :  template<typename LockType>
  32    :  struct BaseLockAdapter {
  33    :    typedef LockType ConcreteLockType;
  34    :    typedef LockType AbstractLockType;
  35    :  
  36  E :    void AssertAcquired(LockType* lock) {
  37  E :      lock->AssertAcquired();
  38  E :    }
  39    :  
  40  E :    void Acquire(LockType* lock) {
  41  E :      lock->Acquire();
  42  E :    }
  43    :  
  44  E :    void Release(LockType* lock) {
  45  E :      lock->Release();
  46  E :    }
  47    :  
  48    :    void Try(LockType* lock) {
  49    :      return lock->Try();
  50    :    }
  51    :  };
  52    :  
  53    :  
  54    :  // An adapater for allowing a HeapInterface object to be used in the
  55    :  // unittest.
  56    :  template<typename HeapType>
  57    :  struct HeapAdapter {
  58    :    typedef HeapType ConcreteLockType;
  59    :    typedef HeapInterface AbstractLockType;
  60    :  
  61  E :    void AssertAcquired(HeapType* heap) {
  62  E :    }
  63    :  
  64  E :    void Acquire(HeapType* heap) {
  65  E :      heap->Lock();
  66  E :    }
  67    :  
  68  E :    void Release(HeapType* heap) {
  69  E :      heap->Unlock();
  70  E :    }
  71    :  
  72    :    void Try(HeapType* heap) {
  73    :      return heap->TryLock();
  74    :    }
  75    :  };
  76    :  
  77    :  
  78    :  // A thread body that acquires a lock, waits a certain amount of time, then
  79    :  // releases it. Signals when it has acquired the lock for unittest
  80    :  // synchronization purposes.
  81    :  template<typename LockAdapter>
  82    :  class TimedTryTestRunner : public base::DelegateSimpleThread::Delegate {
  83    :   public:
  84    :    typedef typename LockAdapter::ConcreteLockType LockType;
  85    :  
  86    :    TimedTryTestRunner(base::TimeDelta delta, LockType* lock)
  87  E :        : cv_(&cv_lock_), held_(false), delta_(delta), lock_(lock) {
  88  E :      DCHECK_NE(static_cast<LockType*>(NULL), lock);
  89  E :    }
  90    :  
  91  E :    virtual void Run() {
  92    :      LockAdapter adapter;
  93  E :      adapter.Acquire(lock_);
  94    :  
  95    :      // Notify that the lock has been acquired.
  96    :      {
  97  E :        base::AutoLock lock(cv_lock_);
  98  E :        held_ = true;
  99  E :        cv_.Signal();
 100  E :      }
 101    :  
 102  E :      base::Time end = base::Time::Now() + delta_;
 103  E :      while (true) {
 104  E :        base::Time now = base::Time::Now();
 105  E :        if (now >= end)
 106  E :          break;
 107  E :        base::TimeDelta remaining = end - now;
 108  E :        ::Sleep(remaining.InMillisecondsRoundedUp());
 109  E :      }
 110    :  
 111  E :      adapter.Release(lock_);
 112  E :    }
 113    :  
 114  E :    void WaitUntilHeld() {
 115  E :      base::AutoLock auto_lock(cv_lock_);
 116  E :      if (held_)
 117  i :        return;
 118  E :      cv_.Wait();
 119  E :    }
 120    :  
 121    :   private:
 122    :    // Used for signalling when the lock has been acquired.
 123    :    base::Lock cv_lock_;
 124    :    base::ConditionVariable cv_;
 125    :    bool held_;
 126    :  
 127    :    base::TimeDelta delta_;
 128    :    LockType* lock_;
 129    :  
 130    :    DISALLOW_COPY_AND_ASSIGN(TimedTryTestRunner);
 131    :  };
 132    :  
 133  E :  base::TimeDelta kDelay(base::TimeDelta::FromMilliseconds(100));
 134    :  
 135    :  template <typename LockAdapter>
 136  E :  void TimedTryTestImpl() {
 137    :    typedef typename LockAdapter::ConcreteLockType LockType;
 138    :    typedef typename LockAdapter::AbstractLockType LockInterfaceType;
 139    :    LockAdapter adapter;
 140  E :    LockType lock;
 141    :  
 142  E :    TimedTryTestRunner<LockAdapter> runner(kDelay * 2, &lock);
 143  E :    base::DelegateSimpleThread thread(&runner, "TimedTryTestRunner");
 144    :  
 145    :    // Grab the lock.
 146  E :    EXPECT_TRUE(TimedTry<LockInterfaceType>(kDelay, &lock));
 147  E :    adapter.AssertAcquired(&lock);
 148    :  
 149    :    // Try to grab the lock but expect a timeout.
 150  E :    base::Time t0 = base::Time::Now();
 151  E :    thread.Start();
 152  E :    adapter.Release(&lock);
 153  E :    runner.WaitUntilHeld();
 154  E :    ASSERT_FALSE(TimedTry<LockInterfaceType>(kDelay, &lock));
 155    :  
 156    :    // Try to grab the lock again, expecting success this time.
 157  E :    ASSERT_TRUE(TimedTry<LockInterfaceType>(kDelay * 10, &lock));
 158  E :    adapter.Release(&lock);
 159  E :    base::Time t1 = base::Time::Now();
 160  E :    EXPECT_LE(kDelay * 2, t1 - t0);
 161    :  
 162  E :    thread.Join();
 163  E :  }
 164    :  
 165    :  template <typename LockAdapter>
 166  E :  void AutoTimedTryTestImpl() {
 167    :    typedef typename LockAdapter::ConcreteLockType LockType;
 168    :    typedef typename LockAdapter::AbstractLockType LockInterfaceType;
 169  E :    LockType lock;
 170    :  
 171  E :    TimedTryTestRunner<LockAdapter> runner(kDelay * 2, &lock);
 172  E :    base::DelegateSimpleThread thread(&runner, "TimedTryTestRunner");
 173    :  
 174  E :    base::Time t0;
 175    :    {
 176  E :      AutoTimedTry<LockInterfaceType> timed_try(kDelay, &lock);
 177  E :      EXPECT_TRUE(timed_try.is_acquired());
 178  E :      t0 = base::Time::Now();
 179  E :      thread.Start();
 180  E :    }
 181  E :    runner.WaitUntilHeld();
 182    :  
 183    :    // Try to grab the lock, but expect it to fail as the lock will be held
 184    :    // longer than we try.
 185    :    {
 186  E :      AutoTimedTry<LockInterfaceType> timed_try(kDelay, &lock);
 187  E :      EXPECT_FALSE(timed_try.is_acquired());
 188  E :    }
 189    :  
 190    :    // Try to grab the lock and expect it to succeed, as the wait is longer than
 191    :    // the lock will be held.
 192    :    {
 193  E :      AutoTimedTry<LockInterfaceType> timed_try(kDelay * 10, &lock);
 194  E :      base::Time t1 = base::Time::Now();
 195  E :      EXPECT_LE(kDelay * 2, t1 - t0);
 196  E :    }
 197    :  
 198  E :    thread.Join();
 199  E :  }
 200    :  
 201    :  }  // namespace
 202    :  
 203  E :  TEST(TimedTryTest, BaseLock) {
 204    :    typedef BaseLockAdapter<base::Lock> LockAdapter;
 205  E :    ASSERT_NO_FATAL_FAILURE(TimedTryTestImpl<LockAdapter>());
 206  E :  }
 207    :  
 208  E :  TEST(AutoTimedTryTest, BaseLock) {
 209    :    typedef BaseLockAdapter<base::Lock> LockAdapter;
 210  E :    ASSERT_NO_FATAL_FAILURE(AutoTimedTryTestImpl<LockAdapter>());
 211  E :  }
 212    :  
 213  E :  TEST(TimedTryTest, CommonRecursiveLock) {
 214    :    typedef BaseLockAdapter<::common::RecursiveLock> LockAdapter;
 215  E :    ASSERT_NO_FATAL_FAILURE(TimedTryTestImpl<LockAdapter>());
 216  E :  }
 217    :  
 218  E :  TEST(AutoTimedTryTest, CommonRecursiveLock) {
 219    :    typedef BaseLockAdapter<::common::RecursiveLock> LockAdapter;
 220  E :    ASSERT_NO_FATAL_FAILURE(AutoTimedTryTestImpl<LockAdapter>());
 221  E :  }
 222    :  
 223  E :  TEST(TimedTryTest, HeapInterface) {
 224    :    typedef HeapAdapter<heaps::WinHeap> LockAdapter;
 225  E :    ASSERT_NO_FATAL_FAILURE(TimedTryTestImpl<LockAdapter>());
 226  E :  }
 227    :  
 228  E :  TEST(AutoTimedTryTest, HeapInterface) {
 229    :    typedef HeapAdapter<heaps::WinHeap> LockAdapter;
 230  E :    ASSERT_NO_FATAL_FAILURE(AutoTimedTryTestImpl<LockAdapter>());
 231  E :  }
 232    :  
 233    :  }  // namespace asan
 234    :  }  // namespace agent

Coverage information generated Thu Jan 14 17:40:38 2016.