Skip to content

Commit

Permalink
Delete UnvalidatedMockingBitGen
Browse files Browse the repository at this point in the history
See some relevant context on this project in 254b3a5. This type existed to support the incremental migration of added validation to MockingBitGen, validating that the returned value from absl::Uniform() is in bounds. All known cases where an out-of-bounds value was returned have been fixed and migrated to use MockingBitGen.

PiperOrigin-RevId: 693836317
Change-Id: I04f54b7b4856f4280580b294194ce2c25a18e9b1
  • Loading branch information
Quincunx271 authored and copybara-github committed Nov 6, 2024
1 parent 78ed38c commit a302705
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 85 deletions.
12 changes: 4 additions & 8 deletions absl/random/internal/mock_overload_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,8 @@ struct MockSingleOverload<DistrT, ValidatorT, Ret(MockingBitGen&, Args...)> {
auto gmock_Call(MockURBG& gen, const ::testing::Matcher<Args>&... matchers)
-> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())
.gmock_Call(matchers...)) {
static_assert(
std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value ||
std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value,
"Mocking requires an absl::MockingBitGen");
static_assert(std::is_base_of<MockingBitGen, MockURBG>::value,
"Mocking requires an absl::MockingBitGen");
return MockHelpers::MockFor<KeyT>(gen, ValidatorT())
.gmock_Call(matchers...);
}
Expand All @@ -74,10 +72,8 @@ struct MockSingleOverload<DistrT, ValidatorT,
const ::testing::Matcher<Args>&... matchers)
-> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())
.gmock_Call(matcher, matchers...)) {
static_assert(
std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value ||
std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value,
"Mocking requires an absl::MockingBitGen");
static_assert(std::is_base_of<MockingBitGen, MockURBG>::value,
"Mocking requires an absl::MockingBitGen");
return MockHelpers::MockFor<KeyT>(gen, ValidatorT())
.gmock_Call(matcher, matchers...);
}
Expand Down
19 changes: 6 additions & 13 deletions absl/random/mock_distributions_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,15 @@ TEST(MockDistributions, Examples) {
EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
}

TEST(MockUniform, OutOfBoundsIsAllowed) {
absl::UnvalidatedMockingBitGen gen;

EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 100)).WillOnce(Return(0));
EXPECT_EQ(absl::Uniform<int>(gen, 1, 100), 0);
}

TEST(ValidatedMockDistributions, UniformUInt128Works) {
TEST(MockDistributions, UniformUInt128BoundariesAreAllowed) {
absl::MockingBitGen gen;

EXPECT_CALL(absl::MockUniform<absl::uint128>(), Call(gen))
.WillOnce(Return(absl::Uint128Max()));
EXPECT_EQ(absl::Uniform<absl::uint128>(gen), absl::Uint128Max());
}

TEST(ValidatedMockDistributions, UniformDoubleBoundaryCases) {
TEST(MockDistributions, UniformDoubleBoundaryCasesAreAllowed) {
absl::MockingBitGen gen;

EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 1.0, 10.0))
Expand All @@ -114,7 +107,7 @@ TEST(ValidatedMockDistributions, UniformDoubleBoundaryCases) {
std::nextafter(1.0, std::numeric_limits<double>::infinity()));
}

TEST(ValidatedMockDistributions, UniformDoubleEmptyRangeCases) {
TEST(MockDistributions, UniformDoubleEmptyRangesAllowTheBoundary) {
absl::MockingBitGen gen;

ON_CALL(absl::MockUniform<double>(), Call(absl::IntervalOpen, gen, 1.0, 1.0))
Expand All @@ -134,7 +127,7 @@ TEST(ValidatedMockDistributions, UniformDoubleEmptyRangeCases) {
1.0);
}

TEST(ValidatedMockDistributions, UniformIntEmptyRangeCases) {
TEST(MockDistributions, UniformIntEmptyRangeCasesAllowTheBoundary) {
absl::MockingBitGen gen;

ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalOpen, gen, 1, 1))
Expand All @@ -150,7 +143,7 @@ TEST(ValidatedMockDistributions, UniformIntEmptyRangeCases) {
EXPECT_EQ(absl::Uniform<int>(absl::IntervalClosedOpen, gen, 1, 1), 1);
}

TEST(ValidatedMockUniformDeathTest, Examples) {
TEST(MockUniformDeathTest, OutOfBoundsValuesAreRejected) {
absl::MockingBitGen gen;

EXPECT_DEATH_IF_SUPPORTED(
Expand Down Expand Up @@ -252,7 +245,7 @@ TEST(ValidatedMockUniformDeathTest, Examples) {
" 101 is not in \\[1, 100\\]");
}

TEST(ValidatedMockUniformDeathTest, DoubleBoundaryCases) {
TEST(MockUniformDeathTest, OutOfBoundsDoublesAreRejected) {
absl::MockingBitGen gen;

EXPECT_DEATH_IF_SUPPORTED(
Expand Down
114 changes: 50 additions & 64 deletions absl/random/mocking_bit_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,53 @@ namespace random_internal {
template <typename>
struct DistributionCaller;
class MockHelpers;
} // namespace random_internal

// Implements MockingBitGen with an option to turn on extra validation.
template <bool EnableValidation>
class MockingBitGenImpl {
// 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 {
public:
MockingBitGenImpl() = default;
~MockingBitGenImpl() = default;
MockingBitGen() = default;
~MockingBitGen() = default;

// URBG interface
using result_type = absl::BitGen::result_type;
Expand Down Expand Up @@ -138,25 +178,23 @@ class MockingBitGenImpl {
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>;
std::declval<ArgTupleT>())) & {
using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(),
std::declval<ArgTupleT>()));

using WrappedFnType = absl::conditional_t<
std::is_same<SelfT, ::testing::NiceMock<MockingBitGenImpl>>::value,
std::is_same<SelfT, ::testing::NiceMock<MockingBitGen>>::value,
::testing::NiceMock<MockFnType>,
absl::conditional_t<
std::is_same<SelfT, ::testing::NaggyMock<MockingBitGenImpl>>::value,
std::is_same<SelfT, ::testing::NaggyMock<MockingBitGen>>::value,
::testing::NaggyMock<MockFnType>,
absl::conditional_t<
std::is_same<SelfT,
::testing::StrictMock<MockingBitGenImpl>>::value,
::testing::StrictMock<MockingBitGen>>::value,
::testing::StrictMock<MockFnType>, MockFnType>>>;

using ImplT =
FunctionHolderImpl<WrappedFnType, ActualValidatorT, ResultT, ArgTupleT>;
FunctionHolderImpl<WrappedFnType, ValidatorT, ResultT, ArgTupleT>;
auto& mock = mocks_[type];
if (!mock) {
mock = absl::make_unique<ImplT>();
Expand Down Expand Up @@ -196,58 +234,6 @@ class MockingBitGenImpl {
// 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

Expand Down

0 comments on commit a302705

Please sign in to comment.