Skip to content

Commit 1950489

Browse files
committed
Add exception tests for vector capacity operations
1 parent 8eb5baf commit 1950489

File tree

7 files changed

+1458
-152
lines changed

7 files changed

+1458
-152
lines changed

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

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@
1111

1212
#include <cassert>
1313
#include <cstddef>
14+
#include <cstdlib>
1415
#include <memory>
16+
#include <string>
1517
#include <type_traits>
18+
#include <utility>
19+
#include <vector>
1620

1721
#include "count_new.h"
22+
#include "test_macros.h"
1823

1924
struct throwing_t {
2025
int* throw_after_n_ = nullptr;
@@ -48,6 +53,95 @@ struct throwing_t {
4853
}
4954
};
5055

56+
#if TEST_STD_VER >= 11
57+
58+
template <typename T>
59+
struct move_only_throwing_t {
60+
T data_;
61+
int* throw_after_n_ = nullptr;
62+
bool moved_from_ = false;
63+
64+
move_only_throwing_t() = default;
65+
66+
explicit move_only_throwing_t(const T& data, int& throw_after_n) : data_(data), throw_after_n_(&throw_after_n) {
67+
if (throw_after_n == 0)
68+
throw 1;
69+
--throw_after_n;
70+
}
71+
72+
explicit move_only_throwing_t(T&& data, int& throw_after_n) : data_(std::move(data)), throw_after_n_(&throw_after_n) {
73+
if (throw_after_n == 0)
74+
throw 1;
75+
--throw_after_n;
76+
}
77+
78+
move_only_throwing_t(const move_only_throwing_t&) = delete;
79+
move_only_throwing_t& operator=(const move_only_throwing_t&) = delete;
80+
81+
move_only_throwing_t(move_only_throwing_t&& rhs) : data_(std::move(rhs.data_)), throw_after_n_(rhs.throw_after_n_) {
82+
rhs.throw_after_n_ = nullptr;
83+
rhs.moved_from_ = true;
84+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
85+
throw 1;
86+
--*throw_after_n_;
87+
}
88+
89+
move_only_throwing_t& operator=(move_only_throwing_t&& rhs) {
90+
if (this == &rhs)
91+
return *this;
92+
data_ = std::move(rhs.data_);
93+
throw_after_n_ = rhs.throw_after_n_;
94+
rhs.moved_from_ = true;
95+
rhs.throw_after_n_ = nullptr;
96+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
97+
throw 1;
98+
--*throw_after_n_;
99+
return *this;
100+
}
101+
102+
friend bool operator==(const move_only_throwing_t& lhs, const move_only_throwing_t& rhs) {
103+
return lhs.data_ == rhs.data_;
104+
}
105+
friend bool operator!=(const move_only_throwing_t& lhs, const move_only_throwing_t& rhs) {
106+
return lhs.data_ != rhs.data_;
107+
}
108+
};
109+
110+
#endif
111+
112+
template <typename T>
113+
struct throwing_data {
114+
T data_;
115+
int* throw_after_n_ = nullptr;
116+
throwing_data() { throw 0; }
117+
118+
throwing_data(const T& data, int& throw_after_n) : data_(data), throw_after_n_(&throw_after_n) {
119+
if (throw_after_n == 0)
120+
throw 0;
121+
--throw_after_n;
122+
}
123+
124+
throwing_data(const throwing_data& rhs) : data_(rhs.data_), throw_after_n_(rhs.throw_after_n_) {
125+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
126+
throw 1;
127+
--*throw_after_n_;
128+
}
129+
130+
throwing_data& operator=(const throwing_data& rhs) {
131+
data_ = rhs.data_;
132+
throw_after_n_ = rhs.throw_after_n_;
133+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
134+
throw 1;
135+
--*throw_after_n_;
136+
return *this;
137+
}
138+
139+
friend bool operator==(const throwing_data& lhs, const throwing_data& rhs) {
140+
return lhs.data_ == rhs.data_ && lhs.throw_after_n_ == rhs.throw_after_n_;
141+
}
142+
friend bool operator!=(const throwing_data& lhs, const throwing_data& rhs) { return !(lhs == rhs); }
143+
};
144+
51145
template <class T>
52146
struct throwing_allocator {
53147
using value_type = T;
@@ -125,4 +219,43 @@ inline void check_new_delete_called() {
125219
assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called);
126220
}
127221

