-- 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
		
			
				
	
	
		
			196 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			196 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;
 | 
						|
 | 
						|
 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
 | 
						|
ABSL_NAMESPACE_END
 | 
						|
}  // namespace absl
 | 
						|
 | 
						|
#endif  // ABSL_RANDOM_MOCKING_BIT_GEN_H_
 |