Export of internal Abseil changes

--
4503a1945d61540d3f7dd9ee2399297fbd423b82 by Andy Soffer <asoffer@google.com>:

Releasing absl::MockingBitGen and absl::BitGenRef

PiperOrigin-RevId: 281594380

--
2cb926fd9e39b5fa24c9541bfafcf18916cf7df2 by Abseil Team <absl-team@google.com>:

Explicitly export files needed by other packages

PiperOrigin-RevId: 281482304
GitOrigin-RevId: 4503a1945d61540d3f7dd9ee2399297fbd423b82
Change-Id: Id9f694eaaa23f42de817c8e8a28e6f86444f5637
This commit is contained in:
Abseil Team 2019-11-20 13:55:25 -08:00 committed by Andy Soffer
parent 8ba96a8244
commit bcaae6009c
12 changed files with 1598 additions and 0 deletions

View file

@ -110,6 +110,58 @@ cc_library(
],
)
cc_library(
name = "bit_gen_ref",
hdrs = ["bit_gen_ref.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base:core_headers",
"//absl/meta:type_traits",
"//absl/random/internal:distribution_caller",
"//absl/random/internal:fast_uniform_bits",
"//absl/random/internal:mocking_bit_gen_base",
],
)
cc_library(
name = "mock_distributions",
testonly = 1,
hdrs = ["mock_distributions.h"],
deps = [
":distributions",
":mocking_bit_gen",
"//absl/meta:type_traits",
"//absl/random/internal:mock_overload_set",
"@com_google_googletest//:gtest",
],
)
cc_library(
name = "mocking_bit_gen",
testonly = 1,
srcs = [
"mocking_bit_gen.cc",
],
hdrs = [
"mocking_bit_gen.h",
],
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":distributions",
"//absl/base:raw_logging_internal",
"//absl/container:flat_hash_map",
"//absl/meta:type_traits",
"//absl/random/internal:distribution_caller",
"//absl/random/internal:mocking_bit_gen_base",
"//absl/strings",
"//absl/types:span",
"//absl/types:variant",
"//absl/utility",
"@com_google_googletest//:gtest",
],
)
cc_test(
name = "bernoulli_distribution_test",
size = "small",
@ -345,6 +397,46 @@ cc_test(
],
)
cc_test(
name = "bit_gen_ref_test",
size = "small",
srcs = ["bit_gen_ref_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bit_gen_ref",
":random",
"//absl/random/internal:sequence_urbg",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "mocking_bit_gen_test",
size = "small",
srcs = ["mocking_bit_gen_test.cc"],
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bit_gen_ref",
":mock_distributions",
":mocking_bit_gen",
":random",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "mock_distributions_test",
size = "small",
srcs = ["mock_distributions_test.cc"],
deps = [
":mock_distributions",
":mocking_bit_gen",
":random",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "examples_test",
size = "small",

View file

@ -32,6 +32,132 @@ absl_cc_library(
absl::random_seed_sequences
)
absl_cc_library(
NAME
random_bit_gen_ref
HDRS
"bit_gen_ref.h"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::core_headers
absl::random_internal_distribution_caller
absl::random_internal_fast_uniform_bits
absl::random_internal_mocking_bit_gen_base
absl::type_traits
)
absl_cc_test(
NAME
random_bit_gen_ref_test
SRCS
"bit_gen_ref_test.cc"
COPTS
${ABSL_TEST_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_bit_gen_ref
absl::random_random
absl::random_internal_sequence_urbg
gmock
gtest_main
)
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
random_internal_mocking_bit_gen_base
HDRS
"internal/mocking_bit_gen_base.h"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_random
absl::strings
)
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
random_internal_mock_overload_set
HDRS
"internal/mock_overload_set.h"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_mocking_bit_gen
TESTONLY
)
absl_cc_library(
NAME
random_mocking_bit_gen
HDRS
"mock_distributions.h"
"mocking_bit_gen.h"
SRCS
"mocking_bit_gen.cc"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::flat_hash_map
absl::raw_logging_internal
absl::random_distributions
absl::random_internal_distribution_caller
absl::random_internal_mocking_bit_gen_base
absl::random_internal_mock_overload_set
absl::strings
absl::span
absl::type_traits
absl::utility
absl::variant
gmock
gtest
TESTONLY
)
absl_cc_test(
NAME
random_mock_distributions_test
SRCS
"mock_distributions_test.cc"
COPTS
${ABSL_TEST_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_mocking_bit_gen
absl::random_random
gmock
gtest_main
)
absl_cc_test(
NAME
random_mocking_bit_gen_test
SRCS
"mocking_bit_gen_test.cc"
COPTS
${ABSL_TEST_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_bit_gen_ref
absl::random_mocking_bit_gen
absl::random_random
gmock
gtest_main
)
absl_cc_library(
NAME
random_distributions

151
absl/random/bit_gen_ref.h Normal file
View file

@ -0,0 +1,151 @@
//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: bit_gen_ref.h
// -----------------------------------------------------------------------------
//
// This header defines a bit generator "reference" class, for use in interfaces
// that take both Abseil (e.g. `absl::BitGen`) and standard library (e.g.
// `std::mt19937`) bit generators.
#ifndef ABSL_RANDOM_BIT_GEN_REF_H_
#define ABSL_RANDOM_BIT_GEN_REF_H_
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/distribution_caller.h"
#include "absl/random/internal/fast_uniform_bits.h"
#include "absl/random/internal/mocking_bit_gen_base.h"
namespace absl {
namespace random_internal {
template <typename URBG, typename = void, typename = void, typename = void>
struct is_urbg : std::false_type {};
template <typename URBG>
struct is_urbg<
URBG,
absl::enable_if_t<std::is_same<
typename URBG::result_type,
typename std::decay<decltype((URBG::min)())>::type>::value>,
absl::enable_if_t<std::is_same<
typename URBG::result_type,
typename std::decay<decltype((URBG::max)())>::type>::value>,
absl::enable_if_t<std::is_same<
typename URBG::result_type,
typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
: std::true_type {};
} // namespace random_internal
// -----------------------------------------------------------------------------
// absl::BitGenRef
// -----------------------------------------------------------------------------
//
// `absl::BitGenRef` is a type-erasing class that provides a generator-agnostic
// non-owning "reference" interface for use in place of any specific uniform
// random bit generator (URBG). This class may be used for both Abseil
// (e.g. `absl::BitGen`, `absl::InsecureBitGen`) and Standard library (e.g
// `std::mt19937`, `std::minstd_rand`) bit generators.
//
// Like other reference classes, `absl::BitGenRef` does not own the
// underlying bit generator, and the underlying instance must outlive the
// `absl::BitGenRef`.
//
// `absl::BitGenRef` is particularly useful when used with an
// `absl::MockingBitGen` to test specific paths in functions which use random
// values.
//
// Example:
// void TakesBitGenRef(absl::BitGenRef gen) {
// int x = absl::Uniform<int>(gen, 0, 1000);
// }
//
class BitGenRef {
public:
using result_type = uint64_t;
BitGenRef(const absl::BitGenRef&) = default;
BitGenRef(absl::BitGenRef&&) = default;
BitGenRef& operator=(const absl::BitGenRef&) = default;
BitGenRef& operator=(absl::BitGenRef&&) = default;
template <typename URBG,
typename absl::enable_if_t<
(!std::is_same<URBG, BitGenRef>::value &&
random_internal::is_urbg<URBG>::value)>* = nullptr>
BitGenRef(URBG& gen) // NOLINT
: mocked_gen_ptr_(MakeMockPointer(&gen)),
t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
generate_impl_fn_(ImplFn<URBG>) {
}
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
}
static constexpr result_type(max)() {
return (std::numeric_limits<result_type>::max)();
}
result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }
private:
friend struct absl::random_internal::DistributionCaller<absl::BitGenRef>;
using impl_fn = result_type (*)(uintptr_t);
using mocker_base_t = absl::random_internal::MockingBitGenBase;
// Convert an arbitrary URBG pointer into either a valid mocker_base_t
// pointer or a nullptr.
static inline mocker_base_t* MakeMockPointer(mocker_base_t* t) { return t; }
static inline mocker_base_t* MakeMockPointer(void*) { return nullptr; }
template <typename URBG>
static result_type ImplFn(uintptr_t ptr) {
// Ensure that the return values from operator() fill the entire
// range promised by result_type, min() and max().
absl::random_internal::FastUniformBits<result_type> fast_uniform_bits;
return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr));
}
mocker_base_t* mocked_gen_ptr_;
uintptr_t t_erased_gen_ptr_;
impl_fn generate_impl_fn_;
};
namespace random_internal {
template <>
struct DistributionCaller<absl::BitGenRef> {
template <typename DistrT, typename FormatT, typename... Args>
static typename DistrT::result_type Call(absl::BitGenRef* gen_ref,
Args&&... args) {
auto* mock_ptr = gen_ref->mocked_gen_ptr_;
if (mock_ptr == nullptr) {
DistrT dist(std::forward<Args>(args)...);
return dist(*gen_ref);
} else {
return mock_ptr->template Call<DistrT, FormatT>(
std::forward<Args>(args)...);
}
}
};
} // namespace random_internal
} // namespace absl
#endif // ABSL_RANDOM_BIT_GEN_REF_H_

View file

@ -0,0 +1,99 @@
//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "absl/random/bit_gen_ref.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/random/internal/sequence_urbg.h"
#include "absl/random/random.h"
namespace absl {
class ConstBitGen : public absl::random_internal::MockingBitGenBase {
bool CallImpl(const std::type_info&, void*, void* result) override {
*static_cast<int*>(result) = 42;
return true;
}
};
namespace random_internal {
template <>
struct DistributionCaller<ConstBitGen> {
template <typename DistrT, typename FormatT, typename... Args>
static typename DistrT::result_type Call(ConstBitGen* gen, Args&&... args) {
return gen->template Call<DistrT, FormatT>(std::forward<Args>(args)...);
}
};
} // namespace random_internal
namespace {
int FnTest(absl::BitGenRef gen_ref) { return absl::Uniform(gen_ref, 1, 7); }
template <typename T>
class BitGenRefTest : public testing::Test {};
using BitGenTypes =
::testing::Types<absl::BitGen, absl::InsecureBitGen, std::mt19937,
std::mt19937_64, std::minstd_rand>;
TYPED_TEST_SUITE(BitGenRefTest, BitGenTypes);
TYPED_TEST(BitGenRefTest, BasicTest) {
TypeParam gen;
auto x = FnTest(gen);
EXPECT_NEAR(x, 4, 3);
}
TYPED_TEST(BitGenRefTest, Copyable) {
TypeParam gen;
absl::BitGenRef gen_ref(gen);
FnTest(gen_ref); // Copy
}
TEST(BitGenRefTest, PassThroughEquivalence) {
// sequence_urbg returns 64-bit results.
absl::random_internal::sequence_urbg urbg(
{0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
std::vector<uint64_t> output(12);
{
absl::BitGenRef view(urbg);
for (auto& v : output) {
v = view();
}
}
std::vector<uint64_t> expected(
{0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
EXPECT_THAT(output, testing::Eq(expected));
}
TEST(BitGenRefTest, MockingBitGenBaseOverrides) {
ConstBitGen const_gen;
EXPECT_EQ(FnTest(const_gen), 42);
absl::BitGenRef gen_ref(const_gen);
EXPECT_EQ(FnTest(gen_ref), 42); // Copy
}
} // namespace
} // namespace absl

View file

@ -493,6 +493,29 @@ cc_test(
],
)
cc_library(
name = "mocking_bit_gen_base",
hdrs = ["mocking_bit_gen_base.h"],
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/random",
"//absl/strings",
],
)
cc_library(
name = "mock_overload_set",
testonly = 1,
hdrs = ["mock_overload_set.h"],
visibility = [
"//absl/random:__pkg__",
],
deps = [
"//absl/random:mocking_bit_gen",
"@com_google_googletest//:gtest",
],
)
cc_test(
name = "nonsecure_base_test",
size = "small",

View file

@ -0,0 +1,89 @@
//
// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
#define ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
#include <type_traits>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/random/mocking_bit_gen.h"
namespace absl {
namespace random_internal {
template <typename DistrT, typename Fn>
struct MockSingleOverload;
// MockSingleOverload
//
// MockSingleOverload hooks in to gMock's `ON_CALL` and `EXPECT_CALL` macros.
// EXPECT_CALL(mock_single_overload, Call(...))` will expand to a call to
// `mock_single_overload.gmock_Call(...)`. Because expectations are stored on
// the MockingBitGen (an argument passed inside `Call(...)`), this forwards to
// arguments to Mocking::Register.
template <typename DistrT, typename Ret, typename... Args>
struct MockSingleOverload<DistrT, Ret(MockingBitGen&, Args...)> {
static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
"Overload signature must have return type matching the "
"distributions result type.");
auto gmock_Call(
absl::MockingBitGen& gen, // NOLINT(google-runtime-references)
const ::testing::Matcher<Args>&... args)
-> decltype(gen.Register<DistrT, Args...>(args...)) {
return gen.Register<DistrT, Args...>(args...);
}
};
template <typename DistrT, typename Ret, typename Arg, typename... Args>
struct MockSingleOverload<DistrT, Ret(Arg, MockingBitGen&, Args...)> {
static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
"Overload signature must have return type matching the "
"distributions result type.");
auto gmock_Call(
const ::testing::Matcher<Arg>& arg,
absl::MockingBitGen& gen, // NOLINT(google-runtime-references)
const ::testing::Matcher<Args>&... args)
-> decltype(gen.Register<DistrT, Arg, Args...>(arg, args...)) {
return gen.Register<DistrT, Arg, Args...>(arg, args...);
}
};
// MockOverloadSet
//
// MockOverloadSet takes a distribution and a collection of signatures and
// performs overload resolution amongst all the overloads. This makes
// `EXPECT_CALL(mock_overload_set, Call(...))` expand and do overload resolution
// correctly.
template <typename DistrT, typename... Signatures>
struct MockOverloadSet;
template <typename DistrT, typename Sig>
struct MockOverloadSet<DistrT, Sig> : public MockSingleOverload<DistrT, Sig> {
using MockSingleOverload<DistrT, Sig>::gmock_Call;
};
template <typename DistrT, typename FirstSig, typename... Rest>
struct MockOverloadSet<DistrT, FirstSig, Rest...>
: public MockSingleOverload<DistrT, FirstSig>,
public MockOverloadSet<DistrT, Rest...> {
using MockSingleOverload<DistrT, FirstSig>::gmock_Call;
using MockOverloadSet<DistrT, Rest...>::gmock_Call;
};
} // namespace random_internal
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_

View file

@ -0,0 +1,118 @@
//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_
#define ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_
#include <atomic>
#include <deque>
#include <string>
#include <typeinfo>
#include "absl/random/random.h"
#include "absl/strings/str_cat.h"
namespace absl {
namespace random_internal {
// MockingBitGenExpectationFormatter is invoked to format unsatisfied mocks
// and remaining results into a description string.
template <typename DistrT, typename FormatT>
struct MockingBitGenExpectationFormatter {
std::string operator()(absl::string_view args) {
return absl::StrCat(FormatT::FunctionName(), "(", args, ")");
}
};
// MockingBitGenCallFormatter is invoked to format each distribution call
// into a description string for the mock log.
template <typename DistrT, typename FormatT>
struct MockingBitGenCallFormatter {
std::string operator()(const DistrT& dist,
const typename DistrT::result_type& result) {
return absl::StrCat(
FormatT::FunctionName(), "(", FormatT::FormatArgs(dist), ") => {",
FormatT::FormatResults(absl::MakeSpan(&result, 1)), "}");
}
};
class MockingBitGenBase {
template <typename>
friend struct DistributionCaller;
using generator_type = absl::BitGen;
public:
// URBG interface
using result_type = generator_type::result_type;
static constexpr result_type(min)() { return (generator_type::min)(); }
static constexpr result_type(max)() { return (generator_type::max)(); }
result_type operator()() { return gen_(); }
MockingBitGenBase() : gen_(), observed_call_log_() {}
virtual ~MockingBitGenBase() = default;
protected:
const std::deque<std::string>& observed_call_log() {
return observed_call_log_;
}
// CallImpl is the type-erased virtual dispatch.
// The type of dist is always distribution<T>,
// The type of result is always distribution<T>::result_type.
virtual bool CallImpl(const std::type_info& distr_type, void* dist_args,
void* result) = 0;
template <typename DistrT, typename ArgTupleT>
static const std::type_info& GetTypeId() {
return typeid(std::pair<absl::decay_t<DistrT>, absl::decay_t<ArgTupleT>>);
}
// Call the generating distribution function.
// Invoked by DistributionCaller<>::Call<DistT, FormatT>.
// DistT is the distribution type.
// FormatT is the distribution formatter traits type.
template <typename DistrT, typename FormatT, typename... Args>
typename DistrT::result_type Call(Args&&... args) {
using distr_result_type = typename DistrT::result_type;
using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
ArgTupleT arg_tuple(std::forward<Args>(args)...);
auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
distr_result_type result{};
bool found_match =
CallImpl(GetTypeId<DistrT, ArgTupleT>(), &arg_tuple, &result);
if (!found_match) {
result = dist(gen_);
}
// TODO(asoffer): Forwarding the args through means we no longer need to
// extract them from the from the distribution in formatter traits. We can
// just StrJoin them.
observed_call_log_.push_back(
MockingBitGenCallFormatter<DistrT, FormatT>{}(dist, result));
return result;
}
private:
generator_type gen_;
std::deque<std::string> observed_call_log_;
}; // namespace random_internal
} // namespace random_internal
} // namespace absl
#endif // ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_

View file

@ -0,0 +1,259 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: mock_distributions.h
// -----------------------------------------------------------------------------
//
// This file contains mock distribution functions for use alongside an
// `absl::MockingBitGen` object within the Googletest testing framework. Such
// mocks are useful to provide deterministic values as return values within
// (otherwise random) Abseil distribution functions.
//
// The return type of each function is a mock expectation object which
// is used to set the match result.
//
// More information about the Googletest testing framework is available at
// https://github.com/google/googletest
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockUniform<int>(), Call(mock, 1, 1000))
// .WillRepeatedly(testing::ReturnRoundRobin({20, 40}));
//
// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20);
// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40);
// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20);
// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40);
#ifndef ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_
#define ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_
#include <limits>
#include <type_traits>
#include <utility>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/meta/type_traits.h"
#include "absl/random/distributions.h"
#include "absl/random/internal/mock_overload_set.h"
#include "absl/random/mocking_bit_gen.h"
namespace absl {
// -----------------------------------------------------------------------------
// absl::MockUniform
// -----------------------------------------------------------------------------
//
// Matches calls to absl::Uniform.
//
// `absl::MockUniform` is a class template used in conjunction with Googletest's
// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
// same way one would define mocks on a Googletest `MockFunction()`.
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(mock))
// .WillOnce(Return(123456));
// auto x = absl::Uniform<uint32_t>(mock);
// assert(x == 123456)
//
template <typename R>
using MockUniform = random_internal::MockOverloadSet<
random_internal::UniformDistributionWrapper<R>,
R(IntervalClosedOpenTag, MockingBitGen&, R, R),
R(IntervalClosedClosedTag, MockingBitGen&, R, R),
R(IntervalOpenOpenTag, MockingBitGen&, R, R),
R(IntervalOpenClosedTag, MockingBitGen&, R, R), R(MockingBitGen&, R, R),
R(MockingBitGen&)>;
// -----------------------------------------------------------------------------
// absl::MockBernoulli
// -----------------------------------------------------------------------------
//
// Matches calls to absl::Bernoulli.
//
// `absl::MockBernoulli` is a class used in conjunction with Googletest's
// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
// same way one would define mocks on a Googletest `MockFunction()`.
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockBernoulli(), Call(mock, testing::_))
// .WillOnce(Return(false));
// assert(absl::Bernoulli(mock, 0.5) == false);
//
using MockBernoulli =
random_internal::MockOverloadSet<absl::bernoulli_distribution,
bool(MockingBitGen&, double)>;
// -----------------------------------------------------------------------------
// absl::MockBeta
// -----------------------------------------------------------------------------
//
// Matches calls to absl::Beta.
//
// `absl::MockBeta` is a class used in conjunction with Googletest's `ON_CALL()`
// and `EXPECT_CALL()` macros. To use it, default-construct an instance of it
// inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the same way one
// would define mocks on a Googletest `MockFunction()`.
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockBeta(), Call(mock, 3.0, 2.0))
// .WillOnce(Return(0.567));
// auto x = absl::Beta<double>(mock, 3.0, 2.0);
// assert(x == 0.567);
//
template <typename RealType>
using MockBeta =
random_internal::MockOverloadSet<absl::beta_distribution<RealType>,
RealType(MockingBitGen&, RealType,
RealType)>;
// -----------------------------------------------------------------------------
// absl::MockExponential
// -----------------------------------------------------------------------------
//
// Matches calls to absl::Exponential.
//
// `absl::MockExponential` is a class template used in conjunction with
// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
// and use `Call(...)` the same way one would define mocks on a
// Googletest `MockFunction()`.
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockExponential<double>(), Call(mock, 0.5))
// .WillOnce(Return(12.3456789));
// auto x = absl::Exponential<double>(mock, 0.5);
// assert(x == 12.3456789)
//
template <typename RealType>
using MockExponential =
random_internal::MockOverloadSet<absl::exponential_distribution<RealType>,
RealType(MockingBitGen&, RealType)>;
// -----------------------------------------------------------------------------
// absl::MockGaussian
// -----------------------------------------------------------------------------
//
// Matches calls to absl::Gaussian.
//
// `absl::MockGaussian` is a class template used in conjunction with
// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
// and use `Call(...)` the same way one would define mocks on a
// Googletest `MockFunction()`.
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockGaussian<double>(), Call(mock, 16.3, 3.3))
// .WillOnce(Return(12.3456789));
// auto x = absl::Gaussian<double>(mock, 16.3, 3.3);
// assert(x == 12.3456789)
//
template <typename RealType>
using MockGaussian =
random_internal::MockOverloadSet<absl::gaussian_distribution<RealType>,
RealType(MockingBitGen&, RealType,
RealType)>;
// -----------------------------------------------------------------------------
// absl::MockLogUniform
// -----------------------------------------------------------------------------
//
// Matches calls to absl::LogUniform.
//
// `absl::MockLogUniform` is a class template used in conjunction with
// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
// and use `Call(...)` the same way one would define mocks on a
// Googletest `MockFunction()`.
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockLogUniform<int>(), Call(mock, 10, 10000, 10))
// .WillOnce(Return(1221));
// auto x = absl::LogUniform<int>(mock, 10, 10000, 10);
// assert(x == 1221)
//
template <typename IntType>
using MockLogUniform = random_internal::MockOverloadSet<
absl::log_uniform_int_distribution<IntType>,
IntType(MockingBitGen&, IntType, IntType, IntType)>;
// -----------------------------------------------------------------------------
// absl::MockPoisson
// -----------------------------------------------------------------------------
//
// Matches calls to absl::Poisson.
//
// `absl::MockPoisson` is a class template used in conjunction with Googletest's
// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
// same way one would define mocks on a Googletest `MockFunction()`.
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockPoisson<int>(), Call(mock, 2.0))
// .WillOnce(Return(1221));
// auto x = absl::Poisson<int>(mock, 2.0);
// assert(x == 1221)
//
template <typename IntType>
using MockPoisson =
random_internal::MockOverloadSet<absl::poisson_distribution<IntType>,
IntType(MockingBitGen&, double)>;
// -----------------------------------------------------------------------------
// absl::MockZipf
// -----------------------------------------------------------------------------
//
// Matches calls to absl::Zipf.
//
// `absl::MockZipf` is a class template used in conjunction with Googletest's
// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
// same way one would define mocks on a Googletest `MockFunction()`.
//
// Example:
//
// absl::MockingBitGen mock;
// EXPECT_CALL(absl::MockZipf<int>(), Call(mock, 1000000, 2.0, 1.0))
// .WillOnce(Return(1221));
// auto x = absl::Zipf<int>(mock, 1000000, 2.0, 1.0);
// assert(x == 1221)
//
template <typename IntType>
using MockZipf =
random_internal::MockOverloadSet<absl::zipf_distribution<IntType>,
IntType(MockingBitGen&, IntType, double,
double)>;
} // namespace absl
#endif // ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_

