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:
parent
8ba96a8244
commit
bcaae6009c
12 changed files with 1598 additions and 0 deletions
|
@ -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",
|
||||
|
|
|
@ -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
151
absl/random/bit_gen_ref.h
Normal 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_
|
99
absl/random/bit_gen_ref_test.cc
Normal file
99
absl/random/bit_gen_ref_test.cc
Normal 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
|
|
@ -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",
|
||||
|
|
89
absl/random/internal/mock_overload_set.h
Normal file
89
absl/random/internal/mock_overload_set.h
Normal 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_
|
118
absl/random/internal/mocking_bit_gen_base.h
Normal file
118
absl/random/internal/mocking_bit_gen_base.h
Normal 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_
|
259
absl/random/mock_distributions.h
Normal file
259
absl/random/mock_distributions.h
Normal 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_
|
72
absl/random/mock_distributions_test.cc
Normal file
72
absl/random/mock_distributions_test.cc
Normal 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
|
28
absl/random/mocking_bit_gen.cc
Normal file
28
absl/random/mocking_bit_gen.cc
Normal 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
|
194
absl/random/mocking_bit_gen.h
Normal file
194
absl/random/mocking_bit_gen.h
Normal 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_
|
347
absl/random/mocking_bit_gen_test.cc
Normal file
347
absl/random/mocking_bit_gen_test.cc
Normal 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
|
Loading…
Reference in a new issue