summaryrefslogtreecommitdiff
path: root/absl/random/mocking_bit_gen.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/random/mocking_bit_gen.h')
-rw-r--r--absl/random/mocking_bit_gen.h158
1 files changed, 86 insertions, 72 deletions
diff --git a/absl/random/mocking_bit_gen.h b/absl/random/mocking_bit_gen.h
index 89fa5a47..041989de 100644
--- a/absl/random/mocking_bit_gen.h
+++ b/absl/random/mocking_bit_gen.h
@@ -28,83 +28,37 @@
#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 <utility>
#include "gmock/gmock.h"
-#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.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/mock_helpers.h"
#include "absl/random/random.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 {
ABSL_NAMESPACE_BEGIN
+class BitGenRef;
+
namespace random_internal {
template <typename>
struct DistributionCaller;
class MockHelpers;
-} // namespace random_internal
-class BitGenRef;
-
-// 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 - low) / 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.
-//
-// 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 {
+// Implements MockingBitGen with an option to turn on extra validation.
+template <bool EnableValidation>
+class MockingBitGenImpl {
public:
- MockingBitGen() = default;
- ~MockingBitGen() = default;
+ MockingBitGenImpl() = default;
+ ~MockingBitGenImpl() = default;
// URBG interface
using result_type = absl::BitGen::result_type;
@@ -125,15 +79,19 @@ class MockingBitGen {
// 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 MockFnType, typename ResultT, typename Tuple>
+ template <typename MockFnType, typename ValidatorT, typename ResultT,
+ typename Tuple>
struct MockFnCaller;
// specialization for std::tuple.
- template <typename MockFnType, typename ResultT, typename... Args>
- struct MockFnCaller<MockFnType, ResultT, std::tuple<Args...>> {
+ template <typename MockFnType, typename ValidatorT, typename ResultT,
+ typename... Args>
+ struct MockFnCaller<MockFnType, ValidatorT, ResultT, std::tuple<Args...>> {
MockFnType* fn;
inline ResultT operator()(Args... args) {
- return fn->Call(std::move(args)...);
+ ResultT result = fn->Call(args...);
+ ValidatorT::Validate(result, args...);
+ return result;
}
};
@@ -150,16 +108,17 @@ class MockingBitGen {
/*ResultT*/ void* result) = 0;
};
- template <typename MockFnType, typename ResultT, typename ArgTupleT>
+ template <typename MockFnType, typename ValidatorT, typename ResultT,
+ typename ArgTupleT>
class FunctionHolderImpl final : public FunctionHolder {
public:
- void Apply(void* args_tuple, void* result) override {
+ void Apply(void* args_tuple, void* result) final {
// 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.
- *static_cast<ResultT*>(result) =
- absl::apply(MockFnCaller<MockFnType, ResultT, ArgTupleT>{&mock_fn_},
- *static_cast<ArgTupleT*>(args_tuple));
+ *static_cast<ResultT*>(result) = absl::apply(
+ MockFnCaller<MockFnType, ValidatorT, ResultT, ArgTupleT>{&mock_fn_},
+ *static_cast<ArgTupleT*>(args_tuple));
}
MockFnType mock_fn_;
@@ -175,26 +134,29 @@ class MockingBitGen {
//
// The returned MockFunction<...> type can be used to setup additional
// distribution parameters of the expectation.
- template <typename ResultT, typename ArgTupleT, typename SelfT>
- auto RegisterMock(SelfT&, base_internal::FastTypeIdType type)
+ template <typename ResultT, typename ArgTupleT, typename SelfT,
+ typename ValidatorT>
+ auto RegisterMock(SelfT&, base_internal::FastTypeIdType type, ValidatorT)
-> decltype(GetMockFnType(std::declval<ResultT>(),
std::declval<ArgTupleT>()))& {
+ using ActualValidatorT =
+ std::conditional_t<EnableValidation, ValidatorT, NoOpValidator>;
using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(),
std::declval<ArgTupleT>()));
using WrappedFnType = absl::conditional_t<
- std::is_same<SelfT, ::testing::NiceMock<absl::MockingBitGen>>::value,
+ std::is_same<SelfT, ::testing::NiceMock<MockingBitGenImpl>>::value,
::testing::NiceMock<MockFnType>,
absl::conditional_t<
- std::is_same<SelfT,
- ::testing::NaggyMock<absl::MockingBitGen>>::value,
+ std::is_same<SelfT, ::testing::NaggyMock<MockingBitGenImpl>>::value,
::testing::NaggyMock<MockFnType>,
absl::conditional_t<
std::is_same<SelfT,
- ::testing::StrictMock<absl::MockingBitGen>>::value,
+ ::testing::StrictMock<MockingBitGenImpl>>::value,
::testing::StrictMock<MockFnType>, MockFnType>>>;
- using ImplT = FunctionHolderImpl<WrappedFnType, ResultT, ArgTupleT>;
+ using ImplT =
+ FunctionHolderImpl<WrappedFnType, ActualValidatorT, ResultT, ArgTupleT>;
auto& mock = mocks_[type];
if (!mock) {
mock = absl::make_unique<ImplT>();
@@ -234,6 +196,58 @@ class MockingBitGen {
// InvokeMock
};
+} // 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 - low) / 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.
+//
+// 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.
+//
+using MockingBitGen = random_internal::MockingBitGenImpl<true>;
+
+// UnvalidatedMockingBitGen
+//
+// UnvalidatedMockingBitGen is a variant of MockingBitGen which does no extra
+// validation.
+using UnvalidatedMockingBitGen ABSL_DEPRECATED("Use MockingBitGen instead") =
+ random_internal::MockingBitGenImpl<false>;
+
ABSL_NAMESPACE_END
} // namespace absl