1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H 10 #define TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H 11 12 #include <array> 13 #include <cassert> 14 #include <cstddef> 15 #include <cstdlib> 16 #include <memory> 17 #include <string> 18 #include <type_traits> 19 #include <utility> 20 #include <vector> 21 22 #include "count_new.h" 23 #include "test_macros.h" 24 25 struct throwing_t { 26 int* throw_after_n_ = nullptr; 27 throwing_t() { throw 0; } 28 29 explicit throwing_t(int& throw_after_n) : throw_after_n_(&throw_after_n) { 30 if (throw_after_n == 0) 31 throw 0; 32 --throw_after_n; 33 } 34 35 throwing_t(const throwing_t& rhs) : throw_after_n_(rhs.throw_after_n_) { 36 if (throw_after_n_ == nullptr || *throw_after_n_ == 0) 37 throw 1; 38 --*throw_after_n_; 39 } 40 41 throwing_t& operator=(const throwing_t& rhs) { 42 throw_after_n_ = rhs.throw_after_n_; 43 if (throw_after_n_ == nullptr || *throw_after_n_ == 0) 44 throw 1; 45 --*throw_after_n_; 46 return *this; 47 } 48 49 friend bool operator==(const throwing_t& lhs, const throwing_t& rhs) { 50 return lhs.throw_after_n_ == rhs.throw_after_n_; 51 } 52 friend bool operator!=(const throwing_t& lhs, const throwing_t& rhs) { 53 return lhs.throw_after_n_ != rhs.throw_after_n_; 54 } 55 }; 56 57 #if TEST_STD_VER >= 11 58 59 template <typename T> 60 struct move_only_throwing_t { 61 T data_; 62 int* throw_after_n_ = nullptr; 63 bool moved_from_ = false; 64 65 move_only_throwing_t() = default; 66 67 explicit move_only_throwing_t(const T& data, int& throw_after_n) : data_(data), throw_after_n_(&throw_after_n) { 68 if (throw_after_n == 0) 69 throw 1; 70 --throw_after_n; 71 } 72 73 explicit move_only_throwing_t(T&& data, int& throw_after_n) : data_(std::move(data)), throw_after_n_(&throw_after_n) { 74 if (throw_after_n == 0) 75 throw 1; 76 --throw_after_n; 77 } 78 79 move_only_throwing_t(const move_only_throwing_t&) = delete; 80 move_only_throwing_t& operator=(const move_only_throwing_t&) = delete; 81 82 move_only_throwing_t(move_only_throwing_t&& rhs) : data_(std::move(rhs.data_)), throw_after_n_(rhs.throw_after_n_) { 83 rhs.throw_after_n_ = nullptr; 84 rhs.moved_from_ = true; 85 if (throw_after_n_ == nullptr || *throw_after_n_ == 0) 86 throw 1; 87 --*throw_after_n_; 88 } 89 90 move_only_throwing_t& operator=(move_only_throwing_t&& rhs) { 91 if (this == &rhs) 92 return *this; 93 data_ = std::move(rhs.data_); 94 throw_after_n_ = rhs.throw_after_n_; 95 rhs.moved_from_ = true; 96 rhs.throw_after_n_ = nullptr; 97 if (throw_after_n_ == nullptr || *throw_after_n_ == 0) 98 throw 1; 99 --*throw_after_n_; 100 return *this; 101 } 102 103 friend bool operator==(const move_only_throwing_t& lhs, const move_only_throwing_t& rhs) { 104 return lhs.data_ == rhs.data_; 105 } 106 friend bool operator!=(const move_only_throwing_t& lhs, const move_only_throwing_t& rhs) { 107 return lhs.data_ != rhs.data_; 108 } 109 }; 110 111 #endif 112 113 template <typename T> 114 struct throwing_data { 115 T data_; 116 int* throw_after_n_ = nullptr; 117 throwing_data() { throw 0; } 118 119 throwing_data(const T& data, int& throw_after_n) : data_(data), throw_after_n_(&throw_after_n) { 120 if (throw_after_n == 0) 121 throw 0; 122 --throw_after_n; 123 } 124 125 throwing_data(const throwing_data& rhs) : data_(rhs.data_), throw_after_n_(rhs.throw_after_n_) { 126 if (throw_after_n_ == nullptr || *throw_after_n_ == 0) 127 throw 1; 128 --*throw_after_n_; 129 } 130 131 throwing_data& operator=(const throwing_data& rhs) { 132 data_ = rhs.data_; 133 throw_after_n_ = rhs.throw_after_n_; 134 if (throw_after_n_ == nullptr || *throw_after_n_ == 0) 135 throw 1; 136 --*throw_after_n_; 137 return *this; 138 } 139 140 friend bool operator==(const throwing_data& lhs, const throwing_data& rhs) { 141 return lhs.data_ == rhs.data_ && lhs.throw_after_n_ == rhs.throw_after_n_; 142 } 143 friend bool operator!=(const throwing_data& lhs, const throwing_data& rhs) { return !(lhs == rhs); } 144 }; 145 146 template <class T> 147 struct throwing_allocator { 148 using value_type = T; 149 150 bool throw_on_copy_ = false; 151 152 explicit throwing_allocator(bool throw_on_ctor = true) { 153 if (throw_on_ctor) 154 throw 0; 155 } 156 157 explicit throwing_allocator(bool throw_on_ctor, bool throw_on_copy) : throw_on_copy_(throw_on_copy) { 158 if (throw_on_ctor) 159 throw 0; 160 } 161 162 throwing_allocator(const throwing_allocator& rhs) : throw_on_copy_(rhs.throw_on_copy_) { 163 if (throw_on_copy_) 164 throw 0; 165 } 166 167 template <class U> 168 throwing_allocator(const throwing_allocator<U>& rhs) : throw_on_copy_(rhs.throw_on_copy_) { 169 if (throw_on_copy_) 170 throw 0; 171 } 172 173 T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); } 174 void deallocate(T* ptr, std::size_t n) { std::allocator<T>().deallocate(ptr, n); } 175 176 template <class U> 177 friend bool operator==(const throwing_allocator&, const throwing_allocator<U>&) { 178 return true; 179 } 180 }; 181 182 template <class T, class IterCat> 183 struct throwing_iterator { 184 using iterator_category = IterCat; 185 using difference_type = std::ptrdiff_t; 186 using value_type = T; 187 using reference = T&; 188 using pointer = T*; 189 190 int i_; 191 T v_; 192 193 explicit throwing_iterator(int i = 0, const T& v = T()) : i_(i), v_(v) {} 194 195 reference operator*() { 196 if (i_ == 1) 197 throw 1; 198 return v_; 199 } 200 201 friend bool operator==(const throwing_iterator& lhs, const throwing_iterator& rhs) { return lhs.i_ == rhs.i_; } 202 friend bool operator!=(const throwing_iterator& lhs, const throwing_iterator& rhs) { return lhs.i_ != rhs.i_; } 203 204 throwing_iterator& operator++() { 205 ++i_; 206 return *this; 207 } 208 209 throwing_iterator operator++(int) { 210 auto tmp = *this; 211 ++i_; 212 return tmp; 213 } 214 }; 215 216 inline void check_new_delete_called() { 217 assert(globalMemCounter.new_called == globalMemCounter.delete_called); 218 assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called); 219 assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called); 220 assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called); 221 } 222 223 template <class T, typename Alloc> 224 void use_unspecified_but_valid_state_vector(std::vector<T, Alloc> const& v) { 225 assert(v.size() >= 0); // make sure it can be called 226 assert(v.capacity() >= 0); 227 assert(v.empty() || !v.empty()); 228 for (auto it = v.begin(); it != v.end(); ++it) { 229 auto& element = *it; 230 (void)element; 231 } 232 } 233 234 static const std::array<char, 62> letters = { 235 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 236 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 237 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; 238 239 inline std::string getString(std::size_t n, std::size_t len) { 240 std::string s; 241 s.reserve(len); 242 for (std::size_t i = 0; i < len; ++i) 243 s += letters[(i * i + n) % letters.size()]; 244 return s; 245 } 246 247 inline std::vector<int> getIntegerInputs(std::size_t n) { 248 std::vector<int> v; 249 v.reserve(n); 250 for (std::size_t i = 0; i < n; ++i) 251 v.push_back(static_cast<int>(i * i + n)); 252 return v; 253 } 254 255 inline std::vector<std::string> getStringInputsWithLength(std::size_t n, std::size_t len) { 256 std::vector<std::string> v; 257 v.reserve(n); 258 for (std::size_t i = 0; i < n; ++i) 259 v.push_back(getString(i, len)); 260 return v; 261 } 262 263 #endif // TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H 264