Page Speed Optimization Libraries
1.5.27.2
|
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_