diff options
Diffstat (limited to 'absl/random/internal/mocking_bit_gen_base.h')
-rw-r--r-- | absl/random/internal/mocking_bit_gen_base.h | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/absl/random/internal/mocking_bit_gen_base.h b/absl/random/internal/mocking_bit_gen_base.h index acd6387204aa..eeeae9d295b2 100644 --- a/absl/random/internal/mocking_bit_gen_base.h +++ b/absl/random/internal/mocking_bit_gen_base.h @@ -16,14 +16,39 @@ #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 { ABSL_NAMESPACE_BEGIN 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; @@ -36,9 +61,14 @@ class MockingBitGenBase { 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. @@ -51,9 +81,10 @@ class MockingBitGenBase { } // Call the generating distribution function. - // Invoked by DistributionCaller<>::Call<DistT>. + // Invoked by DistributionCaller<>::Call<DistT, FormatT>. // DistT is the distribution type. - template <typename DistrT, typename... Args> + // 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>...>; @@ -68,11 +99,18 @@ class MockingBitGenBase { 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 |