| // 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. |
| // |
| // Generates random values for testing. Specialized only for the few types we |
| // care about. |
| |
| #ifndef ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ |
| #define ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ |
| |
| #include <stdint.h> |
| #include <algorithm> |
| #include <iosfwd> |
| #include <random> |
| #include <tuple> |
| #include <type_traits> |
| #include <utility> |
| |
| #include "absl/container/internal/hash_policy_testing.h" |
| #include "absl/meta/type_traits.h" |
| #include "absl/strings/string_view.h" |
| |
| namespace absl { |
| namespace container_internal { |
| namespace hash_internal { |
| namespace generator_internal { |
| |
| template <class Container, class = void> |
| struct IsMap : std::false_type {}; |
| |
| template <class Map> |
| struct IsMap<Map, absl::void_t<typename Map::mapped_type>> : std::true_type {}; |
| |
| } // namespace generator_internal |
| |
| std::mt19937_64* GetSharedRng(); |
| |
| enum Enum { |
| kEnumEmpty, |
| kEnumDeleted, |
| }; |
| |
| enum class EnumClass : uint64_t { |
| kEmpty, |
| kDeleted, |
| }; |
| |
| inline std::ostream& operator<<(std::ostream& o, const EnumClass& ec) { |
| return o << static_cast<uint64_t>(ec); |
| } |
| |
| template <class T, class E = void> |
| struct Generator; |
| |
| template <class T> |
| struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> { |
| T operator()() const { |
| std::uniform_int_distribution<T> dist; |
| return dist(*GetSharedRng()); |
| } |
| }; |
| |
| template <> |
| struct Generator<Enum> { |
| Enum operator()() const { |
| std::uniform_int_distribution<typename std::underlying_type<Enum>::type> |
| dist; |
| while (true) { |
| auto variate = dist(*GetSharedRng()); |
| if (variate != kEnumEmpty && variate != kEnumDeleted) |
| return static_cast<Enum>(variate); |
| } |
| } |
| }; |
| |
| template <> |
| struct Generator<EnumClass> { |
| EnumClass operator()() const { |
| std::uniform_int_distribution< |
| typename std::underlying_type<EnumClass>::type> |
| dist; |
| while (true) { |
| EnumClass variate = static_cast<EnumClass>(dist(*GetSharedRng())); |
| if (variate != EnumClass::kEmpty && variate != EnumClass::kDeleted) |
| return static_cast<EnumClass>(variate); |
| } |
| } |
| }; |
| |
| template <> |
| struct Generator<std::string> { |
| std::string operator()() const; |
| }; |
| |
| template <> |
| struct Generator<absl::string_view> { |
| absl::string_view operator()() const; |
| }; |
| |
| template <> |
| struct Generator<NonStandardLayout> { |
| NonStandardLayout operator()() const { |
| return NonStandardLayout(Generator<std::string>()()); |
| } |
| }; |
| |
| template <class K, class V> |
| struct Generator<std::pair<K, V>> { |
| std::pair<K, V> operator()() const { |
| return std::pair<K, V>(Generator<typename std::decay<K>::type>()(), |
| Generator<typename std::decay<V>::type>()()); |
| } |
| }; |
| |
| template <class... Ts> |
| struct Generator<std::tuple<Ts...>> { |
| std::tuple<Ts...> operator()() const { |
| return std::tuple<Ts...>(Generator<typename std::decay<Ts>::type>()()...); |
| } |
| }; |
| |
| template <class U> |
| struct Generator<U, absl::void_t<decltype(std::declval<U&>().key()), |
| decltype(std::declval<U&>().value())>> |
| : Generator<std::pair< |
| typename std::decay<decltype(std::declval<U&>().key())>::type, |
| typename std::decay<decltype(std::declval<U&>().value())>::type>> {}; |
| |
| template <class Container> |
| using GeneratedType = decltype( |
| std::declval<const Generator< |
| typename std::conditional<generator_internal::IsMap<Container>::value, |
| typename Container::value_type, |
| typename Container::key_type>::type>&>()()); |
| |
| } // namespace hash_internal |
| } // namespace container_internal |
| } // namespace absl |
| |
| #endif // ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ |