Skip to content

Commit

Permalink
fix for issue #41 (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
thirtytwobits authored Jun 21, 2023
1 parent 3c6718a commit ca2e505
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 19 deletions.
21 changes: 21 additions & 0 deletions cetlvast/include/cetlvast/helpers_gtest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,25 @@ inline void flush_coverage_on_death() {}

#endif

namespace cetlvast
{
/// Used for typed tests to tag that the CETL version of a fixture should be used.
struct CETLTag final
{
CETLTag() = delete;
};

/// Used for typed tests to tag that the STL version of a figure is available and should be used.
struct STLTag final
{
STLTag() = delete;
};

/// Used for typed tests to tag that the given test should be skipped for this type.
struct SkipTag final
{
SkipTag() = delete;
};
} // namespace cetlvast

#endif // CETLVAST_HELPERS_GTEST_H_INCLUDED
32 changes: 32 additions & 0 deletions cetlvast/include/cetlvast/helpers_gtest_memory_resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,24 @@ class MockStdMemoryResource : public std::pmr::memory_resource

/// Memory Resource Helper (MRH)
/// Support for parameterized tests that use both std::pmr::memory_resource and cetl::pf17::pmr::memory_resource.
/// For example:
/// ```
/// typename cetlvast::MRH::template MemoryResourceType<TypeParam>* resource =
// cetlvast::MRH::template new_delete_resource_by_tag<TypeParam>();
/// ```
struct MRH final
{
#if (__cplusplus >= CETL_CPP_STANDARD_17)
template <typename TagType>
using MemoryResourceType = std::conditional_t<std::is_same<cetlvast::CETLTag, TagType>::value,
cetl::pf17::pmr::memory_resource,
std::pmr::memory_resource>;

#else
template <typename TagType>
using MemoryResourceType = cetl::pf17::pmr::memory_resource;
#endif

#if (__cplusplus >= CETL_CPP_STANDARD_17)

template <typename T>
Expand Down Expand Up @@ -94,6 +110,22 @@ struct MRH final
return cetl::pf17::pmr::null_memory_resource();
}

template <typename TagType>
static typename std::enable_if_t<std::is_same<cetlvast::CETLTag, TagType>::value, cetl::pf17::pmr::memory_resource*>
new_delete_resource_by_tag()
{
return cetl::pf17::pmr::new_delete_resource();
}

#if (__cplusplus >= CETL_CPP_STANDARD_17)
template <typename TagType>
static typename std::enable_if_t<std::is_same<cetlvast::STLTag, TagType>::value, std::pmr::memory_resource*>
new_delete_resource_by_tag()
{
return std::pmr::new_delete_resource();
}
#endif

MRH() = delete;
};

Expand Down
106 changes: 106 additions & 0 deletions cetlvast/suites/unittest/test_pf17_polymorphic_allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,3 +256,109 @@ TYPED_TEST(TestPolymorphicAllocatorProtocols, TestPairConstructionNoAllocator)
ASSERT_EQ(test_value, test_instance->first);
ASSERT_EQ(test_value, test_instance->second);
}

// +----------------------------------------------------------------------+
// | Test Suite :: TestPolymorphicAllocatorMoveOnlyProtocols
// +----------------------------------------------------------------------+
///
/// Test suite to verify that cetl::pf17::pmr::polymorphic_allocator adheres
/// to all conventions/protocols required of it by the C++ specification when
/// using move-only types.
///
template <typename T>
class TestPolymorphicAllocatorMoveOnlyProtocols : public ::testing::Test
{
public:
#if (__cplusplus >= CETL_CPP_STANDARD_17)
template <typename U>
using AllocatorType = std::conditional_t<std::is_same<cetlvast::CETLTag, T>::value,
cetl::pf17::pmr::polymorphic_allocator<U>,
std::pmr::polymorphic_allocator<U>>;

#else
template <typename U>
using AllocatorType = cetl::pf17::pmr::polymorphic_allocator<U>;

#endif
};

// clang-format off
using TestPolymorphicAllocatorMoveOnlyProtocolsTypes = ::testing::Types<
cetlvast::CETLTag
#if (__cplusplus >= CETL_CPP_STANDARD_17)
, cetlvast::STLTag
#endif
>;
// clang-format on

