absl::Hash
By Andy Soffer, Engineer
We are happy to announce the arrival of the Abseil Random library, providing simple tools for generating random numbers and testing code that uses random numbers.
Abseil now includes a random number generation library, which can be found in
absl/random/
.
The library includes
<random>
header, with some modest performance improvements.absl::MockingBitGen
)
that, with GoogleTest, enables
deterministic testing of application code.This blog post discusses how to get started using this library. For a more detailed explanation on the design of the helper functions and testing facilities provided by this library, take a look at our design note.
Happy sampling!
We provide several bit generators:
absl::BitGen
:
A general-purpose random bit generator whose default constructor is seeded
correctly.absl::InsecureBitGen
:
A fast bit generator for performance-sensitive use cases when the
computational cost of absl::BitGen
is prohibitively expensive.absl::MockingBitGen
:
A bit generator to be used only in unit tests. For details, see the design
note.absl::BitGenRef
:
A type-erased reference to a bit generator. Used primarily as a means of
swapping bit generators at run-time.For the bit generator, we recommend using absl::BitGen
unless you have
specific performance requirements and have thoroughly vetted
absl::InsecureBitGen
for your use case. Neither absl::BitGen
nor
absl::InsecureBitGen
are guaranteed to be cryptographically secure.
Bit generators are well-seeded by default, so default constructing an
absl::BitGen
is a correct and intended usage. All of our bit generators
provide no stability guarantees. The implementation may change at any time, and
the sequence of variates produced need not be the same, even between two
invocations of the same process.
Distribution function templates are thin wrappers around distribution objects that provide a straightforward API for getting randomness. A generator should be passed to a distribution function as in the examples below:
// Using the C++ standard <random> facilities
std::random_device rd;
std:mt19937 gen(rd());
int die_roll = std::uniform_int_distribution<>(1, 6)(gen);
bool fair_coin_landed_heads = std::bernoulli_distribution(0.5)(gen);
// Using Abseil Random
absl::BitGen gen;
int die_roll = absl::Uniform(absl::IntervalClosedClosed, gen, 1, 6);
bool fair_coin_landed_heads = absl::Bernoulli(gen, 0.5);
The full list of distribution functions provided can be seen in distributions.h.
For testing functions that require randomness, we provide absl::MockingBitGen
,
a bit generator that enables a test author to specify the result of a
call to a distribution. As you will notice in the code-snippet below, this is
not done via a deterministic bit generator (for reasons discusesd in the
design note). Rather, absl::MockingBitGen
allows the user
to specify the result not of the bit generator, but of the entire random sample.
The design note goes into detail about why we believe this is a maintainable
approach to testing code with random behavior. These testing facilities rely on
GoogleTest.
using ::testing::_;
using ::testing::Lt;
using ::testing::Return;
int ComputeValue(absl::BitGenRef gen) {
if (absl::Bernoulli(gen, 0.00001)) {
return 10
} else {
return 0;
}
}
TEST(ComputeValueTest, UnlikelyCase) {
absl::MockingBitGen gen;
ON_CALL(absl::MockBernoulli(), Call(gen, Lt(0.01))
.WillByDefault(Return(true));
EXPECT_EQ(ComputeValue(gen), 10);
}