tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

waiter_test.cc (6529B)


      1 // Copyright 2023 The Abseil Authors
      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 //     https://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 "absl/synchronization/internal/waiter.h"
     16 
     17 #include <ctime>
     18 #include <iostream>
     19 #include <ostream>
     20 
     21 #include "absl/base/config.h"
     22 #include "absl/random/random.h"
     23 #include "absl/synchronization/internal/create_thread_identity.h"
     24 #include "absl/synchronization/internal/futex_waiter.h"
     25 #include "absl/synchronization/internal/kernel_timeout.h"
     26 #include "absl/synchronization/internal/pthread_waiter.h"
     27 #include "absl/synchronization/internal/sem_waiter.h"
     28 #include "absl/synchronization/internal/stdcpp_waiter.h"
     29 #include "absl/synchronization/internal/thread_pool.h"
     30 #include "absl/synchronization/internal/win32_waiter.h"
     31 #include "absl/time/clock.h"
     32 #include "absl/time/time.h"
     33 #include "gtest/gtest.h"
     34 
     35 // Test go/btm support by randomizing the value of clock_gettime() for
     36 // CLOCK_MONOTONIC. This works by overriding a weak symbol in glibc.
     37 // We should be resistant to this randomization when !SupportsSteadyClock().
     38 #if defined(__GOOGLE_GRTE_VERSION__) &&      \
     39    !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
     40    !defined(ABSL_HAVE_MEMORY_SANITIZER) &&  \
     41    !defined(ABSL_HAVE_THREAD_SANITIZER)
     42 extern "C" int __clock_gettime(clockid_t c, struct timespec* ts);
     43 
     44 extern "C" int clock_gettime(clockid_t c, struct timespec* ts) {
     45  if (c == CLOCK_MONOTONIC &&
     46      !absl::synchronization_internal::KernelTimeout::SupportsSteadyClock()) {
     47    thread_local absl::BitGen gen;  // NOLINT
     48    ts->tv_sec = absl::Uniform(gen, 0, 1'000'000'000);
     49    ts->tv_nsec = absl::Uniform(gen, 0, 1'000'000'000);
     50    return 0;
     51  }
     52  return __clock_gettime(c, ts);
     53 }
     54 #endif
     55 
     56 namespace {
     57 
     58 TEST(Waiter, PrintPlatformImplementation) {
     59  // Allows us to verify that the platform is using the expected implementation.
     60  std::cout << absl::synchronization_internal::Waiter::kName << std::endl;
     61 }
     62 
     63 template <typename T>
     64 class WaiterTest : public ::testing::Test {
     65 public:
     66  // Waiter implementations assume that a ThreadIdentity has already been
     67  // created.
     68  WaiterTest() {
     69    absl::synchronization_internal::GetOrCreateCurrentThreadIdentity();
     70  }
     71 };
     72 
     73 TYPED_TEST_SUITE_P(WaiterTest);
     74 
     75 absl::Duration WithTolerance(absl::Duration d) { return d * 0.95; }
     76 
     77 TYPED_TEST_P(WaiterTest, WaitNoTimeout) {
     78  absl::synchronization_internal::ThreadPool tp(1);
     79  TypeParam waiter;
     80  tp.Schedule([&]() {
     81    // Include some `Poke()` calls to ensure they don't cause `waiter` to return
     82    // from `Wait()`.
     83    waiter.Poke();
     84    absl::SleepFor(absl::Seconds(1));
     85    waiter.Poke();
     86    absl::SleepFor(absl::Seconds(1));
     87    waiter.Post();
     88  });
     89  absl::Time start = absl::Now();
     90  EXPECT_TRUE(
     91      waiter.Wait(absl::synchronization_internal::KernelTimeout::Never()));
     92  absl::Duration waited = absl::Now() - start;
     93  EXPECT_GE(waited, WithTolerance(absl::Seconds(2)));
     94 }
     95 
     96 TYPED_TEST_P(WaiterTest, WaitDurationWoken) {
     97  absl::synchronization_internal::ThreadPool tp(1);
     98  TypeParam waiter;
     99  tp.Schedule([&]() {
    100    // Include some `Poke()` calls to ensure they don't cause `waiter` to return
    101    // from `Wait()`.
    102    waiter.Poke();
    103    absl::SleepFor(absl::Milliseconds(500));
    104    waiter.Post();
    105  });
    106  absl::Time start = absl::Now();
    107  EXPECT_TRUE(waiter.Wait(
    108      absl::synchronization_internal::KernelTimeout(absl::Seconds(10))));
    109  absl::Duration waited = absl::Now() - start;
    110  EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
    111 #ifndef _MSC_VER
    112  // Skip on MSVC due to flakiness.
    113  EXPECT_LT(waited, absl::Seconds(2));
    114 #endif
    115 }
    116 
    117 TYPED_TEST_P(WaiterTest, WaitTimeWoken) {
    118  absl::synchronization_internal::ThreadPool tp(1);
    119  TypeParam waiter;
    120  tp.Schedule([&]() {
    121    // Include some `Poke()` calls to ensure they don't cause `waiter` to return
    122    // from `Wait()`.
    123    waiter.Poke();
    124    absl::SleepFor(absl::Milliseconds(500));
    125    waiter.Post();
    126  });
    127  absl::Time start = absl::Now();
    128  EXPECT_TRUE(waiter.Wait(absl::synchronization_internal::KernelTimeout(
    129      start + absl::Seconds(10))));
    130  absl::Duration waited = absl::Now() - start;
    131  EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
    132  EXPECT_LT(waited, absl::Seconds(2));
    133 }
    134 
    135 TYPED_TEST_P(WaiterTest, WaitDurationReached) {
    136  TypeParam waiter;
    137  absl::Time start = absl::Now();
    138  EXPECT_FALSE(waiter.Wait(
    139      absl::synchronization_internal::KernelTimeout(absl::Milliseconds(500))));
    140  absl::Duration waited = absl::Now() - start;
    141  EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
    142  EXPECT_LT(waited, absl::Seconds(1));
    143 }
    144 
    145 TYPED_TEST_P(WaiterTest, WaitTimeReached) {
    146  TypeParam waiter;
    147  absl::Time start = absl::Now();
    148  EXPECT_FALSE(waiter.Wait(absl::synchronization_internal::KernelTimeout(
    149      start + absl::Milliseconds(500))));
    150  absl::Duration waited = absl::Now() - start;
    151  EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
    152  EXPECT_LT(waited, absl::Seconds(1));
    153 }
    154 
    155 REGISTER_TYPED_TEST_SUITE_P(WaiterTest,
    156                            WaitNoTimeout,
    157                            WaitDurationWoken,
    158                            WaitTimeWoken,
    159                            WaitDurationReached,
    160                            WaitTimeReached);
    161 
    162 #ifdef ABSL_INTERNAL_HAVE_FUTEX_WAITER
    163 INSTANTIATE_TYPED_TEST_SUITE_P(Futex, WaiterTest,
    164                               absl::synchronization_internal::FutexWaiter);
    165 #endif
    166 #ifdef ABSL_INTERNAL_HAVE_PTHREAD_WAITER
    167 INSTANTIATE_TYPED_TEST_SUITE_P(Pthread, WaiterTest,
    168                               absl::synchronization_internal::PthreadWaiter);
    169 #endif
    170 #ifdef ABSL_INTERNAL_HAVE_SEM_WAITER
    171 INSTANTIATE_TYPED_TEST_SUITE_P(Sem, WaiterTest,
    172                               absl::synchronization_internal::SemWaiter);
    173 #endif
    174 #ifdef ABSL_INTERNAL_HAVE_WIN32_WAITER
    175 INSTANTIATE_TYPED_TEST_SUITE_P(Win32, WaiterTest,
    176                               absl::synchronization_internal::Win32Waiter);
    177 #endif
    178 #ifdef ABSL_INTERNAL_HAVE_STDCPP_WAITER
    179 INSTANTIATE_TYPED_TEST_SUITE_P(Stdcpp, WaiterTest,
    180                               absl::synchronization_internal::StdcppWaiter);
    181 #endif
    182 
    183 }  // namespace