79e0dc1151
--
990253454819ce26ff1dda9ab4bbc145b61d01e4 by Xiaoyi Zhang <zhangxy@google.com>:
Import github PR https://github.com/abseil/abseil-cpp/pull/645
PiperOrigin-RevId: 303119797
--
5ac845cb7929b7d1eaf59a309afd811db5001175 by Abseil Team <absl-team@google.com>:
Fix internal exception spec compatibility error
PiperOrigin-RevId: 303104081
--
3290595dd866eecab3c7044e2e3ca0adb74f1bf5 by Gennadiy Rozental <rogeeff@google.com>:
Use FlagValue<T> to represent the value of a flag. Place it directly after
FlagImpl and use a computed offset refer to it.
The offset is computed based on the assumption that the `value_` data member
is placed directly after the impl_ data member in Flag<T>.
This change will allow us to migrate to `T`-specific storage in the generic case.
This change decreases the overhead for int flags by 32 bytes.
PiperOrigin-RevId: 303038099
--
f2b37722cd7a6d3a60ef9713f0d2bbff56f3ddbf by Derek Mauro <dmauro@google.com>:
Minor correctness fix for an ABSL_HAVE_BUILTIN conditional
PiperOrigin-RevId: 302980666
--
39c079a6141ae1c5728af8bf33a39c8aff9deb9f by Abseil Team <absl-team@google.com>:
Use ABSL_HARDENING_ASSERT in b-tree and SwissTable iterators.
PiperOrigin-RevId: 302970075
--
9668a044e080c789df32bcaa1ffb5100831cd9fa by Benjamin Barenblat <bbaren@google.com>:
Correct `add_subdirectory` line in CMake googletest support
Commit bcefbdcdf6
added support for building with CMake against a local googletest checkout, but I missed a line when constructing the diff. Change the `add_subdirectory` line to reference the correct directories.
PiperOrigin-RevId: 302947488
--
0a3c10fabf80a43ca69ab8b1570030e55f2be741 by Andy Soffer <asoffer@google.com>:
Remove unused distribution format traits.
PiperOrigin-RevId: 302896176
--
0478f2f6270e5ed64c0e28ec09556ca90b2d46a9 by Samuel Benzaquen <sbenza@google.com>:
Fix for CWG:2310.
PiperOrigin-RevId: 302734089
--
3cb978dda5cae5905affdc0914dcc2d27671ed11 by Samuel Benzaquen <sbenza@google.com>:
Fix the Allocate/Deallocate functions to use the same underlying allocator type.
PiperOrigin-RevId: 302721804
--
ae38d3984fb68b4e3ddc165fa8d5c24d5936be52 by Matthew Brown <matthewbr@google.com>:
Internal Change
PiperOrigin-RevId: 302717314
--
7357cf7abd03cc60b6e82b5f28a8e34935c3b4dc by Andy Getzendanner <durandal@google.com>:
Fix typo: s/ABSL_HARDENED_ASSERT/ABSL_HARDENING_ASSERT/
PiperOrigin-RevId: 302532164
GitOrigin-RevId: 990253454819ce26ff1dda9ab4bbc145b61d01e4
Change-Id: Ie595a221c16e1e7e1255ad42e029b646c5f3e11d
198 lines
6.8 KiB
C++
198 lines
6.8 KiB
C++
// 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 {
|
|
ABSL_NAMESPACE_BEGIN
|
|
|
|
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 {
|
|
for (const auto& del : deleters_) del();
|
|
}
|
|
|
|
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... Args>
|
|
static typename DistrT::result_type Call(absl::MockingBitGen* gen,
|
|
Args&&... args) {
|
|
return gen->template Call<DistrT>(std::forward<Args>(args)...);
|
|
}
|
|
};
|
|
|
|
} // namespace random_internal
|
|
ABSL_NAMESPACE_END
|
|
} // namespace absl
|
|
|
|
#endif // ABSL_RANDOM_MOCKING_BIT_GEN_H_
|