summaryrefslogtreecommitdiff
path: root/absl/random
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-01-07 06:56:49 -0800
committerGravatar Derek Mauro <dmauro@google.com>2020-01-07 14:50:44 -0500
commit63ee2f8877915a3565c29707dba8fe4d7822596a (patch)
tree2fbadda72047a8441c181a0adf1215cec0155036 /absl/random
parenta048203a881f11f4b7b8df5fb563aec85522f8db (diff)
Export of internal Abseil changes
-- 7f6c15aadc4d97e217dd446518dbb4fdc86b36a3 by Derek Mauro <dmauro@google.com>: Upgrade GCC automated testing to use GCC 9.2 and Cmake 3.16.2 PiperOrigin-RevId: 288488783 -- a978cee848d3cf65b0826c981bfd81022fc36660 by Abseil Team <absl-team@google.com>: Removing formatting traits that were only used internally. ON_CALL/EXPECT_CALL do a sufficient job here. PiperOrigin-RevId: 288386509 -- fdec6f40293d5883220f1f0ea1261f7c5b60a66e by Derek Mauro <dmauro@google.com>: Upgrade MacOS tests to use Bazel 2.0.0 PiperOrigin-RevId: 288373298 -- 465865c4123e9481ab50ea0527e92b39519704dd by Derek Mauro <dmauro@google.com>: Changes to support GCC 9 * Fix several -Wredundant-move warnings * Remove FlatHashMap.Any test, which basically doesn't work on any platform any more (see https://cplusplus.github.io/LWG/lwg-active.html#3121) * Fix a constant sign-compare warning * Conditionally compile out the PoisonHash test which doesn't build PiperOrigin-RevId: 288360204 -- 57c4bb07fc58e7dd2a04f3c45027aab5ecaccf25 by Andy Soffer <asoffer@google.com>: Deflaking MockingBitGen test. Because MockingBitGen can return random values, it is inherently flaky. For log-unifrom, 2040 is a common enough value that tests failed unreasonably frequently. Replacing it with a significantly larger value so as to be much less common. 50000 is a good choice because it is (tied for) the least likely to occur randomly from this distribution, but is still in the distribution. PiperOrigin-RevId: 288360112 -- 86f38e4109899d972de353b1c556c018cfe37956 by Matt Calabrese <calabrese@google.com>: Remove construction tests for the internal `CompressedTuple<std::any>` instantiation. This was not guaranteed to work for the reasons that `std::tuple<std::any>` copy construction does not actually work by standard specification (some implementations introduce workarounds for this). In GCC9, `CompressedTuple<std::any>` and `std::tuple<std::any>` both fail for the same reasons, and a proper "fix" requires updating `std::any`, which is out of our control. PiperOrigin-RevId: 288351977 GitOrigin-RevId: 7f6c15aadc4d97e217dd446518dbb4fdc86b36a3 Change-Id: I5d5c62bd297dc0ff1f2970ff076bb5cd088a7e4c
Diffstat (limited to 'absl/random')
-rw-r--r--absl/random/BUILD.bazel1
-rw-r--r--absl/random/CMakeLists.txt2
-rw-r--r--absl/random/bit_gen_ref.h5
-rw-r--r--absl/random/distribution_format_traits.h278
-rw-r--r--absl/random/distributions.h41
-rw-r--r--absl/random/internal/BUILD.bazel1
-rw-r--r--absl/random/internal/distribution_caller.h18
-rw-r--r--absl/random/internal/mocking_bit_gen_base.h42
-rw-r--r--absl/random/mocking_bit_gen.cc1
-rw-r--r--absl/random/mocking_bit_gen.h6
-rw-r--r--absl/random/mocking_bit_gen_test.cc6
11 files changed, 375 insertions, 26 deletions
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index 43ed9840..2585b397 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -53,6 +53,7 @@ cc_library(
"bernoulli_distribution.h",
"beta_distribution.h",
"discrete_distribution.h",
+ "distribution_format_traits.h",
"distributions.h",
"exponential_distribution.h",
"gaussian_distribution.h",
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index 53f1aa5c..46dbc3ef 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -78,6 +78,7 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_random
+ absl::strings
)
# Internal-only target, do not depend on directly.
@@ -167,6 +168,7 @@ absl_cc_library(
"bernoulli_distribution.h"
"beta_distribution.h"
"discrete_distribution.h"
+ "distribution_format_traits.h"
"distributions.h"
"exponential_distribution.h"
"gaussian_distribution.h"
diff --git a/absl/random/bit_gen_ref.h b/absl/random/bit_gen_ref.h
index 59591a47..e8771162 100644
--- a/absl/random/bit_gen_ref.h
+++ b/absl/random/bit_gen_ref.h
@@ -132,7 +132,7 @@ namespace random_internal {
template <>
struct DistributionCaller<absl::BitGenRef> {
- template <typename DistrT, typename... Args>
+ 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_;
@@ -140,7 +140,8 @@ struct DistributionCaller<absl::BitGenRef> {
DistrT dist(std::forward<Args>(args)...);
return dist(*gen_ref);
} else {
- return mock_ptr->template Call<DistrT>(std::forward<Args>(args)...);
+ return mock_ptr->template Call<DistrT, FormatT>(
+ std::forward<Args>(args)...);
}
}
};
diff --git a/absl/random/distribution_format_traits.h b/absl/random/distribution_format_traits.h
new file mode 100644
index 00000000..22b358cc
--- /dev/null
+++ b/absl/random/distribution_format_traits.h
@@ -0,0 +1,278 @@
+//
+// 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_DISTRIBUTION_FORMAT_TRAITS_H_
+#define ABSL_RANDOM_DISTRIBUTION_FORMAT_TRAITS_H_
+
+#include <string>
+#include <tuple>
+#include <typeinfo>
+
+#include "absl/meta/type_traits.h"
+#include "absl/random/bernoulli_distribution.h"
+#include "absl/random/beta_distribution.h"
+#include "absl/random/exponential_distribution.h"
+#include "absl/random/gaussian_distribution.h"
+#include "absl/random/log_uniform_int_distribution.h"
+#include "absl/random/poisson_distribution.h"
+#include "absl/random/uniform_int_distribution.h"
+#include "absl/random/uniform_real_distribution.h"
+#include "absl/random/zipf_distribution.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+struct IntervalClosedClosedTag;
+struct IntervalClosedOpenTag;
+struct IntervalOpenClosedTag;
+struct IntervalOpenOpenTag;
+
+namespace random_internal {
+
+// ScalarTypeName defines a preferred hierarchy of preferred type names for
+// scalars, and is evaluated at compile time for the specific type
+// specialization.
+template <typename T>
+constexpr const char* ScalarTypeName() {
+ static_assert(std::is_integral<T>() || std::is_floating_point<T>(), "");
+ // clang-format off
+ return
+ std::is_same<T, float>::value ? "float" :
+ std::is_same<T, double>::value ? "double" :
+ std::is_same<T, long double>::value ? "long double" :
+ std::is_same<T, bool>::value ? "bool" :
+ std::is_signed<T>::value && sizeof(T) == 1 ? "int8_t" :
+ std::is_signed<T>::value && sizeof(T) == 2 ? "int16_t" :
+ std::is_signed<T>::value && sizeof(T) == 4 ? "int32_t" :
+ std::is_signed<T>::value && sizeof(T) == 8 ? "int64_t" :
+ std::is_unsigned<T>::value && sizeof(T) == 1 ? "uint8_t" :
+ std::is_unsigned<T>::value && sizeof(T) == 2 ? "uint16_t" :
+ std::is_unsigned<T>::value && sizeof(T) == 4 ? "uint32_t" :
+ std::is_unsigned<T>::value && sizeof(T) == 8 ? "uint64_t" :
+ "undefined";
+ // clang-format on
+
+ // NOTE: It would be nice to use typeid(T).name(), but that's an
+ // implementation-defined attribute which does not necessarily
+ // correspond to a name. We could potentially demangle it
+ // using, e.g. abi::__cxa_demangle.
+}
+
+// Distribution traits used by DistributionCaller and internal implementation
+// details of the mocking framework.
+/*
+struct DistributionFormatTraits {
+ // Returns the parameterized name of the distribution function.
+ static constexpr const char* FunctionName()
+ // Format DistrT parameters.
+ static std::string FormatArgs(DistrT& dist);
+ // Format DistrT::result_type results.
+ static std::string FormatResults(DistrT& dist);
+};
+*/
+template <typename DistrT>
+struct DistributionFormatTraits;
+
+template <typename R>
+struct DistributionFormatTraits<absl::uniform_int_distribution<R>> {
+ using distribution_t = absl::uniform_int_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Uniform"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat("absl::IntervalClosedClosed, ", (d.min)(), ", ",
+ (d.max)());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::uniform_real_distribution<R>> {
+ using distribution_t = absl::uniform_real_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Uniform"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat((d.min)(), ", ", (d.max)());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::exponential_distribution<R>> {
+ using distribution_t = absl::exponential_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Exponential"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.lambda());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::poisson_distribution<R>> {
+ using distribution_t = absl::poisson_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Poisson"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.mean());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <>
+struct DistributionFormatTraits<absl::bernoulli_distribution> {
+ using distribution_t = absl::bernoulli_distribution;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Bernoulli"; }
+
+ static constexpr const char* FunctionName() { return Name(); }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.p());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::beta_distribution<R>> {
+ using distribution_t = absl::beta_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Beta"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.alpha(), ", ", d.beta());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::zipf_distribution<R>> {
+ using distribution_t = absl::zipf_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Zipf"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.k(), ", ", d.v(), ", ", d.q());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::gaussian_distribution<R>> {
+ using distribution_t = absl::gaussian_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Gaussian"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrJoin(std::make_tuple(d.mean(), d.stddev()), ", ");
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::log_uniform_int_distribution<R>> {
+ using distribution_t = absl::log_uniform_int_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "LogUniform"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrJoin(std::make_tuple((d.min)(), (d.max)(), d.base()), ", ");
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename NumType>
+struct UniformDistributionWrapper;
+
+template <typename NumType>
+struct DistributionFormatTraits<UniformDistributionWrapper<NumType>> {
+ using distribution_t = UniformDistributionWrapper<NumType>;
+ using result_t = NumType;
+
+ static constexpr const char* Name() { return "Uniform"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<NumType>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat((d.min)(), ", ", (d.max)());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_DISTRIBUTION_FORMAT_TRAITS_H_
diff --git a/absl/random/distributions.h b/absl/random/distributions.h
index 7abdfa8f..c1fb6650 100644
--- a/absl/random/distributions.h
+++ b/absl/random/distributions.h
@@ -55,6 +55,7 @@
#include "absl/base/internal/inline_variable.h"
#include "absl/random/bernoulli_distribution.h"
#include "absl/random/beta_distribution.h"
+#include "absl/random/distribution_format_traits.h"
#include "absl/random/exponential_distribution.h"
#include "absl/random/gaussian_distribution.h"
#include "absl/random/internal/distributions.h" // IWYU pragma: export
@@ -125,13 +126,14 @@ Uniform(TagType tag,
R lo, R hi) {
using gen_t = absl::decay_t<URBG>;
using distribution_t = random_internal::UniformDistributionWrapper<R>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
auto a = random_internal::uniform_lower_bound(tag, lo, hi);
auto b = random_internal::uniform_upper_bound(tag, lo, hi);
if (a > b) return a;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, tag, lo, hi);
+ distribution_t, format_t>(&urbg, tag, lo, hi);
}
// absl::Uniform<T>(bitgen, lo, hi)
@@ -144,6 +146,7 @@ Uniform(URBG&& urbg, // NOLINT(runtime/references)
R lo, R hi) {
using gen_t = absl::decay_t<URBG>;
using distribution_t = random_internal::UniformDistributionWrapper<R>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
constexpr auto tag = absl::IntervalClosedOpen;
auto a = random_internal::uniform_lower_bound(tag, lo, hi);
@@ -151,7 +154,7 @@ Uniform(URBG&& urbg, // NOLINT(runtime/references)
if (a > b) return a;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, lo, hi);
+ distribution_t, format_t>(&urbg, lo, hi);
}
// absl::Uniform(tag, bitgen, lo, hi)
@@ -169,14 +172,15 @@ Uniform(TagType tag,
using gen_t = absl::decay_t<URBG>;
using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
using distribution_t = random_internal::UniformDistributionWrapper<return_t>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);
auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);
if (a > b) return a;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, tag, static_cast<return_t>(lo),
- static_cast<return_t>(hi));
+ distribution_t, format_t>(&urbg, tag, static_cast<return_t>(lo),
+ static_cast<return_t>(hi));
}
// absl::Uniform(bitgen, lo, hi)
@@ -192,6 +196,7 @@ Uniform(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
using distribution_t = random_internal::UniformDistributionWrapper<return_t>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
constexpr auto tag = absl::IntervalClosedOpen;
auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);
@@ -199,8 +204,8 @@ Uniform(URBG&& urbg, // NOLINT(runtime/references)
if (a > b) return a;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, static_cast<return_t>(lo),
- static_cast<return_t>(hi));
+ distribution_t, format_t>(&urbg, static_cast<return_t>(lo),
+ static_cast<return_t>(hi));
}
// absl::Uniform<unsigned T>(bitgen)
@@ -212,9 +217,10 @@ typename absl::enable_if_t<!std::is_signed<R>::value, R> //
Uniform(URBG&& urbg) { // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = random_internal::UniformDistributionWrapper<R>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg);
+ distribution_t, format_t>(&urbg);
}
// -----------------------------------------------------------------------------
@@ -242,9 +248,10 @@ bool Bernoulli(URBG&& urbg, // NOLINT(runtime/references)
double p) {
using gen_t = absl::decay_t<URBG>;
using distribution_t = absl::bernoulli_distribution;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, p);
+ distribution_t, format_t>(&urbg, p);
}
// -----------------------------------------------------------------------------
@@ -274,9 +281,10 @@ RealType Beta(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::beta_distribution<RealType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, alpha, beta);
+ distribution_t, format_t>(&urbg, alpha, beta);
}
// -----------------------------------------------------------------------------
@@ -306,9 +314,10 @@ RealType Exponential(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::exponential_distribution<RealType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, lambda);
+ distribution_t, format_t>(&urbg, lambda);
}
// -----------------------------------------------------------------------------
@@ -337,9 +346,10 @@ RealType Gaussian(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::gaussian_distribution<RealType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, mean, stddev);
+ distribution_t, format_t>(&urbg, mean, stddev);
}
// -----------------------------------------------------------------------------
@@ -379,9 +389,10 @@ IntType LogUniform(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::log_uniform_int_distribution<IntType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, lo, hi, base);
+ distribution_t, format_t>(&urbg, lo, hi, base);
}
// -----------------------------------------------------------------------------
@@ -409,9 +420,10 @@ IntType Poisson(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::poisson_distribution<IntType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, mean);
+ distribution_t, format_t>(&urbg, mean);
}
// -----------------------------------------------------------------------------
@@ -441,9 +453,10 @@ IntType Zipf(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::zipf_distribution<IntType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, hi, q, v);
+ distribution_t, format_t>(&urbg, hi, q, v);
}
ABSL_NAMESPACE_END
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index 8839078f..d7ad4efe 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -509,6 +509,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/random",
+ "//absl/strings",
],
)
diff --git a/absl/random/internal/distribution_caller.h b/absl/random/internal/distribution_caller.h
index ae2680dd..02603cf8 100644
--- a/absl/random/internal/distribution_caller.h
+++ b/absl/random/internal/distribution_caller.h
@@ -31,8 +31,22 @@ namespace random_internal {
template <typename URBG>
struct DistributionCaller {
// Call the provided distribution type. The parameters are expected
- // to be explicitly specified. DistrT is the distribution type.
- template <typename DistrT, typename... Args>
+ // to be explicitly specified.
+ // DistrT is the distribution type.
+ // FormatT is the formatter type:
+ //
+ // struct FormatT {
+ // using result_type = distribution_t::result_type;
+ // static std::string FormatCall(
+ // const distribution_t& distr,
+ // absl::Span<const result_type>);
+ //
+ // static std::string FormatExpectation(
+ // absl::string_view match_args,
+ // absl::Span<const result_t> results);
+ // }
+ //
+ template <typename DistrT, typename FormatT, typename... Args>
static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
DistrT dist(std::forward<Args>(args)...);
return dist(*urbg);
diff --git a/absl/random/internal/mocking_bit_gen_base.h b/absl/random/internal/mocking_bit_gen_base.h
index acd63872..eeeae9d2 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
diff --git a/absl/random/mocking_bit_gen.cc b/absl/random/mocking_bit_gen.cc
index 02209115..6bb1e414 100644
--- a/absl/random/mocking_bit_gen.cc
+++ b/absl/random/mocking_bit_gen.cc
@@ -20,6 +20,7 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
MockingBitGen::~MockingBitGen() {
+
for (const auto& del : deleters_) {
del();
}
diff --git a/absl/random/mocking_bit_gen.h b/absl/random/mocking_bit_gen.h
index 246c5b1e..36cef911 100644
--- a/absl/random/mocking_bit_gen.h
+++ b/absl/random/mocking_bit_gen.h
@@ -109,7 +109,7 @@ class MockingBitGen : public absl::random_internal::MockingBitGenBase {
// MockingBitGen::Register
//
- // Register<DistrT, ArgTupleT> is the main extension point for
+ // 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.
@@ -182,10 +182,10 @@ namespace random_internal {
template <>
struct DistributionCaller<absl::MockingBitGen> {
- template <typename DistrT, typename... Args>
+ template <typename DistrT, typename FormatT, typename... Args>
static typename DistrT::result_type Call(absl::MockingBitGen* gen,
Args&&... args) {
- return gen->template Call<DistrT>(std::forward<Args>(args)...);
+ return gen->template Call<DistrT, FormatT>(std::forward<Args>(args)...);
}
};
diff --git a/absl/random/mocking_bit_gen_test.cc b/absl/random/mocking_bit_gen_test.cc
index dcf74fd6..f0ffc9ac 100644
--- a/absl/random/mocking_bit_gen_test.cc
+++ b/absl/random/mocking_bit_gen_test.cc
@@ -66,10 +66,10 @@ TEST(BasicMocking, AllDistributionsAreOverridable) {
.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_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000);
EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
- .WillOnce(Return(2040));
- EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+ .WillOnce(Return(500000));
+ EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000);
}
TEST(BasicMocking, OnDistribution) {