Skip to content

Commit d673cc8

Browse files
committed
Add exception tests for vector capacity operations
1 parent 1ef9410 commit d673cc8

File tree

8 files changed

+1587
-152
lines changed

8 files changed

+1587
-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,104 @@
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"
23+
24+
#if TEST_STD_VER >= 11
25+
26+
template <typename T>
27+
struct move_only_throwing_t {
28+
T data_;
29+
int* throw_after_n_ = nullptr;
30+
bool moved_from_ = false;
31+
32+
move_only_throwing_t() = default;
33+
34+
move_only_throwing_t(const T& data, int& throw_after_n) : data_(data), throw_after_n_(&throw_after_n) {
35+
if (throw_after_n == 0)
36+
throw 1;
37+
--throw_after_n;
38+
}
39+
40+
move_only_throwing_t(T&& data, int& throw_after_n) : data_(std::move(data)), throw_after_n_(&throw_after_n) {
41+
if (throw_after_n == 0)
42+
throw 1;
43+
--throw_after_n;
44+
}
45+
46+
move_only_throwing_t(const move_only_throwing_t&) = delete;
47+
move_only_throwing_t& operator=(const move_only_throwing_t&) = delete;
48+
49+
move_only_throwing_t(move_only_throwing_t&& rhs) : data_(std::move(rhs.data_)), throw_after_n_(rhs.throw_after_n_) {
50+
rhs.throw_after_n_ = nullptr;
51+
rhs.moved_from_ = true;
52+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
53+
throw 1;
54+
--*throw_after_n_;
55+
}
56+
57+
move_only_throwing_t& operator=(move_only_throwing_t&& rhs) {
58+
if (this == &rhs)
59+
return *this;
60+
data_ = std::move(rhs.data_);
61+
throw_after_n_ = rhs.throw_after_n_;
62+
rhs.moved_from_ = true;
63+
rhs.throw_after_n_ = nullptr;
64+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
65+
throw 1;
66+
--*throw_after_n_;
67+
return *this;
68+
}
69+
70+
friend bool operator==(const move_only_throwing_t& lhs, const move_only_throwing_t& rhs) {
71+
return lhs.data_ == rhs.data_;
72+
}
73+
friend bool operator!=(const move_only_throwing_t& lhs, const move_only_throwing_t& rhs) {
74+
return lhs.data_ != rhs.data_;
75+
}
76+
};
77+
78+
#endif
79+
80+
template <typename T>
81+
struct throwing_data {
82+
T data_;
83+
int* throw_after_n_ = nullptr;
84+
throwing_data() { throw 0; }
85+
86+
throwing_data(const T& data, int& throw_after_n) : data_(data), throw_after_n_(&throw_after_n) {
87+
if (throw_after_n == 0)
88+
throw 0;
89+
--throw_after_n;
90+
}
91+
92+
throwing_data(const throwing_data& rhs) : data_(rhs.data_), throw_after_n_(rhs.throw_after_n_) {
93+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
94+
throw 1;
95+
--*throw_after_n_;
96+
}
97+
98+
throwing_data& operator=(const throwing_data& rhs) {
99+
data_ = rhs.data_;
100+
throw_after_n_ = rhs.throw_after_n_;
101+
if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
102+
throw 1;
103+
--*throw_after_n_;
104+
return *this;
105+
}
106+
107+
friend bool operator==(const throwing_data& lhs, const throwing_data& rhs) {
108+
return lhs.data_ == rhs.data_ && lhs.throw_after_n_ == rhs.throw_after_n_;
109+
}
110+
friend bool operator!=(const throwing_data& lhs, const throwing_data& rhs) { return !(lhs == rhs); }
111+
};
18112

19113
template <class T>
20114
struct throwing_allocator {
@@ -94,4 +188,43 @@ inline void check_new_delete_called() {
94188
assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called);
95189
}
96190

191+
class Rnd {
192+
public:
193+
static void initializeSeed(unsigned int seed = 12345) { std::srand(seed); }
194+
195+
static std::vector<int> getRandomIntegerInputs(std::size_t N) {
196+
std::vector<int> v;
197+
v.reserve(N);
198+
for (std::size_t i = 0; i < N; ++i)
199+
v.push_back(std::rand());
200+
return v;
201+
}
202+
203+
static std::vector<std::string> getRandomStringInputsWithLength(std::size_t N, std::size_t len) {
204+
std::vector<std::string> v;
205+
v.reserve(N);
206+
for (std::size_t i = 0; i < N; ++i)
207+
v.push_back(getRandomString(len));
208+
return v;
209+
}
210+
211+
private:
212+
static const char Letters[];
213+
static const std::size_t LettersSize;
214+
215+
static std::string getRandomString(std::size_t len) {
216+
std::string s;
217+
s.reserve(len);
218+
for (std::size_t i = 0; i < len; ++i)
219+
s += Letters[std::rand() % LettersSize];
220+
return s;
221+
}
222+
};
223+
224+
const char Rnd::Letters[] = {
225+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
226+
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
227+
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
228+
const std::size_t Rnd::LettersSize = sizeof(Rnd::Letters) / sizeof(Rnd::Letters[0]);
229+
97230
#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)