mutex_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "absl/synchronization/mutex.h"
00016 
00017 #ifdef WIN32
00018 #include <windows.h>
00019 #endif
00020 
00021 #include <algorithm>
00022 #include <atomic>
00023 #include <cstdlib>
00024 #include <functional>
00025 #include <memory>
00026 #include <random>
00027 #include <string>
00028 #include <thread>  // NOLINT(build/c++11)
00029 #include <vector>
00030 
00031 #include "gtest/gtest.h"
00032 #include "absl/base/attributes.h"
00033 #include "absl/base/internal/raw_logging.h"
00034 #include "absl/base/internal/sysinfo.h"
00035 #include "absl/memory/memory.h"
00036 #include "absl/synchronization/internal/thread_pool.h"
00037 #include "absl/time/clock.h"
00038 #include "absl/time/time.h"
00039 
00040 namespace {
00041 
00042 // TODO(dmauro): Replace with a commandline flag.
00043 static constexpr bool kExtendedTest = false;
00044 
00045 std::unique_ptr<absl::synchronization_internal::ThreadPool> CreatePool(
00046     int threads) {
00047   return absl::make_unique<absl::synchronization_internal::ThreadPool>(threads);
00048 }
00049 
00050 std::unique_ptr<absl::synchronization_internal::ThreadPool>
00051 CreateDefaultPool() {
00052   return CreatePool(kExtendedTest ? 32 : 10);
00053 }
00054 
00055 // Hack to schedule a function to run on a thread pool thread after a
00056 // duration has elapsed.
00057 static void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp,
00058                           absl::Duration after,
00059                           const std::function<void()> &func) {
00060   tp->Schedule([func, after] {
00061     absl::SleepFor(after);
00062     func();
00063   });
00064 }
00065 
00066 struct TestContext {
00067   int iterations;
00068   int threads;
00069   int g0;  // global 0
00070   int g1;  // global 1
00071   absl::Mutex mu;
00072   absl::CondVar cv;
00073 };
00074 
00075 // To test whether the invariant check call occurs
00076 static std::atomic<bool> invariant_checked;
00077 
00078 static bool GetInvariantChecked() {
00079   return invariant_checked.load(std::memory_order_relaxed);
00080 }
00081 
00082 static void SetInvariantChecked(bool new_value) {
00083   invariant_checked.store(new_value, std::memory_order_relaxed);
00084 }
00085 
00086 static void CheckSumG0G1(void *v) {
00087   TestContext *cxt = static_cast<TestContext *>(v);
00088   ABSL_RAW_CHECK(cxt->g0 == -cxt->g1, "Error in CheckSumG0G1");
00089   SetInvariantChecked(true);
00090 }
00091 
00092 static void TestMu(TestContext *cxt, int c) {
00093   for (int i = 0; i != cxt->iterations; i++) {
00094     absl::MutexLock l(&cxt->mu);
00095     int a = cxt->g0 + 1;
00096     cxt->g0 = a;
00097     cxt->g1--;
00098   }
00099 }
00100 
00101 static void TestTry(TestContext *cxt, int c) {
00102   for (int i = 0; i != cxt->iterations; i++) {
00103     do {
00104       std::this_thread::yield();
00105     } while (!cxt->mu.TryLock());
00106     int a = cxt->g0 + 1;
00107     cxt->g0 = a;
00108     cxt->g1--;
00109     cxt->mu.Unlock();
00110   }
00111 }
00112 
00113 static void TestR20ms(TestContext *cxt, int c) {
00114   for (int i = 0; i != cxt->iterations; i++) {
00115     absl::ReaderMutexLock l(&cxt->mu);
00116     absl::SleepFor(absl::Milliseconds(20));
00117     cxt->mu.AssertReaderHeld();
00118   }
00119 }
00120 
00121 static void TestRW(TestContext *cxt, int c) {
00122   if ((c & 1) == 0) {
00123     for (int i = 0; i != cxt->iterations; i++) {
00124       absl::WriterMutexLock l(&cxt->mu);
00125       cxt->g0++;
00126       cxt->g1--;
00127       cxt->mu.AssertHeld();
00128       cxt->mu.AssertReaderHeld();
00129     }
00130   } else {
00131     for (int i = 0; i != cxt->iterations; i++) {
00132       absl::ReaderMutexLock l(&cxt->mu);
00133       ABSL_RAW_CHECK(cxt->g0 == -cxt->g1, "Error in TestRW");
00134       cxt->mu.AssertReaderHeld();
00135     }
00136   }
00137 }
00138 
00139 struct MyContext {
00140   int target;
00141   TestContext *cxt;
00142   bool MyTurn();
00143 };
00144 
00145 bool MyContext::MyTurn() {
00146   TestContext *cxt = this->cxt;
00147   return cxt->g0 == this->target || cxt->g0 == cxt->iterations;
00148 }
00149 
00150 static void TestAwait(TestContext *cxt, int c) {
00151   MyContext mc;
00152   mc.target = c;
00153   mc.cxt = cxt;
00154   absl::MutexLock l(&cxt->mu);
00155   cxt->mu.AssertHeld();
00156   while (cxt->g0 < cxt->iterations) {
00157     cxt->mu.Await(absl::Condition(&mc, &MyContext::MyTurn));
00158     ABSL_RAW_CHECK(mc.MyTurn(), "Error in TestAwait");
00159     cxt->mu.AssertHeld();
00160     if (cxt->g0 < cxt->iterations) {
00161       int a = cxt->g0 + 1;
00162       cxt->g0 = a;
00163       mc.target += cxt->threads;
00164     }
00165   }
00166 }
00167 
00168 static void TestSignalAll(TestContext *cxt, int c) {
00169   int target = c;
00170   absl::MutexLock l(&cxt->mu);
00171   cxt->mu.AssertHeld();
00172   while (cxt->g0 < cxt->iterations) {
00173     while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
00174       cxt->cv.Wait(&cxt->mu);
00175     }
00176     if (cxt->g0 < cxt->iterations) {
00177       int a = cxt->g0 + 1;
00178       cxt->g0 = a;
00179       cxt->cv.SignalAll();
00180       target += cxt->threads;
00181     }
00182   }
00183 }
00184 
00185 static void TestSignal(TestContext *cxt, int c) {
00186   ABSL_RAW_CHECK(cxt->threads == 2, "TestSignal should use 2 threads");
00187   int target = c;
00188   absl::MutexLock l(&cxt->mu);
00189   cxt->mu.AssertHeld();
00190   while (cxt->g0 < cxt->iterations) {
00191     while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
00192       cxt->cv.Wait(&cxt->mu);
00193     }
00194     if (cxt->g0 < cxt->iterations) {
00195       int a = cxt->g0 + 1;
00196       cxt->g0 = a;
00197       cxt->cv.Signal();
00198       target += cxt->threads;
00199     }
00200   }
00201 }
00202 
00203 static void TestCVTimeout(TestContext *cxt, int c) {
00204   int target = c;
00205   absl::MutexLock l(&cxt->mu);
00206   cxt->mu.AssertHeld();
00207   while (cxt->g0 < cxt->iterations) {
00208     while (cxt->g0 != target && cxt->g0 != cxt->iterations) {
00209       cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100));
00210     }
00211     if (cxt->g0 < cxt->iterations) {
00212       int a = cxt->g0 + 1;
00213       cxt->g0 = a;
00214       cxt->cv.SignalAll();
00215       target += cxt->threads;
00216     }
00217   }
00218 }
00219 
00220 static bool G0GE2(TestContext *cxt) { return cxt->g0 >= 2; }
00221 
00222 static void TestTime(TestContext *cxt, int c, bool use_cv) {
00223   ABSL_RAW_CHECK(cxt->iterations == 1, "TestTime should only use 1 iteration");
00224   ABSL_RAW_CHECK(cxt->threads > 2, "TestTime should use more than 2 threads");
00225   const bool kFalse = false;
00226   absl::Condition false_cond(&kFalse);
00227   absl::Condition g0ge2(G0GE2, cxt);
00228   if (c == 0) {
00229     absl::MutexLock l(&cxt->mu);
00230 
00231     absl::Time start = absl::Now();
00232     if (use_cv) {
00233       cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
00234     } else {
00235       ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
00236                      "TestTime failed");
00237     }
00238     absl::Duration elapsed = absl::Now() - start;
00239     ABSL_RAW_CHECK(
00240         absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
00241         "TestTime failed");
00242     ABSL_RAW_CHECK(cxt->g0 == 1, "TestTime failed");
00243 
00244     start = absl::Now();
00245     if (use_cv) {
00246       cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
00247     } else {
00248       ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
00249                      "TestTime failed");
00250     }
00251     elapsed = absl::Now() - start;
00252     ABSL_RAW_CHECK(
00253         absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
00254         "TestTime failed");
00255     cxt->g0++;
00256     if (use_cv) {
00257       cxt->cv.Signal();
00258     }
00259 
00260     start = absl::Now();
00261     if (use_cv) {
00262       cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(4));
00263     } else {
00264       ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(4)),
00265                      "TestTime failed");
00266     }
00267     elapsed = absl::Now() - start;
00268     ABSL_RAW_CHECK(
00269         absl::Seconds(3.9) <= elapsed && elapsed <= absl::Seconds(6.0),
00270         "TestTime failed");
00271     ABSL_RAW_CHECK(cxt->g0 >= 3, "TestTime failed");
00272 
00273     start = absl::Now();
00274     if (use_cv) {
00275       cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
00276     } else {
00277       ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
00278                      "TestTime failed");
00279     }
00280     elapsed = absl::Now() - start;
00281     ABSL_RAW_CHECK(
00282         absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
00283         "TestTime failed");
00284     if (use_cv) {
00285       cxt->cv.SignalAll();
00286     }
00287 
00288     start = absl::Now();
00289     if (use_cv) {
00290       cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(1));
00291     } else {
00292       ABSL_RAW_CHECK(!cxt->mu.AwaitWithTimeout(false_cond, absl::Seconds(1)),
00293                      "TestTime failed");
00294     }
00295     elapsed = absl::Now() - start;
00296     ABSL_RAW_CHECK(absl::Seconds(0.9) <= elapsed &&
00297                    elapsed <= absl::Seconds(2.0), "TestTime failed");
00298     ABSL_RAW_CHECK(cxt->g0 == cxt->threads, "TestTime failed");
00299 
00300   } else if (c == 1) {
00301     absl::MutexLock l(&cxt->mu);
00302     const absl::Time start = absl::Now();
00303     if (use_cv) {
00304       cxt->cv.WaitWithTimeout(&cxt->mu, absl::Milliseconds(500));
00305     } else {
00306       ABSL_RAW_CHECK(
00307           !cxt->mu.AwaitWithTimeout(false_cond, absl::Milliseconds(500)),
00308           "TestTime failed");
00309     }
00310     const absl::Duration elapsed = absl::Now() - start;
00311     ABSL_RAW_CHECK(
00312         absl::Seconds(0.4) <= elapsed && elapsed <= absl::Seconds(0.9),
00313         "TestTime failed");
00314     cxt->g0++;
00315   } else if (c == 2) {
00316     absl::MutexLock l(&cxt->mu);
00317     if (use_cv) {
00318       while (cxt->g0 < 2) {
00319         cxt->cv.WaitWithTimeout(&cxt->mu, absl::Seconds(100));
00320       }
00321     } else {
00322       ABSL_RAW_CHECK(cxt->mu.AwaitWithTimeout(g0ge2, absl::Seconds(100)),
00323                      "TestTime failed");
00324     }
00325     cxt->g0++;
00326   } else {
00327     absl::MutexLock l(&cxt->mu);
00328     if (use_cv) {
00329       while (cxt->g0 < 2) {
00330         cxt->cv.Wait(&cxt->mu);
00331       }
00332     } else {
00333       cxt->mu.Await(g0ge2);
00334     }
00335     cxt->g0++;
00336   }
00337 }
00338 
00339 static void TestMuTime(TestContext *cxt, int c) { TestTime(cxt, c, false); }
00340 
00341 static void TestCVTime(TestContext *cxt, int c) { TestTime(cxt, c, true); }
00342 
00343 static void EndTest(int *c0, int *c1, absl::Mutex *mu, absl::CondVar *cv,
00344                     const std::function<void(int)>& cb) {
00345   mu->Lock();
00346   int c = (*c0)++;
00347   mu->Unlock();
00348   cb(c);
00349   absl::MutexLock l(mu);
00350   (*c1)++;
00351   cv->Signal();
00352 }
00353 
00354 // Code common to RunTest() and RunTestWithInvariantDebugging().
00355 static int RunTestCommon(TestContext *cxt, void (*test)(TestContext *cxt, int),
00356                          int threads, int iterations, int operations) {
00357   absl::Mutex mu2;
00358   absl::CondVar cv2;
00359   int c0 = 0;
00360   int c1 = 0;
00361   cxt->g0 = 0;
00362   cxt->g1 = 0;
00363   cxt->iterations = iterations;
00364   cxt->threads = threads;
00365   absl::synchronization_internal::ThreadPool tp(threads);
00366   for (int i = 0; i != threads; i++) {
00367     tp.Schedule(std::bind(&EndTest, &c0, &c1, &mu2, &cv2,
00368                           std::function<void(int)>(
00369                               std::bind(test, cxt, std::placeholders::_1))));
00370   }
00371   mu2.Lock();
00372   while (c1 != threads) {
00373     cv2.Wait(&mu2);
00374   }
00375   mu2.Unlock();
00376   return cxt->g0;
00377 }
00378 
00379 // Basis for the parameterized tests configured below.
00380 static int RunTest(void (*test)(TestContext *cxt, int), int threads,
00381                    int iterations, int operations) {
00382   TestContext cxt;
00383   return RunTestCommon(&cxt, test, threads, iterations, operations);
00384 }
00385 
00386 // Like RunTest(), but sets an invariant on the tested Mutex and
00387 // verifies that the invariant check happened. The invariant function
00388 // will be passed the TestContext* as its arg and must call
00389 // SetInvariantChecked(true);
00390 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
00391 static int RunTestWithInvariantDebugging(void (*test)(TestContext *cxt, int),
00392                                          int threads, int iterations,
00393                                          int operations,
00394                                          void (*invariant)(void *)) {
00395   absl::EnableMutexInvariantDebugging(true);
00396   SetInvariantChecked(false);
00397   TestContext cxt;
00398   cxt.mu.EnableInvariantDebugging(invariant, &cxt);
00399   int ret = RunTestCommon(&cxt, test, threads, iterations, operations);
00400   ABSL_RAW_CHECK(GetInvariantChecked(), "Invariant not checked");
00401   absl::EnableMutexInvariantDebugging(false);  // Restore.
00402   return ret;
00403 }
00404 #endif
00405 
00406 // --------------------------------------------------------
00407 // Test for fix of bug in TryRemove()
00408 struct TimeoutBugStruct {
00409   absl::Mutex mu;
00410   bool a;
00411   int a_waiter_count;
00412 };
00413 
00414 static void WaitForA(TimeoutBugStruct *x) {
00415   x->mu.LockWhen(absl::Condition(&x->a));
00416   x->a_waiter_count--;
00417   x->mu.Unlock();
00418 }
00419 
00420 static bool NoAWaiters(TimeoutBugStruct *x) { return x->a_waiter_count == 0; }
00421 
00422 // Test that a CondVar.Wait(&mutex) can un-block a call to mutex.Await() in
00423 // another thread.
00424 TEST(Mutex, CondVarWaitSignalsAwait) {
00425   // Use a struct so the lock annotations apply.
00426   struct {
00427     absl::Mutex barrier_mu;
00428     bool barrier GUARDED_BY(barrier_mu) = false;
00429 
00430     absl::Mutex release_mu;
00431     bool release GUARDED_BY(release_mu) = false;
00432     absl::CondVar released_cv;
00433   } state;
00434 
00435   auto pool = CreateDefaultPool();
00436 
00437   // Thread A.  Sets barrier, waits for release using Mutex::Await, then
00438   // signals released_cv.
00439   pool->Schedule([&state] {
00440     state.release_mu.Lock();
00441 
00442     state.barrier_mu.Lock();
00443     state.barrier = true;
00444     state.barrier_mu.Unlock();
00445 
00446     state.release_mu.Await(absl::Condition(&state.release));
00447     state.released_cv.Signal();
00448     state.release_mu.Unlock();
00449   });
00450 
00451   state.barrier_mu.LockWhen(absl::Condition(&state.barrier));
00452   state.barrier_mu.Unlock();
00453   state.release_mu.Lock();
00454   // Thread A is now blocked on release by way of Mutex::Await().
00455 
00456   // Set release.  Calling released_cv.Wait() should un-block thread A,
00457   // which will signal released_cv.  If not, the test will hang.
00458   state.release = true;
00459   state.released_cv.Wait(&state.release_mu);
00460   state.release_mu.Unlock();
00461 }
00462 
00463 // Test that a CondVar.WaitWithTimeout(&mutex) can un-block a call to
00464 // mutex.Await() in another thread.
00465 TEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) {
00466   // Use a struct so the lock annotations apply.
00467   struct {
00468     absl::Mutex barrier_mu;
00469     bool barrier GUARDED_BY(barrier_mu) = false;
00470 
00471     absl::Mutex release_mu;
00472     bool release GUARDED_BY(release_mu) = false;
00473     absl::CondVar released_cv;
00474   } state;
00475 
00476   auto pool = CreateDefaultPool();
00477 
00478   // Thread A.  Sets barrier, waits for release using Mutex::Await, then
00479   // signals released_cv.
00480   pool->Schedule([&state] {
00481     state.release_mu.Lock();
00482 
00483     state.barrier_mu.Lock();
00484     state.barrier = true;
00485     state.barrier_mu.Unlock();
00486 
00487     state.release_mu.Await(absl::Condition(&state.release));
00488     state.released_cv.Signal();
00489     state.release_mu.Unlock();
00490   });
00491 
00492   state.barrier_mu.LockWhen(absl::Condition(&state.barrier));
00493   state.barrier_mu.Unlock();
00494   state.release_mu.Lock();
00495   // Thread A is now blocked on release by way of Mutex::Await().
00496 
00497   // Set release.  Calling released_cv.Wait() should un-block thread A,
00498   // which will signal released_cv.  If not, the test will hang.
00499   state.release = true;
00500   EXPECT_TRUE(
00501       !state.released_cv.WaitWithTimeout(&state.release_mu, absl::Seconds(10)))
00502       << "; Unrecoverable test failure: CondVar::WaitWithTimeout did not "
00503          "unblock the absl::Mutex::Await call in another thread.";
00504 
00505   state.release_mu.Unlock();
00506 }
00507 
00508 // Test for regression of a bug in loop of TryRemove()
00509 TEST(Mutex, MutexTimeoutBug) {
00510   auto tp = CreateDefaultPool();
00511 
00512   TimeoutBugStruct x;
00513   x.a = false;
00514   x.a_waiter_count = 2;
00515   tp->Schedule(std::bind(&WaitForA, &x));
00516   tp->Schedule(std::bind(&WaitForA, &x));
00517   absl::SleepFor(absl::Seconds(1));  // Allow first two threads to hang.
00518   // The skip field of the second will point to the first because there are
00519   // only two.
00520 
00521   // Now cause a thread waiting on an always-false to time out
00522   // This would deadlock when the bug was present.
00523   bool always_false = false;
00524   x.mu.LockWhenWithTimeout(absl::Condition(&always_false),
00525                            absl::Milliseconds(500));
00526 
00527   // if we get here, the bug is not present.   Cleanup the state.
00528 
00529   x.a = true;                                    // wakeup the two waiters on A
00530   x.mu.Await(absl::Condition(&NoAWaiters, &x));  // wait for them to exit
00531   x.mu.Unlock();
00532 }
00533 
00534 struct CondVarWaitDeadlock : testing::TestWithParam<int> {
00535   absl::Mutex mu;
00536   absl::CondVar cv;
00537   bool cond1 = false;
00538   bool cond2 = false;
00539   bool read_lock1;
00540   bool read_lock2;
00541   bool signal_unlocked;
00542 
00543   CondVarWaitDeadlock() {
00544     read_lock1 = GetParam() & (1 << 0);
00545     read_lock2 = GetParam() & (1 << 1);
00546     signal_unlocked = GetParam() & (1 << 2);
00547   }
00548 
00549   void Waiter1() {
00550     if (read_lock1) {
00551       mu.ReaderLock();
00552       while (!cond1) {
00553         cv.Wait(&mu);
00554       }
00555       mu.ReaderUnlock();
00556     } else {
00557       mu.Lock();
00558       while (!cond1) {
00559         cv.Wait(&mu);
00560       }
00561       mu.Unlock();
00562     }
00563   }
00564 
00565   void Waiter2() {
00566     if (read_lock2) {
00567       mu.ReaderLockWhen(absl::Condition(&cond2));
00568       mu.ReaderUnlock();
00569     } else {
00570       mu.LockWhen(absl::Condition(&cond2));
00571       mu.Unlock();
00572     }
00573   }
00574 };
00575 
00576 // Test for a deadlock bug in Mutex::Fer().
00577 // The sequence of events that lead to the deadlock is:
00578 // 1. waiter1 blocks on cv in read mode (mu bits = 0).
00579 // 2. waiter2 blocks on mu in either mode (mu bits = kMuWait).
00580 // 3. main thread locks mu, sets cond1, unlocks mu (mu bits = kMuWait).
00581 // 4. main thread signals on cv and this eventually calls Mutex::Fer().
00582 // Currently Fer wakes waiter1 since mu bits = kMuWait (mutex is unlocked).
00583 // Before the bug fix Fer neither woke waiter1 nor queued it on mutex,
00584 // which resulted in deadlock.
00585 TEST_P(CondVarWaitDeadlock, Test) {
00586   auto waiter1 = CreatePool(1);
00587   auto waiter2 = CreatePool(1);
00588   waiter1->Schedule([this] { this->Waiter1(); });
00589   waiter2->Schedule([this] { this->Waiter2(); });
00590 
00591   // Wait while threads block (best-effort is fine).
00592   absl::SleepFor(absl::Milliseconds(100));
00593 
00594   // Wake condwaiter.
00595   mu.Lock();
00596   cond1 = true;
00597   if (signal_unlocked) {
00598     mu.Unlock();
00599     cv.Signal();
00600   } else {
00601     cv.Signal();
00602     mu.Unlock();
00603   }
00604   waiter1.reset();  // "join" waiter1
00605 
00606   // Wake waiter.
00607   mu.Lock();
00608   cond2 = true;
00609   mu.Unlock();
00610   waiter2.reset();  // "join" waiter2
00611 }
00612 
00613 INSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
00614                          ::testing::Range(0, 8),
00615                          ::testing::PrintToStringParamName());
00616 
00617 // --------------------------------------------------------
00618 // Test for fix of bug in DequeueAllWakeable()
00619 // Bug was that if there was more than one waiting reader
00620 // and all should be woken, the most recently blocked one
00621 // would not be.
00622 
00623 struct DequeueAllWakeableBugStruct {
00624   absl::Mutex mu;
00625   absl::Mutex mu2;       // protects all fields below
00626   int unfinished_count;  // count of unfinished readers; under mu2
00627   bool done1;            // unfinished_count == 0; under mu2
00628   int finished_count;    // count of finished readers, under mu2
00629   bool done2;            // finished_count == 0; under mu2
00630 };
00631 
00632 // Test for regression of a bug in loop of DequeueAllWakeable()
00633 static void AcquireAsReader(DequeueAllWakeableBugStruct *x) {
00634   x->mu.ReaderLock();
00635   x->mu2.Lock();
00636   x->unfinished_count--;
00637   x->done1 = (x->unfinished_count == 0);
00638   x->mu2.Unlock();
00639   // make sure that both readers acquired mu before we release it.
00640   absl::SleepFor(absl::Seconds(2));
00641   x->mu.ReaderUnlock();
00642 
00643   x->mu2.Lock();
00644   x->finished_count--;
00645   x->done2 = (x->finished_count == 0);
00646   x->mu2.Unlock();
00647 }
00648 
00649 // Test for regression of a bug in loop of DequeueAllWakeable()
00650 TEST(Mutex, MutexReaderWakeupBug) {
00651   auto tp = CreateDefaultPool();
00652 
00653   DequeueAllWakeableBugStruct x;
00654   x.unfinished_count = 2;
00655   x.done1 = false;
00656   x.finished_count = 2;
00657   x.done2 = false;
00658   x.mu.Lock();  // acquire mu exclusively
00659   // queue two thread that will block on reader locks on x.mu
00660   tp->Schedule(std::bind(&AcquireAsReader, &x));
00661   tp->Schedule(std::bind(&AcquireAsReader, &x));
00662   absl::SleepFor(absl::Seconds(1));  // give time for reader threads to block
00663   x.mu.Unlock();                     // wake them up
00664 
00665   // both readers should finish promptly
00666   EXPECT_TRUE(
00667       x.mu2.LockWhenWithTimeout(absl::Condition(&x.done1), absl::Seconds(10)));
00668   x.mu2.Unlock();
00669 
00670   EXPECT_TRUE(
00671       x.mu2.LockWhenWithTimeout(absl::Condition(&x.done2), absl::Seconds(10)));
00672   x.mu2.Unlock();
00673 }
00674 
00675 struct LockWhenTestStruct {
00676   absl::Mutex mu1;
00677   bool cond = false;
00678 
00679   absl::Mutex mu2;
00680   bool waiting = false;
00681 };
00682 
00683 static bool LockWhenTestIsCond(LockWhenTestStruct* s) {
00684   s->mu2.Lock();
00685   s->waiting = true;
00686   s->mu2.Unlock();
00687   return s->cond;
00688 }
00689 
00690 static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) {
00691   s->mu1.LockWhen(absl::Condition(&LockWhenTestIsCond, s));
00692   s->mu1.Unlock();
00693 }
00694 
00695 TEST(Mutex, LockWhen) {
00696   LockWhenTestStruct s;
00697 
00698   std::thread t(LockWhenTestWaitForIsCond, &s);
00699   s.mu2.LockWhen(absl::Condition(&s.waiting));
00700   s.mu2.Unlock();
00701 
00702   s.mu1.Lock();
00703   s.cond = true;
00704   s.mu1.Unlock();
00705 
00706   t.join();
00707 }
00708 
00709 // --------------------------------------------------------
00710 // The following test requires Mutex::ReaderLock to be a real shared
00711 // lock, which is not the case in all builds.
00712 #if !defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
00713 
00714 // Test for fix of bug in UnlockSlow() that incorrectly decremented the reader
00715 // count when putting a thread to sleep waiting for a false condition when the
00716 // lock was not held.
00717 
00718 // For this bug to strike, we make a thread wait on a free mutex with no
00719 // waiters by causing its wakeup condition to be false.   Then the
00720 // next two acquirers must be readers.   The bug causes the lock
00721 // to be released when one reader unlocks, rather than both.
00722 
00723 struct ReaderDecrementBugStruct {
00724   bool cond;  // to delay first thread (under mu)
00725   int done;   // reference count (under mu)
00726   absl::Mutex mu;
00727 
00728   bool waiting_on_cond;   // under mu2
00729   bool have_reader_lock;  // under mu2
00730   bool complete;          // under mu2
00731   absl::Mutex mu2;        // > mu
00732 };
00733 
00734 // L >= mu, L < mu_waiting_on_cond
00735 static bool IsCond(void *v) {
00736   ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);
00737   x->mu2.Lock();
00738   x->waiting_on_cond = true;
00739   x->mu2.Unlock();
00740   return x->cond;
00741 }
00742 
00743 // L >= mu
00744 static bool AllDone(void *v) {
00745   ReaderDecrementBugStruct *x = reinterpret_cast<ReaderDecrementBugStruct *>(v);
00746   return x->done == 0;
00747 }
00748 
00749 // L={}
00750 static void WaitForCond(ReaderDecrementBugStruct *x) {
00751   absl::Mutex dummy;
00752   absl::MutexLock l(&dummy);
00753   x->mu.LockWhen(absl::Condition(&IsCond, x));
00754   x->done--;
00755   x->mu.Unlock();
00756 }
00757 
00758 // L={}
00759 static void GetReadLock(ReaderDecrementBugStruct *x) {
00760   x->mu.ReaderLock();
00761   x->mu2.Lock();
00762   x->have_reader_lock = true;
00763   x->mu2.Await(absl::Condition(&x->complete));
00764   x->mu2.Unlock();
00765   x->mu.ReaderUnlock();
00766   x->mu.Lock();
00767   x->done--;
00768   x->mu.Unlock();
00769 }
00770 
00771 // Test for reader counter being decremented incorrectly by waiter
00772 // with false condition.
00773 TEST(Mutex, MutexReaderDecrementBug) NO_THREAD_SAFETY_ANALYSIS {
00774   ReaderDecrementBugStruct x;
00775   x.cond = false;
00776   x.waiting_on_cond = false;
00777   x.have_reader_lock = false;
00778   x.complete = false;
00779   x.done = 2;  // initial ref count
00780 
00781   // Run WaitForCond() and wait for it to sleep
00782   std::thread thread1(WaitForCond, &x);
00783   x.mu2.LockWhen(absl::Condition(&x.waiting_on_cond));
00784   x.mu2.Unlock();
00785 
00786   // Run GetReadLock(), and wait for it to get the read lock
00787   std::thread thread2(GetReadLock, &x);
00788   x.mu2.LockWhen(absl::Condition(&x.have_reader_lock));
00789   x.mu2.Unlock();
00790 
00791   // Get the reader lock ourselves, and release it.
00792   x.mu.ReaderLock();
00793   x.mu.ReaderUnlock();
00794 
00795   // The lock should be held in read mode by GetReadLock().
00796   // If we have the bug, the lock will be free.
00797   x.mu.AssertReaderHeld();
00798 
00799   // Wake up all the threads.
00800   x.mu2.Lock();
00801   x.complete = true;
00802   x.mu2.Unlock();
00803 
00804   // TODO(delesley): turn on analysis once lock upgrading is supported.
00805   // (This call upgrades the lock from shared to exclusive.)
00806   x.mu.Lock();
00807   x.cond = true;
00808   x.mu.Await(absl::Condition(&AllDone, &x));
00809   x.mu.Unlock();
00810 
00811   thread1.join();
00812   thread2.join();
00813 }
00814 #endif  // !ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE
00815 
00816 // Test that we correctly handle the situation when a lock is
00817 // held and then destroyed (w/o unlocking).
00818 #ifdef THREAD_SANITIZER
00819 // TSAN reports errors when locked Mutexes are destroyed.
00820 TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
00821 #else
00822 TEST(Mutex, LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
00823 #endif
00824   for (int i = 0; i != 10; i++) {
00825     // Create, lock and destroy 10 locks.
00826     const int kNumLocks = 10;
00827     auto mu = absl::make_unique<absl::Mutex[]>(kNumLocks);
00828     for (int j = 0; j != kNumLocks; j++) {
00829       if ((j % 2) == 0) {
00830         mu[j].WriterLock();
00831       } else {
00832         mu[j].ReaderLock();
00833       }
00834     }
00835   }
00836 }
00837 
00838 // --------------------------------------------------------
00839 // Test for bug with pattern of readers using a condvar.  The bug was that if a
00840 // reader went to sleep on a condition variable while one or more other readers
00841 // held the lock, but there were no waiters, the reader count (held in the
00842 // mutex word) would be lost.  (This is because Enqueue() had at one time
00843 // always placed the thread on the Mutex queue.  Later (CL 4075610), to
00844 // tolerate re-entry into Mutex from a Condition predicate, Enqueue() was
00845 // changed so that it could also place a thread on a condition-variable.  This
00846 // introduced the case where Enqueue() returned with an empty queue, and this
00847 // case was handled incorrectly in one place.)
00848 
00849 static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,
00850                                      int *running) {
00851   std::random_device dev;
00852   std::mt19937 gen(dev());
00853   std::uniform_int_distribution<int> random_millis(0, 15);
00854   mu->ReaderLock();
00855   while (*running == 3) {
00856     absl::SleepFor(absl::Milliseconds(random_millis(gen)));
00857     cv->WaitWithTimeout(mu, absl::Milliseconds(random_millis(gen)));
00858   }
00859   mu->ReaderUnlock();
00860   mu->Lock();
00861   (*running)--;
00862   mu->Unlock();
00863 }
00864 
00865 struct True {
00866   template <class... Args>
00867   bool operator()(Args...) const {
00868     return true;
00869   }
00870 };
00871 
00872 struct DerivedTrue : True {};
00873 
00874 TEST(Mutex, FunctorCondition) {
00875   {  // Variadic
00876     True f;
00877     EXPECT_TRUE(absl::Condition(&f).Eval());
00878   }
00879 
00880   {  // Inherited
00881     DerivedTrue g;
00882     EXPECT_TRUE(absl::Condition(&g).Eval());
00883   }
00884 
00885   {  // lambda
00886     int value = 3;
00887     auto is_zero = [&value] { return value == 0; };
00888     absl::Condition c(&is_zero);
00889     EXPECT_FALSE(c.Eval());
00890     value = 0;
00891     EXPECT_TRUE(c.Eval());
00892   }
00893 
00894   {  // bind
00895     int value = 0;
00896     auto is_positive = std::bind(std::less<int>(), 0, std::cref(value));
00897     absl::Condition c(&is_positive);
00898     EXPECT_FALSE(c.Eval());
00899     value = 1;
00900     EXPECT_TRUE(c.Eval());
00901   }
00902 
00903   {  // std::function
00904     int value = 3;
00905     std::function<bool()> is_zero = [&value] { return value == 0; };
00906     absl::Condition c(&is_zero);
00907     EXPECT_FALSE(c.Eval());
00908     value = 0;
00909     EXPECT_TRUE(c.Eval());
00910   }
00911 }
00912 
00913 static bool IntIsZero(int *x) { return *x == 0; }
00914 
00915 // Test for reader waiting condition variable when there are other readers
00916 // but no waiters.
00917 TEST(Mutex, TestReaderOnCondVar) {
00918   auto tp = CreateDefaultPool();
00919   absl::Mutex mu;
00920   absl::CondVar cv;
00921   int running = 3;
00922   tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));
00923   tp->Schedule(std::bind(&ReaderForReaderOnCondVar, &mu, &cv, &running));
00924   absl::SleepFor(absl::Seconds(2));
00925   mu.Lock();
00926   running--;
00927   mu.Await(absl::Condition(&IntIsZero, &running));
00928   mu.Unlock();
00929 }
00930 
00931 // --------------------------------------------------------
00932 struct AcquireFromConditionStruct {
00933   absl::Mutex mu0;   // protects value, done
00934   int value;         // times condition function is called; under mu0,
00935   bool done;         // done with test?  under mu0
00936   absl::Mutex mu1;   // used to attempt to mess up state of mu0
00937   absl::CondVar cv;  // so the condition function can be invoked from
00938                      // CondVar::Wait().
00939 };
00940 
00941 static bool ConditionWithAcquire(AcquireFromConditionStruct *x) {
00942   x->value++;  // count times this function is called
00943 
00944   if (x->value == 2 || x->value == 3) {
00945     // On the second and third invocation of this function, sleep for 100ms,
00946     // but with the side-effect of altering the state of a Mutex other than
00947     // than one for which this is a condition.  The spec now explicitly allows
00948     // this side effect; previously it did not.  it was illegal.
00949     bool always_false = false;
00950     x->mu1.LockWhenWithTimeout(absl::Condition(&always_false),
00951                                absl::Milliseconds(100));
00952     x->mu1.Unlock();
00953   }
00954   ABSL_RAW_CHECK(x->value < 4, "should not be invoked a fourth time");
00955 
00956   // We arrange for the condition to return true on only the 2nd and 3rd calls.
00957   return x->value == 2 || x->value == 3;
00958 }
00959 
00960 static void WaitForCond2(AcquireFromConditionStruct *x) {
00961   // wait for cond0 to become true
00962   x->mu0.LockWhen(absl::Condition(&ConditionWithAcquire, x));
00963   x->done = true;
00964   x->mu0.Unlock();
00965 }
00966 
00967 // Test for Condition whose function acquires other Mutexes
00968 TEST(Mutex, AcquireFromCondition) {
00969   auto tp = CreateDefaultPool();
00970 
00971   AcquireFromConditionStruct x;
00972   x.value = 0;
00973   x.done = false;
00974   tp->Schedule(
00975       std::bind(&WaitForCond2, &x));  // run WaitForCond2() in a thread T
00976   // T will hang because the first invocation of ConditionWithAcquire() will
00977   // return false.
00978   absl::SleepFor(absl::Milliseconds(500));  // allow T time to hang
00979 
00980   x.mu0.Lock();
00981   x.cv.WaitWithTimeout(&x.mu0, absl::Milliseconds(500));  // wake T
00982   // T will be woken because the Wait() will call ConditionWithAcquire()
00983   // for the second time, and it will return true.
00984 
00985   x.mu0.Unlock();
00986 
00987   // T will then acquire the lock and recheck its own condition.
00988   // It will find the condition true, as this is the third invocation,
00989   // but the use of another Mutex by the calling function will
00990   // cause the old mutex implementation to think that the outer
00991   // LockWhen() has timed out because the inner LockWhenWithTimeout() did.
00992   // T will then check the condition a fourth time because it finds a
00993   // timeout occurred.  This should not happen in the new
00994   // implementation that allows the Condition function to use Mutexes.
00995 
00996   // It should also succeed, even though the Condition function
00997   // is being invoked from CondVar::Wait, and thus this thread
00998   // is conceptually waiting both on the condition variable, and on mu2.
00999 
01000   x.mu0.LockWhen(absl::Condition(&x.done));
01001   x.mu0.Unlock();
01002 }
01003 
01004 // The deadlock detector is not part of non-prod builds, so do not test it.
01005 #if !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
01006 
01007 TEST(Mutex, DeadlockDetector) {
01008   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
01009 
01010   // check that we can call ForgetDeadlockInfo() on a lock with the lock held
01011   absl::Mutex m1;
01012   absl::Mutex m2;
01013   absl::Mutex m3;
01014   absl::Mutex m4;
01015 
01016   m1.Lock();  // m1 gets ID1
01017   m2.Lock();  // m2 gets ID2
01018   m3.Lock();  // m3 gets ID3
01019   m3.Unlock();
01020   m2.Unlock();
01021   // m1 still held
01022   m1.ForgetDeadlockInfo();  // m1 loses ID
01023   m2.Lock();                // m2 gets ID2
01024   m3.Lock();                // m3 gets ID3
01025   m4.Lock();                // m4 gets ID4
01026   m3.Unlock();
01027   m2.Unlock();
01028   m4.Unlock();
01029   m1.Unlock();
01030 }
01031 
01032 // Bazel has a test "warning" file that programs can write to if the
01033 // test should pass with a warning.  This class disables the warning
01034 // file until it goes out of scope.
01035 class ScopedDisableBazelTestWarnings {
01036  public:
01037   ScopedDisableBazelTestWarnings() {
01038 #ifdef WIN32
01039     char file[MAX_PATH];
01040     if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) {
01041       warnings_output_file_ = file;
01042       SetEnvironmentVariableA(kVarName, nullptr);
01043     }
01044 #else
01045     const char *file = getenv(kVarName);
01046     if (file != nullptr) {
01047       warnings_output_file_ = file;
01048       unsetenv(kVarName);
01049     }
01050 #endif
01051   }
01052 
01053   ~ScopedDisableBazelTestWarnings() {
01054     if (!warnings_output_file_.empty()) {
01055 #ifdef WIN32
01056       SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());
01057 #else
01058       setenv(kVarName, warnings_output_file_.c_str(), 0);
01059 #endif
01060     }
01061   }
01062 
01063  private:
01064   static const char kVarName[];
01065   std::string warnings_output_file_;
01066 };
01067 const char ScopedDisableBazelTestWarnings::kVarName[] =
01068     "TEST_WARNINGS_OUTPUT_FILE";
01069 
01070 #ifdef THREAD_SANITIZER
01071 // This test intentionally creates deadlocks to test the deadlock detector.
01072 TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) {
01073 #else
01074 TEST(Mutex, DeadlockDetectorBazelWarning) {
01075 #endif
01076   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport);
01077 
01078   // Cause deadlock detection to detect something, if it's
01079   // compiled in and enabled.  But turn off the bazel warning.
01080   ScopedDisableBazelTestWarnings disable_bazel_test_warnings;
01081 
01082   absl::Mutex mu0;
01083   absl::Mutex mu1;
01084   bool got_mu0 = mu0.TryLock();
01085   mu1.Lock();  // acquire mu1 while holding mu0
01086   if (got_mu0) {
01087     mu0.Unlock();
01088   }
01089   if (mu0.TryLock()) {  // try lock shouldn't cause deadlock detector to fire
01090     mu0.Unlock();
01091   }
01092   mu0.Lock();  // acquire mu0 while holding mu1; should get one deadlock
01093                // report here
01094   mu0.Unlock();
01095   mu1.Unlock();
01096 
01097   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
01098 }
01099 
01100 // This test is tagged with NO_THREAD_SAFETY_ANALYSIS because the
01101 // annotation-based static thread-safety analysis is not currently
01102 // predicate-aware and cannot tell if the two for-loops that acquire and
01103 // release the locks have the same predicates.
01104 TEST(Mutex, DeadlockDetectorStessTest) NO_THREAD_SAFETY_ANALYSIS {
01105   // Stress test: Here we create a large number of locks and use all of them.
01106   // If a deadlock detector keeps a full graph of lock acquisition order,
01107   // it will likely be too slow for this test to pass.
01108   const int n_locks = 1 << 17;
01109   auto array_of_locks = absl::make_unique<absl::Mutex[]>(n_locks);
01110   for (int i = 0; i < n_locks; i++) {
01111     int end = std::min(n_locks, i + 5);
01112     // acquire and then release locks i, i+1, ..., i+4
01113     for (int j = i; j < end; j++) {
01114       array_of_locks[j].Lock();
01115     }
01116     for (int j = i; j < end; j++) {
01117       array_of_locks[j].Unlock();
01118     }
01119   }
01120 }
01121 
01122 #ifdef THREAD_SANITIZER
01123 // TSAN reports errors when locked Mutexes are destroyed.
01124 TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
01125 #else
01126 TEST(Mutex, DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
01127 #endif
01128   // Test a scenario where a cached deadlock graph node id in the
01129   // list of held locks is not invalidated when the corresponding
01130   // mutex is deleted.
01131   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
01132   // Mutex that will be destroyed while being held
01133   absl::Mutex *a = new absl::Mutex;
01134   // Other mutexes needed by test
01135   absl::Mutex b, c;
01136 
01137   // Hold mutex.
01138   a->Lock();
01139 
01140   // Force deadlock id assignment by acquiring another lock.
01141   b.Lock();
01142   b.Unlock();
01143 
01144   // Delete the mutex. The Mutex destructor tries to remove held locks,
01145   // but the attempt isn't foolproof.  It can fail if:
01146   //   (a) Deadlock detection is currently disabled.
01147   //   (b) The destruction is from another thread.
01148   // We exploit (a) by temporarily disabling deadlock detection.
01149   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore);
01150   delete a;
01151   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
01152 
01153   // Now acquire another lock which will force a deadlock id assignment.
01154   // We should end up getting assigned the same deadlock id that was
01155   // freed up when "a" was deleted, which will cause a spurious deadlock
01156   // report if the held lock entry for "a" was not invalidated.
01157   c.Lock();
01158   c.Unlock();
01159 }
01160 #endif  // !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
01161 
01162 // --------------------------------------------------------
01163 // Test for timeouts/deadlines on condition waits that are specified using
01164 // absl::Duration and absl::Time.  For each waiting function we test with
01165 // a timeout/deadline that has already expired/passed, one that is infinite
01166 // and so never expires/passes, and one that will expire/pass in the near
01167 // future.
01168 
01169 static absl::Duration TimeoutTestAllowedSchedulingDelay() {
01170   // Note: we use a function here because Microsoft Visual Studio fails to
01171   // properly initialize constexpr static absl::Duration variables.
01172   return absl::Milliseconds(150);
01173 }
01174 
01175 // Returns true if `actual_delay` is close enough to `expected_delay` to pass
01176 // the timeouts/deadlines test.  Otherwise, logs warnings and returns false.
01177 ABSL_MUST_USE_RESULT
01178 static bool DelayIsWithinBounds(absl::Duration expected_delay,
01179                                 absl::Duration actual_delay) {
01180   bool pass = true;
01181   // Do not allow the observed delay to be less than expected.  This may occur
01182   // in practice due to clock skew or when the synchronization primitives use a
01183   // different clock than absl::Now(), but these cases should be handled by the
01184   // the retry mechanism in each TimeoutTest.
01185   if (actual_delay < expected_delay) {
01186     ABSL_RAW_LOG(WARNING,
01187                  "Actual delay %s was too short, expected %s (difference %s)",
01188                  absl::FormatDuration(actual_delay).c_str(),
01189                  absl::FormatDuration(expected_delay).c_str(),
01190                  absl::FormatDuration(actual_delay - expected_delay).c_str());
01191     pass = false;
01192   }
01193   // If the expected delay is <= zero then allow a small error tolerance, since
01194   // we do not expect context switches to occur during test execution.
01195   // Otherwise, thread scheduling delays may be substantial in rare cases, so
01196   // tolerate up to kTimeoutTestAllowedSchedulingDelay of error.
01197   absl::Duration tolerance = expected_delay <= absl::ZeroDuration()
01198                                  ? absl::Milliseconds(10)
01199                                  : TimeoutTestAllowedSchedulingDelay();
01200   if (actual_delay > expected_delay + tolerance) {
01201     ABSL_RAW_LOG(WARNING,
01202                  "Actual delay %s was too long, expected %s (difference %s)",
01203                  absl::FormatDuration(actual_delay).c_str(),
01204                  absl::FormatDuration(expected_delay).c_str(),
01205                  absl::FormatDuration(actual_delay - expected_delay).c_str());
01206     pass = false;
01207   }
01208   return pass;
01209 }
01210 
01211 // Parameters for TimeoutTest, below.
01212 struct TimeoutTestParam {
01213   // The file and line number (used for logging purposes only).
01214   const char *from_file;
01215   int from_line;
01216 
01217   // Should the absolute deadline API based on absl::Time be tested?  If false,
01218   // the relative deadline API based on absl::Duration is tested.
01219   bool use_absolute_deadline;
01220 
01221   // The deadline/timeout used when calling the API being tested
01222   // (e.g. Mutex::LockWhenWithDeadline).
01223   absl::Duration wait_timeout;
01224 
01225   // The delay before the condition will be set true by the test code.  If zero
01226   // or negative, the condition is set true immediately (before calling the API
01227   // being tested).  Otherwise, if infinite, the condition is never set true.
01228   // Otherwise a closure is scheduled for the future that sets the condition
01229   // true.
01230   absl::Duration satisfy_condition_delay;
01231 
01232   // The expected result of the condition after the call to the API being
01233   // tested. Generally `true` means the condition was true when the API returns,
01234   // `false` indicates an expected timeout.
01235   bool expected_result;
01236 
01237   // The expected delay before the API under test returns.  This is inherently
01238   // flaky, so some slop is allowed (see `DelayIsWithinBounds` above), and the
01239   // test keeps trying indefinitely until this constraint passes.
01240   absl::Duration expected_delay;
01241 };
01242 
01243 // Print a `TimeoutTestParam` to a debug log.
01244 std::ostream &operator<<(std::ostream &os, const TimeoutTestParam &param) {
01245   return os << "from: " << param.from_file << ":" << param.from_line
01246             << " use_absolute_deadline: "
01247             << (param.use_absolute_deadline ? "true" : "false")
01248             << " wait_timeout: " << param.wait_timeout
01249             << " satisfy_condition_delay: " << param.satisfy_condition_delay
01250             << " expected_result: "
01251             << (param.expected_result ? "true" : "false")
01252             << " expected_delay: " << param.expected_delay;
01253 }
01254 
01255 std::string FormatString(const TimeoutTestParam &param) {
01256   std::ostringstream os;
01257   os << param;
01258   return os.str();
01259 }
01260 
01261 // Like `thread::Executor::ScheduleAt` except:
01262 // a) Delays zero or negative are executed immediately in the current thread.
01263 // b) Infinite delays are never scheduled.
01264 // c) Calls this test's `ScheduleAt` helper instead of using `pool` directly.
01265 static void RunAfterDelay(absl::Duration delay,
01266                           absl::synchronization_internal::ThreadPool *pool,
01267                           const std::function<void()> &callback) {
01268   if (delay <= absl::ZeroDuration()) {
01269     callback();  // immediate
01270   } else if (delay != absl::InfiniteDuration()) {
01271     ScheduleAfter(pool, delay, callback);
01272   }
01273 }
01274 
01275 class TimeoutTest : public ::testing::Test,
01276                     public ::testing::WithParamInterface<TimeoutTestParam> {};
01277 
01278 std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() {
01279   // The `finite` delay is a finite, relatively short, delay.  We make it larger
01280   // than our allowed scheduling delay (slop factor) to avoid confusion when
01281   // diagnosing test failures.  The other constants here have clear meanings.
01282   const absl::Duration finite = 3 * TimeoutTestAllowedSchedulingDelay();
01283   const absl::Duration never = absl::InfiniteDuration();
01284   const absl::Duration negative = -absl::InfiniteDuration();
01285   const absl::Duration immediate = absl::ZeroDuration();
01286 
01287   // Every test case is run twice; once using the absolute deadline API and once
01288   // using the relative timeout API.
01289   std::vector<TimeoutTestParam> values;
01290   for (bool use_absolute_deadline : {false, true}) {
01291     // Tests with a negative timeout (deadline in the past), which should
01292     // immediately return current state of the condition.
01293 
01294     // The condition is already true:
01295     values.push_back(TimeoutTestParam{
01296         __FILE__, __LINE__, use_absolute_deadline,
01297         negative,   // wait_timeout
01298         immediate,  // satisfy_condition_delay
01299         true,       // expected_result
01300         immediate,  // expected_delay
01301     });
01302 
01303     // The condition becomes true, but the timeout has already expired:
01304     values.push_back(TimeoutTestParam{
01305         __FILE__, __LINE__, use_absolute_deadline,
01306         negative,  // wait_timeout
01307         finite,    // satisfy_condition_delay
01308         false,     // expected_result
01309         immediate  // expected_delay
01310     });
01311 
01312     // The condition never becomes true:
01313     values.push_back(TimeoutTestParam{
01314         __FILE__, __LINE__, use_absolute_deadline,
01315         negative,  // wait_timeout
01316         never,     // satisfy_condition_delay
01317         false,     // expected_result
01318         immediate  // expected_delay
01319     });
01320 
01321     // Tests with an infinite timeout (deadline in the infinite future), which
01322     // should only return when the condition becomes true.
01323 
01324     // The condition is already true:
01325     values.push_back(TimeoutTestParam{
01326         __FILE__, __LINE__, use_absolute_deadline,
01327         never,      // wait_timeout
01328         immediate,  // satisfy_condition_delay
01329         true,       // expected_result
01330         immediate   // expected_delay
01331     });
01332 
01333     // The condition becomes true before the (infinite) expiry:
01334     values.push_back(TimeoutTestParam{
01335         __FILE__, __LINE__, use_absolute_deadline,
01336         never,   // wait_timeout
01337         finite,  // satisfy_condition_delay
01338         true,    // expected_result
01339         finite,  // expected_delay
01340     });
01341 
01342     // Tests with a (small) finite timeout (deadline soon), with the condition
01343     // becoming true both before and after its expiry.
01344 
01345     // The condition is already true:
01346     values.push_back(TimeoutTestParam{
01347         __FILE__, __LINE__, use_absolute_deadline,
01348         never,      // wait_timeout
01349         immediate,  // satisfy_condition_delay
01350         true,       // expected_result
01351         immediate   // expected_delay
01352     });
01353 
01354     // The condition becomes true before the expiry:
01355     values.push_back(TimeoutTestParam{
01356         __FILE__, __LINE__, use_absolute_deadline,
01357         finite * 2,  // wait_timeout
01358         finite,      // satisfy_condition_delay
01359         true,        // expected_result
01360         finite       // expected_delay
01361     });
01362 
01363     // The condition becomes true, but the timeout has already expired:
01364     values.push_back(TimeoutTestParam{
01365         __FILE__, __LINE__, use_absolute_deadline,
01366         finite,      // wait_timeout
01367         finite * 2,  // satisfy_condition_delay
01368         false,       // expected_result
01369         finite       // expected_delay
01370     });
01371 
01372     // The condition never becomes true:
01373     values.push_back(TimeoutTestParam{
01374         __FILE__, __LINE__, use_absolute_deadline,
01375         finite,  // wait_timeout
01376         never,   // satisfy_condition_delay
01377         false,   // expected_result
01378         finite   // expected_delay
01379     });
01380   }
01381   return values;
01382 }
01383 
01384 // Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`.
01385 INSTANTIATE_TEST_SUITE_P(All, TimeoutTest,
01386                          testing::ValuesIn(MakeTimeoutTestParamValues()));
01387 
01388 TEST_P(TimeoutTest, Await) {
01389   const TimeoutTestParam params = GetParam();
01390   ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
01391 
01392   // Because this test asserts bounds on scheduling delays it is flaky.  To
01393   // compensate it loops forever until it passes.  Failures express as test
01394   // timeouts, in which case the test log can be used to diagnose the issue.
01395   for (int attempt = 1;; ++attempt) {
01396     ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
01397 
01398     absl::Mutex mu;
01399     bool value = false;  // condition value (under mu)
01400 
01401     std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
01402         CreateDefaultPool();
01403     RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
01404       absl::MutexLock l(&mu);
01405       value = true;
01406     });
01407 
01408     absl::MutexLock lock(&mu);
01409     absl::Time start_time = absl::Now();
01410     absl::Condition cond(&value);
01411     bool result =
01412         params.use_absolute_deadline
01413             ? mu.AwaitWithDeadline(cond, start_time + params.wait_timeout)
01414             : mu.AwaitWithTimeout(cond, params.wait_timeout);
01415     if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
01416       EXPECT_EQ(params.expected_result, result);
01417       break;
01418     }
01419   }
01420 }
01421 
01422 TEST_P(TimeoutTest, LockWhen) {
01423   const TimeoutTestParam params = GetParam();
01424   ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
01425 
01426   // Because this test asserts bounds on scheduling delays it is flaky.  To
01427   // compensate it loops forever until it passes.  Failures express as test
01428   // timeouts, in which case the test log can be used to diagnose the issue.
01429   for (int attempt = 1;; ++attempt) {
01430     ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
01431 
01432     absl::Mutex mu;
01433     bool value = false;  // condition value (under mu)
01434 
01435     std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
01436         CreateDefaultPool();
01437     RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
01438       absl::MutexLock l(&mu);
01439       value = true;
01440     });
01441 
01442     absl::Time start_time = absl::Now();
01443     absl::Condition cond(&value);
01444     bool result =
01445         params.use_absolute_deadline
01446             ? mu.LockWhenWithDeadline(cond, start_time + params.wait_timeout)
01447             : mu.LockWhenWithTimeout(cond, params.wait_timeout);
01448     mu.Unlock();
01449 
01450     if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
01451       EXPECT_EQ(params.expected_result, result);
01452       break;
01453     }
01454   }
01455 }
01456 
01457 TEST_P(TimeoutTest, ReaderLockWhen) {
01458   const TimeoutTestParam params = GetParam();
01459   ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
01460 
01461   // Because this test asserts bounds on scheduling delays it is flaky.  To
01462   // compensate it loops forever until it passes.  Failures express as test
01463   // timeouts, in which case the test log can be used to diagnose the issue.
01464   for (int attempt = 0;; ++attempt) {
01465     ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
01466 
01467     absl::Mutex mu;
01468     bool value = false;  // condition value (under mu)
01469 
01470     std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
01471         CreateDefaultPool();
01472     RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
01473       absl::MutexLock l(&mu);
01474       value = true;
01475     });
01476 
01477     absl::Time start_time = absl::Now();
01478     bool result =
01479         params.use_absolute_deadline
01480             ? mu.ReaderLockWhenWithDeadline(absl::Condition(&value),
01481                                             start_time + params.wait_timeout)
01482             : mu.ReaderLockWhenWithTimeout(absl::Condition(&value),
01483                                            params.wait_timeout);
01484     mu.ReaderUnlock();
01485 
01486     if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
01487       EXPECT_EQ(params.expected_result, result);
01488       break;
01489     }
01490   }
01491 }
01492 
01493 TEST_P(TimeoutTest, Wait) {
01494   const TimeoutTestParam params = GetParam();
01495   ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
01496 
01497   // Because this test asserts bounds on scheduling delays it is flaky.  To
01498   // compensate it loops forever until it passes.  Failures express as test
01499   // timeouts, in which case the test log can be used to diagnose the issue.
01500   for (int attempt = 0;; ++attempt) {
01501     ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
01502 
01503     absl::Mutex mu;
01504     bool value = false;  // condition value (under mu)
01505     absl::CondVar cv;    // signals a change of `value`
01506 
01507     std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
01508         CreateDefaultPool();
01509     RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
01510       absl::MutexLock l(&mu);
01511       value = true;
01512       cv.Signal();
01513     });
01514 
01515     absl::MutexLock lock(&mu);
01516     absl::Time start_time = absl::Now();
01517     absl::Duration timeout = params.wait_timeout;
01518     absl::Time deadline = start_time + timeout;
01519     while (!value) {
01520       if (params.use_absolute_deadline ? cv.WaitWithDeadline(&mu, deadline)
01521                                        : cv.WaitWithTimeout(&mu, timeout)) {
01522         break;  // deadline/timeout exceeded
01523       }
01524       timeout = deadline - absl::Now();  // recompute
01525     }
01526     bool result = value;  // note: `mu` is still held
01527 
01528     if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
01529       EXPECT_EQ(params.expected_result, result);
01530       break;
01531     }
01532   }
01533 }
01534 
01535 TEST(Mutex, Logging) {
01536   // Allow user to look at logging output
01537   absl::Mutex logged_mutex;
01538   logged_mutex.EnableDebugLog("fido_mutex");
01539   absl::CondVar logged_cv;
01540   logged_cv.EnableDebugLog("rover_cv");
01541   logged_mutex.Lock();
01542   logged_cv.WaitWithTimeout(&logged_mutex, absl::Milliseconds(20));
01543   logged_mutex.Unlock();
01544   logged_mutex.ReaderLock();
01545   logged_mutex.ReaderUnlock();
01546   logged_mutex.Lock();
01547   logged_mutex.Unlock();
01548   logged_cv.Signal();
01549   logged_cv.SignalAll();
01550 }
01551 
01552 // --------------------------------------------------------
01553 
01554 // Generate the vector of thread counts for tests parameterized on thread count.
01555 static std::vector<int> AllThreadCountValues() {
01556   if (kExtendedTest) {
01557     return {2, 4, 8, 10, 16, 20, 24, 30, 32};
01558   }
01559   return {2, 4, 10};
01560 }
01561 
01562 // A test fixture parameterized by thread count.
01563 class MutexVariableThreadCountTest : public ::testing::TestWithParam<int> {};
01564 
01565 // Instantiate the above with AllThreadCountOptions().
01566 INSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest,
01567                          ::testing::ValuesIn(AllThreadCountValues()),
01568                          ::testing::PrintToStringParamName());
01569 
01570 // Reduces iterations by some factor for slow platforms
01571 // (determined empirically).
01572 static int ScaleIterations(int x) {
01573   // ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE is set in the implementation
01574   // of Mutex that uses either std::mutex or pthread_mutex_t. Use
01575   // these as keys to determine the slow implementation.
01576 #if defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
01577   return x / 10;
01578 #else
01579   return x;
01580 #endif
01581 }
01582 
01583 TEST_P(MutexVariableThreadCountTest, Mutex) {
01584   int threads = GetParam();
01585   int iterations = ScaleIterations(10000000) / threads;
01586   int operations = threads * iterations;
01587   EXPECT_EQ(RunTest(&TestMu, threads, iterations, operations), operations);
01588 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
01589   iterations = std::min(iterations, 10);
01590   operations = threads * iterations;
01591   EXPECT_EQ(RunTestWithInvariantDebugging(&TestMu, threads, iterations,
01592                                           operations, CheckSumG0G1),
01593             operations);
01594 #endif
01595 }
01596 
01597 TEST_P(MutexVariableThreadCountTest, Try) {
01598   int threads = GetParam();
01599   int iterations = 1000000 / threads;
01600   int operations = iterations * threads;
01601   EXPECT_EQ(RunTest(&TestTry, threads, iterations, operations), operations);
01602 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
01603   iterations = std::min(iterations, 10);
01604   operations = threads * iterations;
01605   EXPECT_EQ(RunTestWithInvariantDebugging(&TestTry, threads, iterations,
01606                                           operations, CheckSumG0G1),
01607             operations);
01608 #endif
01609 }
01610 
01611 TEST_P(MutexVariableThreadCountTest, R20ms) {
01612   int threads = GetParam();
01613   int iterations = 100;
01614   int operations = iterations * threads;
01615   EXPECT_EQ(RunTest(&TestR20ms, threads, iterations, operations), 0);
01616 }
01617 
01618 TEST_P(MutexVariableThreadCountTest, RW) {
01619   int threads = GetParam();
01620   int iterations = ScaleIterations(20000000) / threads;
01621   int operations = iterations * threads;
01622   EXPECT_EQ(RunTest(&TestRW, threads, iterations, operations), operations / 2);
01623 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
01624   iterations = std::min(iterations, 10);
01625   operations = threads * iterations;
01626   EXPECT_EQ(RunTestWithInvariantDebugging(&TestRW, threads, iterations,
01627                                           operations, CheckSumG0G1),
01628             operations / 2);
01629 #endif
01630 }
01631 
01632 TEST_P(MutexVariableThreadCountTest, Await) {
01633   int threads = GetParam();
01634   int iterations = ScaleIterations(500000);
01635   int operations = iterations;
01636   EXPECT_EQ(RunTest(&TestAwait, threads, iterations, operations), operations);
01637 }
01638 
01639 TEST_P(MutexVariableThreadCountTest, SignalAll) {
01640   int threads = GetParam();
01641   int iterations = 200000 / threads;
01642   int operations = iterations;
01643   EXPECT_EQ(RunTest(&TestSignalAll, threads, iterations, operations),
01644             operations);
01645 }
01646 
01647 TEST(Mutex, Signal) {
01648   int threads = 2;  // TestSignal must use two threads
01649   int iterations = 200000;
01650   int operations = iterations;
01651   EXPECT_EQ(RunTest(&TestSignal, threads, iterations, operations), operations);
01652 }
01653 
01654 TEST(Mutex, Timed) {
01655   int threads = 10;  // Use a fixed thread count of 10
01656   int iterations = 1000;
01657   int operations = iterations;
01658   EXPECT_EQ(RunTest(&TestCVTimeout, threads, iterations, operations),
01659             operations);
01660 }
01661 
01662 TEST(Mutex, CVTime) {
01663   int threads = 10;  // Use a fixed thread count of 10
01664   int iterations = 1;
01665   EXPECT_EQ(RunTest(&TestCVTime, threads, iterations, 1),
01666             threads * iterations);
01667 }
01668 
01669 TEST(Mutex, MuTime) {
01670   int threads = 10;  // Use a fixed thread count of 10
01671   int iterations = 1;
01672   EXPECT_EQ(RunTest(&TestMuTime, threads, iterations, 1), threads * iterations);
01673 }
01674 
01675 }  // namespace


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15