[libcxx-commits] [libcxx] [libc++][test] Refactor increasing_allocator (PR #115671)

Peng Liu via libcxx-commits libcxx-commits at lists.llvm.org
Fri Nov 29 06:09:52 PST 2024


https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/115671

>From d8b0c822a2406647c4927052a9ef3c816c96cee6 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Sun, 10 Nov 2024 17:13:54 -0500
Subject: [PATCH 1/3] Fix increasing_allocator to conform to standard

---
 .../containers/sequences/vector.bool/shrink_to_fit.pass.cpp   | 2 +-
 .../sequences/vector/vector.capacity/shrink_to_fit.pass.cpp   | 2 +-
 .../basic.string/string.capacity/shrink_to_fit.pass.cpp       | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
index f8bcee31964bbb..136b151efa29ef 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
@@ -55,7 +55,7 @@ struct increasing_allocator {
     min_elements += 1000;
     return std::allocator<T>{}.allocate_at_least(n);
   }
-  constexpr T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
+  constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
   constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
 };
 
diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
index e39afb2d48f0a0..97d67dac2baa8c 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
@@ -87,7 +87,7 @@ struct increasing_allocator {
     min_elements += 1000;
     return std::allocator<T>{}.allocate_at_least(n);
   }
-  constexpr T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
+  constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
   constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
 };
 
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
index 6f5e43d1341f53..9f0b5ff7abdfe7 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
@@ -79,8 +79,8 @@ struct increasing_allocator {
     min_bytes += 1000;
     return {static_cast<T*>(::operator new(allocation_amount)), allocation_amount / sizeof(T)};
   }
-  T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
-  void deallocate(T* p, std::size_t) noexcept { ::operator delete(static_cast<void*>(p)); }
+  T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
+  void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
 };
 
 template <typename T, typename U>

>From d654ed4e061526cec7ddf74e7e614768d9b909cd Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 13 Nov 2024 11:15:10 -0500
Subject: [PATCH 2/3] Factor out increasing_allocator

---
 .../vector.bool/shrink_to_fit.pass.cpp        |  73 +++-------
 .../vector.capacity/shrink_to_fit.pass.cpp    | 137 ++++++++----------
 .../string.capacity/shrink_to_fit.pass.cpp    |  31 +---
 libcxx/test/support/increasing_allocator.h    |  43 ++++++
 4 files changed, 128 insertions(+), 156 deletions(-)
 create mode 100644 libcxx/test/support/increasing_allocator.h

diff --git a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
index 136b151efa29ef..3bc639d0479f96 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
@@ -11,59 +11,35 @@
 
 // void shrink_to_fit();
 
-#include <vector>
 #include <cassert>
+#include <vector>
 
-#include "test_macros.h"
+#include "increasing_allocator.h"
 #include "min_allocator.h"
+#include "test_macros.h"
 
-TEST_CONSTEXPR_CXX20 bool tests()
-{
-    {
-        std::vector<bool> v(100);
-        v.push_back(1);
-        v.shrink_to_fit();
-        assert(v.capacity() >= 101);
-        assert(v.size() >= 101);
-    }
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<bool> v(100);
+    v.push_back(1);
+    v.shrink_to_fit();
+    assert(v.capacity() >= 101);
+    assert(v.size() >= 101);
+  }
 #if TEST_STD_VER >= 11
-    {
-        std::vector<bool, min_allocator<bool>> v(100);
-        v.push_back(1);
-        v.shrink_to_fit();
-        assert(v.capacity() >= 101);
-        assert(v.size() >= 101);
-    }
-#endif
-
-    return true;
-}
-
-#if TEST_STD_VER >= 23
-template <typename T>
-struct increasing_allocator {
-  using value_type         = T;
-  std::size_t min_elements = 1000;
-  increasing_allocator()   = default;
-
-  template <typename U>
-  constexpr increasing_allocator(const increasing_allocator<U>& other) noexcept : min_elements(other.min_elements) {}
-
-  constexpr std::allocation_result<T*> allocate_at_least(std::size_t n) {
-    if (n < min_elements)
-      n = min_elements;
-    min_elements += 1000;
-    return std::allocator<T>{}.allocate_at_least(n);
+  {
+    std::vector<bool, min_allocator<bool>> v(100);
+    v.push_back(1);
+    v.shrink_to_fit();
+    assert(v.capacity() >= 101);
+    assert(v.size() >= 101);
   }
-  constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
-  constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
-};
+#endif
 
-template <typename T, typename U>
-bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
   return true;
 }
 
+#if TEST_STD_VER >= 23
 // https://github.com/llvm/llvm-project/issues/95161
 constexpr bool test_increasing_allocator() {
   std::vector<bool, increasing_allocator<bool>> v;
@@ -77,16 +53,15 @@ constexpr bool test_increasing_allocator() {
 }
 #endif // TEST_STD_VER >= 23
 
-int main(int, char**)
-{
+int main(int, char**) {
   tests();
 #if TEST_STD_VER > 17
-    static_assert(tests());
+  static_assert(tests());
 #endif
 #if TEST_STD_VER >= 23
-    test_increasing_allocator();
-    static_assert(test_increasing_allocator());
+  test_increasing_allocator();
+  static_assert(test_increasing_allocator());
 #endif // TEST_STD_VER >= 23
 
-    return 0;
+  return 0;
 }
diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
index 97d67dac2baa8c..48eb6ed85d47c6 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
@@ -10,92 +10,70 @@
 
 // void shrink_to_fit();
 
-#include <vector>
 #include <cassert>
-#include "test_macros.h"
-#include "test_allocator.h"
-#include "min_allocator.h"
+#include <vector>
+
 #include "asan_testing.h"
+#include "increasing_allocator.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+#include "test_macros.h"
 
 TEST_CONSTEXPR_CXX20 bool tests() {
-    {
-        std::vector<int> v(100);
-        v.push_back(1);
-        assert(is_contiguous_container_asan_correct(v));
-        v.shrink_to_fit();
-        assert(v.capacity() == 101);
-        assert(v.size() == 101);
-        assert(is_contiguous_container_asan_correct(v));
-    }
-    {
-        std::vector<int, limited_allocator<int, 401> > v(100);
-        v.push_back(1);
-        assert(is_contiguous_container_asan_correct(v));
-        v.shrink_to_fit();
-        assert(v.capacity() == 101);
-        assert(v.size() == 101);
-        assert(is_contiguous_container_asan_correct(v));
-    }
+  {
+    std::vector<int> v(100);
+    v.push_back(1);
+    assert(is_contiguous_container_asan_correct(v));
+    v.shrink_to_fit();
+    assert(v.capacity() == 101);
+    assert(v.size() == 101);
+    assert(is_contiguous_container_asan_correct(v));
+  }
+  {
+    std::vector<int, limited_allocator<int, 401> > v(100);
+    v.push_back(1);
+    assert(is_contiguous_container_asan_correct(v));
+    v.shrink_to_fit();
+    assert(v.capacity() == 101);
+    assert(v.size() == 101);
+    assert(is_contiguous_container_asan_correct(v));
+  }
 #ifndef TEST_HAS_NO_EXCEPTIONS
-    if (!TEST_IS_CONSTANT_EVALUATED) {
-        std::vector<int, limited_allocator<int, 400> > v(100);
-        v.push_back(1);
-        assert(is_contiguous_container_asan_correct(v));
-        v.shrink_to_fit();
-        LIBCPP_ASSERT(v.capacity() == 200); // assumes libc++'s 2x growth factor
-        assert(v.size() == 101);
-        assert(is_contiguous_container_asan_correct(v));
-    }
+  if (!TEST_IS_CONSTANT_EVALUATED) {
+    std::vector<int, limited_allocator<int, 400> > v(100);
+    v.push_back(1);
+    assert(is_contiguous_container_asan_correct(v));
+    v.shrink_to_fit();
+    LIBCPP_ASSERT(v.capacity() == 200); // assumes libc++'s 2x growth factor
+    assert(v.size() == 101);
+    assert(is_contiguous_container_asan_correct(v));
+  }
 #endif
 #if TEST_STD_VER >= 11
-    {
-        std::vector<int, min_allocator<int>> v(100);
-        v.push_back(1);
-        assert(is_contiguous_container_asan_correct(v));
-        v.shrink_to_fit();
-        assert(v.capacity() == 101);
-        assert(v.size() == 101);
-        assert(is_contiguous_container_asan_correct(v));
-    }
-    {
-      std::vector<int, safe_allocator<int>> v(100);
-      v.push_back(1);
-      assert(is_contiguous_container_asan_correct(v));
-      v.shrink_to_fit();
-      assert(v.capacity() == 101);
-      assert(v.size() == 101);
-      assert(is_contiguous_container_asan_correct(v));
-    }
-#endif
-
-    return true;
-}
-
-#if TEST_STD_VER >= 23
-template <typename T>
-struct increasing_allocator {
-  using value_type         = T;
-  std::size_t min_elements = 1000;
-  increasing_allocator()   = default;
-
-  template <typename U>
-  constexpr increasing_allocator(const increasing_allocator<U>& other) noexcept : min_elements(other.min_elements) {}
-
-  constexpr std::allocation_result<T*> allocate_at_least(std::size_t n) {
-    if (n < min_elements)
-      n = min_elements;
-    min_elements += 1000;
-    return std::allocator<T>{}.allocate_at_least(n);
+  {
+    std::vector<int, min_allocator<int>> v(100);
+    v.push_back(1);
+    assert(is_contiguous_container_asan_correct(v));
+    v.shrink_to_fit();
+    assert(v.capacity() == 101);
+    assert(v.size() == 101);
+    assert(is_contiguous_container_asan_correct(v));
+  }
+  {
+    std::vector<int, safe_allocator<int>> v(100);
+    v.push_back(1);
+    assert(is_contiguous_container_asan_correct(v));
+    v.shrink_to_fit();
+    assert(v.capacity() == 101);
+    assert(v.size() == 101);
+    assert(is_contiguous_container_asan_correct(v));
   }
-  constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
-  constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
-};
+#endif
 
-template <typename T, typename U>
-bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
   return true;
 }
 
+#if TEST_STD_VER >= 23
 // https://github.com/llvm/llvm-project/issues/95161
 constexpr bool test_increasing_allocator() {
   std::vector<int, increasing_allocator<int>> v;
@@ -111,16 +89,15 @@ constexpr bool test_increasing_allocator() {
 }
 #endif // TEST_STD_VER >= 23
 
-int main(int, char**)
-{
+int main(int, char**) {
   tests();
 #if TEST_STD_VER > 17
-    static_assert(tests());
+  static_assert(tests());
 #endif
 #if TEST_STD_VER >= 23
-    test_increasing_allocator();
-    static_assert(test_increasing_allocator());
+  test_increasing_allocator();
+  static_assert(test_increasing_allocator());
 #endif
 
-    return 0;
+  return 0;
 }
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
index 9f0b5ff7abdfe7..2d901e7afe2b67 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
@@ -10,12 +10,13 @@
 
 // void shrink_to_fit(); // constexpr since C++20
 
-#include <string>
 #include <cassert>
+#include <string>
 
-#include "test_macros.h"
-#include "min_allocator.h"
 #include "asan_testing.h"
+#include "increasing_allocator.h"
+#include "min_allocator.h"
+#include "test_macros.h"
 
 template <class S>
 TEST_CONSTEXPR_CXX20 void test(S s) {
@@ -64,30 +65,6 @@ TEST_CONSTEXPR_CXX20 bool test() {
 }
 
 #if TEST_STD_VER >= 23
-std::size_t min_bytes = 1000;
-
-template <typename T>
-struct increasing_allocator {
-  using value_type       = T;
-  increasing_allocator() = default;
-  template <typename U>
-  increasing_allocator(const increasing_allocator<U>&) noexcept {}
-  std::allocation_result<T*> allocate_at_least(std::size_t n) {
-    std::size_t allocation_amount = n * sizeof(T);
-    if (allocation_amount < min_bytes)
-      allocation_amount = min_bytes;
-    min_bytes += 1000;
-    return {static_cast<T*>(::operator new(allocation_amount)), allocation_amount / sizeof(T)};
-  }
-  T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
-  void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
-};
-
-template <typename T, typename U>
-bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
-  return true;
-}
-
 // https://github.com/llvm/llvm-project/issues/95161
 void test_increasing_allocator() {
   std::basic_string<char, std::char_traits<char>, increasing_allocator<char>> s{
diff --git a/libcxx/test/support/increasing_allocator.h b/libcxx/test/support/increasing_allocator.h
new file mode 100644
index 00000000000000..4fef6d35849909
--- /dev/null
+++ b/libcxx/test/support/increasing_allocator.h
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INCREASING_ALLOCATOR_H
+#define INCREASING_ALLOCATOR_H
+
+#include <cstddef>
+#include <memory>
+
+#include "test_macros.h"
+
+#if TEST_STD_VER >= 23
+template <typename T>
+struct increasing_allocator {
+  using value_type         = T;
+  std::size_t min_elements = 1000;
+  increasing_allocator()   = default;
+
+  template <typename U>
+  constexpr increasing_allocator(const increasing_allocator<U>& other) noexcept : min_elements(other.min_elements) {}
+
+  constexpr std::allocation_result<T*> allocate_at_least(std::size_t n) {
+    if (n < min_elements)
+      n = min_elements;
+    min_elements += 1000;
+    return std::allocator<T>{}.allocate_at_least(n);
+  }
+  constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
+  constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
+};
+
+template <typename T, typename U>
+bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
+  return true;
+}
+#endif // TEST_STD_VER >= 23
+
+#endif // INCREASING_ALLOCATOR_H
\ No newline at end of file

>From 837b6d1b24e0bf97e95e2e35a3782be62996a20f Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Fri, 29 Nov 2024 08:55:36 -0500
Subject: [PATCH 3/3] Add comment for increasing_allocator

---
 libcxx/test/support/increasing_allocator.h | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/libcxx/test/support/increasing_allocator.h b/libcxx/test/support/increasing_allocator.h
index 4fef6d35849909..6ae25c04f30693 100644
--- a/libcxx/test/support/increasing_allocator.h
+++ b/libcxx/test/support/increasing_allocator.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef INCREASING_ALLOCATOR_H
-#define INCREASING_ALLOCATOR_H
+#ifndef TEST_SUPPORT_INCREASING_ALLOCATOR_H
+#define TEST_SUPPORT_INCREASING_ALLOCATOR_H
 
 #include <cstddef>
 #include <memory>
@@ -15,6 +15,13 @@
 #include "test_macros.h"
 
 #if TEST_STD_VER >= 23
+
+// increasing_allocator is a custom allocator that maintains an incrementing minimum allocation size,
+// requiring that each call to allocate_at_least allocate at least this minimum size, which may exceed
+// the requested amount. This unique design makes increasing_allocator particularly useful for testing
+// the shrink_to_fit functionality in std::vector, vector<bool>, and std::basic_string, ensuring that
+// shrink_to_fit does not increase the capacity of the allocated memory.
+
 template <typename T>
 struct increasing_allocator {
   using value_type         = T;
@@ -40,4 +47,4 @@ bool operator==(increasing_allocator<T>, increasing_allocator<U>) {
 }
 #endif // TEST_STD_VER >= 23
 
-#endif // INCREASING_ALLOCATOR_H
\ No newline at end of file
+#endif // TEST_SUPPORT_INCREASING_ALLOCATOR_H
\ No newline at end of file



More information about the libcxx-commits mailing list