[libcxx-commits] [libcxx] b935ab8 - [libc++] Add tests to make sure that stable algorithms work without memory available
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jun 15 10:59:38 PDT 2023
Author: Nikolas Klauser
Date: 2023-06-15T10:59:34-07:00
New Revision: b935ab8e747cf52ff12471879460206a9f433eea
URL: https://github.com/llvm/llvm-project/commit/b935ab8e747cf52ff12471879460206a9f433eea
DIFF: https://github.com/llvm/llvm-project/commit/b935ab8e747cf52ff12471879460206a9f433eea.diff
LOG: [libc++] Add tests to make sure that stable algorithms work without memory available
Reviewed By: #libc, ldionne
Spies: power-llvm-team, ldionne, libcxx-commits, arichardson, mstorsjo
Differential Revision: https://reviews.llvm.org/D152939
Added:
Modified:
libcxx/include/__algorithm/stable_partition.h
libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
libcxx/test/support/count_new.h
Removed:
################################################################################
diff --git a/libcxx/include/__algorithm/stable_partition.h b/libcxx/include/__algorithm/stable_partition.h
index 3b68bd3061e6b..38fa9ce37d00d 100644
--- a/libcxx/include/__algorithm/stable_partition.h
+++ b/libcxx/include/__algorithm/stable_partition.h
@@ -122,7 +122,10 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator
__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
forward_iterator_tag)
{
- const unsigned __alloc_limit = 3; // might want to make this a function of trivial assignment
+ typedef typename iterator_traits<_ForwardIterator>::
diff erence_type
diff erence_type;
+ typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
+
+ const
diff erence_type __alloc_limit = 3; // might want to make this a function of trivial assignment
// Either prove all true and return __first or point to first false
while (true)
{
@@ -134,8 +137,6 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred
}
// We now have a reduced range [__first, __last)
// *__first is known to be false
- typedef typename iterator_traits<_ForwardIterator>::
diff erence_type
diff erence_type;
- typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
diff erence_type __len = _IterOps<_AlgPolicy>::distance(__first, __last);
pair<value_type*, ptr
diff _t> __p(0, 0);
unique_ptr<value_type, __return_temporary_buffer> __h;
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp
index 948ec482b0abb..5fc66339d5f80 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp
@@ -17,9 +17,11 @@
#include <algorithm>
#include <cassert>
#include <memory>
+#include <vector>
-#include "test_macros.h"
+#include "count_new.h"
#include "test_iterators.h"
+#include "test_macros.h"
struct is_odd
{
@@ -36,7 +38,7 @@ template <class Iter>
void
test()
{
- { // check mixed
+ { // check mixed
typedef std::pair<int,int> P;
P array[] =
{
@@ -64,8 +66,8 @@ test()
assert(array[7] == P(2, 2));
assert(array[8] == P(4, 1));
assert(array[9] == P(4, 2));
- }
- {
+ }
+ {
typedef std::pair<int,int> P;
P array[] =
{
@@ -104,8 +106,8 @@ test()
r = std::stable_partition(Iter(array+4), Iter(array+5), odd_first());
assert(base(r) == array+4);
assert(array[4] == P(0, 1));
- }
- { // check all false
+ }
+ { // check all false
typedef std::pair<int,int> P;
P array[] =
{
@@ -133,8 +135,8 @@ test()
assert(array[7] == P(6, 2));
assert(array[8] == P(8, 1));
assert(array[9] == P(8, 2));
- }
- { // check all true
+ }
+ { // check all true
typedef std::pair<int,int> P;
P array[] =
{
@@ -162,8 +164,8 @@ test()
assert(array[7] == P(7, 2));
assert(array[8] == P(9, 1));
assert(array[9] == P(9, 2));
- }
- { // check all false but first true
+ }
+ { // check all false but first true
typedef std::pair<int,int> P;
P array[] =
{
@@ -191,8 +193,8 @@ test()
assert(array[7] == P(6, 2));
assert(array[8] == P(8, 1));
assert(array[9] == P(8, 2));
- }
- { // check all false but last true
+ }
+ { // check all false but last true
typedef std::pair<int,int> P;
P array[] =
{
@@ -220,8 +222,8 @@ test()
assert(array[7] == P(6, 1));
assert(array[8] == P(6, 2));
assert(array[9] == P(8, 1));
- }
- { // check all true but first false
+ }
+ { // check all true but first false
typedef std::pair<int,int> P;
P array[] =
{
@@ -249,8 +251,8 @@ test()
assert(array[7] == P(9, 1));
assert(array[8] == P(9, 2));
assert(array[9] == P(0, 1));
- }
- { // check all true but last false
+ }
+ { // check all true but last false
typedef std::pair<int,int> P;
P array[] =
{
@@ -278,7 +280,24 @@ test()
assert(array[7] == P(7, 2));
assert(array[8] == P(9, 1));
assert(array[9] == P(0, 2));
- }
+ }
+#if TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
+ { // check that the algorithm still works when no memory is available
+ std::vector<int> vec(150, 3);
+ vec[5] = 6;
+ getGlobalMemCounter()->throw_after = 0;
+ std::stable_partition(vec.begin(), vec.end(), [](int i) { return i < 5; });
+ assert(std::is_partitioned(vec.begin(), vec.end(), [](int i) { return i < 5; }));
+ vec[5] = 6;
+ getGlobalMemCounter()->throw_after = 0;
+ std::stable_partition(
+ forward_iterator<int*>(vec.data()), forward_iterator<int*>(vec.data() + vec.size()), [](int i) {
+ return i < 5;
+ });
+ assert(std::is_partitioned(vec.begin(), vec.end(), [](int i) { return i < 5; }));
+ getGlobalMemCounter()->reset();
+ }
+#endif // TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
}
#if TEST_STD_VER >= 11
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp
index 12718652b1937..44f2868af3693 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp
@@ -14,12 +14,16 @@
// void
// inplace_merge(Iter first, Iter middle, Iter last);
+// XFAIL: LIBCXX-AIX-FIXME
+
#include <algorithm>
-#include <random>
#include <cassert>
+#include <random>
+#include <vector>
-#include "test_macros.h"
+#include "count_new.h"
#include "test_iterators.h"
+#include "test_macros.h"
#if TEST_STD_VER >= 11
struct S {
@@ -107,7 +111,16 @@ int main(int, char**)
test<bidirectional_iterator<S*> >();
test<random_access_iterator<S*> >();
test<S*>();
-#endif // TEST_STD_VER >= 11
+#endif
+
+#if TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
+ {
+ std::vector<int> vec(150, 3);
+ getGlobalMemCounter()->throw_after = 0;
+ std::inplace_merge(vec.begin(), vec.begin() + 100, vec.end());
+ assert(std::all_of(vec.begin(), vec.end(), [](int i) { return i == 3; }));
+ }
+#endif // TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
return 0;
}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
index aee94c63465f9..765e50e72d4aa 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp
@@ -15,10 +15,11 @@
// stable_sort(Iter first, Iter last);
#include <algorithm>
+#include <cassert>
#include <iterator>
#include <random>
-#include <cassert>
+#include "count_new.h"
#include "test_macros.h"
std::mt19937 randomness;
@@ -155,5 +156,13 @@ int main(int, char**)
test_larger_sorts(1000);
test_larger_sorts(1009);
+#if !defined(TEST_HAS_NO_EXCEPTIONS)
+ { // check that the algorithm works without memory
+ std::vector<int> vec(150, 3);
+ getGlobalMemCounter()->throw_after = 0;
+ std::stable_sort(vec.begin(), vec.end());
+ }
+#endif // !defined(TEST_HAS_NO_EXCEPTIONS)
+
return 0;
}
diff --git a/libcxx/test/support/count_new.h b/libcxx/test/support/count_new.h
index fc53cd6f0ab47..3e3856ca30e04 100644
--- a/libcxx/test/support/count_new.h
+++ b/libcxx/test/support/count_new.h
@@ -9,9 +9,10 @@
#ifndef COUNT_NEW_H
#define COUNT_NEW_H
-# include <cstdlib>
-# include <cassert>
-# include <new>
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+#include <new>
#include <type_traits>
#include "test_macros.h"
@@ -78,7 +79,6 @@ class MemCounter
void newCalled(std::size_t s)
{
assert(disable_allocations == false);
- assert(s);
if (throw_after == 0) {
throw_after = never_throw_value;
detail::throw_bad_alloc_helper();
@@ -112,7 +112,6 @@ class MemCounter
void newArrayCalled(std::size_t s)
{
assert(disable_allocations == false);
- assert(s);
if (throw_after == 0) {
throw_after = never_throw_value;
detail::throw_bad_alloc_helper();
@@ -410,11 +409,11 @@ void operator delete[](void* p) TEST_NOEXCEPT
void* operator new(std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
const std::size_t a = static_cast<std::size_t>(av);
getGlobalMemCounter()->alignedNewCalled(s, a);
- void *ret;
+ void *ret = nullptr;
#ifdef USE_ALIGNED_ALLOC
ret = _aligned_malloc(s, a);
#else
- posix_memalign(&ret, a, s);
+ assert(posix_memalign(&ret, std::max(a, sizeof(void*)), s) != EINVAL);
#endif
if (ret == nullptr)
detail::throw_bad_alloc_helper();
More information about the libcxx-commits
mailing list