abseil-cpp/absl/random/uniform_int_distribution_test.cc
Go to the documentation of this file.
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/uniform_int_distribution.h"
16 
17 #include <cmath>
18 #include <cstdint>
19 #include <iterator>
20 #include <random>
21 #include <sstream>
22 #include <vector>
23 
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "absl/base/internal/raw_logging.h"
27 #include "absl/random/internal/chi_square.h"
28 #include "absl/random/internal/distribution_test_util.h"
29 #include "absl/random/internal/pcg_engine.h"
30 #include "absl/random/internal/sequence_urbg.h"
31 #include "absl/random/random.h"
32 #include "absl/strings/str_cat.h"
33 
34 namespace {
35 
36 template <typename IntType>
37 class UniformIntDistributionTest : public ::testing::Test {};
38 
41 TYPED_TEST_SUITE(UniformIntDistributionTest, IntTypes);
42 
43 TYPED_TEST(UniformIntDistributionTest, ParamSerializeTest) {
44  // This test essentially ensures that the parameters serialize,
45  // not that the values generated cover the full range.
46  using Limits = std::numeric_limits<TypeParam>;
47  using param_type =
49  const TypeParam kMin = std::is_unsigned<TypeParam>::value ? 37 : -105;
50  const TypeParam kNegOneOrZero = std::is_unsigned<TypeParam>::value ? 0 : -1;
51 
52  constexpr int kCount = 1000;
54  for (const auto& param : {
55  param_type(),
56  param_type(2, 2), // Same
57  param_type(9, 32),
58  param_type(kMin, 115),
59  param_type(kNegOneOrZero, Limits::max()),
60  param_type(Limits::min(), Limits::max()),
61  param_type(Limits::lowest(), Limits::max()),
62  param_type(Limits::min() + 1, Limits::max() - 1),
63  }) {
64  const auto a = param.a();
65  const auto b = param.b();
67  EXPECT_EQ(before.a(), param.a());
68  EXPECT_EQ(before.b(), param.b());
69 
70  {
71  // Initialize via param_type
73  EXPECT_EQ(via_param, before);
74  }
75 
76  // Initialize via iostreams
77  std::stringstream ss;
78  ss << before;
79 
81  Limits::max() - 5);
82 
83  EXPECT_NE(before.a(), after.a());
84  EXPECT_NE(before.b(), after.b());
85  EXPECT_NE(before.param(), after.param());
87 
88  ss >> after;
89 
90  EXPECT_EQ(before.a(), after.a());
91  EXPECT_EQ(before.b(), after.b());
92  EXPECT_EQ(before.param(), after.param());
94 
95  // Smoke test.
96  auto sample_min = after.max();
97  auto sample_max = after.min();
98  for (int i = 0; i < kCount; i++) {
99  auto sample = after(gen);
100  EXPECT_GE(sample, after.min());
101  EXPECT_LE(sample, after.max());
102  if (sample > sample_max) {
103  sample_max = sample;
104  }
105  if (sample < sample_min) {
106  sample_min = sample;
107  }
108  }
109  std::string msg = absl::StrCat("Range: ", +sample_min, ", ", +sample_max);
110  ABSL_RAW_LOG(INFO, "%s", msg.c_str());
111  }
112 }
113 
114 TYPED_TEST(UniformIntDistributionTest, ViolatesPreconditionsDeathTest) {
115 #if GTEST_HAS_DEATH_TEST
116  // Hi < Lo
117  EXPECT_DEBUG_DEATH({ absl::uniform_int_distribution<TypeParam> dist(10, 1); },
118  "");
119 #endif // GTEST_HAS_DEATH_TEST
120 #if defined(NDEBUG)
121  // opt-mode, for invalid parameters, will generate a garbage value,
122  // but should not enter an infinite loop.
125  auto x = dist(gen);
126 
127  // Any value will generate a non-empty string.
129 #endif // NDEBUG
130 }
131 
132 TYPED_TEST(UniformIntDistributionTest, TestMoments) {
133  constexpr int kSize = 100000;
134  using Limits = std::numeric_limits<TypeParam>;
135  using param_type =
137 
138  // We use a fixed bit generator for distribution accuracy tests. This allows
139  // these tests to be deterministic, while still testing the qualify of the
140  // implementation.
141  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
142 
143  std::vector<double> values(kSize);
144  for (const auto& param :
145  {param_type(0, Limits::max()), param_type(13, 127)}) {
147  for (int i = 0; i < kSize; i++) {
148  const auto sample = dist(rng);
149  ASSERT_LE(dist.param().a(), sample);
150  ASSERT_GE(dist.param().b(), sample);
151  values[i] = sample;
152  }
153 
155  const double a = dist.param().a();
156  const double b = dist.param().b();
157  const double n = (b - a + 1);
158  const double mean = (a + b) / 2;
159  const double var = ((b - a + 1) * (b - a + 1) - 1) / 12;
160  const double kurtosis = 3 - 6 * (n * n + 1) / (5 * (n * n - 1));
161 
162  // TODO(ahh): this is not the right bound
163  // empirically validated with --runs_per_test=10000.
164  EXPECT_NEAR(mean, moments.mean, 0.01 * var);
165  EXPECT_NEAR(var, moments.variance, 0.015 * var);
166  EXPECT_NEAR(0.0, moments.skewness, 0.025);
167  EXPECT_NEAR(kurtosis, moments.kurtosis, 0.02 * kurtosis);
168  }
169 }
170 
171 TYPED_TEST(UniformIntDistributionTest, ChiSquaredTest50) {
173 
174  constexpr size_t kTrials = 1000;
175  constexpr int kBuckets = 50; // inclusive, so actally +1
176  constexpr double kExpected =
177  static_cast<double>(kTrials) / static_cast<double>(kBuckets);
178 
179  // Empirically validated with --runs_per_test=10000.
180  const int kThreshold =
181  absl::random_internal::ChiSquareValue(kBuckets, 0.999999);
182 
183  const TypeParam min = std::is_unsigned<TypeParam>::value ? 37 : -37;
184  const TypeParam max = min + kBuckets;
185 
186  // We use a fixed bit generator for distribution accuracy tests. This allows
187  // these tests to be deterministic, while still testing the qualify of the
188  // implementation.
189  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
190 
192 
193  std::vector<int32_t> counts(kBuckets + 1, 0);
194  for (size_t i = 0; i < kTrials; i++) {
195  auto x = dist(rng);
196  counts[x - min]++;
197  }
199  std::begin(counts), std::end(counts), kExpected);
200  if (chi_square > kThreshold) {
201  double p_value =
202  absl::random_internal::ChiSquarePValue(chi_square, kBuckets);
203 
204  // Chi-squared test failed. Output does not appear to be uniform.
206  for (const auto& a : counts) {
207  absl::StrAppend(&msg, a, "\n");
208  }
209  absl::StrAppend(&msg, kChiSquared, " p-value ", p_value, "\n");
210  absl::StrAppend(&msg, "High ", kChiSquared, " value: ", chi_square, " > ",
211  kThreshold);
212  ABSL_RAW_LOG(INFO, "%s", msg.c_str());
213  FAIL() << msg;
214  }
215 }
216 
217 TEST(UniformIntDistributionTest, StabilityTest) {
218  // absl::uniform_int_distribution stability relies only on integer operations.
220  {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
221  0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
222  0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
223  0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
224 
225  std::vector<int> output(12);
226 
227  {
229  for (auto& v : output) {
230  v = dist(urbg);
231  }
232  }
233  EXPECT_EQ(12, urbg.invocations());
234  EXPECT_THAT(output, testing::ElementsAre(4, 4, 3, 2, 1, 0, 1, 4, 3, 1, 3, 1));
235 
236  {
237  urbg.reset();
239  for (auto& v : output) {
240  v = dist(urbg);
241  }
242  }
243  EXPECT_EQ(12, urbg.invocations());
244  EXPECT_THAT(output, testing::ElementsAre(97, 86, 75, 41, 36, 16, 38, 92, 67,
245  30, 80, 38));
246 
247  {
248  urbg.reset();
250  for (auto& v : output) {
251  v = dist(urbg);
252  }
253  }
254  EXPECT_EQ(12, urbg.invocations());
255  EXPECT_THAT(output, testing::ElementsAre(9648, 8562, 7439, 4089, 3571, 1602,
256  3813, 9195, 6641, 2986, 7956, 3765));
257 }
258 
259 } // namespace
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
kSize
static constexpr Tag kSize
Definition: protobuf/src/google/protobuf/descriptor.cc:873
absl::StrAppend
void StrAppend(std::string *dest, const AlphaNum &a)
Definition: abseil-cpp/absl/strings/str_cat.cc:193
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
absl::uniform_int_distribution::param_type
Definition: abseil-cpp/absl/random/uniform_int_distribution.h:66
begin
char * begin
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1007
EXPECT_THAT
#define EXPECT_THAT(value, matcher)
uint16_t
unsigned short uint16_t
Definition: stdint-msvc2008.h:79
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
absl::uniform_int_distribution
Definition: abseil-cpp/absl/random/internal/uniform_helper.h:30
ASSERT_GE
#define ASSERT_GE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2072
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
ASSERT_LE
#define ASSERT_LE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2064
EXPECT_LE
#define EXPECT_LE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2030
absl::random_internal::sequence_urbg
Definition: abseil-cpp/absl/random/internal/sequence_urbg.h:33
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
absl::random_internal::ChiSquareWithExpected
double ChiSquareWithExpected(Iterator begin, Iterator end, double expected)
Definition: abseil-cpp/absl/random/internal/chi_square.h:40
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
absl::random_internal::ComputeDistributionMoments
DistributionMoments ComputeDistributionMoments(absl::Span< const double > data_points)
Definition: abseil-cpp/absl/random/internal/distribution_test_util.cc:39
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
testing::ElementsAre
internal::ElementsAreMatcher< ::testing::tuple<> > ElementsAre()
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:13040
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
before
IntBeforeRegisterTypedTestSuiteP before
Definition: googletest/googletest/test/gtest-typed-test_test.cc:376
testing::internal::ProxyTypeList
Definition: googletest/googletest/include/gtest/internal/gtest-type-util.h:155
int16_t
signed short int16_t
Definition: stdint-msvc2008.h:76
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
TEST
#define TEST(name, init_size,...)
Definition: arena_test.cc:75
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
python_utils.jobset.INFO
INFO
Definition: jobset.py:111
EXPECT_NE
#define EXPECT_NE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2028
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
TYPED_TEST
#define TYPED_TEST(CaseName, TestName)
Definition: googletest/googletest/include/gtest/gtest-typed-test.h:197
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
FAIL
@ FAIL
Definition: call_creds.cc:42
absl::random_internal::ChiSquarePValue
double ChiSquarePValue(double chi_square, int dof)
Definition: abseil-cpp/absl/random/internal/chi_square.cc:157
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
gen
OPENSSL_EXPORT GENERAL_NAME * gen
Definition: x509v3.h:495
min
#define min(a, b)
Definition: qsort.h:83
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
after
IntAfterTypedTestSuiteP after
Definition: googletest/googletest/test/gtest-typed-test_test.cc:375
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
google_benchmark.example.empty
def empty(state)
Definition: example.py:31
value
const char * value
Definition: hpack_parser_table.cc:165
absl::random_internal::pcg_engine
Definition: abseil-cpp/absl/random/internal/pcg_engine.h:41
TYPED_TEST_SUITE
#define TYPED_TEST_SUITE(CaseName, Types,...)
Definition: googletest/googletest/include/gtest/gtest-typed-test.h:191
absl::random_internal::NonsecureURBGBase
Definition: abseil-cpp/absl/random/internal/nonsecure_base.h:96
values
std::array< int64_t, Size > values
Definition: abseil-cpp/absl/container/btree_benchmark.cc:608
absl::random_internal::ChiSquareValue
double ChiSquareValue(int dof, double p)
Definition: abseil-cpp/absl/random/internal/chi_square.cc:106
EXPECT_GE
#define EXPECT_GE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2034
EXPECT_NEAR
#define EXPECT_NEAR(val1, val2, abs_error)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2143
int8_t
signed char int8_t
Definition: stdint-msvc2008.h:75
absl::random_internal::kChiSquared
constexpr const char kChiSquared[]
Definition: abseil-cpp/absl/random/internal/chi_square.h:35
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
ABSL_RAW_LOG
#define ABSL_RAW_LOG(severity,...)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:44
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:44