Files
libcxx/test/support/unique_ptr_test_helper.h
Eric Fiselier 81f58e5052 Rewrite and cleanup unique_ptr tests.
This patch almost entirely rewrites the unique_ptr tests. There are a couple
of reasons for this:

A) Most of the *.fail.cpp tests were either incorrect or could be better written
  as a *.pass.cpp test that uses <type_traits> to check if certain operations
  are valid (Ex. Using static_assert(!std::is_copy_constructible_v<T>) instead
  of writing a failure test).

B) [unique.ptr.runtime] has very poor test coverage. Many of the constructors
  and assignment operators have to tests at all. The special members that have
  tests have very few test cases and are typically way out of date.

C) The tests for [unique.ptr.single] and [unique.ptr.runtime] are largely
  duplicates of each other. This means common requirements have two different
  sets of tests in two different test files. This makes the tests harder to
  maintain than if there was a single copy.

To address (A) this patch changes almost all of the *.fail.cpp tests into
.pass.cpp tests using type traits; Allowing the *.fail.cpp tests to be removed.

The address (B) and (C) the tests for [unique.ptr.single] and [unique.ptr.runtime]
have been combined into a single directory, allowing both specializations to share
common tests. Tests specific to the single/runtime specializations are given the
suffix "*.single.pass.cpp" or "*.runtime.pass.cpp".

Finally the unique.ptr test have been moved into the correct directory according
to the standard. Specifically they have been removed from "utilities/memory" into
"utilities/smartptr".

PS. This patch also adds newly written tests for upcoming unique_ptr changes/fixes.
However since these tests don't currently pass they are guarded by the macro
TEST_WORKAROUND_UPCOMING_UNIQUE_PTR_CHANGES. This allows other STL's to validate
the tests before libc++ implements the changes. The relevant libc++ changes should
land in the next week.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@300388 91177308-0d34-0410-b5e6-96231b3b80d8
2017-04-15 05:28:06 +00:00

165 lines
5.5 KiB
C++

//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
#define TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
#include <memory>
#include <type_traits>
#include "test_macros.h"
#include "deleter_types.h"
struct A {
static int count;
A() { ++count; }
A(const A&) { ++count; }
virtual ~A() { --count; }
};
int A::count = 0;
struct B : public A {
static int count;
B() { ++count; }
B(const B&) { ++count; }
virtual ~B() { --count; }
};
int B::count = 0;
template <class T>
typename std::enable_if<!std::is_array<T>::value, T*>::type
newValue(int num_elements) {
assert(num_elements == 1);
return new T;
}
template <class T>
typename std::enable_if<std::is_array<T>::value,
typename std::remove_all_extents<T>::type*>::type
newValue(int num_elements) {
typedef typename std::remove_all_extents<T>::type VT;
assert(num_elements >= 1);
return new VT[num_elements];
}
struct IncompleteType;
void checkNumIncompleteTypeAlive(int i);
int getNumIncompleteTypeAlive();
IncompleteType* getNewIncomplete();
IncompleteType* getNewIncompleteArray(int size);
#if TEST_STD_VER >= 11
template <class ThisT, class ...Args>
struct args_is_this_type : std::false_type {};
template <class ThisT, class A1>
struct args_is_this_type<ThisT, A1> : std::is_same<ThisT, typename std::decay<A1>::type> {};
#endif
template <class IncompleteT = IncompleteType,
class Del = std::default_delete<IncompleteT> >
struct StoresIncomplete {
static_assert((std::is_same<IncompleteT, IncompleteType>::value ||
std::is_same<IncompleteT, IncompleteType[]>::value), "");
std::unique_ptr<IncompleteT, Del> m_ptr;
#if TEST_STD_VER >= 11
StoresIncomplete(StoresIncomplete const&) = delete;
StoresIncomplete(StoresIncomplete&&) = default;
template <class ...Args>
StoresIncomplete(Args&&... args) : m_ptr(std::forward<Args>(args)...) {
static_assert(!args_is_this_type<StoresIncomplete, Args...>::value, "");
}
#else
private:
StoresIncomplete();
StoresIncomplete(StoresIncomplete const&);
public:
#endif
~StoresIncomplete();
IncompleteType* get() const { return m_ptr.get(); }
Del& get_deleter() { return m_ptr.get_deleter(); }
};
#if TEST_STD_VER >= 11
template <class IncompleteT = IncompleteType,
class Del = std::default_delete<IncompleteT>, class... Args>
void doIncompleteTypeTest(int expect_alive, Args&&... ctor_args) {
using ValueT = typename std::remove_all_extents<IncompleteT>::type;
if (expect_alive == 0)
checkNumIncompleteTypeAlive(0);
else
checkNumIncompleteTypeAlive(expect_alive);
{
StoresIncomplete<IncompleteT, Del> sptr(std::forward<Args>(ctor_args)...);
checkNumIncompleteTypeAlive(expect_alive);
if (expect_alive == 0)
assert(sptr.get() == nullptr);
else
assert(sptr.get() != nullptr);
}
checkNumIncompleteTypeAlive(0);
}
#endif
#define INCOMPLETE_TEST_EPILOGUE() \
int is_incomplete_test_anchor = is_incomplete_test(); \
\
struct IncompleteType { \
static int count; \
IncompleteType() { ++count; } \
~IncompleteType() { --count; } \
}; \
\
int IncompleteType::count = 0; \
\
void checkNumIncompleteTypeAlive(int i) { \
assert(IncompleteType::count == i); \
} \
int getNumIncompleteTypeAlive() { return IncompleteType::count; } \
IncompleteType* getNewIncomplete() { return new IncompleteType; } \
IncompleteType* getNewIncompleteArray(int size) { \
return new IncompleteType[size]; \
} \
\
template <class IncompleteT, class Del> \
StoresIncomplete<IncompleteT, Del>::~StoresIncomplete() {}
#
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
#endif
#if TEST_STD_VER >= 11
#define DEFINE_AND_RUN_IS_INCOMPLETE_TEST(...) \
static int is_incomplete_test() { __VA_ARGS__ return 0; } \
INCOMPLETE_TEST_EPILOGUE()
#else
#define DEFINE_AND_RUN_IS_INCOMPLETE_TEST(...) \
static int is_incomplete_test() { return 0; } \
INCOMPLETE_TEST_EPILOGUE()
#endif
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#endif // TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H