Page Speed Optimization Libraries  1.2.24.1
net/instaweb/util/public/condvar_test_base.h
Go to the documentation of this file.
00001 // Copyright 2011 Google Inc.
00016 
00017 #ifndef NET_INSTAWEB_UTIL_PUBLIC_CONDVAR_TEST_BASE_H_
00018 #define NET_INSTAWEB_UTIL_PUBLIC_CONDVAR_TEST_BASE_H_
00019 
00020 #include "net/instaweb/util/public/condvar.h"
00021 
00022 #include "base/logging.h"
00023 #include "net/instaweb/util/public/abstract_mutex.h"
00024 #include "net/instaweb/util/public/basictypes.h"
00025 #include "net/instaweb/util/public/gtest.h"
00026 #include "net/instaweb/util/public/timer.h"
00027 #include "net/instaweb/util/public/thread_system.h"
00028 
00029 namespace net_instaweb {
00030 
00031 class CondvarTestBase : public testing::Test {
00032  protected:
00033   typedef void (ThreadSystem::Condvar::*SignalMethod)();
00034 
00035   CondvarTestBase()
00036       : mutex_(NULL),
00037         startup_condvar_(NULL),
00038         condvar_(NULL),
00039         ready_to_start_(false),
00040         iters_(0),
00041         current_iter_(0),
00042         signal_method_(&ThreadSystem::Condvar::Signal),
00043         wait_after_signal_(false),
00044         helper_increments_(0),
00045         init_called_(false) {
00046   }
00047 
00050   void Init(ThreadSystem::CondvarCapableMutex* mutex,
00051             ThreadSystem::Condvar* startup_condvar,
00052             ThreadSystem::Condvar* condvar) {
00053     CHECK(!init_called_);
00054     mutex_ = mutex;
00055     startup_condvar_ = startup_condvar;
00056     condvar_ = condvar;
00057     init_called_ = true;
00058   }
00059 
00060   static void* HelperThread(void* data) {
00061     CondvarTestBase* test = static_cast<CondvarTestBase*>(data);
00062     test->HelperThreadMethod();
00063     return NULL;
00064   }
00065 
00069   virtual void CreateHelper() = 0;
00070 
00073   virtual void FinishHelper() = 0;
00074 
00075   void StartHelper() {
00076     CHECK(init_called_);
00077     CreateHelper();
00078     {
00079       ScopedMutex lock(mutex_);
00080       ready_to_start_ = true;
00081       startup_condvar_->Signal();
00082     }
00083   }
00084 
00085   virtual void HelperThreadMethod() {
00086     {
00087       ScopedMutex lock(mutex_);
00088       while (!ready_to_start_) {
00089         startup_condvar_->Wait();
00090       }
00091     }
00092     while (true) {
00093       ScopedMutex lock(mutex_);
00096       int iter = current_iter_ + 1;
00097       if (iter > iters_) {
00098         return;
00099       }
00100       ++helper_increments_;
00101       current_iter_ = iter;
00102       (condvar_->*signal_method_)();
00103       while (wait_after_signal_ && current_iter_ == iter) {
00104         condvar_->Wait();
00105       }
00106     }
00107   }
00108 
00110 
00112   void StartupTest() {
00113     StartHelper();
00114     EXPECT_TRUE(ready_to_start_);
00115     FinishHelper();
00116     EXPECT_EQ(helper_increments_, 0);
00117   }
00118 
00121   void BlindSignalsTest() {
00122     iters_ = 10;
00123     StartHelper();
00124     EXPECT_TRUE(ready_to_start_);
00125     FinishHelper();
00126     EXPECT_EQ(helper_increments_, 10);
00127   }
00128 
00131   void PingPongTest() {
00132     iters_ = 10;
00133     wait_after_signal_ = true;
00134     StartHelper();
00135     int local_increments = 0;
00136     while (true) {
00137       ScopedMutex lock(mutex_);
00138       while ((current_iter_ % 2) == 0 && current_iter_ < iters_) {
00139         condvar_->Wait();
00140       }
00143       if (current_iter_ == iters_) {
00144         break;
00145       }
00146       ++current_iter_;
00147       ++local_increments;
00148       condvar_->Signal();
00149     }
00150     EXPECT_EQ(local_increments, 5);
00151     FinishHelper();
00152     EXPECT_EQ(helper_increments_, 5);
00153   }
00154 
00156   void TimeoutTest() {
00157     iters_ = 0;
00158     StartHelper();
00159     {
00160       ScopedMutex lock(mutex_);
00161       condvar_->TimedWait(10); 
00162     }
00163     FinishHelper();
00164   }
00165 
00167   void LongTimeoutTest(int wait_ms) {
00168     iters_ = 0;
00169     StartHelper();
00170     int64 start_ms = timer()->NowMs();
00171     {
00172       ScopedMutex lock(mutex_);
00173       condvar_->TimedWait(wait_ms);
00174     }
00175     int64 end_ms = timer()->NowMs();
00176 
00179     EXPECT_LE(wait_ms, end_ms - start_ms);
00180     FinishHelper();
00181   }
00182 
00186   void TimeoutPingPongTest() {
00187     iters_ = 10;
00188     wait_after_signal_ = true;
00189     StartHelper();
00190     int local_increments = 0;
00191     while (true) {
00192       ScopedMutex lock(mutex_);
00193       if ((current_iter_ % 2) == 0) {
00194         condvar_->TimedWait(1);
00195       }
00200       if (current_iter_ > iters_) {
00201         break;
00202       }
00203       ++current_iter_;
00204       ++local_increments;
00205       condvar_->Signal();
00206     }
00207     FinishHelper();
00208     EXPECT_LE(6, local_increments);
00209     EXPECT_GE(5, helper_increments_);
00210     EXPECT_EQ(11, local_increments + helper_increments_);
00211   }
00212 
00213   virtual Timer* timer() = 0;
00214 
00215   ThreadSystem::CondvarCapableMutex* mutex_;
00216   ThreadSystem::Condvar* startup_condvar_;
00217   ThreadSystem::Condvar* condvar_;
00218   bool ready_to_start_;
00219   int iters_;
00220   int current_iter_;
00221   SignalMethod signal_method_;
00222   bool wait_after_signal_;
00223   int helper_increments_;
00224   bool init_called_;
00225 
00226  private:
00227   DISALLOW_COPY_AND_ASSIGN(CondvarTestBase);
00228 };
00229 
00230 }  
00231 
00232 #endif  ///< NET_INSTAWEB_UTIL_PUBLIC_CONDVAR_TEST_BASE_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines