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

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Dec 5 12:44:08 PST 2024


Author: Peng Liu
Date: 2024-12-05T15:44:05-05:00
New Revision: a821937b6d29f874d2561c6ef073faeed302b1a9

URL: https://github.com/llvm/llvm-project/commit/a821937b6d29f874d2561c6ef073faeed302b1a9
DIFF: https://github.com/llvm/llvm-project/commit/a821937b6d29f874d2561c6ef073faeed302b1a9.diff

LOG: [libc++][test] Refactor increasing_allocator (#115671)

The increasing_allocator<T> class, originally introduced to test shrink_to_fit()
for std::vector, std::vector<bool>, and std::basic_string, has duplicated
definitions across several test files. Given the potential utility of this
class for capacity-related tests in various sequence containers, this patch
refactors the definition of increasing_allocator<T> into a single, reusable
location.

Added: 
    libcxx/test/support/increasing_allocator.h

Modified: 
    libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
    libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
    libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp

Removed: 
    


################################################################################
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..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 allocate_at_least(n).ptr; }
-  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 e39afb2d48f0a0..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 allocate_at_least(n).ptr; }
-  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 6f5e43d1341f53..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 allocate_at_least(n).ptr; }
-  void deallocate(T* p, std::size_t) noexcept { ::operator delete(static_cast<void*>(p)); }
-};
-
-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..30bd6f40c8dad2
--- /dev/null
+++ b/libcxx/test/support/increasing_allocator.h
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 TEST_SUPPORT_INCREASING_ALLOCATOR_H
+#define TEST_SUPPORT_INCREASING_ALLOCATOR_H
+
+#include <cstddef>
+#include <memory>
+
+#include "test_macros.h"
+
+// The increasing_allocator is a custom allocator that enforces an increasing minimum allocation size,
+// ensuring that it allocates an increasing amount of memory, possibly exceeding the requested amount.
+// This unique behavior is 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;
+  std::size_t min_elements = 1000;
+  increasing_allocator()   = default;
+
+  template <typename U>
+  TEST_CONSTEXPR_CXX20 increasing_allocator(const increasing_allocator<U>& other) TEST_NOEXCEPT
+      : min_elements(other.min_elements) {}
+
+#if TEST_STD_VER >= 23
+  TEST_CONSTEXPR_CXX23 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);
+  }
+#endif // TEST_STD_VER >= 23
+
+  TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); }
+
+  TEST_CONSTEXPR_CXX20 void deallocate(T* p, std::size_t n) TEST_NOEXCEPT { std::allocator<T>().deallocate(p, n); }
+};
+
+template <typename T, typename U>
+TEST_CONSTEXPR_CXX20 bool operator==(increasing_allocator<T>, increasing_allocator<U>) TEST_NOEXCEPT {
+  return true;
+}
+
+#endif // TEST_SUPPORT_INCREASING_ALLOCATOR_H


        


More information about the libcxx-commits mailing list