tor-browser

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

blocking_counter_test.cc (3952B)


      1 // Copyright 2017 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/blocking_counter.h"
     16 
     17 #include <thread>  // NOLINT(build/c++11)
     18 #include <tuple>
     19 #include <vector>
     20 
     21 #include "gtest/gtest.h"
     22 #include "absl/base/attributes.h"
     23 #include "absl/base/config.h"
     24 #include "absl/base/internal/tracing.h"
     25 #include "absl/time/clock.h"
     26 #include "absl/time/time.h"
     27 
     28 namespace absl {
     29 ABSL_NAMESPACE_BEGIN
     30 namespace {
     31 
     32 void PauseAndDecreaseCounter(BlockingCounter* counter, int* done) {
     33  absl::SleepFor(absl::Seconds(1));
     34  *done = 1;
     35  counter->DecrementCount();
     36 }
     37 
     38 TEST(BlockingCounterTest, BasicFunctionality) {
     39  // This test verifies that BlockingCounter functions correctly. Starts a
     40  // number of threads that just sleep for a second and decrement a counter.
     41 
     42  // Initialize the counter.
     43  const int num_workers = 10;
     44  BlockingCounter counter(num_workers);
     45 
     46  std::vector<std::thread> workers;
     47  std::vector<int> done(num_workers, 0);
     48 
     49  // Start a number of parallel tasks that will just wait for a seconds and
     50  // then decrement the count.
     51  workers.reserve(num_workers);
     52  for (int k = 0; k < num_workers; k++) {
     53    workers.emplace_back(
     54        [&counter, &done, k] { PauseAndDecreaseCounter(&counter, &done[k]); });
     55  }
     56 
     57  // Wait for the threads to have all finished.
     58  counter.Wait();
     59 
     60  // Check that all the workers have completed.
     61  for (int k = 0; k < num_workers; k++) {
     62    EXPECT_EQ(1, done[k]);
     63  }
     64 
     65  for (std::thread& w : workers) {
     66    w.join();
     67  }
     68 }
     69 
     70 TEST(BlockingCounterTest, WaitZeroInitialCount) {
     71  BlockingCounter counter(0);
     72  counter.Wait();
     73 }
     74 
     75 #if GTEST_HAS_DEATH_TEST
     76 TEST(BlockingCounterTest, WaitNegativeInitialCount) {
     77  EXPECT_DEATH(BlockingCounter counter(-1),
     78               "BlockingCounter initial_count negative");
     79 }
     80 #endif
     81 
     82 }  // namespace
     83 
     84 #if ABSL_HAVE_ATTRIBUTE_WEAK
     85 
     86 namespace base_internal {
     87 
     88 namespace {
     89 
     90 using TraceRecord = std::tuple<const void*, ObjectKind>;
     91 
     92 thread_local TraceRecord tls_signal;
     93 thread_local TraceRecord tls_wait;
     94 thread_local TraceRecord tls_continue;
     95 
     96 }  // namespace
     97 
     98 // Strong extern "C" implementation.
     99 extern "C" {
    100 
    101 void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
    102                                                   ObjectKind kind) {
    103  tls_wait = {object, kind};
    104 }
    105 
    106 void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
    107                                                       ObjectKind kind) {
    108  tls_continue = {object, kind};
    109 }
    110 
    111 void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
    112                                                     ObjectKind kind) {
    113  tls_signal = {object, kind};
    114 }
    115 
    116 }  // extern "C"
    117 
    118 TEST(BlockingCounterTest, TracesSignal) {
    119  BlockingCounter counter(2);
    120 
    121  tls_signal = {};
    122  counter.DecrementCount();
    123  EXPECT_EQ(tls_signal, TraceRecord(nullptr, ObjectKind::kUnknown));
    124 
    125  tls_signal = {};
    126  counter.DecrementCount();
    127  EXPECT_EQ(tls_signal, TraceRecord(&counter, ObjectKind::kBlockingCounter));
    128 }
    129 
    130 TEST(BlockingCounterTest, TracesWaitContinue) {
    131  BlockingCounter counter(1);
    132  counter.DecrementCount();
    133 
    134  tls_wait = {};
    135  tls_continue = {};
    136  counter.Wait();
    137  EXPECT_EQ(tls_wait, TraceRecord(&counter, ObjectKind::kBlockingCounter));
    138  EXPECT_EQ(tls_continue, TraceRecord(&counter, ObjectKind::kBlockingCounter));
    139 }
    140 
    141 }  // namespace base_internal
    142 
    143 #endif  // ABSL_HAVE_ATTRIBUTE_WEAK
    144 
    145 ABSL_NAMESPACE_END
    146 }  // namespace absl