Skip to content

Commit f1ecff8

Browse files
authored
[libc++] Improve test coverage and readability for swap_ranges (#133752)
This patch enhances the test coverage of `{std,ranges}::swap_ranges` by adding larger test cases with 100 elements across different containers. It also inlines standalone tests for better readability, avoiding unnecessary navigation. This patch addresses a follow-up suggestion from PR #121138 to extend test coverage beyond 3 elements.
1 parent 4ac8e90 commit f1ecff8

File tree

2 files changed

+146
-109
lines changed

2 files changed

+146
-109
lines changed

libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp

Lines changed: 121 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -30,108 +30,40 @@
3030
#include "test_iterators.h"
3131
#include "type_algorithms.h"
3232

33-
constexpr void test_different_lengths() {
34-
using Expected = std::ranges::swap_ranges_result<int*, int*>;
35-
int i[3] = {1, 2, 3};
36-
int j[1] = {4};
37-
std::same_as<Expected> auto r = std::ranges::swap_ranges(i, i + 3, j, j + 1);
38-
assert(r.in1 == i + 1);
39-
assert(r.in2 == j + 1);
40-
assert(std::ranges::equal(i, std::array{4, 2, 3}));
41-
assert(std::ranges::equal(j, std::array{1}));
42-
std::same_as<Expected> auto r2 = std::ranges::swap_ranges(i, j);
43-
assert(r2.in1 == i + 1);
44-
assert(r2.in2 == j + 1);
45-
assert(std::ranges::equal(i, std::array{1, 2, 3}));
46-
assert(std::ranges::equal(j, std::array{4}));
47-
std::same_as<Expected> auto r3 = std::ranges::swap_ranges(j, j + 1, i, i + 3);
48-
assert(r3.in1 == j + 1);
49-
assert(r3.in2 == i + 1);
50-
assert(std::ranges::equal(i, std::array{4, 2, 3}));
51-
assert(std::ranges::equal(j, std::array{1}));
52-
std::same_as<Expected> auto r4 = std::ranges::swap_ranges(j, i);
53-
assert(r4.in1 == j + 1);
54-
assert(r4.in2 == i + 1);
55-
assert(std::ranges::equal(i, std::array{1, 2, 3}));
56-
assert(std::ranges::equal(j, std::array{4}));
57-
}
58-
59-
constexpr void test_range() {
60-
std::array r1 = {1, 2, 3};
61-
std::array r2 = {4, 5, 6};
62-
63-
std::same_as<std::ranges::in_in_result<std::array<int, 3>::iterator, std::array<int, 3>::iterator>> auto r =
64-
std::ranges::swap_ranges(r1, r2);
65-
assert(r.in1 == r1.end());
66-
assert(r.in2 == r2.end());
67-
assert((r1 == std::array{4, 5, 6}));
68-
assert((r2 == std::array{1, 2, 3}));
69-
}
70-
71-
constexpr void test_borrowed_input_range() {
72-
{
73-
int r1[] = {1, 2, 3};
74-
int r2[] = {4, 5, 6};
75-
std::ranges::swap_ranges(std::views::all(r1), r2);
76-
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
77-
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
78-
}
79-
{
80-
int r1[] = {1, 2, 3};
81-
int r2[] = {4, 5, 6};
82-
std::ranges::swap_ranges(r1, std::views::all(r2));
83-
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
84-
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
85-
}
86-
{
87-
int r1[] = {1, 2, 3};
88-
int r2[] = {4, 5, 6};
89-
std::ranges::swap_ranges(std::views::all(r1), std::views::all(r2));
90-
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
91-
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
92-
}
93-
}
94-
95-
constexpr void test_sentinel() {
96-
int i[3] = {1, 2, 3};
97-
int j[3] = {4, 5, 6};
98-
using It = cpp17_input_iterator<int*>;
99-
using Sent = sentinel_wrapper<It>;
100-
using Expected = std::ranges::swap_ranges_result<It, It>;
101-
std::same_as<Expected> auto r = std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));
102-
assert(base(r.in1) == i + 3);
103-
assert(base(r.in2) == j + 3);
104-
assert(std::ranges::equal(i, std::array{4, 5, 6}));
105-
assert(std::ranges::equal(j, std::array{1, 2, 3}));
106-
}
107-
10833
template <class Iter1, class Iter2>
10934
TEST_CONSTEXPR_CXX20 void test_iterators() {
11035
using Expected = std::ranges::swap_ranges_result<Iter1, Iter2>;
111-
int a[3] = {1, 2, 3};
112-
int b[3] = {4, 5, 6};
113-
std::same_as<Expected> auto r =
114-
std::ranges::swap_ranges(Iter1(a), sentinel_wrapper(Iter1(a + 3)), Iter2(b), sentinel_wrapper(Iter2(b + 3)));
115-
assert(base(r.in1) == a + 3);
116-
assert(base(r.in2) == b + 3);
117-
assert(std::ranges::equal(a, std::array{4, 5, 6}));
118-
assert(std::ranges::equal(b, std::array{1, 2, 3}));
119-
}
120-
121-
constexpr void test_rval_range() {
122-
{
123-
using Expected = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;
124-
std::array<int, 3> r = {1, 2, 3};
125-
std::same_as<Expected> auto a = std::ranges::swap_ranges(r, std::array{4, 5, 6});
126-
assert((r == std::array{4, 5, 6}));
127-
assert(a.in1 == r.begin() + 3);
36+
{ // Basic test case: swapping three elements between two arrays
37+
int a[3] = {1, 2, 3};
38+
int b[3] = {4, 5, 6};
39+
std::same_as<Expected> auto r =
40+
std::ranges::swap_ranges(Iter1(a), sentinel_wrapper(Iter1(a + 3)), Iter2(b), sentinel_wrapper(Iter2(b + 3)));
41+
assert(base(r.in1) == a + 3);
42+
assert(base(r.in2) == b + 3);
43+
assert(std::ranges::equal(a, std::array{4, 5, 6}));
44+
assert(std::ranges::equal(b, std::array{1, 2, 3}));
12845
}
129-
{
130-
std::array<int, 3> r = {1, 2, 3};
131-
using Expected = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;
132-
std::same_as<Expected> auto b = std::ranges::swap_ranges(std::array{4, 5, 6}, r);
133-
assert((r == std::array{4, 5, 6}));
134-
assert(b.in2 == r.begin() + 3);
46+
{ // Large-scale test: swapping 100 elements between two different containers
47+
const int N = 100;
48+
std::array<int, N> a;
49+
std::vector<int> b(N + 2, 42);
50+
b.front() = 1;
51+
b.back() = -1;
52+
for (int i = 0; i < N; ++i)
53+
a[i] = i * i + 1;
54+
std::same_as<Expected> auto r = std::ranges::swap_ranges(
55+
Iter1(a.data()),
56+
sentinel_wrapper(Iter1(a.data() + N)),
57+
Iter2(b.data() + 1),
58+
sentinel_wrapper(Iter2(b.data() + b.size())));
59+
assert(base(r.in1) == a.data() + N);
60+
assert(base(r.in2) == b.data() + N + 1);
61+
assert(b.front() == 1); // Ensure that the unswapped portion remains unchanged
62+
assert(b.back() == -1);
63+
for (int i = 0; i < N; ++i) {
64+
assert(a[i] == 42);
65+
assert(b[i + 1] == i * i + 1);
66+
}
13567
}
13668
}
13769

@@ -152,11 +84,97 @@ constexpr void test_vector_bool() {
15284
}
15385

15486
constexpr bool test() {
155-
test_range();
156-
test_sentinel();
157-
test_different_lengths();
158-
test_borrowed_input_range();
159-
test_rval_range();
87+
{ // Validate swapping ranges directly
88+
std::array r1 = {1, 2, 3};
89+
std::array r2 = {4, 5, 6};
90+
91+
std::same_as<std::ranges::in_in_result<std::array<int, 3>::iterator, std::array<int, 3>::iterator>> auto r =
92+
std::ranges::swap_ranges(r1, r2);
93+
assert(r.in1 == r1.end());
94+
assert(r.in2 == r2.end());
95+
assert((r1 == std::array{4, 5, 6}));
96+
assert((r2 == std::array{1, 2, 3}));
97+
}
98+
99+
{ // Validate swapping ranges using iterator and sentinels
100+
int i[3] = {1, 2, 3};
101+
int j[3] = {4, 5, 6};
102+
using It = cpp17_input_iterator<int*>;
103+
using Sent = sentinel_wrapper<It>;
104+
using Expected = std::ranges::swap_ranges_result<It, It>;
105+
std::same_as<Expected> auto r = std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));
106+
assert(base(r.in1) == i + 3);
107+
assert(base(r.in2) == j + 3);
108+
assert(std::ranges::equal(i, std::array{4, 5, 6}));
109+
assert(std::ranges::equal(j, std::array{1, 2, 3}));
110+
}
111+
112+
{ // Validate swapping ranges of different lengths
113+
using Expected = std::ranges::swap_ranges_result<int*, int*>;
114+
int i[3] = {1, 2, 3};
115+
int j[1] = {4};
116+
std::same_as<Expected> auto r = std::ranges::swap_ranges(i, i + 3, j, j + 1);
117+
assert(r.in1 == i + 1);
118+
assert(r.in2 == j + 1);
119+
assert(std::ranges::equal(i, std::array{4, 2, 3}));
120+
assert(std::ranges::equal(j, std::array{1}));
121+
std::same_as<Expected> auto r2 = std::ranges::swap_ranges(i, j);
122+
assert(r2.in1 == i + 1);
123+
assert(r2.in2 == j + 1);
124+
assert(std::ranges::equal(i, std::array{1, 2, 3}));
125+
assert(std::ranges::equal(j, std::array{4}));
126+
std::same_as<Expected> auto r3 = std::ranges::swap_ranges(j, j + 1, i, i + 3);
127+
assert(r3.in1 == j + 1);
128+
assert(r3.in2 == i + 1);
129+
assert(std::ranges::equal(i, std::array{4, 2, 3}));
130+
assert(std::ranges::equal(j, std::array{1}));
131+
std::same_as<Expected> auto r4 = std::ranges::swap_ranges(j, i);
132+
assert(r4.in1 == j + 1);
133+
assert(r4.in2 == i + 1);
134+
assert(std::ranges::equal(i, std::array{1, 2, 3}));
135+
assert(std::ranges::equal(j, std::array{4}));
136+
}
137+
138+
{ // Validate swapping when one or both are borrowed input ranges (views)
139+
{
140+
int r1[] = {1, 2, 3};
141+
int r2[] = {4, 5, 6};
142+
std::ranges::swap_ranges(std::views::all(r1), r2);
143+
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
144+
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
145+
}
146+
{
147+
int r1[] = {1, 2, 3};
148+
int r2[] = {4, 5, 6};
149+
std::ranges::swap_ranges(r1, std::views::all(r2));
150+
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
151+
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
152+
}
153+
{
154+
int r1[] = {1, 2, 3};
155+
int r2[] = {4, 5, 6};
156+
std::ranges::swap_ranges(std::views::all(r1), std::views::all(r2));
157+
assert(std::ranges::equal(r1, std::array{4, 5, 6}));
158+
assert(std::ranges::equal(r2, std::array{1, 2, 3}));
159+
}
160+
}
161+
162+
{ // Validate swapping involving rvalue ranges
163+
{
164+
using Expected = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;
165+
std::array<int, 3> r = {1, 2, 3};
166+
std::same_as<Expected> auto a = std::ranges::swap_ranges(r, std::array{4, 5, 6});
167+
assert((r == std::array{4, 5, 6}));
168+
assert(a.in1 == r.begin() + 3);
169+
}
170+
{
171+
std::array<int, 3> r = {1, 2, 3};
172+
using Expected = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;
173+
std::same_as<Expected> auto b = std::ranges::swap_ranges(std::array{4, 5, 6}, r);
174+
assert((r == std::array{4, 5, 6}));
175+
assert(b.in2 == r.begin() + 3);
176+
}
177+
}
160178

161179
types::for_each(types::cpp20_input_iterator_list<int*>(), []<class Iter1>() {
162180
types::for_each(types::cpp20_input_iterator_list<int*>(), []<class Iter2>() {

libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/swap_ranges.pass.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,31 @@ struct TestPtr {
3535
struct TestImpl {
3636
template <class Iter2>
3737
TEST_CONSTEXPR_CXX20 void operator()() {
38-
int a[] = {1, 2, 3};
39-
int b[] = {4, 5, 6};
40-
Iter2 r = std::swap_ranges(Iter1(a), Iter1(a + 3), Iter2(b));
41-
assert(base(r) == b + 3);
42-
assert(a[0] == 4 && a[1] == 5 && a[2] == 6);
43-
assert(b[0] == 1 && b[1] == 2 && b[2] == 3);
38+
{ // Basic test case: swapping three elements between two arrays
39+
int a[] = {1, 2, 3};
40+
int b[] = {4, 5, 6};
41+
Iter2 r = std::swap_ranges(Iter1(a), Iter1(a + 3), Iter2(b));
42+
assert(base(r) == b + 3);
43+
assert(a[0] == 4 && a[1] == 5 && a[2] == 6);
44+
assert(b[0] == 1 && b[1] == 2 && b[2] == 3);
45+
}
46+
{ // Large-scale test: swapping 100 elements between two different containers
47+
const int N = 100;
48+
std::array<int, N> a;
49+
std::vector<int> b(N + 2, 42);
50+
b.front() = 1;
51+
b.back() = -1;
52+
for (int i = 0; i < N; ++i)
53+
a[i] = i * i + 1;
54+
Iter2 r = std::swap_ranges(Iter1(a.data()), Iter1(a.data() + N), Iter2(b.data() + 1));
55+
assert(base(r) == b.data() + N + 1);
56+
assert(b.front() == 1); // Ensure that the unswapped portion remains unchanged
57+
assert(b.back() == -1);
58+
for (int i = 0; i < N; ++i) {
59+
assert(a[i] == 42);
60+
assert(b[i + 1] == i * i + 1);
61+
}
62+
}
4463
}
4564
};
4665
};

0 commit comments

Comments
 (0)