Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[libc++] Improve test coverage and readability for swap_ranges #133752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 14, 2025

Conversation

winner245
Copy link
Contributor

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.

@winner245 winner245 marked this pull request as ready for review April 8, 2025 21:37
@winner245 winner245 requested a review from a team as a code owner April 8, 2025 21:37
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Apr 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 8, 2025

@llvm/pr-subscribers-libcxx

Author: Peng Liu (winner245)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/133752.diff

2 Files Affected:

  • (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp (+121-103)
  • (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/swap_ranges.pass.cpp (+25-6)
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);
+        }
+      }
     }
   };
 };

@ldionne ldionne merged commit f1ecff8 into llvm:main May 14, 2025
86 checks passed
@winner245 winner245 deleted the test-swap-ranges branch May 14, 2025 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. test-suite
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.