tor-browser

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

nonsecure_base_test.cc (7382B)


      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/random/internal/nonsecure_base.h"
     16 
     17 #include <algorithm>
     18 #include <cstddef>
     19 #include <cstdint>
     20 #include <iterator>
     21 #include <random>
     22 #include <thread>  // NOLINT
     23 #include <type_traits>
     24 #include <utility>
     25 #include <vector>
     26 
     27 #include "gtest/gtest.h"
     28 #include "absl/container/flat_hash_set.h"
     29 #include "absl/meta/type_traits.h"
     30 #include "absl/random/distributions.h"
     31 #include "absl/random/random.h"
     32 #include "absl/synchronization/mutex.h"
     33 
     34 namespace {
     35 
     36 using ExampleNonsecureURBG =
     37    absl::random_internal::NonsecureURBGBase<std::mt19937>;
     38 
     39 template <typename T>
     40 void Use(const T&) {}
     41 
     42 }  // namespace
     43 
     44 TEST(NonsecureURBGBase, DefaultConstructorIsValid) {
     45  ExampleNonsecureURBG urbg;
     46 }
     47 
     48 // Ensure that the recommended template-instantiations are valid.
     49 TEST(RecommendedTemplates, CanBeConstructed) {
     50  absl::BitGen default_generator;
     51  absl::InsecureBitGen insecure_generator;
     52 }
     53 
     54 TEST(RecommendedTemplates, CanDiscardValues) {
     55  absl::BitGen default_generator;
     56  absl::InsecureBitGen insecure_generator;
     57 
     58  default_generator.discard(5);
     59  insecure_generator.discard(5);
     60 }
     61 
     62 TEST(NonsecureURBGBase, StandardInterface) {
     63  // Names after definition of [rand.req.urbg] in C++ standard.
     64  // e us a value of E
     65  // v is a lvalue of E
     66  // x, y are possibly const values of E
     67  // s is a value of T
     68  // q is a value satisfying requirements of seed_sequence
     69  // z is a value of type unsigned long long
     70  // os is a some specialization of basic_ostream
     71  // is is a some specialization of basic_istream
     72 
     73  using E = absl::random_internal::NonsecureURBGBase<std::minstd_rand>;
     74 
     75  using T = typename E::result_type;
     76 
     77  static_assert(!std::is_copy_constructible<E>::value,
     78                "NonsecureURBGBase should not be copy constructible");
     79 
     80  static_assert(!absl::is_copy_assignable<E>::value,
     81                "NonsecureURBGBase should not be copy assignable");
     82 
     83  static_assert(std::is_move_constructible<E>::value,
     84                "NonsecureURBGBase should be move constructible");
     85 
     86  static_assert(absl::is_move_assignable<E>::value,
     87                "NonsecureURBGBase should be move assignable");
     88 
     89  static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
     90                "return type of operator() must be result_type");
     91 
     92  {
     93    const E x, y;
     94    Use(x);
     95    Use(y);
     96 
     97    static_assert(std::is_same<decltype(x == y), bool>::value,
     98                  "return type of operator== must be bool");
     99 
    100    static_assert(std::is_same<decltype(x != y), bool>::value,
    101                  "return type of operator== must be bool");
    102  }
    103 
    104  E e;
    105  std::seed_seq q{1, 2, 3};
    106 
    107  E{};
    108  E{q};
    109 
    110  // Copy constructor not supported.
    111  // E{x};
    112 
    113  // result_type seed constructor not supported.
    114  // E{T{1}};
    115 
    116  // Move constructors are supported.
    117  {
    118    E tmp(q);
    119    E m = std::move(tmp);
    120    E n(std::move(m));
    121    EXPECT_TRUE(e != n);
    122  }
    123 
    124  // Comparisons work.
    125  {
    126    // MSVC emits error 2718 when using EXPECT_EQ(e, x)
    127    //  * actual parameter with __declspec(align('#')) won't be aligned
    128    E a(q);
    129    E b(q);
    130 
    131    EXPECT_TRUE(a != e);
    132    EXPECT_TRUE(a == b);
    133 
    134    a();
    135    EXPECT_TRUE(a != b);
    136  }
    137 
    138  // e.seed(s) not supported.
    139 
    140  // [rand.req.eng] specifies the parameter as 'unsigned long long'
    141  // e.discard(unsigned long long) is supported.
    142  unsigned long long z = 1;  // NOLINT(runtime/int)
    143  e.discard(z);
    144 }
    145 
    146 TEST(NonsecureURBGBase, SeedSeqConstructorIsValid) {
    147  std::seed_seq seq;
    148  ExampleNonsecureURBG rbg(seq);
    149 }
    150 
    151 TEST(NonsecureURBGBase, CompatibleWithDistributionUtils) {
    152  ExampleNonsecureURBG rbg;
    153 
    154  absl::Uniform(rbg, 0, 100);
    155  absl::Uniform(rbg, 0.5, 0.7);
    156  absl::Poisson<uint32_t>(rbg);
    157  absl::Exponential<float>(rbg);
    158 }
    159 
    160 TEST(NonsecureURBGBase, CompatibleWithStdDistributions) {
    161  ExampleNonsecureURBG rbg;
    162 
    163  // Cast to void to suppress [[nodiscard]] warnings
    164  static_cast<void>(std::uniform_int_distribution<uint32_t>(0, 100)(rbg));
    165  static_cast<void>(std::uniform_real_distribution<float>()(rbg));
    166  static_cast<void>(std::bernoulli_distribution(0.2)(rbg));
    167 }
    168 
    169 TEST(NonsecureURBGBase, ConsecutiveDefaultInstancesYieldUniqueVariates) {
    170  const size_t kNumSamples = 128;
    171 
    172  ExampleNonsecureURBG rbg1;
    173  ExampleNonsecureURBG rbg2;
    174 
    175  for (size_t i = 0; i < kNumSamples; i++) {
    176    EXPECT_NE(rbg1(), rbg2());
    177  }
    178 }
    179 
    180 TEST(NonsecureURBGBase, EqualSeedSequencesYieldEqualVariates) {
    181  std::seed_seq seq;
    182 
    183  ExampleNonsecureURBG rbg1(seq);
    184  ExampleNonsecureURBG rbg2(seq);
    185 
    186  // ExampleNonsecureURBG rbg3({1, 2, 3});  // Should not compile.
    187 
    188  for (uint32_t i = 0; i < 1000; i++) {
    189    EXPECT_EQ(rbg1(), rbg2());
    190  }
    191 
    192  rbg1.discard(100);
    193  rbg2.discard(100);
    194 
    195  // The sequences should continue after discarding
    196  for (uint32_t i = 0; i < 1000; i++) {
    197    EXPECT_EQ(rbg1(), rbg2());
    198  }
    199 }
    200 
    201 TEST(NonsecureURBGBase, DistinctSequencesPerThread) {
    202  constexpr int kNumThreads = 12;
    203  constexpr size_t kValuesPerThread = 32;
    204  using result_type = absl::BitGen::result_type;
    205 
    206  // Acquire initial sequences from multiple threads.
    207  std::vector<std::vector<result_type>> data;
    208  {
    209    absl::Mutex mu;
    210    std::vector<std::thread> threads;
    211    for (int i = 0; i < kNumThreads; i++) {
    212      threads.emplace_back([&]() {
    213        absl::BitGen gen;
    214 
    215        std::vector<result_type> v(kValuesPerThread);
    216        std::generate(v.begin(), v.end(), [&]() { return gen(); });
    217        absl::MutexLock l(&mu);
    218        data.push_back(std::move(v));
    219      });
    220    }
    221    for (auto& t : threads) t.join();
    222  }
    223 
    224  EXPECT_EQ(data.size(), kNumThreads);
    225 
    226  // There should be essentially no duplicates in the sequences.
    227  size_t expected_size = 0;
    228  absl::flat_hash_set<result_type> seen;
    229  for (const auto& v : data) {
    230    expected_size += v.size();
    231    for (result_type x : v) seen.insert(x);
    232  }
    233  EXPECT_GE(seen.size(), expected_size - 1);
    234 }
    235 
    236 TEST(RandenPoolSeedSeqTest, SeederWorksForU32) {
    237  absl::random_internal::RandenPoolSeedSeq seeder;
    238 
    239  uint32_t state[2] = {0, 0};
    240  seeder.generate(std::begin(state), std::end(state));
    241  EXPECT_FALSE(state[0] == 0 && state[1] == 0);
    242 }
    243 
    244 TEST(RandenPoolSeedSeqTest, SeederWorksForU64) {
    245  absl::random_internal::RandenPoolSeedSeq seeder;
    246 
    247  uint64_t state[2] = {0, 0};
    248  seeder.generate(std::begin(state), std::end(state));
    249  EXPECT_FALSE(state[0] == 0 && state[1] == 0);
    250  EXPECT_FALSE((state[0] >> 32) == 0 && (state[1] >> 32) == 0);
    251 }
    252 
    253 TEST(RandenPoolSeedSeqTest, SeederWorksForS32) {
    254  absl::random_internal::RandenPoolSeedSeq seeder;
    255 
    256  int32_t state[2] = {0, 0};
    257  seeder.generate(std::begin(state), std::end(state));
    258  EXPECT_FALSE(state[0] == 0 && state[1] == 0);
    259 }
    260 
    261 TEST(RandenPoolSeedSeqTest, SeederWorksForVector) {
    262  absl::random_internal::RandenPoolSeedSeq seeder;
    263 
    264  std::vector<uint32_t> state(2);
    265  seeder.generate(std::begin(state), std::end(state));
    266  EXPECT_FALSE(state[0] == 0 && state[1] == 0);
    267 }