xref: /llvm-project/libcxx/test/std/containers/sequences/vector/common.h (revision 550d32f205202b73f21903b29df04fe2e89ae648)
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