View file

@ -0,0 +1,72 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "absl/random/mock_distributions.h"
#include "gtest/gtest.h"
#include "absl/random/mocking_bit_gen.h"
#include "absl/random/random.h"
namespace {
using ::testing::Return;
TEST(MockDistributions, Examples) {
absl::MockingBitGen gen;
EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
.WillOnce(Return(20));
EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
.WillOnce(Return(5.0));
EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
.WillOnce(Return(42));
EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500));
EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
.WillOnce(Return(true));
EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
EXPECT_NE(absl::Beta<double>(gen, 3.0, 2.0), 0.567);
EXPECT_CALL(absl::MockBeta<double>(), Call(gen, 3.0, 2.0))
.WillOnce(Return(0.567));
EXPECT_EQ(absl::Beta<double>(gen, 3.0, 2.0), 0.567);
EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
.WillOnce(Return(1221));
EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
.WillOnce(Return(0.001));
EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
.WillOnce(Return(2040));
EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
}
} // namespace

View file

@ -0,0 +1,28 @@
//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "absl/random/mocking_bit_gen.h"
#include <string>
namespace absl {
MockingBitGen::~MockingBitGen() {
for (const auto& del : deleters_) {
del();
}
}
} // namespace absl

View file

@ -0,0 +1,194 @@
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// mocking_bit_gen.h
// -----------------------------------------------------------------------------
//
// This file includes an `absl::MockingBitGen` class to use as a mock within the
// Googletest testing framework. Such a mock is useful to provide deterministic
// values as return values within (otherwise random) Abseil distribution
// functions. Such determinism within a mock is useful within testing frameworks
// to test otherwise indeterminate APIs.
//
// More information about the Googletest testing framework is available at
// https://github.com/google/googletest
#ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_
#define ABSL_RANDOM_MOCKING_BIT_GEN_H_
#include <iterator>
#include <limits>
#include <memory>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <typeinfo>
#include <utility>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/container/flat_hash_map.h"
#include "absl/meta/type_traits.h"
#include "absl/random/distributions.h"
#include "absl/random/internal/distribution_caller.h"
#include "absl/random/internal/mocking_bit_gen_base.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/types/span.h"
#include "absl/types/variant.h"
#include "absl/utility/utility.h"
namespace absl {
namespace random_internal {
template <typename, typename>
struct MockSingleOverload;
} // namespace random_internal
// MockingBitGen
//
// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class
// which can act in place of an `absl::BitGen` URBG within tests using the
// Googletest testing framework.
//
// Usage:
//
// Use an `absl::MockingBitGen` along with a mock distribution object (within
// mock_distributions.h) inside Googletest constructs such as ON_CALL(),
// EXPECT_TRUE(), etc. to produce deterministic results conforming to the
// distribution's API contract.
//
// Example:
//
// // Mock a call to an `absl::Bernoulli` distribution using Googletest
// absl::MockingBitGen bitgen;
//
// ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5))
// .WillByDefault(testing::Return(true));
// EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5));
//
// // Mock a call to an `absl::Uniform` distribution within Googletest
// absl::MockingBitGen bitgen;
//
// ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_))
// .WillByDefault([] (int low, int high) {
// return (low + high) / 2;
// });
//
// EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5);
// EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35);
//
// At this time, only mock distributions supplied within the Abseil random
// library are officially supported.
//
class MockingBitGen : public absl::random_internal::MockingBitGenBase {
public:
MockingBitGen() {}
~MockingBitGen() override;
private:
template <typename DistrT, typename... Args>
using MockFnType =
::testing::MockFunction<typename DistrT::result_type(Args...)>;
// MockingBitGen::Register
//
// Register<DistrT, FormatT, ArgTupleT> is the main extension point for
// extending the MockingBitGen framework. It provides a mechanism to install a
// mock expectation for the distribution `distr_t` onto the MockingBitGen
// context.
//
// The returned MockFunction<...> type can be used to setup additional
// distribution parameters of the expectation.
template <typename DistrT, typename... Args, typename... Ms>
decltype(std::declval<MockFnType<DistrT, Args...>>().gmock_Call(
std::declval<Ms>()...))
Register(Ms&&... matchers) {
auto& mock =
mocks_[std::type_index(GetTypeId<DistrT, std::tuple<Args...>>())];
if (!mock.mock_fn) {
auto* mock_fn = new MockFnType<DistrT, Args...>;
mock.mock_fn = mock_fn;
mock.match_impl = &MatchImpl<DistrT, Args...>;
deleters_.emplace_back([mock_fn] { delete mock_fn; });
}
return static_cast<MockFnType<DistrT, Args...>*>(mock.mock_fn)
->gmock_Call(std::forward<Ms>(matchers)...);
}
mutable std::vector<std::function<void()>> deleters_;
using match_impl_fn = void (*)(void* mock_fn, void* t_erased_dist_args,
void* t_erased_result);
struct MockData {
void* mock_fn = nullptr;
match_impl_fn match_impl = nullptr;
};
mutable absl::flat_hash_map<std::type_index, MockData> mocks_;
template <typename DistrT, typename... Args>
static void MatchImpl(void* mock_fn, void* dist_args, void* result) {
using result_type = typename DistrT::result_type;
*static_cast<result_type*>(result) = absl::apply(
[mock_fn](Args... args) -> result_type {
return (*static_cast<MockFnType<DistrT, Args...>*>(mock_fn))
.Call(std::move(args)...);
},
*static_cast<std::tuple<Args...>*>(dist_args));
}
// Looks for an appropriate mock - Returns the mocked result if one is found.
// Otherwise, returns a random value generated by the underlying URBG.
bool CallImpl(const std::type_info& key_type, void* dist_args,
void* result) override {
// Trigger a mock, if there exists one that matches `param`.
auto it = mocks_.find(std::type_index(key_type));
if (it == mocks_.end()) return false;
auto* mock_data = static_cast<MockData*>(&it->second);
mock_data->match_impl(mock_data->mock_fn, dist_args, result);
return true;
}
template <typename, typename>
friend struct ::absl::random_internal::MockSingleOverload;
friend struct ::absl::random_internal::DistributionCaller<
absl::MockingBitGen>;
};
// -----------------------------------------------------------------------------
// Implementation Details Only Below
// -----------------------------------------------------------------------------
namespace random_internal {
template <>
struct DistributionCaller<absl::MockingBitGen> {
template <typename DistrT, typename FormatT, typename... Args>
static typename DistrT::result_type Call(absl::MockingBitGen* gen,
Args&&... args) {
return gen->template Call<DistrT, FormatT>(std::forward<Args>(args)...);
}
};
} // namespace random_internal
} // namespace absl
#endif // ABSL_RANDOM_MOCKING_BIT_GEN_H_

