1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2017 SUSE LINUX GmbH
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
17 #include "include/random.h"
19 #include "gtest/gtest.h"
21 // Helper to see if calls compile with various types:
23 T
type_check_ok(const T min
, const T max
)
25 return ceph::util::generate_random_number(min
, max
);
28 /* Help wrangle "unused variable" warnings: */
30 void swallow_values(const X x
)
35 template <typename X
, typename
...XS
>
36 void swallow_values(const X x
, const XS
... xs
)
38 swallow_values(x
), swallow_values(xs
...);
41 // Mini-examples showing canonical usage:
42 TEST(util
, test_random_canonical
)
44 // Seed random number generation:
45 ceph::util::randomize_rng();
47 // Get a random int between 0 and max int:
48 auto a
= ceph::util::generate_random_number();
50 // Get a random int between 0 and 20:
51 auto b
= ceph::util::generate_random_number(20);
53 // Get a random int between 1 and 20:
54 auto c
= ceph::util::generate_random_number(1, 20);
56 // Get a random float between 0.0 and 20.0:
57 auto d
= ceph::util::generate_random_number(20.0);
59 // Get a random float between 0.001 and 0.991:
60 auto e
= ceph::util::generate_random_number(0.001, 0.991);
62 // Make a function object RNG suitable for putting on its own thread:
63 auto gen_fn
= ceph::util::random_number_generator
<int>();
65 gen_fn
.seed(42); // re-seed
67 // Placate the compiler:
68 swallow_values(a
, b
, c
, d
, e
, z
);
71 TEST(util
, test_random
)
73 /* The intent of this test is not to formally test random number generation,
74 but rather to casually check that "it works" and catch regressions: */
76 // The default overload should compile:
77 ceph::util::randomize_rng();
80 int a
= ceph::util::generate_random_number();
81 int b
= ceph::util::generate_random_number();
83 /* Technically, this can still collide and cause a false negative, but let's
85 if (std::numeric_limits
<int>::max() > 32767) {
90 // Check that the nullary version accepts different numeric types:
92 long def
= ceph::util::generate_random_number();
93 long l
= ceph::util::generate_random_number
<long>();
94 int64_t i
= ceph::util::generate_random_number
<int64_t>();
95 double d
= ceph::util::generate_random_number
<double>();
97 swallow_values(def
, l
, i
, d
);
100 // (optimistically) Check that the nullary and unary versions never return < 0:
102 for(long i
= 0; 1000000 != i
; i
++) {
103 ASSERT_LE(0, ceph::util::generate_random_number());
104 ASSERT_LE(0, ceph::util::generate_random_number(1));
105 ASSERT_LE(0, ceph::util::generate_random_number
<float>(1.0));
110 auto a
= ceph::util::generate_random_number(1, std::numeric_limits
<int>::max());
111 auto b
= ceph::util::generate_random_number(1, std::numeric_limits
<int>::max());
113 if (std::numeric_limits
<int>::max() > 32767) {
121 for (auto n
= 100000; n
; --n
) {
122 int a
= ceph::util::generate_random_number(0, 6);
127 // Check bounding on zero (checking appropriate value for zero compiles and works):
128 for (auto n
= 10; n
; --n
) {
129 ASSERT_EQ(0, ceph::util::generate_random_number
<int>(0, 0));
130 ASSERT_EQ(0, ceph::util::generate_random_number
<float>(0.0, 0.0));
133 // Multiple types (integral):
135 int min
= 0, max
= 1;
136 type_check_ok(min
, max
);
140 long min
= 0, max
= 1l;
141 type_check_ok(min
, max
);
144 // Multiple types (floating point):
146 double min
= 0.0, max
= 1.0;
147 type_check_ok(min
, max
);
151 float min
= 0.0, max
= 1.0;
152 type_check_ok(min
, max
);
155 // When combining types, everything should convert to the largest type:
157 // Check with integral types:
162 auto z
= ceph::util::generate_random_number(x
, y
);
164 bool result
= std::is_same_v
<decltype(z
), decltype(y
)>;
169 // Check with floating-point types:
174 auto z
= ceph::util::generate_random_number(x
, y
);
176 bool result
= std::is_same_v
<decltype(z
), decltype(y
)>;
181 // It would be nice to have a test to check that mixing integral and floating point
182 // numbers should not compile, however we currently have no good way I know of
183 // to do such negative tests.
187 TEST(util
, test_random_class_interface
)
189 ceph::util::random_number_generator
<int> rng_i
;
190 ceph::util::random_number_generator
<float> rng_f
;
194 ceph::util::random_number_generator
<int> rng(1234); // seed
197 // Test deduction guides:
199 { ceph::util::random_number_generator
rng(1234); }
200 { ceph::util::random_number_generator
rng(1234.1234); }
204 ceph::util::random_number_generator
rng(x
);
212 // Technically can fail, but should "almost never" happen:
223 float a
= rng_f(10.0);
229 int a
= rng_i(10, 20);
235 float a
= rng_f(10.0, 20.0);