-- 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: Id9f694eaaa23f42de817c8e8a28e6f86444f5637pull/559/head
parent
8ba96a8244
commit
bcaae6009c
12 changed files with 1598 additions and 0 deletions
@ -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_
|
@ -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
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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
|
@ -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
|
@ -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_
|
@ -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 new issue