View file

@ -0,0 +1,347 @@
//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "absl/random/mocking_bit_gen.h"
#include <numeric>
#include <random>
#include "gmock/gmock.h"
#include "gtest/gtest-spi.h"
#include "gtest/gtest.h"
#include "absl/random/bit_gen_ref.h"
#include "absl/random/mock_distributions.h"
#include "absl/random/random.h"
namespace {
using ::testing::Ne;
using ::testing::Return;
TEST(BasicMocking, AllDistributionsAreOverridable) {
absl::MockingBitGen gen;
EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
.WillOnce(Return(20));
EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
.WillOnce(Return(5.0));
EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
.WillOnce(Return(42));
EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500));
EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
.WillOnce(Return(true));
EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
.WillOnce(Return(1221));
EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
.WillOnce(Return(0.001));
EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
.WillOnce(Return(2040));
EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
}
TEST(BasicMocking, OnDistribution) {
absl::MockingBitGen gen;
EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
ON_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
.WillByDefault(Return(20));
EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
ON_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
.WillByDefault(Return(5.0));
EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
.WillByDefault(Return(42));
EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
ON_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillByDefault(Return(500));
EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
ON_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
.WillByDefault(Return(true));
EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
.WillByDefault(Return(1221));
EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
ON_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
.WillByDefault(Return(0.001));
EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
ON_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
.WillByDefault(Return(2040));
EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
}
TEST(BasicMocking, GMockMatchers) {
absl::MockingBitGen gen;
EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
.WillByDefault(Return(1221));
EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
}
TEST(BasicMocking, OverridesWithMultipleGMockExpectations) {
absl::MockingBitGen gen;
EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 10000))
.WillOnce(Return(20))
.WillOnce(Return(40))
.WillOnce(Return(60));
EXPECT_EQ(absl::Uniform(gen, 1, 10000), 20);
EXPECT_EQ(absl::Uniform(gen, 1, 10000), 40);
EXPECT_EQ(absl::Uniform(gen, 1, 10000), 60);
}
TEST(BasicMocking, DefaultArgument) {
absl::MockingBitGen gen;
ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
.WillByDefault(Return(200));
EXPECT_EQ(absl::Exponential<double>(gen), 200);
EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 200);
}
TEST(BasicMocking, MultipleGenerators) {
auto get_value = [](absl::BitGenRef gen_ref) {
return absl::Uniform(gen_ref, 1, 1000000);
};
absl::MockingBitGen unmocked_generator;
absl::MockingBitGen mocked_with_3;
absl::MockingBitGen mocked_with_11;
EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_3, 1, 1000000))
.WillOnce(Return(3))
.WillRepeatedly(Return(17));
EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_11, 1, 1000000))
.WillOnce(Return(11))
.WillRepeatedly(Return(17));
// Ensure that unmocked generator generates neither value.
int unmocked_value = get_value(unmocked_generator);
EXPECT_NE(unmocked_value, 3);
EXPECT_NE(unmocked_value, 11);
// Mocked generators should generate their mocked values.
EXPECT_EQ(get_value(mocked_with_3), 3);
EXPECT_EQ(get_value(mocked_with_11), 11);
// Ensure that the mocks have expired.
EXPECT_NE(get_value(mocked_with_3), 3);
EXPECT_NE(get_value(mocked_with_11), 11);
}
TEST(BasicMocking, MocksNotTrigeredForIncorrectTypes) {
absl::MockingBitGen gen;
EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42));
EXPECT_NE(absl::Uniform<uint16_t>(gen), 42); // Not mocked
EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42); // Mock triggered
}
TEST(BasicMocking, FailsOnUnsatisfiedMocks) {
EXPECT_NONFATAL_FAILURE(
[]() {
absl::MockingBitGen gen;
EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
.WillOnce(Return(3.0));
// Does not call absl::Exponential().
}(),
"unsatisfied and active");
}
TEST(OnUniform, RespectsUniformIntervalSemantics) {
absl::MockingBitGen gen;
EXPECT_CALL(absl::MockUniform<int>(),
Call(absl::IntervalClosed, gen, 1, 1000000))
.WillOnce(Return(301));
EXPECT_NE(absl::Uniform(gen, 1, 1000000), 301); // Not mocked
EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 1, 1000000), 301);
}
TEST(OnUniform, RespectsNoArgUnsignedShorthand) {
absl::MockingBitGen gen;
EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42));
EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42);
}
TEST(RepeatedlyModifier, ForceSnakeEyesForManyDice) {
auto roll_some_dice = [](absl::BitGenRef gen_ref) {
std::vector<int> results(16);
for (auto& r : results) {
r = absl::Uniform(absl::IntervalClosed, gen_ref, 1, 6);
}
return results;
};
std::vector<int> results;
absl::MockingBitGen gen;
// Without any mocked calls, not all dice roll a "6".
results = roll_some_dice(gen);
EXPECT_LT(std::accumulate(std::begin(results), std::end(results), 0),
results.size() * 6);
// Verify that we can force all "6"-rolls, with mocking.
ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, 1, 6))
.WillByDefault(Return(6));
results = roll_some_dice(gen);
EXPECT_EQ(std::accumulate(std::begin(results), std::end(results), 0),
results.size() * 6);
}
TEST(WillOnce, DistinctCounters) {
absl::MockingBitGen gen;
EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
.Times(3)
.WillRepeatedly(Return(0));
EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1000001, 2000000))
.Times(3)
.WillRepeatedly(Return(1));
EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
}
TEST(TimesModifier, ModifierSaturatesAndExpires) {
EXPECT_NONFATAL_FAILURE(
[]() {
absl::MockingBitGen gen;
EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
.Times(3)
.WillRepeatedly(Return(15))
.RetiresOnSaturation();
EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
// Times(3) has expired - Should get a different value now.
EXPECT_NE(absl::Uniform(gen, 1, 1000000), 15);
}(),
"");
}
TEST(TimesModifier, Times0) {
absl::MockingBitGen gen;
EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.0)).Times(0);
EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).Times(0);
}
TEST(AnythingMatcher, MatchesAnyArgument) {
using testing::_;
{
absl::MockingBitGen gen;
ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, _, 1000))
.WillByDefault(Return(11));
ON_CALL(absl::MockUniform<int>(),
Call(absl::IntervalClosed, gen, _, Ne(1000)))
.WillByDefault(Return(99));
EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000000), 99);
EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000), 11);
}
{
absl::MockingBitGen gen;
ON_CALL(absl::MockUniform<int>(), Call(gen, 1, _))
.WillByDefault(Return(25));
ON_CALL(absl::MockUniform<int>(), Call(gen, Ne(1), _))
.WillByDefault(Return(99));
EXPECT_EQ(absl::Uniform(gen, 3, 1000000), 99);
EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 25);
}
{
absl::MockingBitGen gen;
ON_CALL(absl::MockUniform<int>(), Call(gen, _, _))
.WillByDefault(Return(145));
EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);
EXPECT_EQ(absl::Uniform(gen, 10, 1000), 145);
EXPECT_EQ(absl::Uniform(gen, 100, 1000), 145);
}
}
TEST(AnythingMatcher, WithWillByDefault) {
using testing::_;
absl::MockingBitGen gen;
std::vector<int> values = {11, 22, 33, 44, 55, 66, 77, 88, 99, 1010};
ON_CALL(absl::MockUniform<size_t>(), Call(gen, 0, _))
.WillByDefault(Return(0));
for (int i = 0; i < 100; i++) {
auto& elem = values[absl::Uniform(gen, 0u, values.size())];
EXPECT_EQ(elem, 11);
}
}
TEST(BasicMocking, WillByDefaultWithArgs) {
using testing::_;
absl::MockingBitGen gen;
ON_CALL(absl::MockPoisson<int>(), Call(gen, _))
.WillByDefault(
[](double lambda) { return static_cast<int>(lambda * 10); });
EXPECT_EQ(absl::Poisson<int>(gen, 1.7), 17);
EXPECT_EQ(absl::Poisson<int>(gen, 0.03), 0);
}
TEST(MockingBitGen, InSequenceSucceedsInOrder) {
absl::MockingBitGen gen;
testing::InSequence seq;
EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(3));
EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 2.0)).WillOnce(Return(4));
EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 3);
EXPECT_EQ(absl::Poisson<int>(gen, 2.0), 4);
}
} // namespace