[libcxx-commits] [libcxx] [libc++] Improve test coverage and readability for swap_ranges (PR #133752)
Peng Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Apr 2 19:38:18 PDT 2025
https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/133752
>From 1068ac19977dc78213f9dc35a49d90595fd87893 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Mon, 31 Mar 2025 12:50:39 -0400
Subject: [PATCH] Improve test coverage and inline standalone tests
---
.../alg.swap/ranges.swap_ranges.pass.cpp | 224 ++++++++++--------
.../alg.swap/swap_ranges.pass.cpp | 31 ++-
2 files changed, 146 insertions(+), 109 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
index 93090ed6138f8..85557ecbbfabc 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
@@ -30,108 +30,40 @@
#include "test_iterators.h"
#include "type_algorithms.h"
-constexpr void test_different_lengths() {
- using Expected = std::ranges::swap_ranges_result<int*, int*>;
- int i[3] = {1, 2, 3};
- int j[1] = {4};
- std::same_as<Expected> auto r = std::ranges::swap_ranges(i, i + 3, j, j + 1);
- assert(r.in1 == i + 1);
- assert(r.in2 == j + 1);
- assert(std::ranges::equal(i, std::array{4, 2, 3}));
- assert(std::ranges::equal(j, std::array{1}));
- std::same_as<Expected> auto r2 = std::ranges::swap_ranges(i, j);
- assert(r2.in1 == i + 1);
- assert(r2.in2 == j + 1);
- assert(std::ranges::equal(i, std::array{1, 2, 3}));
- assert(std::ranges::equal(j, std::array{4}));
- std::same_as<Expected> auto r3 = std::ranges::swap_ranges(j, j + 1, i, i + 3);
- assert(r3.in1 == j + 1);
- assert(r3.in2 == i + 1);
- assert(std::ranges::equal(i, std::array{4, 2, 3}));
- assert(std::ranges::equal(j, std::array{1}));
- std::same_as<Expected> auto r4 = std::ranges::swap_ranges(j, i);
- assert(r4.in1 == j + 1);
- assert(r4.in2 == i + 1);
- assert(std::ranges::equal(i, std::array{1, 2, 3}));
- assert(std::ranges::equal(j, std::array{4}));
-}
-
-constexpr void test_range() {
- std::array r1 = {1, 2, 3};
- std::array r2 = {4, 5, 6};
-
- std::same_as<std::ranges::in_in_result<std::array<int, 3>::iterator, std::array<int, 3>::iterator>> auto r =
- std::ranges::swap_ranges(r1, r2);
- assert(r.in1 == r1.end());
- assert(r.in2 == r2.end());
- assert((r1 == std::array{4, 5, 6}));
- assert((r2 == std::array{1, 2, 3}));
-}
-
-constexpr void test_borrowed_input_range() {
- {
- int r1[] = {1, 2, 3};
- int r2[] = {4, 5, 6};
- std::ranges::swap_ranges(std::views::all(r1), r2);
- assert(std::ranges::equal(r1, std::array{4, 5, 6}));
- assert(std::ranges::equal(r2, std::array{1, 2, 3}));
- }
- {
- int r1[] = {1, 2, 3};
- int r2[] = {4, 5, 6};
- std::ranges::swap_ranges(r1, std::views::all(r2));
- assert(std::ranges::equal(r1, std::array{4, 5, 6}));
- assert(std::ranges::equal(r2, std::array{1, 2, 3}));
- }
- {
- int r1[] = {1, 2, 3};
- int r2[] = {4, 5, 6};
- std::ranges::swap_ranges(std::views::all(r1), std::views::all(r2));
- assert(std::ranges::equal(r1, std::array{4, 5, 6}));
- assert(std::ranges::equal(r2, std::array{1, 2, 3}));
- }
-}
-
-constexpr void test_sentinel() {
- int i[3] = {1, 2, 3};
- int j[3] = {4, 5, 6};
- using It = cpp17_input_iterator<int*>;
- using Sent = sentinel_wrapper<It>;
- using Expected = std::ranges::swap_ranges_result<It, It>;
- std::same_as<Expected> auto r = std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));
- assert(base(r.in1) == i + 3);
- assert(base(r.in2) == j + 3);
- assert(std::ranges::equal(i, std::array{4, 5, 6}));
- assert(std::ranges::equal(j, std::array{1, 2, 3}));
-}
-
template <class Iter1, class Iter2>
TEST_CONSTEXPR_CXX20 void test_iterators() {
using Expected = std::ranges::swap_ranges_result<Iter1, Iter2>;
- int a[3] = {1, 2, 3};
- int b[3] = {4, 5, 6};
- std::same_as<Expected> auto r =
- std::ranges::swap_ranges(Iter1(a), sentinel_wrapper(Iter1(a + 3)), Iter2(b), sentinel_wrapper(Iter2(b + 3)));
- assert(base(r.in1) == a + 3);
- assert(base(r.in2) == b + 3);
- assert(std::ranges::equal(a, std::array{4, 5, 6}));
- assert(std::ranges::equal(b, std::array{1, 2, 3}));
-}
-
-constexpr void test_rval_range() {
- {
- using Expected = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;
- std::array<int, 3> r = {1, 2, 3};
- std::same_as<Expected> auto a = std::ranges::swap_ranges(r, std::array{4, 5, 6});
- assert((r == std::array{4, 5, 6}));
- assert(a.in1 == r.begin() + 3);
+ { // Basic test case: swapping three elements between two arrays
+ int a[3] = {1, 2, 3};
+ int b[3] = {4, 5, 6};
+ std::same_as<Expected> auto r =
+ std::ranges::swap_ranges(Iter1(a), sentinel_wrapper(Iter1(a + 3)), Iter2(b), sentinel_wrapper(Iter2(b + 3)));
+ assert(base(r.in1) == a + 3);
+ assert(base(r.in2) == b + 3);
+ assert(std::ranges::equal(a, std::array{4, 5, 6}));
+ assert(std::ranges::equal(b, std::array{1, 2, 3}));
}
- {
- std::array<int, 3> r = {1, 2, 3};
- using Expected = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;
- std::same_as<Expected> auto b = std::ranges::swap_ranges(std::array{4, 5, 6}, r);
- assert((r == std::array{4, 5, 6}));
- assert(b.in2 == r.begin() + 3);
+ { // Large-scale test: swapping 100 elements between two different containers
+ const int N = 100;
+ std::array<int, N> a;
+ std::vector<int> b(N + 2, 42);
+ b.front() = 1;
+ b.back() = -1;
+ for (int i = 0; i < N; ++i)
+ a[i] = i * i + 1;
+ std::same_as<Expected> auto r = std::ranges::swap_ranges(
+ Iter1(a.data()),
+ sentinel_wrapper(Iter1(a.data() + N)),
+ Iter2(b.data() + 1),
+ sentinel_wrapper(Iter2(b.data() + b.size())));
+ assert(base(r.in1) == a.data() + N);
+ assert(base(r.in2) == b.data() + N + 1);
+ assert(b.front() == 1); // Ensure that the unswapped portion remains unchanged
+ assert(b.back() == -1);
+ for (int i = 0; i < N; ++i) {
+ assert(a[i] == 42);
+ assert(b[i + 1] == i * i + 1);
+ }
}
}
@@ -152,11 +84,97 @@ constexpr void test_vector_bool() {
}
constexpr bool test() {
- test_range();
- test_sentinel();
- test_different_lengths();
- test_borrowed_input_range();
- test_rval_range();
+ { // Validate swapping ranges directly
+ std::array r1 = {1, 2, 3};
+ std::array r2 = {4, 5, 6};
+
+ std::same_as<std::ranges::in_in_result<std::array<int, 3>::iterator, std::array<int, 3>::iterator>> auto r =
+ std::ranges::swap_ranges(r1, r2);
+ assert(r.in1 == r1.end());
+ assert(r.in2 == r2.end());
+ assert((r1 == std::array{4, 5, 6}));
+ assert((r2 == std::array{1, 2, 3}));
+ }
+
+ { // Validate swapping ranges using iterator and sentinels
+ int i[3] = {1, 2, 3};
+ int j[3] = {4, 5, 6};
+ using It = cpp17_input_iterator<int*>;
+ using Sent = sentinel_wrapper<It>;
+ using Expected = std::ranges::swap_ranges_result<It, It>;
+ std::same_as<Expected> auto r = std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));
+ assert(base(r.in1) == i + 3);
+ assert(base(r.in2) == j + 3);
+ assert(std::ranges::equal(i, std::array{4, 5, 6}));
+ assert(std::ranges::equal(j, std::array{1, 2, 3}));
+ }
+
+ { // Validate swapping ranges of different lengths
+ using Expected = std::ranges::swap_ranges_result<int*, int*>;
+ int i[3] = {1, 2, 3};
+ int j[1] = {4};
+ std::same_as<Expected> auto r = std::ranges::swap_ranges(i, i + 3, j, j + 1);
+ assert(r.in1 == i + 1);
+ assert(r.in2 == j + 1);
+ assert(std::ranges::equal(i, std::array{4, 2, 3}));
+ assert(std::ranges::equal(j, std::array{1}));
+ std::same_as<Expected> auto r2 = std::ranges::swap_ranges(i, j);
+ assert(r2.in1 == i + 1);
+ assert(r2.in2 == j + 1);
+ assert(std::ranges::equal(i, std::array{1, 2, 3}));
+ assert(std::ranges::equal(j, std::array{4}));
+ std::same_as<Expected> auto r3 = std::ranges::swap_ranges(j, j + 1, i, i + 3);
+ assert(r3.in1 == j + 1);
+ assert(r3.in2 == i + 1);
+ assert(std::ranges::equal(i, std::array{4, 2, 3}));
+ assert(std::ranges::equal(j, std::array{1}));
+ std::same_as<Expected> auto r4 = std::ranges::swap_ranges(j, i);
+ assert(r4.in1 == j + 1);
+ assert(r4.in2 == i + 1);
+ assert(std::ranges::equal(i, std::array{1, 2, 3}));
+ assert(std::ranges::equal(j, std::array{4}));
+ }
+
+ { // Validate swapping when one or both are borrowed input ranges (views)
+ {
+ int r1[] = {1, 2, 3};
+ int r2[] = {4, 5, 6};
+ std::ranges::swap_ranges(std::views::all(r1), r2);
+ assert(std::ranges::equal(r1, std::array{4, 5, 6}));
+ assert(std::ranges::equal(r2, std::array{1, 2, 3}));
+ }
+ {
+ int r1[] = {1, 2, 3};
+ int r2[] = {4, 5, 6};
+ std::ranges::swap_ranges(r1, std::views::all(r2));
+ assert(std::ranges::equal(r1, std::array{4, 5, 6}));
+ assert(std::ranges::equal(r2, std::array{1, 2, 3}));
+ }
+ {
+ int r1[] = {1, 2, 3};
+ int r2[] = {4, 5, 6};
+ std::ranges::swap_ranges(std::views::all(r1), std::views::all(r2));
+ assert(std::ranges::equal(r1, std::array{4, 5, 6}));
+ assert(std::ranges::equal(r2, std::array{1, 2, 3}));
+ }
+ }
+
+ { // Validate swapping involving rvalue ranges
+ {
+ using Expected = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;
+ std::array<int, 3> r = {1, 2, 3};
+ std::same_as<Expected> auto a = std::ranges::swap_ranges(r, std::array{4, 5, 6});
+ assert((r == std::array{4, 5, 6}));
+ assert(a.in1 == r.begin() + 3);
+ }
+ {
+ std::array<int, 3> r = {1, 2, 3};
+ using Expected = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;
+ std::same_as<Expected> auto b = std::ranges::swap_ranges(std::array{4, 5, 6}, r);
+ assert((r == std::array{4, 5, 6}));
+ assert(b.in2 == r.begin() + 3);
+ }
+ }
types::for_each(types::cpp20_input_iterator_list<int*>(), []<class Iter1>() {
types::for_each(types::cpp20_input_iterator_list<int*>(), []<class Iter2>() {
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/swap_ranges.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/swap_ranges.pass.cpp
index 01cd33150e236..84ebedf213f5b 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/swap_ranges.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/swap_ranges.pass.cpp
@@ -35,12 +35,31 @@ struct TestPtr {
struct TestImpl {
template <class Iter2>
TEST_CONSTEXPR_CXX20 void operator()() {
- int a[] = {1, 2, 3};
- int b[] = {4, 5, 6};
- Iter2 r = std::swap_ranges(Iter1(a), Iter1(a + 3), Iter2(b));
- assert(base(r) == b + 3);
- assert(a[0] == 4 && a[1] == 5 && a[2] == 6);
- assert(b[0] == 1 && b[1] == 2 && b[2] == 3);
+ { // Basic test case: swapping three elements between two arrays
+ int a[] = {1, 2, 3};
+ int b[] = {4, 5, 6};
+ Iter2 r = std::swap_ranges(Iter1(a), Iter1(a + 3), Iter2(b));
+ assert(base(r) == b + 3);
+ assert(a[0] == 4 && a[1] == 5 && a[2] == 6);
+ assert(b[0] == 1 && b[1] == 2 && b[2] == 3);
+ }
+ { // Large-scale test: swapping 100 elements between two different containers
+ const int N = 100;
+ std::array<int, N> a;
+ std::vector<int> b(N + 2, 42);
+ b.front() = 1;
+ b.back() = -1;
+ for (int i = 0; i < N; ++i)
+ a[i] = i * i + 1;
+ Iter2 r = std::swap_ranges(Iter1(a.data()), Iter1(a.data() + N), Iter2(b.data() + 1));
+ assert(base(r) == b.data() + N + 1);
+ assert(b.front() == 1); // Ensure that the unswapped portion remains unchanged
+ assert(b.back() == -1);
+ for (int i = 0; i < N; ++i) {
+ assert(a[i] == 42);
+ assert(b[i + 1] == i * i + 1);
+ }
+ }
}
};
};
More information about the libcxx-commits
mailing list