Skip to content

Commit 1d583ed

Browse files
authored
[libc++][test] Augment ranges::{fill, fill_n, find} with missing tests (#121209)
libc++ currently has very limited test coverage for `std::ranges{fill, fill_n, find}` with `vector<bool>::iterator` optimizations. Specifically, the existing tests for `std::ranges::fill` only covers cases of 1 - 2 bytes, which is merely 1/8 to 1/4 of the `__storage_type` word size. This renders the tests insufficient to validate functionality for whole words, with or without partial words (which necessitates at least 8 bytes of data). Moreover, no tests were provided for `ranges::{find, fill_n}` with `vector<bool>::iterator` optimizations. This PR fills in the gap.
1 parent 1ec1d25 commit 1d583ed

File tree

6 files changed

+371
-175
lines changed

6 files changed

+371
-175
lines changed

libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp

+72-65
Original file line numberDiff line numberDiff line change
@@ -48,89 +48,96 @@ struct Test {
4848
}
4949
};
5050

51-
// Make sure std::fill behaves properly with std::vector<bool> iterators with custom size types.
52-
// See https://github.com/llvm/llvm-project/pull/122410.
53-
TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
54-
{
55-
using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
56-
std::vector<bool, Alloc> in(100, false, Alloc(1));
57-
std::vector<bool, Alloc> expected(100, true, Alloc(1));
58-
std::fill(in.begin(), in.end(), true);
59-
assert(in == expected);
60-
}
61-
{
62-
using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
63-
std::vector<bool, Alloc> in(200, false, Alloc(1));
64-
std::vector<bool, Alloc> expected(200, true, Alloc(1));
65-
std::fill(in.begin(), in.end(), true);
66-
assert(in == expected);
67-
}
68-
{
69-
using Alloc = sized_allocator<bool, std::uint32_t, std::int32_t>;
70-
std::vector<bool, Alloc> in(200, false, Alloc(1));
71-
std::vector<bool, Alloc> expected(200, true, Alloc(1));
72-
std::fill(in.begin(), in.end(), true);
73-
assert(in == expected);
51+
TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
52+
{ // Test cases validating leading/trailing bits unfilled remain unchanged
53+
{ // Leading bits are not filled
54+
std::vector<bool> in(N, false);
55+
std::vector<bool> expected(N, true);
56+
expected[0] = expected[1] = false;
57+
std::fill(in.begin() + 2, in.end(), true);
58+
assert(in == expected);
59+
}
60+
{ // Trailing bits are not filled
61+
std::vector<bool> in(N, false);
62+
std::vector<bool> expected(N, true);
63+
expected[N - 1] = expected[N - 2] = false;
64+
std::fill(in.begin(), in.end() - 2, true);
65+
assert(in == expected);
66+
}
67+
{ // Leading and trailing bits are not filled
68+
std::vector<bool> in(N, false);
69+
std::vector<bool> expected(N, true);
70+
expected[0] = expected[1] = expected[N - 1] = expected[N - 2] = false;
71+
std::fill(in.begin() + 2, in.end() - 2, true);
72+
assert(in == expected);
73+
}
7474
}
75-
{
76-
using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
77-
std::vector<bool, Alloc> in(200, false, Alloc(1));
78-
std::vector<bool, Alloc> expected(200, true, Alloc(1));
79-
std::fill(in.begin(), in.end(), true);
80-
assert(in == expected);
75+
76+
{ // Test cases with full or partial bytes filled
77+
{ // Full bytes filled
78+
std::vector<bool> in(N, false);
79+
std::vector<bool> expected(N, true);
80+
std::fill(in.begin(), in.end(), true);
81+
assert(in == expected);
82+
}
83+
{ // Partial bytes with offset filled
84+
std::vector<bool> in(N, false);
85+
std::vector<bool> expected(N, true);
86+
std::fill(in.begin() + 4, in.end() - 4, true);
87+
std::fill(expected.begin(), expected.begin() + 4, false);
88+
std::fill(expected.end() - 4, expected.end(), false);
89+
assert(in == expected);
90+
}
8191
}
92+
93+
return true;
8294
}
8395

8496
TEST_CONSTEXPR_CXX20 bool test() {
8597
types::for_each(types::forward_iterator_list<char*>(), Test<char>());
8698
types::for_each(types::forward_iterator_list<int*>(), Test<int>());
87-
{ // test vector<bool>::iterator optimization
88-
{ // simple case
89-
std::vector<bool> in(4, false);
90-
std::vector<bool> expected(4, true);
99+
100+
{ // Test vector<bool>::iterator optimization
101+
assert(test_vector_bool(8));
102+
assert(test_vector_bool(19));
103+
assert(test_vector_bool(32));
104+
assert(test_vector_bool(49));
105+
assert(test_vector_bool(64));
106+
assert(test_vector_bool(199));
107+
assert(test_vector_bool(256));
108+
109+
// Make sure std::fill behaves properly with std::vector<bool> iterators with custom size types.
110+
// See https://github.com/llvm/llvm-project/pull/122410.
111+
{
112+
using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
113+
std::vector<bool, Alloc> in(100, false, Alloc(1));
114+
std::vector<bool, Alloc> expected(100, true, Alloc(1));
91115
std::fill(in.begin(), in.end(), true);
92116
assert(in == expected);
93117
}
94-
{ // partial byte in the front is not filled
95-
std::vector<bool> in(8, false);
96-
std::vector<bool> expected(8, true);
97-
expected[0] = false;
98-
expected[1] = false;
99-
std::fill(in.begin() + 2, in.end(), true);
100-
assert(in == expected);
101-
}
102-
{ // partial byte in the back is not filled
103-
std::vector<bool> in(8, false);
104-
std::vector<bool> expected(8, true);
105-
expected[6] = false;
106-
expected[7] = false;
107-
std::fill(in.begin(), in.end() - 2, true);
118+
{
119+
using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
120+
std::vector<bool, Alloc> in(200, false, Alloc(1));
121+
std::vector<bool, Alloc> expected(200, true, Alloc(1));
122+
std::fill(in.begin(), in.end(), true);
108123
assert(in == expected);
109124
}
110-
{ // partial byte in the front and back is not filled
111-
std::vector<bool> in(16, false);
112-
std::vector<bool> expected(16, true);
113-
expected[0] = false;
114-
expected[1] = false;
115-
expected[14] = false;
116-
expected[15] = false;
117-
std::fill(in.begin() + 2, in.end() - 2, true);
125+
{
126+
using Alloc = sized_allocator<bool, std::uint32_t, std::int32_t>;
127+
std::vector<bool, Alloc> in(200, false, Alloc(1));
128+
std::vector<bool, Alloc> expected(200, true, Alloc(1));
129+
std::fill(in.begin(), in.end(), true);
118130
assert(in == expected);
119131
}
120-
{ // only a few bits of a byte are set
121-
std::vector<bool> in(8, false);
122-
std::vector<bool> expected(8, true);
123-
expected[0] = false;
124-
expected[1] = false;
125-
expected[6] = false;
126-
expected[7] = false;
127-
std::fill(in.begin() + 2, in.end() - 2, true);
132+
{
133+
using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
134+
std::vector<bool, Alloc> in(200, false, Alloc(1));
135+
std::vector<bool, Alloc> expected(200, true, Alloc(1));
136+
std::fill(in.begin(), in.end(), true);
128137
assert(in == expected);
129138
}
130139
}
131140

132-
test_bititer_with_custom_sized_types();
133-
134141
return true;
135142
}
136143

libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp

+82-30
Original file line numberDiff line numberDiff line change
@@ -109,37 +109,49 @@ struct Storage {
109109
};
110110
};
111111

112-
// Make sure std::fill_n behaves properly with std::vector<bool> iterators with custom size types.
113-
// See https://github.com/llvm/llvm-project/pull/122410.
114-
TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
115-
{
116-
using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
117-
std::vector<bool, Alloc> in(100, false, Alloc(1));
118-
std::vector<bool, Alloc> expected(100, true, Alloc(1));
119-
std::fill_n(in.begin(), in.size(), true);
120-
assert(in == expected);
121-
}
122-
{
123-
using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
124-
std::vector<bool, Alloc> in(200, false, Alloc(1));
125-
std::vector<bool, Alloc> expected(200, true, Alloc(1));
126-
std::fill_n(in.begin(), in.size(), true);
127-
assert(in == expected);
128-
}
129-
{
130-
using Alloc = sized_allocator<bool, std::uint32_t, std::int32_t>;
131-
std::vector<bool, Alloc> in(200, false, Alloc(1));
132-
std::vector<bool, Alloc> expected(200, true, Alloc(1));
133-
std::fill_n(in.begin(), in.size(), true);
134-
assert(in == expected);
112+
TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
113+
{ // Test cases validating leading/trailing bits unfilled remain unchanged
114+
{ // Leading bits are not filled
115+
std::vector<bool> in(N, false);
116+
std::vector<bool> expected(N, true);
117+
expected[0] = expected[1] = false;
118+
std::fill_n(in.begin() + 2, N - 2, true);
119+
assert(in == expected);
120+
}
121+
{ // Trailing bits are not filled
122+
std::vector<bool> in(N, false);
123+
std::vector<bool> expected(N, true);
124+
expected[N - 1] = expected[N - 2] = false;
125+
std::fill_n(in.begin(), N - 2, true);
126+
assert(in == expected);
127+
}
128+
{ // Leading and trailing bits are not filled
129+
std::vector<bool> in(N, false);
130+
std::vector<bool> expected(N, true);
131+
expected[0] = expected[1] = expected[N - 1] = expected[N - 2] = false;
132+
std::fill_n(in.begin() + 2, N - 4, true);
133+
assert(in == expected);
134+
}
135135
}
136-
{
137-
using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
138-
std::vector<bool, Alloc> in(200, false, Alloc(1));
139-
std::vector<bool, Alloc> expected(200, true, Alloc(1));
140-
std::fill_n(in.begin(), in.size(), true);
141-
assert(in == expected);
136+
137+
{ // Test cases with full or partial bytes filled
138+
{ // Full bytes filled
139+
std::vector<bool> in(N, false);
140+
std::vector<bool> expected(N, true);
141+
std::fill_n(in.begin(), N, true);
142+
assert(in == expected);
143+
}
144+
{ // Partial bytes with offset filled
145+
std::vector<bool> in(N, false);
146+
std::vector<bool> expected(N, true);
147+
std::fill_n(in.begin() + 4, N - 8, true);
148+
std::fill_n(expected.begin(), 4, false);
149+
std::fill_n(expected.end() - 4, 4, false);
150+
assert(in == expected);
151+
}
142152
}
153+
154+
return true;
143155
}
144156

145157
TEST_CONSTEXPR_CXX20 void test_struct_array() {
@@ -171,7 +183,47 @@ TEST_CONSTEXPR_CXX20 bool test() {
171183
test_int_array();
172184
test_struct_array();
173185
test_int_array_struct_source();
174-
test_bititer_with_custom_sized_types();
186+
187+
{ // Test vector<bool>::iterator optimization
188+
assert(test_vector_bool(8));
189+
assert(test_vector_bool(19));
190+
assert(test_vector_bool(32));
191+
assert(test_vector_bool(49));
192+
assert(test_vector_bool(64));
193+
assert(test_vector_bool(199));
194+
assert(test_vector_bool(256));
195+
196+
// Make sure std::fill_n behaves properly with std::vector<bool> iterators with custom size types.
197+
// See https://github.com/llvm/llvm-project/pull/122410.
198+
{
199+
using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
200+
std::vector<bool, Alloc> in(100, false, Alloc(1));
201+
std::vector<bool, Alloc> expected(100, true, Alloc(1));
202+
std::fill_n(in.begin(), in.size(), true);
203+
assert(in == expected);
204+
}
205+
{
206+
using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
207+
std::vector<bool, Alloc> in(200, false, Alloc(1));
208+
std::vector<bool, Alloc> expected(200, true, Alloc(1));
209+
std::fill_n(in.begin(), in.size(), true);
210+
assert(in == expected);
211+
}
212+
{
213+
using Alloc = sized_allocator<bool, std::uint32_t, std::int32_t>;
214+
std::vector<bool, Alloc> in(200, false, Alloc(1));
215+
std::vector<bool, Alloc> expected(200, true, Alloc(1));
216+
std::fill_n(in.begin(), in.size(), true);
217+
assert(in == expected);
218+
}
219+
{
220+
using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
221+
std::vector<bool, Alloc> in(200, false, Alloc(1));
222+
std::vector<bool, Alloc> expected(200, true, Alloc(1));
223+
std::fill_n(in.begin(), in.size(), true);
224+
assert(in == expected);
225+
}
226+
}
175227

176228
return true;
177229
}

0 commit comments

Comments
 (0)