TYPED_TEST_SUITE(TestPolymorphicAllocatorMoveOnlyProtocols, TestPolymorphicAllocatorMoveOnlyProtocolsTypes, );

namespace
{

struct OnlyMovable
{
OnlyMovable()
: value{nullptr}
{}

OnlyMovable(OnlyMovable&& rhs)
: value(rhs.value)
{
rhs.value = nullptr;
}

OnlyMovable& operator=(OnlyMovable&& rhs)
{
value = rhs.value;
rhs.value = nullptr;
return *this;
}

OnlyMovable(const OnlyMovable&) = delete;
OnlyMovable& operator=(const OnlyMovable&) = delete;

OnlyMovable(int* value)
: value(value)
{
}

int* value;
};

} // namespace

// +----------------------------------------------------------------------+

TYPED_TEST(TestPolymorphicAllocatorMoveOnlyProtocols, TestDefaultConstruction)
{
typename cetlvast::MRH::template MemoryResourceType<TypeParam>* resource =
cetlvast::MRH::template new_delete_resource_by_tag<TypeParam>();
using AllocatorType = typename TestFixture::template AllocatorType<OnlyMovable>;
AllocatorType subject{resource};
OnlyMovable* p = subject.allocate(1);
ASSERT_FALSE(nullptr == p);
subject.deallocate(p, 1);
}

// +----------------------------------------------------------------------+

