catch2/tests/SelfTest/IntrospectiveTests/UniquePtr.tests.cpp
Martin Hořeňovský cc18bd719d
Sweep out Wshadow
Most of the changes are completely pointless renaming of constructor
arguments so that they do not use the same name as the type members,
but 🤷

Closes #2015
2020-09-06 13:11:42 +02:00

134 lines
4.2 KiB
C++

#include <catch2/catch_test_macros.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <tuple>
namespace {
struct unique_ptr_test_helper {
bool dummy = false;
};
} // end unnamed namespace
TEST_CASE("unique_ptr reimplementation: basic functionality", "[internals][unique-ptr]") {
using Catch::Detail::unique_ptr;
SECTION("Default constructed unique_ptr is empty") {
unique_ptr<int> ptr;
REQUIRE_FALSE(ptr);
REQUIRE(ptr.get() == nullptr);
}
SECTION("Take ownership of allocation") {
auto naked_ptr = new int{ 0 };
unique_ptr<int> ptr(naked_ptr);
REQUIRE(ptr);
REQUIRE(*ptr == 0);
REQUIRE(ptr.get() == naked_ptr);
SECTION("Plain reset deallocates") {
ptr.reset(); // this makes naked_ptr dangling!
REQUIRE_FALSE(ptr);
REQUIRE(ptr.get() == nullptr);
}
SECTION("Reset replaces ownership") {
ptr.reset(new int{ 2 });
REQUIRE(ptr);
REQUIRE(ptr.get() != nullptr);
REQUIRE(*ptr == 2);
}
}
SECTION("Release releases ownership") {
auto naked_ptr = new int{ 1 };
unique_ptr<int> ptr(naked_ptr);
ptr.release();
CHECK_FALSE(ptr);
CHECK(ptr.get() == nullptr);
delete naked_ptr;
}
SECTION("Move constructor") {
unique_ptr<int> ptr1(new int{ 1 });
auto ptr2(std::move(ptr1));
REQUIRE_FALSE(ptr1);
REQUIRE(ptr2);
REQUIRE(*ptr2 == 1);
}
SECTION("Move assignment") {
unique_ptr<int> ptr1(new int{ 1 }), ptr2(new int{ 2 });
ptr1 = std::move(ptr2);
REQUIRE_FALSE(ptr2);
REQUIRE(ptr1);
REQUIRE(*ptr1 == 2);
}
SECTION("free swap") {
unique_ptr<int> ptr1(new int{ 1 }), ptr2(new int{ 2 });
swap(ptr1, ptr2);
REQUIRE(*ptr1 == 2);
REQUIRE(*ptr2 == 1);
}
}
namespace {
struct base {
int i;
base(int i_) :i(i_) {}
};
struct derived : base { using base::base; };
struct unrelated {};
} // end unnamed namespace
static_assert( std::is_constructible<Catch::Detail::unique_ptr<base>,
Catch::Detail::unique_ptr<derived>>::value, "Upcasting is supported");
static_assert(!std::is_constructible<Catch::Detail::unique_ptr<derived>,
Catch::Detail::unique_ptr<base>>::value, "Downcasting is not supported");
static_assert(!std::is_constructible<Catch::Detail::unique_ptr<base>,
Catch::Detail::unique_ptr<unrelated>>::value, "Cannot just convert one ptr type to another");
TEST_CASE("Upcasting special member functions", "[internals][unique-ptr]") {
using Catch::Detail::unique_ptr;
unique_ptr<derived> dptr(new derived{3});
SECTION("Move constructor") {
unique_ptr<base> bptr(std::move(dptr));
REQUIRE(bptr->i == 3);
}
SECTION("move assignment") {
unique_ptr<base> bptr(new base{ 1 });
bptr = std::move(dptr);
REQUIRE(bptr->i == 3);
}
}
namespace {
struct move_detector {
bool has_moved = false;
move_detector() = default;
move_detector(move_detector const& rhs) = default;
move_detector& operator=(move_detector const& rhs) = default;
move_detector(move_detector&& rhs) noexcept {
rhs.has_moved = true;
}
move_detector& operator=(move_detector&& rhs) noexcept {
rhs.has_moved = true;
return *this;
}
};
} // end unnamed namespace
TEST_CASE("make_unique reimplementation", "[internals][unique-ptr]") {
using Catch::Detail::make_unique;
SECTION("From lvalue copies") {
move_detector lval;
auto ptr = make_unique<move_detector>(lval);
REQUIRE_FALSE(lval.has_moved);
}
SECTION("From rvalue moves") {
move_detector rval;
auto ptr = make_unique<move_detector>(std::move(rval));
REQUIRE(rval.has_moved);
}
SECTION("Variadic constructor") {
auto ptr = make_unique<std::tuple<int, double, int>>(1, 2., 3);
REQUIRE(*ptr == std::tuple<int, double, int>{1, 2., 3});
}
}