Squashed 'third_party/abseil_cpp/' changes from 768eb2ca2..ccdbb5941
ccdbb5941 Export of internal Abseil changes 01f5f81f9 Export of internal Abseil changes 2c92bdc7c Export of internal Abseil changes e7ebf9803 Export of internal Abseil changes 2eba343b5 Export of internal Abseil changes a8b03d90e Export of internal Abseil changes 1d31b5c36 Export of internal Abseil changes da3a87690 Export of internal Abseil changes 8faf20461 Exclude empty directories (#697) 2069dc796 Export of internal Abseil changes 4832bf6bf Added a BUILD file in root to expose license. (#695) af8f994af Export of internal Abseil changes 33caf1097 Export of internal Abseil changes cf1a02e2d Export of internal Abseil changes git-subtree-dir: third_party/abseil_cpp git-subtree-split: ccdbb5941f992fabda7eae3ce72f55efc17c826a
This commit is contained in:
parent
768eb2ca28
commit
8f2828c4b4
97 changed files with 3546 additions and 2316 deletions
|
|
@ -69,7 +69,7 @@ cc_library(
|
|||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/random/internal:distributions",
|
||||
"//absl/random/internal:distribution_caller",
|
||||
"//absl/random/internal:fast_uniform_bits",
|
||||
"//absl/random/internal:fastmath",
|
||||
"//absl/random/internal:generate_real",
|
||||
|
|
@ -78,7 +78,6 @@ cc_library(
|
|||
"//absl/random/internal:uniform_helper",
|
||||
"//absl/random/internal:wide_multiply",
|
||||
"//absl/strings",
|
||||
"//absl/types:span",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -116,11 +115,12 @@ cc_library(
|
|||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":random",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:fast_type_id",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/random/internal:distribution_caller",
|
||||
"//absl/random/internal:fast_uniform_bits",
|
||||
"//absl/random/internal:mocking_bit_gen_base",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -146,10 +146,11 @@ cc_library(
|
|||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":distributions",
|
||||
":random",
|
||||
"//absl/base:fast_type_id",
|
||||
"//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",
|
||||
|
|
@ -411,6 +412,7 @@ cc_test(
|
|||
deps = [
|
||||
":bit_gen_ref",
|
||||
":random",
|
||||
"//absl/base:fast_type_id",
|
||||
"//absl/random/internal:sequence_urbg",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ absl_cc_library(
|
|||
absl::core_headers
|
||||
absl::random_internal_distribution_caller
|
||||
absl::random_internal_fast_uniform_bits
|
||||
absl::random_internal_mocking_bit_gen_base
|
||||
absl::type_traits
|
||||
)
|
||||
|
||||
|
|
@ -62,6 +61,7 @@ absl_cc_test(
|
|||
absl::random_bit_gen_ref
|
||||
absl::random_random
|
||||
absl::random_internal_sequence_urbg
|
||||
absl::fast_type_id
|
||||
gmock
|
||||
gtest_main
|
||||
)
|
||||
|
|
@ -69,16 +69,16 @@ absl_cc_test(
|
|||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
random_internal_mocking_bit_gen_base
|
||||
random_internal_mock_helpers
|
||||
HDRS
|
||||
"internal/mocking_bit_gen_base.h"
|
||||
"internal/mock_helpers.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::random_random
|
||||
absl::strings
|
||||
absl::fast_type_id
|
||||
absl::optional
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
|
|
@ -93,6 +93,7 @@ absl_cc_library(
|
|||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::random_mocking_bit_gen
|
||||
absl::random_internal_mock_helpers
|
||||
TESTONLY
|
||||
)
|
||||
|
||||
|
|
@ -111,8 +112,8 @@ absl_cc_library(
|
|||
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::random_random
|
||||
absl::strings
|
||||
absl::span
|
||||
absl::type_traits
|
||||
|
|
@ -183,7 +184,7 @@ absl_cc_library(
|
|||
absl::config
|
||||
absl::core_headers
|
||||
absl::random_internal_generate_real
|
||||
absl::random_internal_distributions
|
||||
absl::random_internal_distribution_caller
|
||||
absl::random_internal_fast_uniform_bits
|
||||
absl::random_internal_fastmath
|
||||
absl::random_internal_iostream_state_saver
|
||||
|
|
@ -191,7 +192,6 @@ absl_cc_library(
|
|||
absl::random_internal_uniform_helper
|
||||
absl::random_internal_wide_multiply
|
||||
absl::strings
|
||||
absl::span
|
||||
absl::type_traits
|
||||
)
|
||||
|
||||
|
|
@ -534,27 +534,8 @@ absl_cc_library(
|
|||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::config
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
absl_cc_library(
|
||||
NAME
|
||||
random_internal_distributions
|
||||
HDRS
|
||||
"internal/distributions.h"
|
||||
COPTS
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::random_internal_distribution_caller
|
||||
absl::random_internal_fast_uniform_bits
|
||||
absl::random_internal_fastmath
|
||||
absl::random_internal_traits
|
||||
absl::random_internal_uniform_helper
|
||||
absl::span
|
||||
absl::strings
|
||||
absl::type_traits
|
||||
absl::utility
|
||||
absl::fast_type_id
|
||||
)
|
||||
|
||||
# Internal-only target, do not depend on directly.
|
||||
|
|
@ -745,7 +726,6 @@ absl_cc_library(
|
|||
absl::random_internal_salted_seed_seq
|
||||
absl::random_internal_seed_material
|
||||
absl::span
|
||||
absl::strings
|
||||
absl::type_traits
|
||||
)
|
||||
|
||||
|
|
@ -1174,9 +1154,7 @@ absl_cc_library(
|
|||
LINKOPTS
|
||||
${ABSL_DEFAULT_LINKOPTS}
|
||||
DEPS
|
||||
absl::core_headers
|
||||
absl::random_internal_fast_uniform_bits
|
||||
absl::random_internal_iostream_state_saver
|
||||
absl::config
|
||||
absl::random_internal_traits
|
||||
absl::type_traits
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@
|
|||
#ifndef ABSL_RANDOM_BIT_GEN_REF_H_
|
||||
#define ABSL_RANDOM_BIT_GEN_REF_H_
|
||||
|
||||
#include "absl/base/internal/fast_type_id.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 {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
|
@ -51,6 +51,10 @@ struct is_urbg<
|
|||
typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename>
|
||||
struct DistributionCaller;
|
||||
class MockHelpers;
|
||||
|
||||
} // namespace random_internal
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -77,23 +81,50 @@ struct is_urbg<
|
|||
// }
|
||||
//
|
||||
class BitGenRef {
|
||||
public:
|
||||
using result_type = uint64_t;
|
||||
// SFINAE to detect whether the URBG type includes a member matching
|
||||
// bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
|
||||
//
|
||||
// These live inside BitGenRef so that they have friend access
|
||||
// to MockingBitGen. (see similar methods in DistributionCaller).
|
||||
template <template <class...> class Trait, class AlwaysVoid, class... Args>
|
||||
struct detector : std::false_type {};
|
||||
template <template <class...> class Trait, class... Args>
|
||||
struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
|
||||
: std::true_type {};
|
||||
|
||||
BitGenRef(const absl::BitGenRef&) = default;
|
||||
BitGenRef(absl::BitGenRef&&) = default;
|
||||
BitGenRef& operator=(const absl::BitGenRef&) = default;
|
||||
BitGenRef& operator=(absl::BitGenRef&&) = default;
|
||||
template <class T>
|
||||
using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
|
||||
std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
|
||||
std::declval<void*>()));
|
||||
|
||||
template <typename T>
|
||||
using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
|
||||
|
||||
public:
|
||||
BitGenRef(const BitGenRef&) = default;
|
||||
BitGenRef(BitGenRef&&) = default;
|
||||
BitGenRef& operator=(const BitGenRef&) = default;
|
||||
BitGenRef& operator=(BitGenRef&&) = default;
|
||||
|
||||
template <typename URBG, typename absl::enable_if_t<
|
||||
(!std::is_same<URBG, BitGenRef>::value &&
|
||||
random_internal::is_urbg<URBG>::value &&
|
||||
!HasInvokeMock<URBG>::value)>* = nullptr>
|
||||
BitGenRef(URBG& gen) // NOLINT
|
||||
: t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
|
||||
mock_call_(NotAMock),
|
||||
generate_impl_fn_(ImplFn<URBG>) {}
|
||||
|
||||
template <typename URBG,
|
||||
typename absl::enable_if_t<
|
||||
(!std::is_same<URBG, BitGenRef>::value &&
|
||||
random_internal::is_urbg<URBG>::value)>* = nullptr>
|
||||
typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
|
||||
random_internal::is_urbg<URBG>::value &&
|
||||
HasInvokeMock<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>) {
|
||||
}
|
||||
: t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
|
||||
mock_call_(&MockCall<URBG>),
|
||||
generate_impl_fn_(ImplFn<URBG>) {}
|
||||
|
||||
using result_type = uint64_t;
|
||||
|
||||
static constexpr result_type(min)() {
|
||||
return (std::numeric_limits<result_type>::min)();
|
||||
|
|
@ -106,14 +137,9 @@ class BitGenRef {
|
|||
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; }
|
||||
using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
|
||||
void*);
|
||||
|
||||
template <typename URBG>
|
||||
static result_type ImplFn(uintptr_t ptr) {
|
||||
|
|
@ -123,29 +149,32 @@ class BitGenRef {
|
|||
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... 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>(std::forward<Args>(args)...);
|
||||
}
|
||||
// Get a type-erased InvokeMock pointer.
|
||||
template <typename URBG>
|
||||
static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type,
|
||||
void* result, void* arg_tuple) {
|
||||
return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result,
|
||||
arg_tuple);
|
||||
}
|
||||
static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
|
||||
void* result) {
|
||||
if (mock_call_ == NotAMock) return false; // avoids an indirect call.
|
||||
return mock_call_(t_erased_gen_ptr_, type, args_tuple, result);
|
||||
}
|
||||
|
||||
uintptr_t t_erased_gen_ptr_;
|
||||
mock_call_fn mock_call_;
|
||||
impl_fn generate_impl_fn_;
|
||||
|
||||
template <typename>
|
||||
friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock
|
||||
friend class ::absl::random_internal::MockHelpers; // for InvokeMock
|
||||
};
|
||||
|
||||
} // namespace random_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
|
|
|
|||
|
|
@ -17,30 +17,31 @@
|
|||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/internal/fast_type_id.h"
|
||||
#include "absl/random/internal/sequence_urbg.h"
|
||||
#include "absl/random/random.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
class ConstBitGen : public absl::random_internal::MockingBitGenBase {
|
||||
bool CallImpl(const std::type_info&, void*, void* result) override {
|
||||
class ConstBitGen {
|
||||
public:
|
||||
// URBG interface
|
||||
using result_type = absl::BitGen::result_type;
|
||||
|
||||
static constexpr result_type(min)() { return (absl::BitGen::min)(); }
|
||||
static constexpr result_type(max)() { return (absl::BitGen::max)(); }
|
||||
result_type operator()() { return 1; }
|
||||
|
||||
// InvokeMock method
|
||||
bool InvokeMock(base_internal::FastTypeIdType index, void*, void* result) {
|
||||
*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>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
#include "absl/random/beta_distribution.h"
|
||||
#include "absl/random/exponential_distribution.h"
|
||||
#include "absl/random/gaussian_distribution.h"
|
||||
#include "absl/random/internal/distributions.h" // IWYU pragma: export
|
||||
#include "absl/random/internal/distribution_caller.h" // IWYU pragma: export
|
||||
#include "absl/random/internal/uniform_helper.h" // IWYU pragma: export
|
||||
#include "absl/random/log_uniform_int_distribution.h"
|
||||
#include "absl/random/poisson_distribution.h"
|
||||
|
|
|
|||
|
|
@ -45,21 +45,10 @@ cc_library(
|
|||
hdrs = ["distribution_caller.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = ["//absl/base:config"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "distributions",
|
||||
hdrs = ["distributions.h"],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":distribution_caller",
|
||||
":traits",
|
||||
":uniform_helper",
|
||||
"//absl/base",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/strings",
|
||||
"//absl/base:config",
|
||||
"//absl/base:fast_type_id",
|
||||
"//absl/utility",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -221,7 +210,6 @@ cc_library(
|
|||
":seed_material",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/meta:type_traits",
|
||||
"//absl/strings",
|
||||
"//absl/types:optional",
|
||||
"//absl/types:span",
|
||||
],
|
||||
|
|
@ -497,12 +485,11 @@ cc_test(
|
|||
)
|
||||
|
||||
cc_library(
|
||||
name = "mocking_bit_gen_base",
|
||||
hdrs = ["mocking_bit_gen_base.h"],
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
name = "mock_helpers",
|
||||
hdrs = ["mock_helpers.h"],
|
||||
deps = [
|
||||
"//absl/random",
|
||||
"//absl/strings",
|
||||
"//absl/base:fast_type_id",
|
||||
"//absl/types:optional",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -511,6 +498,7 @@ cc_library(
|
|||
testonly = 1,
|
||||
hdrs = ["mock_overload_set.h"],
|
||||
deps = [
|
||||
":mock_helpers",
|
||||
"//absl/random:mocking_bit_gen",
|
||||
"@com_google_googletest//:gtest",
|
||||
],
|
||||
|
|
@ -672,6 +660,8 @@ cc_library(
|
|||
copts = ABSL_DEFAULT_COPTS,
|
||||
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||
deps = [
|
||||
":traits",
|
||||
"//absl/base:config",
|
||||
"//absl/meta:type_traits",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
#include <utility>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/fast_type_id.h"
|
||||
#include "absl/utility/utility.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
|
@ -30,14 +32,57 @@ namespace random_internal {
|
|||
// to intercept such calls.
|
||||
template <typename URBG>
|
||||
struct DistributionCaller {
|
||||
// Call the provided distribution type. The parameters are expected
|
||||
// to be explicitly specified.
|
||||
// DistrT is the distribution type.
|
||||
// SFINAE to detect whether the URBG type includes a member matching
|
||||
// bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
|
||||
//
|
||||
// These live inside BitGenRef so that they have friend access
|
||||
// to MockingBitGen. (see similar methods in DistributionCaller).
|
||||
template <template <class...> class Trait, class AlwaysVoid, class... Args>
|
||||
struct detector : std::false_type {};
|
||||
template <template <class...> class Trait, class... Args>
|
||||
struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
|
||||
: std::true_type {};
|
||||
|
||||
template <class T>
|
||||
using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
|
||||
std::declval<::absl::base_internal::FastTypeIdType>(),
|
||||
std::declval<void*>(), std::declval<void*>()));
|
||||
|
||||
using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
|
||||
|
||||
// Default implementation of distribution caller.
|
||||
template <typename DistrT, typename... Args>
|
||||
static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
|
||||
static typename DistrT::result_type Impl(std::false_type, URBG* urbg,
|
||||
Args&&... args) {
|
||||
DistrT dist(std::forward<Args>(args)...);
|
||||
return dist(*urbg);
|
||||
}
|
||||
|
||||
// Mock implementation of distribution caller.
|
||||
// The underlying KeyT must match the KeyT constructed by MockOverloadSet.
|
||||
template <typename DistrT, typename... Args>
|
||||
static typename DistrT::result_type Impl(std::true_type, URBG* urbg,
|
||||
Args&&... args) {
|
||||
using ResultT = typename DistrT::result_type;
|
||||
using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
|
||||
using KeyT = ResultT(DistrT, ArgTupleT);
|
||||
|
||||
ArgTupleT arg_tuple(std::forward<Args>(args)...);
|
||||
ResultT result;
|
||||
if (!urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
|
||||
&result)) {
|
||||
auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
|
||||
result = dist(*urbg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Default implementation of distribution caller.
|
||||
template <typename DistrT, typename... Args>
|
||||
static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
|
||||
return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace random_internal
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
// 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_DISTRIBUTIONS_H_
|
||||
#define ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/meta/type_traits.h"
|
||||
#include "absl/random/internal/distribution_caller.h"
|
||||
#include "absl/random/internal/traits.h"
|
||||
#include "absl/random/internal/uniform_helper.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace random_internal {
|
||||
|
||||
// In the absence of an explicitly provided return-type, the template
|
||||
// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
|
||||
// the data-types of the endpoint-arguments {A lo, B hi}.
|
||||
//
|
||||
// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
|
||||
// return-type, if one type can be implicitly converted into the other, in a
|
||||
// lossless way. The template "is_widening_convertible" implements the
|
||||
// compile-time logic for deciding if such a conversion is possible.
|
||||
//
|
||||
// If no such conversion between {A, B} exists, then the overload for
|
||||
// absl::Uniform() will be discarded, and the call will be ill-formed.
|
||||
// Return-type for absl::Uniform() when the return-type is inferred.
|
||||
template <typename A, typename B>
|
||||
using uniform_inferred_return_t =
|
||||
absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
|
||||
is_widening_convertible<B, A>>::value,
|
||||
typename std::conditional<
|
||||
is_widening_convertible<A, B>::value, B, A>::type>;
|
||||
|
||||
} // namespace random_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
|
||||
127
absl/random/internal/mock_helpers.h
Normal file
127
absl/random/internal/mock_helpers.h
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// 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_HELPERS_H_
|
||||
#define ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/internal/fast_type_id.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace random_internal {
|
||||
|
||||
// MockHelpers works in conjunction with MockOverloadSet, MockingBitGen, and
|
||||
// BitGenRef to enable the mocking capability for absl distribution functions.
|
||||
//
|
||||
// MockingBitGen registers mocks based on the typeid of a mock signature, KeyT,
|
||||
// which is used to generate a unique id.
|
||||
//
|
||||
// KeyT is a signature of the form:
|
||||
// result_type(discriminator_type, std::tuple<args...>)
|
||||
// The mocked function signature will be composed from KeyT as:
|
||||
// result_type(args...)
|
||||
//
|
||||
class MockHelpers {
|
||||
using IdType = ::absl::base_internal::FastTypeIdType;
|
||||
|
||||
// Given a key signature type used to index the mock, extract the components.
|
||||
// KeyT is expected to have the form:
|
||||
// result_type(discriminator_type, arg_tuple_type)
|
||||
template <typename KeyT>
|
||||
struct KeySignature;
|
||||
|
||||
template <typename ResultT, typename DiscriminatorT, typename ArgTupleT>
|
||||
struct KeySignature<ResultT(DiscriminatorT, ArgTupleT)> {
|
||||
using result_type = ResultT;
|
||||
using discriminator_type = DiscriminatorT;
|
||||
using arg_tuple_type = ArgTupleT;
|
||||
};
|
||||
|
||||
// Detector for InvokeMock.
|
||||
template <class T>
|
||||
using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
|
||||
std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
|
||||
|
||||
// Empty implementation of InvokeMock.
|
||||
template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
|
||||
typename... Args>
|
||||
static absl::optional<ReturnT> InvokeMockImpl(char, URBG*, Args&&...) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
// Non-empty implementation of InvokeMock.
|
||||
template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
|
||||
typename = invoke_mock_t<URBG>, typename... Args>
|
||||
static absl::optional<ReturnT> InvokeMockImpl(int, URBG* urbg,
|
||||
Args&&... args) {
|
||||
ArgTupleT arg_tuple(std::forward<Args>(args)...);
|
||||
ReturnT result;
|
||||
if (urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
|
||||
&result)) {
|
||||
return result;
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
public:
|
||||
// Invoke a mock for the KeyT (may or may not be a signature).
|
||||
//
|
||||
// KeyT is used to generate a typeid-based lookup key for the mock.
|
||||
// KeyT is a signature of the form:
|
||||
// result_type(discriminator_type, std::tuple<args...>)
|
||||
// The mocked function signature will be composed from KeyT as:
|
||||
// result_type(args...)
|
||||
//
|
||||
// An instance of arg_tuple_type must be constructable from Args..., since
|
||||
// the underlying mechanism requires a pointer to an argument tuple.
|
||||
template <typename KeyT, typename URBG, typename... Args>
|
||||
static auto MaybeInvokeMock(URBG* urbg, Args&&... args)
|
||||
-> absl::optional<typename KeySignature<KeyT>::result_type> {
|
||||
// Use function overloading to dispatch to the implemenation since
|
||||
// more modern patterns (e.g. require + constexpr) are not supported in all
|
||||
// compiler configurations.
|
||||
return InvokeMockImpl<KeyT, typename KeySignature<KeyT>::result_type,
|
||||
typename KeySignature<KeyT>::arg_tuple_type, URBG>(
|
||||
0, urbg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Acquire a mock for the KeyT (may or may not be a signature).
|
||||
//
|
||||
// KeyT is used to generate a typeid-based lookup for the mock.
|
||||
// KeyT is a signature of the form:
|
||||
// result_type(discriminator_type, std::tuple<args...>)
|
||||
// The mocked function signature will be composed from KeyT as:
|
||||
// result_type(args...)
|
||||
template <typename KeyT, typename MockURBG>
|
||||
static auto MockFor(MockURBG& m) -> decltype(
|
||||
std::declval<MockURBG>()
|
||||
.template RegisterMock<typename KeySignature<KeyT>::result_type,
|
||||
typename KeySignature<KeyT>::arg_tuple_type>(
|
||||
std::declval<IdType>())) {
|
||||
return m.template RegisterMock<typename KeySignature<KeyT>::result_type,
|
||||
typename KeySignature<KeyT>::arg_tuple_type>(
|
||||
::absl::base_internal::FastTypeId<KeyT>());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace random_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/random/internal/mock_helpers.h"
|
||||
#include "absl/random/mocking_bit_gen.h"
|
||||
|
||||
namespace absl {
|
||||
|
|
@ -35,17 +36,20 @@ struct MockSingleOverload;
|
|||
// 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.
|
||||
// arguments to MockingBitGen::Register.
|
||||
//
|
||||
// The underlying KeyT must match the KeyT constructed by DistributionCaller.
|
||||
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.");
|
||||
"distribution result_type.");
|
||||
using KeyT = Ret(DistrT, std::tuple<Args...>);
|
||||
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...);
|
||||
const ::testing::Matcher<Args>&... matchers)
|
||||
-> decltype(MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...)) {
|
||||
return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -53,13 +57,15 @@ 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.");
|
||||
"distribution result_type.");
|
||||
using KeyT = Ret(DistrT, std::tuple<Arg, Args...>);
|
||||
auto gmock_Call(
|
||||
const ::testing::Matcher<Arg>& arg,
|
||||
const ::testing::Matcher<Arg>& matcher,
|
||||
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...);
|
||||
const ::testing::Matcher<Args>&... matchers)
|
||||
-> decltype(MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher,
|
||||
matchers...)) {
|
||||
return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher, matchers...);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,85 +0,0 @@
|
|||
//
|
||||
// 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 <string>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "absl/random/random.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace random_internal {
|
||||
|
||||
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_(); }
|
||||
|
||||
virtual ~MockingBitGenBase() = default;
|
||||
|
||||
protected:
|
||||
// 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>.
|
||||
// DistT is the distribution type.
|
||||
template <typename DistrT, 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_);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
generator_type gen_;
|
||||
}; // namespace random_internal
|
||||
|
||||
} // namespace random_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_
|
||||
|
|
@ -19,10 +19,13 @@
|
|||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/meta/type_traits.h"
|
||||
#include "absl/random/internal/traits.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
template <typename IntType>
|
||||
class uniform_int_distribution;
|
||||
|
||||
|
|
@ -58,6 +61,26 @@ struct IntervalOpenOpenTag
|
|||
: public random_internal::TagTypeCompare<IntervalOpenOpenTag> {};
|
||||
|
||||
namespace random_internal {
|
||||
|
||||
// In the absence of an explicitly provided return-type, the template
|
||||
// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
|
||||
// the data-types of the endpoint-arguments {A lo, B hi}.
|
||||
//
|
||||
// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
|
||||
// return-type, if one type can be implicitly converted into the other, in a
|
||||
// lossless way. The template "is_widening_convertible" implements the
|
||||
// compile-time logic for deciding if such a conversion is possible.
|
||||
//
|
||||
// If no such conversion between {A, B} exists, then the overload for
|
||||
// absl::Uniform() will be discarded, and the call will be ill-formed.
|
||||
// Return-type for absl::Uniform() when the return-type is inferred.
|
||||
template <typename A, typename B>
|
||||
using uniform_inferred_return_t =
|
||||
absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
|
||||
is_widening_convertible<B, A>>::value,
|
||||
typename std::conditional<
|
||||
is_widening_convertible<A, B>::value, B, A>::type>;
|
||||
|
||||
// The functions
|
||||
// uniform_lower_bound(tag, a, b)
|
||||
// and
|
||||
|
|
@ -149,12 +172,19 @@ uniform_upper_bound(Tag, FloatType, FloatType b) {
|
|||
return std::nextafter(b, (std::numeric_limits<FloatType>::max)());
|
||||
}
|
||||
|
||||
// UniformDistribution selects either absl::uniform_int_distribution
|
||||
// or absl::uniform_real_distribution depending on the NumType parameter.
|
||||
template <typename NumType>
|
||||
using UniformDistribution =
|
||||
typename std::conditional<std::is_integral<NumType>::value,
|
||||
absl::uniform_int_distribution<NumType>,
|
||||
absl::uniform_real_distribution<NumType>>::type;
|
||||
|
||||
// UniformDistributionWrapper is used as the underlying distribution type
|
||||
// by the absl::Uniform template function. It selects the proper Abseil
|
||||
// uniform distribution and provides constructor overloads that match the
|
||||
// expected parameter order as well as adjusting distribtuion bounds based
|
||||
// on the tag.
|
||||
template <typename NumType>
|
||||
struct UniformDistributionWrapper : public UniformDistribution<NumType> {
|
||||
template <typename TagType>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
// More information about the Googletest testing framework is available at
|
||||
// https://github.com/google/googletest
|
||||
//
|
||||
// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
|
||||
// the call to absl::Uniform and related methods, otherwise mocking will fail
|
||||
// since the underlying implementation creates a type-specific pointer which
|
||||
// will be distinct across different DLL boundaries.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// absl::MockingBitGen mock;
|
||||
|
|
|
|||
|
|
@ -33,17 +33,16 @@
|
|||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/internal/fast_type_id.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/random/random.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "absl/types/span.h"
|
||||
|
|
@ -54,11 +53,12 @@ namespace absl {
|
|||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
namespace random_internal {
|
||||
|
||||
template <typename, typename>
|
||||
struct MockSingleOverload;
|
||||
template <typename>
|
||||
struct DistributionCaller;
|
||||
class MockHelpers;
|
||||
|
||||
} // namespace random_internal
|
||||
class BitGenRef;
|
||||
|
||||
// MockingBitGen
|
||||
//
|
||||
|
|
@ -96,102 +96,132 @@ struct MockSingleOverload;
|
|||
// At this time, only mock distributions supplied within the Abseil random
|
||||
// library are officially supported.
|
||||
//
|
||||
class MockingBitGen : public absl::random_internal::MockingBitGenBase {
|
||||
// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
|
||||
// the call to absl::Uniform and related methods, otherwise mocking will fail
|
||||
// since the underlying implementation creates a type-specific pointer which
|
||||
// will be distinct across different DLL boundaries.
|
||||
//
|
||||
class MockingBitGen {
|
||||
public:
|
||||
MockingBitGen() {}
|
||||
MockingBitGen() = default;
|
||||
|
||||
~MockingBitGen() override {
|
||||
~MockingBitGen() {
|
||||
for (const auto& del : deleters_) del();
|
||||
}
|
||||
|
||||
// URBG interface
|
||||
using result_type = absl::BitGen::result_type;
|
||||
|
||||
static constexpr result_type(min)() { return (absl::BitGen::min)(); }
|
||||
static constexpr result_type(max)() { return (absl::BitGen::max)(); }
|
||||
result_type operator()() { return gen_(); }
|
||||
|
||||
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,
|
||||
using match_impl_fn = void (*)(void* mock_fn, void* t_erased_arg_tuple,
|
||||
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_;
|
||||
// GetMockFnType returns the testing::MockFunction for a result and tuple.
|
||||
// This method only exists for type deduction and is otherwise unimplemented.
|
||||
template <typename ResultT, typename... Args>
|
||||
static auto GetMockFnType(ResultT, std::tuple<Args...>)
|
||||
-> ::testing::MockFunction<ResultT(Args...)>;
|
||||
|
||||
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));
|
||||
// MockFnCaller is a helper method for use with absl::apply to
|
||||
// apply an ArgTupleT to a compatible MockFunction.
|
||||
// NOTE: MockFnCaller is essentially equivalent to the lambda:
|
||||
// [fn](auto... args) { return fn->Call(std::move(args)...)}
|
||||
// however that fails to build on some supported platforms.
|
||||
template <typename ResultT, typename MockFnType, typename Tuple>
|
||||
struct MockFnCaller;
|
||||
// specialization for std::tuple.
|
||||
template <typename ResultT, typename MockFnType, typename... Args>
|
||||
struct MockFnCaller<ResultT, MockFnType, std::tuple<Args...>> {
|
||||
MockFnType* fn;
|
||||
inline ResultT operator()(Args... args) {
|
||||
return fn->Call(std::move(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// MockingBitGen::RegisterMock
|
||||
//
|
||||
// RegisterMock<ResultT, ArgTupleT>(FastTypeIdType) is the main extension
|
||||
// point for extending the MockingBitGen framework. It provides a mechanism to
|
||||
// install a mock expectation for a function like ResultT(Args...) keyed by
|
||||
// type_idex onto the MockingBitGen context. The key is that the type_index
|
||||
// used to register must match the type index used to call the mock.
|
||||
//
|
||||
// The returned MockFunction<...> type can be used to setup additional
|
||||
// distribution parameters of the expectation.
|
||||
template <typename ResultT, typename ArgTupleT>
|
||||
auto RegisterMock(base_internal::FastTypeIdType type)
|
||||
-> decltype(GetMockFnType(std::declval<ResultT>(),
|
||||
std::declval<ArgTupleT>()))& {
|
||||
using MockFnType = decltype(
|
||||
GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>()));
|
||||
auto& mock = mocks_[type];
|
||||
if (!mock.mock_fn) {
|
||||
auto* mock_fn = new MockFnType;
|
||||
mock.mock_fn = mock_fn;
|
||||
mock.match_impl = &MatchImpl<ResultT, ArgTupleT>;
|
||||
deleters_.emplace_back([mock_fn] { delete mock_fn; });
|
||||
}
|
||||
return *static_cast<MockFnType*>(mock.mock_fn);
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// MockingBitGen::MatchImpl<> is a dispatch function which converts the
|
||||
// generic type-erased parameters into a specific mock invocation call.
|
||||
// Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>
|
||||
// used to invoke the mock function.
|
||||
// Requires result to point to a ResultT, which is the result of the call.
|
||||
template <typename ResultT, typename ArgTupleT>
|
||||
static void MatchImpl(/*MockFnType<ResultT, Args...>*/ void* mock_fn,
|
||||
/*ArgTupleT*/ void* args_tuple,
|
||||
/*ResultT*/ void* result) {
|
||||
using MockFnType = decltype(
|
||||
GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>()));
|
||||
*static_cast<ResultT*>(result) = absl::apply(
|
||||
MockFnCaller<ResultT, MockFnType, ArgTupleT>{
|
||||
static_cast<MockFnType*>(mock_fn)},
|
||||
*static_cast<ArgTupleT*>(args_tuple));
|
||||
}
|
||||
|
||||
// MockingBitGen::InvokeMock
|
||||
//
|
||||
// InvokeMock(FastTypeIdType, args, result) is the entrypoint for invoking
|
||||
// mocks registered on MockingBitGen.
|
||||
//
|
||||
// When no mocks are registered on the provided FastTypeIdType, returns false.
|
||||
// Otherwise attempts to invoke the mock function ResultT(Args...) that
|
||||
// was previously registered via the type_index.
|
||||
// Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>
|
||||
// used to invoke the mock function.
|
||||
// Requires result to point to a ResultT, which is the result of the call.
|
||||
inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
|
||||
void* result) {
|
||||
// Trigger a mock, if there exists one that matches `param`.
|
||||
auto it = mocks_.find(std::type_index(key_type));
|
||||
auto it = mocks_.find(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);
|
||||
mock_data->match_impl(mock_data->mock_fn, args_tuple, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename, typename>
|
||||
friend struct ::absl::random_internal::MockSingleOverload;
|
||||
friend struct ::absl::random_internal::DistributionCaller<
|
||||
absl::MockingBitGen>;
|
||||
absl::flat_hash_map<base_internal::FastTypeIdType, MockData> mocks_;
|
||||
std::vector<std::function<void()>> deleters_;
|
||||
absl::BitGen gen_;
|
||||
|
||||
template <typename>
|
||||
friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock
|
||||
friend class ::absl::BitGenRef; // for InvokeMock
|
||||
friend class ::absl::random_internal::MockHelpers; // for RegisterMock,
|
||||
// InvokeMock
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation Details Only Below
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace random_internal {
|
||||
|
||||
template <>
|
||||
struct DistributionCaller<absl::MockingBitGen> {
|
||||
template <typename DistrT, typename... Args>
|
||||
static typename DistrT::result_type Call(absl::MockingBitGen* gen,
|
||||
Args&&... args) {
|
||||
return gen->template Call<DistrT>(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace random_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ template <typename URBG>
|
|||
void TestReproducibleVariateSequencesForNonsecureURBG() {
|
||||
const size_t kNumVariates = 1000;
|
||||
|
||||
// Master RNG instance.
|
||||
URBG rng;
|
||||
// Reused for both RNG instances.
|
||||
auto reusable_seed = absl::CreateSeedSeqFrom(&rng);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue