UniquePtr.tests.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright Catch2 Authors
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // https://www.boost.org/LICENSE_1_0.txt)
  5. // SPDX-License-Identifier: BSL-1.0
  6. #include <catch2/catch_test_macros.hpp>
  7. #include <catch2/internal/catch_unique_ptr.hpp>
  8. #include <tuple>
  9. namespace {
  10. struct unique_ptr_test_helper {
  11. bool dummy = false;
  12. };
  13. } // end unnamed namespace
  14. TEST_CASE("unique_ptr reimplementation: basic functionality", "[internals][unique-ptr]") {
  15. using Catch::Detail::unique_ptr;
  16. SECTION("Default constructed unique_ptr is empty") {
  17. unique_ptr<int> ptr;
  18. REQUIRE_FALSE(ptr);
  19. REQUIRE(ptr.get() == nullptr);
  20. }
  21. SECTION("Take ownership of allocation") {
  22. auto naked_ptr = new int{ 0 };
  23. unique_ptr<int> ptr(naked_ptr);
  24. REQUIRE(ptr);
  25. REQUIRE(*ptr == 0);
  26. REQUIRE(ptr.get() == naked_ptr);
  27. SECTION("Plain reset deallocates") {
  28. ptr.reset(); // this makes naked_ptr dangling!
  29. REQUIRE_FALSE(ptr);
  30. REQUIRE(ptr.get() == nullptr);
  31. }
  32. SECTION("Reset replaces ownership") {
  33. ptr.reset(new int{ 2 });
  34. REQUIRE(ptr);
  35. REQUIRE(ptr.get() != nullptr);
  36. REQUIRE(*ptr == 2);
  37. }
  38. }
  39. SECTION("Release releases ownership") {
  40. auto naked_ptr = new int{ 1 };
  41. unique_ptr<int> ptr(naked_ptr);
  42. ptr.release();
  43. CHECK_FALSE(ptr);
  44. CHECK(ptr.get() == nullptr);
  45. delete naked_ptr;
  46. }
  47. SECTION("Move constructor") {
  48. unique_ptr<int> ptr1(new int{ 1 });
  49. auto ptr2(std::move(ptr1));
  50. REQUIRE_FALSE(ptr1);
  51. REQUIRE(ptr2);
  52. REQUIRE(*ptr2 == 1);
  53. }
  54. SECTION("Move assignment") {
  55. unique_ptr<int> ptr1(new int{ 1 }), ptr2(new int{ 2 });
  56. ptr1 = std::move(ptr2);
  57. REQUIRE_FALSE(ptr2);
  58. REQUIRE(ptr1);
  59. REQUIRE(*ptr1 == 2);
  60. }
  61. SECTION("free swap") {
  62. unique_ptr<int> ptr1(new int{ 1 }), ptr2(new int{ 2 });
  63. swap(ptr1, ptr2);
  64. REQUIRE(*ptr1 == 2);
  65. REQUIRE(*ptr2 == 1);
  66. }
  67. }
  68. namespace {
  69. struct base {
  70. int i;
  71. base(int i_) :i(i_) {}
  72. };
  73. struct derived : base { using base::base; };
  74. struct unrelated {};
  75. } // end unnamed namespace
  76. static_assert( std::is_constructible<Catch::Detail::unique_ptr<base>,
  77. Catch::Detail::unique_ptr<derived>>::value, "Upcasting is supported");
  78. static_assert(!std::is_constructible<Catch::Detail::unique_ptr<derived>,
  79. Catch::Detail::unique_ptr<base>>::value, "Downcasting is not supported");
  80. static_assert(!std::is_constructible<Catch::Detail::unique_ptr<base>,
  81. Catch::Detail::unique_ptr<unrelated>>::value, "Cannot just convert one ptr type to another");
  82. TEST_CASE("Upcasting special member functions", "[internals][unique-ptr]") {
  83. using Catch::Detail::unique_ptr;
  84. unique_ptr<derived> dptr(new derived{3});
  85. SECTION("Move constructor") {
  86. unique_ptr<base> bptr(std::move(dptr));
  87. REQUIRE(bptr->i == 3);
  88. }
  89. SECTION("move assignment") {
  90. unique_ptr<base> bptr(new base{ 1 });
  91. bptr = std::move(dptr);
  92. REQUIRE(bptr->i == 3);
  93. }
  94. }
  95. namespace {
  96. struct move_detector {
  97. bool has_moved = false;
  98. move_detector() = default;
  99. move_detector(move_detector const& rhs) = default;
  100. move_detector& operator=(move_detector const& rhs) = default;
  101. move_detector(move_detector&& rhs) noexcept {
  102. rhs.has_moved = true;
  103. }
  104. move_detector& operator=(move_detector&& rhs) noexcept {
  105. rhs.has_moved = true;
  106. return *this;
  107. }
  108. };
  109. } // end unnamed namespace
  110. TEST_CASE("make_unique reimplementation", "[internals][unique-ptr]") {
  111. using Catch::Detail::make_unique;
  112. SECTION("From lvalue copies") {
  113. move_detector lval;
  114. auto ptr = make_unique<move_detector>(lval);
  115. REQUIRE_FALSE(lval.has_moved);
  116. }
  117. SECTION("From rvalue moves") {
  118. move_detector rval;
  119. auto ptr = make_unique<move_detector>(std::move(rval));
  120. REQUIRE(rval.has_moved);
  121. }
  122. SECTION("Variadic constructor") {
  123. auto ptr = make_unique<std::tuple<int, double, int>>(1, 2., 3);
  124. REQUIRE(*ptr == std::tuple<int, double, int>{1, 2., 3});
  125. }
  126. }