[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