Skip to content

Commit 4039a79

Browse files
authored
[libc++][test] Improve tests for assign in std::vector and vector<bool> (#119163)
This PR enhances the test coverage for std::vector::assign by adding new tests for several important test cases that were previously missing, as shown in the following table: | test cases | forward_iterator | input_iterator | |-----------------------------------|------------------|----------------| | new_size > capacity() | Yes | Yes | | size() < new_size <= capacity() | No | No | | new_size <= size() | No | No | Similarly, no tests have previously covered `assign(InputIterator, InputIterator)` and `assign(size_type, const value_type&)` for `vector<bool>`. With this patch applied, all missing tests are covered.
1 parent cc246d4 commit 4039a79

File tree

3 files changed

+250
-7
lines changed

3 files changed

+250
-7
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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+
// <vector>
10+
11+
// template <class InputIt>
12+
// constexpr void assign(InputIt first, InputIt last);
13+
14+
#include <vector>
15+
#include <cassert>
16+
#include "test_macros.h"
17+
#include "test_iterators.h"
18+
19+
TEST_CONSTEXPR_CXX20 bool tests() {
20+
{ // Test with various cases where assign may or may not trigger reallocations for forward_iterator
21+
{ // Reallocation happens
22+
std::vector<bool> in(128, true);
23+
std::vector<bool> v(5, false);
24+
assert(v.capacity() < in.size());
25+
using It = forward_iterator<std::vector<bool>::iterator>;
26+
v.assign(It(in.begin()), It(in.end()));
27+
assert(v == in);
28+
}
29+
{ // No reallocation: fit within current size
30+
bool in[] = {false, true, false, true, true};
31+
std::size_t N = sizeof(in) / sizeof(in[0]);
32+
std::vector<bool> v(2 * N, false);
33+
using It = forward_iterator<bool*>;
34+
v.assign(It(in), It(in + N));
35+
assert(v.size() == N);
36+
for (std::size_t i = 0; i < N; ++i)
37+
assert(v[i] == in[i]);
38+
}
39+
{ // No reallocation: fit within spare space
40+
bool in[] = {false, true, false, true, true};
41+
std::size_t N = sizeof(in) / sizeof(in[0]);
42+
std::vector<bool> v(N / 2, false);
43+
v.reserve(N * 2);
44+
using It = forward_iterator<bool*>;
45+
v.assign(It(in), It(in + N));
46+
assert(v.size() == N);
47+
for (std::size_t i = 0; i < N; ++i)
48+
assert(v[i] == in[i]);
49+
}
50+
}
51+
52+
{ // Test with various cases where assign may or may not trigger reallocations for input_iterator
53+
{ // Reallocation happens
54+
std::vector<bool> in(128, true);
55+
std::vector<bool> v(5, false);
56+
assert(v.capacity() < in.size());
57+
using It = cpp17_input_iterator<std::vector<bool>::iterator>;
58+
v.assign(It(in.begin()), It(in.end()));
59+
assert(v == in);
60+
}
61+
{ // No reallocation: fit within current size
62+
bool in[] = {false, true, false, true, true};
63+
std::size_t N = sizeof(in) / sizeof(in[0]);
64+
std::vector<bool> v(2 * N, false);
65+
using It = cpp17_input_iterator<bool*>;
66+
v.assign(It(in), It(in + N));
67+
assert(v.size() == N);
68+
for (std::size_t i = 0; i < N; ++i)
69+
assert(v[i] == in[i]);
70+
}
71+
{ // No reallocation: fit within spare space
72+
bool in[] = {false, true, false, true, true};
73+
std::size_t N = sizeof(in) / sizeof(in[0]);
74+
std::vector<bool> v(N / 2, false);
75+
v.reserve(N * 2);
76+
using It = cpp17_input_iterator<bool*>;
77+
v.assign(It(in), It(in + N));
78+
assert(v.size() == N);
79+
for (std::size_t i = 0; i < N; ++i)
80+
assert(v[i] == in[i]);
81+
}
82+
}
83+
84+
return true;
85+
}
86+
87+
int main(int, char**) {
88+
tests();
89+
#if TEST_STD_VER > 17
90+
static_assert(tests());
91+
#endif
92+
return 0;
93+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
// <vector>
10+
11+
// void assign(size_type n, const value_type& x);
12+
13+
#include <vector>
14+
#include <cassert>
15+
#include "test_macros.h"
16+
#include "test_iterators.h"
17+
18+
TEST_CONSTEXPR_CXX20 bool tests() {
19+
{ // Test with various cases where assign may or may not trigger reallocations
20+
{ // Reallocation happens
21+
std::size_t N = 128;
22+
std::vector<bool> v(5, false);
23+
assert(v.capacity() < N);
24+
v.assign(N, true);
25+
assert(v.size() == N);
26+
for (std::size_t i = 0; i < N; ++i)
27+
assert(v[i] == true);
28+
}
29+
{ // No reallocation: fit within current size
30+
std::size_t N = 5;
31+
std::vector<bool> v(2 * N, false);
32+
v.assign(N, true);
33+
assert(v.size() == N);
34+
for (std::size_t i = 0; i < N; ++i)
35+
assert(v[i] == true);
36+
}
37+
{ // No reallocation: fit within spare space
38+
std::size_t N = 5;
39+
std::vector<bool> v(N / 2, false);
40+
v.reserve(N * 2);
41+
v.assign(N, true);
42+
assert(v.size() == N);
43+
for (std::size_t i = 0; i < N; ++i)
44+
assert(v[i] == true);
45+
}
46+
}
47+
48+
return true;
49+
}
50+
51+
int main(int, char**) {
52+
tests();
53+
#if TEST_STD_VER > 17
54+
static_assert(tests());
55+
#endif
56+
return 0;
57+
}

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

Lines changed: 100 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,16 @@
1919
#include "asan_testing.h"
2020
#include "test_iterators.h"
2121
#if TEST_STD_VER >= 11
22-
#include "emplace_constructible.h"
23-
#include "container_test_types.h"
22+
# include "emplace_constructible.h"
23+
# include "container_test_types.h"
2424
#endif
2525

26-
2726
TEST_CONSTEXPR_CXX20 bool test() {
2827
#if TEST_STD_VER >= 11
2928
int arr1[] = {42};
3029
int arr2[] = {1, 101, 42};
31-
{
32-
using T = EmplaceConstructibleMoveableAndAssignable<int>;
30+
{ // Test with new_size > capacity() == 0 for forward_iterator, resulting in reallocation during assign
31+
using T = EmplaceConstructibleMoveableAndAssignable<int>;
3332
using It = forward_iterator<int*>;
3433
{
3534
std::vector<T> v;
@@ -44,8 +43,8 @@ TEST_CONSTEXPR_CXX20 bool test() {
4443
assert(v[2].value == 42);
4544
}
4645
}
47-
{
48-
using T = EmplaceConstructibleMoveableAndAssignable<int>;
46+
{ // Test with new_size > capacity() == 0 for input_iterator, resulting in reallocation during assign
47+
using T = EmplaceConstructibleMoveableAndAssignable<int>;
4948
using It = cpp17_input_iterator<int*>;
5049
{
5150
std::vector<T> v;
@@ -64,6 +63,100 @@ TEST_CONSTEXPR_CXX20 bool test() {
6463
assert(v[2].value == 42);
6564
}
6665
}
66+
67+
{ // Test with new_size < size() for forward_iterator, resulting in destruction at end during assign
68+
using T = EmplaceConstructibleMoveableAndAssignable<int>;
69+
using It = forward_iterator<int*>;
70+
{
71+
std::vector<T> v;
72+
v.reserve(5);
73+
for (std::size_t i = 0; i < v.capacity(); ++i)
74+
v.emplace_back(99);
75+
v.assign(It(arr1), It(std::end(arr1)));
76+
assert(v.size() == 1);
77+
assert(v[0].value == 42);
78+
}
79+
{
80+
std::vector<T> v;
81+
v.reserve(5);
82+
for (std::size_t i = 0; i < v.capacity(); ++i)
83+
v.emplace_back(99);
84+
v.assign(It(arr2), It(std::end(arr2)));
85+
assert(v.size() == 3);
86+
assert(v[0].value == 1);
87+
assert(v[1].value == 101);
88+
assert(v[2].value == 42);
89+
}
90+
}
91+
{ // Test with new_size < size() for input_iterator, resulting in destruction at end during assign
92+
using T = EmplaceConstructibleMoveableAndAssignable<int>;
93+
using It = cpp17_input_iterator<int*>;
94+
{
95+
std::vector<T> v;
96+
v.reserve(5);
97+
for (std::size_t i = 0; i < v.capacity(); ++i)
98+
v.emplace_back(99);
99+
v.assign(It(arr1), It(std::end(arr1)));
100+
assert(v.size() == 1);
101+
assert(v[0].value == 42);
102+
}
103+
{
104+
std::vector<T> v;
105+
v.reserve(5);
106+
for (std::size_t i = 0; i < v.capacity(); ++i)
107+
v.emplace_back(99);
108+
v.assign(It(arr2), It(std::end(arr2)));
109+
assert(v.size() == 3);
110+
assert(v[0].value == 1);
111+
assert(v[1].value == 101);
112+
assert(v[2].value == 42);
113+
}
114+
}
115+
116+
{ // Test with size() < new_size < capacity() for forward_iterator, resulting in construction at end during assign
117+
using T = EmplaceConstructibleMoveableAndAssignable<int>;
118+
using It = forward_iterator<int*>;
119+
{
120+
std::vector<T> v;
121+
v.reserve(5);
122+
v.assign(It(arr1), It(std::end(arr1)));
123+
assert(v.size() == 1);
124+
assert(v[0].value == 42);
125+
}
126+
{
127+
std::vector<T> v;
128+
v.reserve(5);
129+
for (std::size_t i = 0; i < 2; ++i)
130+
v.emplace_back(99);
131+
v.assign(It(arr2), It(std::end(arr2)));
132+
assert(v.size() == 3);
133+
assert(v[0].value == 1);
134+
assert(v[1].value == 101);
135+
assert(v[2].value == 42);
136+
}
137+
}
138+
{ // Test with size() < new_size < capacity() for input_iterator, resulting in construction at end during assign
139+
using T = EmplaceConstructibleMoveableAndAssignable<int>;
140+
using It = cpp17_input_iterator<int*>;
141+
{
142+
std::vector<T> v;
143+
v.reserve(5);
144+
v.assign(It(arr1), It(std::end(arr1)));
145+
assert(v.size() == 1);
146+
assert(v[0].value == 42);
147+
}
148+
{
149+
std::vector<T> v;
150+
v.reserve(5);
151+
for (std::size_t i = 0; i < 2; ++i)
152+
v.emplace_back(99);
153+
v.assign(It(arr2), It(std::end(arr2)));
154+
assert(v.size() == 3);
155+
assert(v[0].value == 1);
156+
assert(v[1].value == 101);
157+
assert(v[2].value == 42);
158+
}
159+
}
67160
#endif
68161

69162
// Test with a number of elements in the source range that is greater than capacity

0 commit comments

Comments
 (0)