TYPED_TEST(TestPolymorphicAllocatorMoveOnlyProtocols, TestEmplace)
{
int test_data = 0;
int other_test_data = 0;
typename cetlvast::MRH::template MemoryResourceType<TypeParam>* resource =
cetlvast::MRH::template new_delete_resource_by_tag<TypeParam>();
using AllocatorType = typename TestFixture::template AllocatorType<OnlyMovable>;
AllocatorType subject{resource};
OnlyMovable* p = subject.allocate(1);
ASSERT_FALSE(nullptr == p);
subject.construct(p, &test_data);
ASSERT_EQ(&test_data, p->value);
OnlyMovable other{&other_test_data};
// This is where Issue #41 was found
subject.construct(p, std::move(other));
ASSERT_EQ(&other_test_data, p->value);
ASSERT_EQ(nullptr, other.value);
subject.deallocate(p, 1);
}
29 changes: 11 additions & 18 deletions cetlvast/suites/unittest/test_variable_length_array_compat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,13 +401,6 @@ static_assert(!std::is_trivially_constructible<NotTriviallyConstructable>::value
// | TYPED TEST PROTOCOL
// +-------------------------------------------------------------------------------------------------------------------+

struct VectorTag
{};
struct VectorSkipReallocTag
{};
struct VLATag
{};

/// The primary test protocol. Each test case will have a single VLA (the subject) with the given value_type and
/// allocator_type. The allocator_type will be constructed with the given memory_resource_factory_type and that
/// memory resource will be given the providing memory_resource_upstream_factory_type.
Expand Down Expand Up @@ -444,7 +437,7 @@ class VLATestsGeneric : public ::testing::Test
using MemoryResourceUpstreamFactoryTypePtr = typename std::add_pointer<MemoryResourceUpstreamFactoryType>::type;
using Allocator = typename T::allocator_type;
using Value = typename T::value_type;
using SubjectType = typename std::conditional<std::is_same<typename T::container_type, VLATag>::value,
using SubjectType = typename std::conditional<std::is_same<typename T::container_type, cetlvast::CETLTag>::value,
cetl::VariableLengthArray<Value, Allocator>,
std::vector<Value, Allocator>>::type;

Expand Down Expand Up @@ -506,16 +499,16 @@ const std::size_t VLATestsGeneric<T>::maximumMaxSize;

using MyTypes = ::testing::Types<
/* container type tag | allocator type | primary memory resource factory */
/* 0 */ TestAllocatorType<VLATag, cetl::pf17::pmr::polymorphic_allocator<std::uint64_t>, CetlUnsynchronizedArrayMemoryResourceFactory<24>>
/* 1 */ , TestAllocatorType<VectorSkipReallocTag, cetl::pf17::pmr::polymorphic_allocator<std::uint64_t>, CetlUnsynchronizedArrayMemoryResourceFactory<24>>
/* 2 */ , TestAllocatorType<VLATag, cetl::pf17::pmr::polymorphic_allocator<NotTriviallyConstructable>, CetlUnsynchronizedArrayMemoryResourceFactory<sizeof(NotTriviallyConstructable) * 8>>
/* 3 */ , TestAllocatorType<VectorSkipReallocTag, cetl::pf17::pmr::polymorphic_allocator<NotTriviallyConstructable>, CetlUnsynchronizedArrayMemoryResourceFactory<sizeof(NotTriviallyConstructable) * 8>>
/* 4 */ , TestAllocatorType<VectorTag, MaxAllocator<std::uint32_t, 24>, MaxSizeResourceFactory<24>>
/* 5 */ , TestAllocatorType<VLATag, cetl::pf17::pmr::polymorphic_allocator<std::uint64_t>, CetlNewDeleteResourceFactory>
/* 6 */ , TestAllocatorType<VectorTag, cetl::pf17::pmr::polymorphic_allocator<std::uint64_t>, CetlNewDeleteResourceFactory>
/* 0 */ TestAllocatorType<cetlvast::CETLTag, cetl::pf17::pmr::polymorphic_allocator<std::uint64_t>, CetlUnsynchronizedArrayMemoryResourceFactory<24>>
/* 1 */ , TestAllocatorType<cetlvast::SkipTag, cetl::pf17::pmr::polymorphic_allocator<std::uint64_t>, CetlUnsynchronizedArrayMemoryResourceFactory<24>>
/* 2 */ , TestAllocatorType<cetlvast::CETLTag, cetl::pf17::pmr::polymorphic_allocator<NotTriviallyConstructable>, CetlUnsynchronizedArrayMemoryResourceFactory<sizeof(NotTriviallyConstructable) * 8>>
/* 3 */ , TestAllocatorType<cetlvast::SkipTag, cetl::pf17::pmr::polymorphic_allocator<NotTriviallyConstructable>, CetlUnsynchronizedArrayMemoryResourceFactory<sizeof(NotTriviallyConstructable) * 8>>
/* 4 */ , TestAllocatorType<cetlvast::STLTag, MaxAllocator<std::uint32_t, 24>, MaxSizeResourceFactory<24>>
/* 5 */ , TestAllocatorType<cetlvast::CETLTag, cetl::pf17::pmr::polymorphic_allocator<std::uint64_t>, CetlNewDeleteResourceFactory>
/* 6 */ , TestAllocatorType<cetlvast::STLTag, cetl::pf17::pmr::polymorphic_allocator<std::uint64_t>, CetlNewDeleteResourceFactory>
#if (__cplusplus >= CETL_CPP_STANDARD_17)
/* 7 */ , TestAllocatorType<VLATag, std::pmr::polymorphic_allocator<std::uint64_t>, StdNewDeleteResourceFactory>
/* 8 */ , TestAllocatorType<VectorTag, std::pmr::polymorphic_allocator<std::uint64_t>, StdNewDeleteResourceFactory>
/* 7 */ , TestAllocatorType<cetlvast::CETLTag, std::pmr::polymorphic_allocator<std::uint64_t>, StdNewDeleteResourceFactory>
/* 8 */ , TestAllocatorType<cetlvast::STLTag, std::pmr::polymorphic_allocator<std::uint64_t>, StdNewDeleteResourceFactory>
#endif
>;
// clang-format on
Expand Down Expand Up @@ -609,7 +602,7 @@ TYPED_TEST(VLATestsGeneric, TestShrink)

TYPED_TEST(VLATestsGeneric, TestCopyAssignment)
{
if (std::is_same<typename TypeParam::container_type, VectorSkipReallocTag>::value)
if (std::is_same<typename TypeParam::container_type, cetlvast::SkipTag>::value)
{
GTEST_SKIP() << "Skipping test that requires CETL reallocation support.";
}
Expand Down
2 changes: 1 addition & 1 deletion include/cetl/pf17/memory_resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ class polymorphic_allocator
template <typename U, typename... Args>
typename EnableIfNotPair<U>::return_type construct(U* p, Args&&... args)
{
construct_not_pair_impl(p, args...);
construct_not_pair_impl(p, std::forward<Args>(args)...);
}

template <class FirstType, class SecondType, class... FirstTypeConstructorArgs, class... SecondTypeConstructorArgs>
Expand Down

0 comments on commit ca2e505

Please sign in to comment.