1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Generates random values for testing. Specialized only for the few types we 16 // care about. 17 18 #ifndef ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ 19 #define ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ 20 21 #include <stdint.h> 22 23 #include <algorithm> 24 #include <iosfwd> 25 #include <random> 26 #include <tuple> 27 #include <type_traits> 28 #include <utility> 29 30 #include "absl/container/internal/hash_policy_testing.h" 31 #include "absl/memory/memory.h" 32 #include "absl/meta/type_traits.h" 33 #include "absl/strings/string_view.h" 34 35 namespace absl { 36 ABSL_NAMESPACE_BEGIN 37 namespace container_internal { 38 namespace hash_internal { 39 namespace generator_internal { 40 41 template <class Container, class = void> 42 struct IsMap : std::false_type {}; 43 44 template <class Map> 45 struct IsMap<Map, absl::void_t<typename Map::mapped_type>> : std::true_type {}; 46 47 } // namespace generator_internal 48 49 std::mt19937_64* GetSharedRng(); 50 51 enum Enum { 52 kEnumEmpty, 53 kEnumDeleted, 54 }; 55 56 enum class EnumClass : uint64_t { 57 kEmpty, 58 kDeleted, 59 }; 60 61 inline std::ostream& operator<<(std::ostream& o, const EnumClass& ec) { 62 return o << static_cast<uint64_t>(ec); 63 } 64 65 template <class T, class E = void> 66 struct Generator; 67 68 template <class T> 69 struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> { 70 T operator()() const { 71 std::uniform_int_distribution<T> dist; 72 return dist(*GetSharedRng()); 73 } 74 }; 75 76 template <> 77 struct Generator<Enum> { 78 Enum operator()() const { 79 std::uniform_int_distribution<typename std::underlying_type<Enum>::type> 80 dist; 81 while (true) { 82 auto variate = dist(*GetSharedRng()); 83 if (variate != kEnumEmpty && variate != kEnumDeleted) 84 return static_cast<Enum>(variate); 85 } 86 } 87 }; 88 89 template <> 90 struct Generator<EnumClass> { 91 EnumClass operator()() const { 92 std::uniform_int_distribution< 93 typename std::underlying_type<EnumClass>::type> 94 dist; 95 while (true) { 96 EnumClass variate = static_cast<EnumClass>(dist(*GetSharedRng())); 97 if (variate != EnumClass::kEmpty && variate != EnumClass::kDeleted) 98 return static_cast<EnumClass>(variate); 99 } 100 } 101 }; 102 103 template <> 104 struct Generator<std::string> { 105 std::string operator()() const; 106 }; 107 108 template <> 109 struct Generator<absl::string_view> { 110 absl::string_view operator()() const; 111 }; 112 113 template <> 114 struct Generator<NonStandardLayout> { 115 NonStandardLayout operator()() const { 116 return NonStandardLayout(Generator<std::string>()()); 117 } 118 }; 119 120 template <class K, class V> 121 struct Generator<std::pair<K, V>> { 122 std::pair<K, V> operator()() const { 123 return std::pair<K, V>(Generator<typename std::decay<K>::type>()(), 124 Generator<typename std::decay<V>::type>()()); 125 } 126 }; 127 128 template <class... Ts> 129 struct Generator<std::tuple<Ts...>> { 130 std::tuple<Ts...> operator()() const { 131 return std::tuple<Ts...>(Generator<typename std::decay<Ts>::type>()()...); 132 } 133 }; 134 135 template <class T> 136 struct Generator<std::unique_ptr<T>> { 137 std::unique_ptr<T> operator()() const { 138 return absl::make_unique<T>(Generator<T>()()); 139 } 140 }; 141 142 template <class U> 143 struct Generator<U, absl::void_t<decltype(std::declval<U&>().key()), 144 decltype(std::declval<U&>().value())>> 145 : Generator<std::pair< 146 typename std::decay<decltype(std::declval<U&>().key())>::type, 147 typename std::decay<decltype(std::declval<U&>().value())>::type>> {}; 148 149 template <class Container> 150 using GeneratedType = decltype( 151 std::declval<const Generator< 152 typename std::conditional<generator_internal::IsMap<Container>::value, 153 typename Container::value_type, 154 typename Container::key_type>::type>&>()()); 155 156 } // namespace hash_internal 157 } // namespace container_internal 158 ABSL_NAMESPACE_END 159 } // namespace absl 160 161 #endif // ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ 162