From fb88c7bd147221f7a64f7ffad018b4f4ec02eac5 Mon Sep 17 00:00:00 2001 From: Antony Peacock Date: Wed, 12 Oct 2022 11:42:56 +0100 Subject: [PATCH] Test failure path for allocated objects --- polymorphic_value.h | 3 ++- polymorphic_value_test.cpp | 46 +++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/polymorphic_value.h b/polymorphic_value.h index bd33c37..d290a1b 100644 --- a/polymorphic_value.h +++ b/polymorphic_value.h @@ -52,9 +52,10 @@ struct copier_traits_deleter_base { class control_block_deleter { public: template - void operator()(T* t) const noexcept { + void operator()(T*& t) const noexcept { if (t != nullptr) { t->destroy(); + t = nullptr; } } }; diff --git a/polymorphic_value_test.cpp b/polymorphic_value_test.cpp index 02cf14c..a0f0fc6 100644 --- a/polymorphic_value_test.cpp +++ b/polymorphic_value_test.cpp @@ -856,18 +856,38 @@ TEST_CASE("Copying object with allocator allocates") { } TEST_CASE("Allocator used to construct with make_polymorphic") { - unsigned allocs = 0; - unsigned deallocs = 0; - - tracking_allocator alloc(&allocs, &deallocs); - - { - unsigned const value = 99; - polymorphic_value p = make_polymorphic_value( - std::allocator_arg_t{}, alloc, value); - CHECK(allocs == 2); - CHECK(deallocs == 0); + GIVEN("an alloator which tracks allocations") { + unsigned allocs = 0; + unsigned deallocs = 0; + + tracking_allocator alloc(&allocs, &deallocs); + WHEN("Constructing a type from the allocator") { + unsigned const value = 99; + auto p = make_polymorphic_value(std::allocator_arg_t{}, + alloc, value); + THEN("Expect the allocation to be tracked") { + CHECK(allocs == 2); + CHECK(deallocs == 0); + } + AND_THEN("Expect the deallocation to be tracked") { + p.~polymorphic_value(); + CHECK(allocs == 2); + CHECK(deallocs == 2); + } + } + WHEN("Constructing a type that throws on construction from the allocator") { + struct ThrowOnConstruction : DerivedType { + ThrowOnConstruction() { throw "I throw in my default constructor"; } + }; + + CHECK_THROWS(make_polymorphic_value( + std::allocator_arg_t{}, alloc)); + THEN( + "Expect allocation and subsequent deallocation of the intial T to be " + "tracked after the throw (but not the control block's allocation)") { + CHECK(allocs == 1); + CHECK(deallocs == 1); + } + } } - CHECK(allocs == 2); - CHECK(deallocs == 2); }