aboutsummaryrefslogtreecommitdiffhomepage
path: root/absl/random/internal
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2019-11-20 13:55:25 -0800
committerGravatar Andy Soffer <asoffer@google.com>2019-11-20 17:01:15 -0500
commitbcaae6009c0833b73c6fa7bdd972921d8081a724 (patch)
tree129b38c7e160276c10af9efa482536b05dd514fc /absl/random/internal
parent8ba96a8244bbe334d09542e92d566673a65c1f78 (diff)
Export of internal Abseil changes
-- 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: Id9f694eaaa23f42de817c8e8a28e6f86444f5637
Diffstat (limited to 'absl/random/internal')
-rw-r--r--absl/random/internal/BUILD.bazel23
-rw-r--r--absl/random/internal/mock_overload_set.h89
-rw-r--r--absl/random/internal/mocking_bit_gen_base.h118
3 files changed, 230 insertions, 0 deletions
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index cc9bc01..5026e2b 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -493,6 +493,29 @@ cc_test(
],
)
+cc_library(
+ name = "mocking_bit_gen_base",
+ hdrs = ["mocking_bit_gen_base.h"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/random",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "mock_overload_set",
+ testonly = 1,
+ hdrs = ["mock_overload_set.h"],
+ visibility = [
+ "//absl/random:__pkg__",
+ ],
+ deps = [
+ "//absl/random:mocking_bit_gen",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
cc_test(
name = "nonsecure_base_test",
size = "small",
diff --git a/absl/random/internal/mock_overload_set.h b/absl/random/internal/mock_overload_set.h
new file mode 100644
index 0000000..539313d
--- /dev/null
+++ b/absl/random/internal/mock_overload_set.h
@@ -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_
diff --git a/absl/random/internal/mocking_bit_gen_base.h b/absl/random/internal/mocking_bit_gen_base.h
new file mode 100644
index 0000000..aff2ba6
--- /dev/null
+++ b/absl/random/internal/mocking_bit_gen_base.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_