222+
class Rnd {
223+
public:
224+
static void initializeSeed(unsigned int seed = 12345) { std::srand(seed); }
225+
226+
static std::vector<int> getRandomIntegerInputs(std::size_t N) {
227+
std::vector<int> v;
228+
v.reserve(N);
229+
for (std::size_t i = 0; i < N; ++i)
230+
v.push_back(std::rand());
231+
return v;
232+
}
233+
234+
static std::vector<std::string> getRandomStringInputsWithLength(std::size_t N, std::size_t len) {
235+
std::vector<std::string> v;
236+
v.reserve(N);
237+
for (std::size_t i = 0; i < N; ++i)
238+
v.push_back(getRandomString(len));
239+
return v;
240+
}
241+
242+
private:
243+
static const char Letters[];
244+
static const std::size_t LettersSize;
245+
246+
static std::string getRandomString(std::size_t len) {
247+
std::string s;
248+
s.reserve(len);
249+
for (std::size_t i = 0; i < len; ++i)
250+
s += Letters[std::rand() % LettersSize];
251+
return s;
252+
}
253+
};
254+
255+
const char Rnd::Letters[] = {
256+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
257+
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
258+
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
259+
const std::size_t Rnd::LettersSize = sizeof(Rnd::Letters) / sizeof(Rnd::Letters[0]);
260+
128261
#endif // TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H

libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp

Lines changed: 65 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -19,126 +19,76 @@
1919
#include "asan_testing.h"
2020

2121
TEST_CONSTEXPR_CXX20 bool tests() {
22-
{
23-
std::vector<int> v;
24-
v.reserve(10);
25-
assert(v.capacity() >= 10);
26-
assert(is_contiguous_container_asan_correct(v));
27-
}
28-
{
29-
std::vector<int> v(100);
30-
assert(v.capacity() == 100);
31-
v.reserve(50);
32-
assert(v.size() == 100);
33-
assert(v.capacity() == 100);
34-
v.reserve(150);
35-
assert(v.size() == 100);
36-
assert(v.capacity() == 150);
37-
assert(is_contiguous_container_asan_correct(v));
38-
}
39-
{
40-
// Add 1 for implementations that dynamically allocate a container proxy.
41-
std::vector<int, limited_allocator<int, 250 + 1> > v(100);
42-
assert(v.capacity() == 100);
43-
v.reserve(50);
44-
assert(v.size() == 100);
45-
assert(v.capacity() == 100);
46-
v.reserve(150);
47-
assert(v.size() == 100);
48-
assert(v.capacity() == 150);
49-
assert(is_contiguous_container_asan_correct(v));
50-
}
51-
#ifndef TEST_HAS_NO_EXCEPTIONS
52-
if (!TEST_IS_CONSTANT_EVALUATED) {
53-
std::vector<int> v;
54-
std::size_t sz = v.max_size() + 1;
55-
56-
try {
57-
v.reserve(sz);
58-
assert(false);
59-
} catch (const std::length_error&) {
60-
assert(v.size() == 0);
61-
assert(v.capacity() == 0);
62-
}
63-
}
64-
if (!TEST_IS_CONSTANT_EVALUATED) {
65-
std::vector<int> v(10, 42);
66-
int* previous_data = v.data();
67-
std::size_t previous_capacity = v.capacity();
68-
std::size_t sz = v.max_size() + 1;
69-
70-
try {
71-
v.reserve(sz);
72-
assert(false);
73-
} catch (std::length_error&) {
74-
assert(v.size() == 10);
75-
assert(v.capacity() == previous_capacity);
76-
assert(v.data() == previous_data);
77-
78-
for (int i = 0; i < 10; ++i) {
79-
assert(v[i] == 42);
80-
}
81-
}
82-
}
83-
#endif
22+
{
23+
std::vector<int> v;
24+
v.reserve(10);
25+
assert(v.capacity() >= 10);
26+
assert(is_contiguous_container_asan_correct(v));
27+
}
28+
{
29+
std::vector<int> v(100);
30+
assert(v.capacity() == 100);
31+
v.reserve(50);
32+
assert(v.size() == 100);
33+
assert(v.capacity() == 100);
34+
v.reserve(150);
35+
assert(v.size() == 100);
36+
assert(v.capacity() == 150);
37+
assert(is_contiguous_container_asan_correct(v));
38+
}
39+
{
40+
// Add 1 for implementations that dynamically allocate a container proxy.
41+
std::vector<int, limited_allocator<int, 250 + 1> > v(100);
42+
assert(v.capacity() == 100);
43+
v.reserve(50);
44+
assert(v.size() == 100);
45+
assert(v.capacity() == 100);
46+
v.reserve(150);
47+
assert(v.size() == 100);
48+
assert(v.capacity() == 150);
49+
assert(is_contiguous_container_asan_correct(v));
50+
}
8451
#if TEST_STD_VER >= 11
85-
{
86-
std::vector<int, min_allocator<int>> v;
87-
v.reserve(10);
88-
assert(v.capacity() >= 10);
89-
assert(is_contiguous_container_asan_correct(v));
90-
}
91-
{
92-
std::vector<int, min_allocator<int>> v(100);
93-
assert(v.capacity() == 100);
94-
v.reserve(50);
95-
assert(v.size() == 100);
96-
assert(v.capacity() == 100);
97-
v.reserve(150);
98-
assert(v.size() == 100);
99-
assert(v.capacity() == 150);
100-
assert(is_contiguous_container_asan_correct(v));
101-
}
102-
{
103-
std::vector<int, safe_allocator<int>> v;
104-
v.reserve(10);
105-
assert(v.capacity() >= 10);
106-
assert(is_contiguous_container_asan_correct(v));
107-
}
108-
{
109-
std::vector<int, safe_allocator<int>> v(100);
110-
assert(v.capacity() == 100);
111-
v.reserve(50);
112-
assert(v.size() == 100);
113-
assert(v.capacity() == 100);
114-
v.reserve(150);
115-
assert(v.size() == 100);
116-
assert(v.capacity() == 150);
117-
assert(is_contiguous_container_asan_correct(v));
118-
}
119-
#endif
120-
#ifndef TEST_HAS_NO_EXCEPTIONS
121-
if (!TEST_IS_CONSTANT_EVALUATED) {
122-
std::vector<int, limited_allocator<int, 100> > v;
123-
v.reserve(50);
124-
assert(v.capacity() == 50);
125-
assert(is_contiguous_container_asan_correct(v));
126-
try {
127-
v.reserve(101);
128-
assert(false);
129-
} catch (const std::length_error&) {
130-
// no-op
131-
}
132-
assert(v.capacity() == 50);
133-
assert(is_contiguous_container_asan_correct(v));
134-
}
52+
{
53+
std::vector<int, min_allocator<int>> v;
54+
v.reserve(10);
55+
assert(v.capacity() >= 10);
56+
assert(is_contiguous_container_asan_correct(v));
57+
}
58+
{
59+
std::vector<int, min_allocator<int>> v(100);
60+
assert(v.capacity() == 100);
61+
v.reserve(50);
62+
assert(v.size() == 100);
63+
assert(v.capacity() == 100);
64+
v.reserve(150);
65+
assert(v.size() == 100);
66+
assert(v.capacity() == 150);
67+
assert(is_contiguous_container_asan_correct(v));
68+
}
69+
{
70+
std::vector<int, safe_allocator<int>> v;
71+
v.reserve(10);
72+
assert(v.capacity() >= 10);
73+
assert(is_contiguous_container_asan_correct(v));
74+
}
75+
{
76+
std::vector<int, safe_allocator<int>> v(100);
77+
assert(v.capacity() == 100);
78+
v.reserve(50);
79+
assert(v.size() == 100);
80+
assert(v.capacity() == 100);
81+
v.reserve(150);
82+
assert(v.size() == 100);
83+
assert(v.capacity() == 150);
84+
assert(is_contiguous_container_asan_correct(v));
85+
}
13586
#endif
13687

137-
return true;
88+
return true;
13889
}
13990

140-
int main(int, char**)
141-
{
91+
int main(int, char**) {
14292
tests();
14393

14494
#if TEST_STD_VER > 17

0 commit comments

Comments
 (0)