Skip to content

Commit a94d839

Browse files
committed
Add exception tests for vector capacity operations
1 parent e0a79ee commit a94d839

File tree

6 files changed

+1405
-115
lines changed

6 files changed

+1405
-115
lines changed

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

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@
99
#ifndef TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H
1010
#define TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H
1111

12+
#include <array>
1213
#include <cassert>
1314
#include <cstddef>
15+
#include <cstdlib>
1416
#include <memory>
17+
#include <string>
1518
#include <type_traits>
19+
#include <utility>
20+
#include <vector>
1621

1722
#include "count_new.h"
23+
#include "test_macros.h"
1824

1925
struct throwing_t {
2026
int* throw_after_n_ = nullptr;
@@ -48,6 +54,95 @@ struct throwing_t {
4854
}
4955
};
5056

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+
51146
template <class T>
52147
struct throwing_allocator {
53148
using value_type = T;
@@ -125,4 +220,39 @@ inline void check_new_delete_called() {
125220
assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called);
126221
}
127222

223+
class Rnd {
224+
public:
225+
static std::vector<int> getIntegerInputs(std::size_t n) {
226+
std::vector<int> v;
227+
v.reserve(n);
228+
for (std::size_t i = 0; i < n; ++i)
229+
v.push_back(static_cast<int>(i * i + n));
230+
return v;
231+
}
232+
233+
static std::vector<std::string> getStringInputsWithLength(std::size_t n, std::size_t len) {
234+
std::vector<std::string> v;
235+
v.reserve(n);
236+
for (std::size_t i = 0; i < n; ++i)
237+
v.push_back(getString(i, len));
238+
return v;
239+
}
240+
241+
private:
242+
static const std::array<char, 62> letters;
243+
244+
static std::string getString(std::size_t n, std::size_t len) {
245+
std::string s;
246+
s.reserve(len);
247+
for (std::size_t i = 0; i < len; ++i)
248+
s += letters[(i * i + n) % letters.size()];
249+
return s;
250+
}
251+
};
252+
253+
const std::array<char, 62> Rnd::letters = {
254+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
255+
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
256+
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
257+
128258
#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)