Skip to content

Commit 27d013a

Browse files
committed
Fix and refactor exception tests for std::vector
1 parent 3a01b46 commit 27d013a

File tree

2 files changed

+62
-110
lines changed

2 files changed

+62
-110
lines changed

libcxx/test/std/containers/sequences/vector/common.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,38 @@
1616

1717
#include "count_new.h"
1818

19+
struct throwing_t {
20+
int* throw_after_n_ = nullptr;
21+
throwing_t() { throw 0; }
22+
23+
throwing_t(int& throw_after_n) : throw_after_n_(&throw_after_n) {
24+
if (throw_after_n == 0)
25+
throw 0;
26+
--throw_after_n;
27+
}
28+
29+
throwing_t(const throwing_t& rhs) : throw_after_n_(rhs.throw_after_n_) {
30+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
31+
throw 1;
32+
--*throw_after_n_;
33+
}
34+
35+
throwing_t& operator=(const throwing_t& rhs) {
36+
throw_after_n_ = rhs.throw_after_n_;
37+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
38+
throw 1;
39+
--*throw_after_n_;
40+
return *this;
41+
}
42+
43+
friend bool operator==(const throwing_t& lhs, const throwing_t& rhs) {
44+
return lhs.throw_after_n_ == rhs.throw_after_n_;
45+
}
46+
friend bool operator!=(const throwing_t& lhs, const throwing_t& rhs) {
47+
return lhs.throw_after_n_ != rhs.throw_after_n_;
48+
}
49+
};
50+
1951
template <class T>
2052
struct throwing_allocator {
2153
using value_type = T;

libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp

Lines changed: 30 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -16,149 +16,66 @@
1616
#include <type_traits>
1717
#include <vector>
1818

19+
#include "../common.h"
1920
#include "count_new.h"
2021
#include "test_allocator.h"
2122
#include "test_iterators.h"
2223

23-
template <class T>
24-
struct Allocator {
25-
using value_type = T;
26-
using is_always_equal = std::false_type;
27-
28-
template <class U>
29-
Allocator(const Allocator<U>&) {}
30-
31-
Allocator(bool should_throw = true) {
32-
if (should_throw)
33-
throw 0;
34-
}
35-
36-
T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); }
37-
void deallocate(T* ptr, std::size_t n) { std::allocator<T>().deallocate(ptr, n); }
38-
39-
template <class U>
40-
friend bool operator==(const Allocator&, const Allocator<U>&) {
41-
return true;
42-
}
43-
};
44-
45-
struct ThrowingT {
46-
int* throw_after_n_ = nullptr;
47-
ThrowingT() { throw 0; }
48-
49-
ThrowingT(int& throw_after_n) : throw_after_n_(&throw_after_n) {
50-
if (throw_after_n == 0)
51-
throw 0;
52-
--throw_after_n;
53-
}
54-
55-
ThrowingT(const ThrowingT& rhs) : throw_after_n_(rhs.throw_after_n_) {
56-
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
57-
throw 1;
58-
--*throw_after_n_;
59-
}
60-
61-
ThrowingT& operator=(const ThrowingT& rhs) {
62-
throw_after_n_ = rhs.throw_after_n_;
63-
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
64-
throw 1;
65-
--*throw_after_n_;
66-
return *this;
67-
}
68-
};
69-
70-
template <class IterCat>
71-
struct Iterator {
72-
using iterator_category = IterCat;
73-
using difference_type = std::ptrdiff_t;
74-
using value_type = int;
75-
using reference = int&;
76-
using pointer = int*;
77-
78-
int i_;
79-
Iterator(int i = 0) : i_(i) {}
80-
int& operator*() {
81-
if (i_ == 1)
82-
throw 1;
83-
return i_;
84-
}
85-
86-
friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; }
87-
88-
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; }
89-
90-
Iterator& operator++() {
91-
++i_;
92-
return *this;
93-
}
94-
95-
Iterator operator++(int) {
96-
auto tmp = *this;
97-
++i_;
98-
return tmp;
99-
}
100-
};
101-
102-
void check_new_delete_called() {
103-
assert(globalMemCounter.new_called == globalMemCounter.delete_called);
104-
assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called);
105-
assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called);
106-
assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called);
107-
}
108-
10924
int main(int, char**) {
110-
using AllocVec = std::vector<int, Allocator<int> >;
25+
using AllocVec = std::vector<int, throwing_allocator<int> >;
11126
try { // vector()
11227
AllocVec vec;
11328
} catch (int) {
11429
}
11530
check_new_delete_called();
11631

11732
try { // Throw in vector(size_type) from type
118-
std::vector<ThrowingT> get_alloc(1);
33+
std::vector<throwing_t> get_alloc(1);
11934
} catch (int) {
12035
}
12136
check_new_delete_called();
12237

12338
#if TEST_STD_VER >= 14
12439
try { // Throw in vector(size_type, value_type) from type
12540
int throw_after = 1;
126-
ThrowingT v(throw_after);
127-
std::vector<ThrowingT> get_alloc(1, v);
41+
throwing_t v(throw_after);
42+
std::vector<throwing_t> get_alloc(1, v);
12843
} catch (int) {
12944
}
13045
check_new_delete_called();
13146

132-
try { // Throw in vector(size_type, const allocator_type&) from allocator
133-
Allocator<int> alloc(false);
47+
try { // Throw in vector(size_type, const allocator_type&) from allocator
48+
throwing_allocator<int> alloc(false, true); // throw on copy only
13449
AllocVec get_alloc(0, alloc);
13550
} catch (int) {
13651
}
13752
check_new_delete_called();
13853

13954
try { // Throw in vector(size_type, const allocator_type&) from the type
140-
std::vector<ThrowingT> vec(1, std::allocator<ThrowingT>());
55+
std::vector<throwing_t> vec(1, std::allocator<throwing_t>());
14156
} catch (int) {
14257
}
14358
check_new_delete_called();
14459
#endif // TEST_STD_VER >= 14
14560

14661
try { // Throw in vector(size_type, value_type, const allocator_type&) from the type
14762
int throw_after = 1;
148-
ThrowingT v(throw_after);
149-
std::vector<ThrowingT> vec(1, v, std::allocator<ThrowingT>());
63+
throwing_t v(throw_after);
64+
std::vector<throwing_t> vec(1, v, std::allocator<throwing_t>());
15065
} catch (int) {
15166
}
15267
check_new_delete_called();
15368

15469
try { // Throw in vector(InputIterator, InputIterator) from input iterator
155-
std::vector<int> vec((Iterator<std::input_iterator_tag>()), Iterator<std::input_iterator_tag>(2));
70+
std::vector<int> vec(
71+
(throwing_iterator<int, std::input_iterator_tag>()), throwing_iterator<int, std::input_iterator_tag>(2));
15672
} catch (int) {
15773
}
15874
check_new_delete_called();
15975

16076
try { // Throw in vector(InputIterator, InputIterator) from forward iterator
161-
std::vector<int> vec((Iterator<std::forward_iterator_tag>()), Iterator<std::forward_iterator_tag>(2));
77+
std::vector<int> vec(
78+
(throwing_iterator<int, std::forward_iterator_tag>()), throwing_iterator<int, std::forward_iterator_tag>(2));
16279
} catch (int) {
16380
}
16481
check_new_delete_called();
@@ -172,21 +89,24 @@ int main(int, char**) {
17289

17390
try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator
17491
std::allocator<int> alloc;
175-
std::vector<int> vec(Iterator<std::input_iterator_tag>(), Iterator<std::input_iterator_tag>(2), alloc);
92+
std::vector<int> vec(
93+
throwing_iterator<int, std::input_iterator_tag>(), throwing_iterator<int, std::input_iterator_tag>(2), alloc);
17694
} catch (int) {
17795
}
17896
check_new_delete_called();
17997

18098
try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator
18199
std::allocator<int> alloc;
182-
std::vector<int> vec(Iterator<std::forward_iterator_tag>(), Iterator<std::forward_iterator_tag>(2), alloc);
100+
std::vector<int> vec(throwing_iterator<int, std::forward_iterator_tag>(),
101+
throwing_iterator<int, std::forward_iterator_tag>(2),
102+
alloc);
183103
} catch (int) {
184104
}
185105
check_new_delete_called();
186106

187107
try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
188108
int a[] = {1, 2};
189-
Allocator<int> alloc(false);
109+
throwing_allocator<int> alloc(false, true); // throw on copy only
190110
AllocVec vec(cpp17_input_iterator<int*>(a), cpp17_input_iterator<int*>(a + 2), alloc);
191111
} catch (int) {
192112
// FIXME: never called.
@@ -195,52 +115,52 @@ int main(int, char**) {
195115

196116
try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
197117
int a[] = {1, 2};
198-
Allocator<int> alloc(false);
118+
throwing_allocator<int> alloc(false, true); // throw on copy only
199119
AllocVec vec(forward_iterator<int*>(a), forward_iterator<int*>(a + 2), alloc);
200120
} catch (int) {
201121
// FIXME: never called.
202122
}
203123
check_new_delete_called();
204124

205125
try { // Throw in vector(const vector&) from type
206-
std::vector<ThrowingT> vec;
207-
int throw_after = 0;
126+
std::vector<throwing_t> vec;
127+
int throw_after = 1;
208128
vec.emplace_back(throw_after);
209129
auto vec2 = vec;
210130
} catch (int) {
211131
}
212132
check_new_delete_called();
213133

214134
try { // Throw in vector(const vector&, const allocator_type&) from type
215-
std::vector<ThrowingT> vec;
135+
std::vector<throwing_t> vec;
216136
int throw_after = 1;
217137
vec.emplace_back(throw_after);
218-
std::vector<ThrowingT> vec2(vec, std::allocator<int>());
138+
std::vector<throwing_t> vec2(vec, std::allocator<int>());
219139
} catch (int) {
220140
}
221141
check_new_delete_called();
222142

223143
try { // Throw in vector(vector&&, const allocator_type&) from type during element-wise move
224-
std::vector<ThrowingT, test_allocator<ThrowingT> > vec(test_allocator<ThrowingT>(1));
144+
std::vector<throwing_t, test_allocator<throwing_t> > vec(test_allocator<throwing_t>(1));
225145
int throw_after = 10;
226-
ThrowingT v(throw_after);
146+
throwing_t v(throw_after);
227147
vec.insert(vec.end(), 6, v);
228-
std::vector<ThrowingT, test_allocator<ThrowingT> > vec2(std::move(vec), test_allocator<ThrowingT>(2));
148+
std::vector<throwing_t, test_allocator<throwing_t> > vec2(std::move(vec), test_allocator<throwing_t>(2));
229149
} catch (int) {
230150
}
231151
check_new_delete_called();
232152

233153
#if TEST_STD_VER >= 11
234154
try { // Throw in vector(initializer_list<value_type>) from type
235155
int throw_after = 1;
236-
std::vector<ThrowingT> vec({ThrowingT(throw_after)});
156+
std::vector<throwing_t> vec({throwing_t(throw_after)});
237157
} catch (int) {
238158
}
239159
check_new_delete_called();
240160

241161
try { // Throw in vector(initializer_list<value_type>, const allocator_type&) constructor from type
242162
int throw_after = 1;
243-
std::vector<ThrowingT> vec({ThrowingT(throw_after)}, std::allocator<ThrowingT>());
163+
std::vector<throwing_t> vec({throwing_t(throw_after)}, std::allocator<throwing_t>());
244164
} catch (int) {
245165
}
246166
check_new_delete_called();

0 commit comments

Comments
 (0)