You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 satır
5.8KB

  1. /*
  2. * Scope Guard
  3. * Copyright (C) 2017 offa
  4. *
  5. * This file is part of Scope Guard.
  6. *
  7. * Scope Guard is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * Scope Guard is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with Scope Guard. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "unique_resource.h"
  21. #include "CallMocks.h"
  22. #include <catch.hpp>
  23. #include <trompeloeil.hpp>
  24. using namespace mock;
  25. using namespace trompeloeil;
  26. namespace
  27. {
  28. CallMock m;
  29. void deleter(Handle h)
  30. {
  31. m.deleter(h);
  32. }
  33. }
  34. TEST_CASE("construction with move", "[UniqueResource]")
  35. {
  36. REQUIRE_CALL(m, deleter(3));
  37. auto guard = sr::unique_resource{Handle{3}, deleter};
  38. static_cast<void>(guard);
  39. }
  40. TEST_CASE("construction with copy", "[UniqueResource]")
  41. {
  42. REQUIRE_CALL(m, deleter(3));
  43. const Handle h{3};
  44. const auto d = [](auto v) { m.deleter(v); };
  45. auto guard = sr::unique_resource{h, d};
  46. static_cast<void>(guard);
  47. }
  48. TEST_CASE("construction with copy calls deleter and rethrows on failed copy", "[UniqueResource]")
  49. {
  50. REQUIRE_THROWS([] {
  51. const ThrowOnCopyMock noMove;
  52. const auto d = [](const auto&) { m.deleter(3); };
  53. REQUIRE_CALL(m, deleter(3));
  54. sr::unique_resource guard{noMove, d};
  55. static_cast<void>(guard);
  56. }());
  57. }
  58. TEST_CASE("move-construction with move", "[UniqueResource]")
  59. {
  60. REQUIRE_CALL(m, deleter(3));
  61. auto movedFrom = sr::unique_resource{Handle{3}, deleter};
  62. auto guard = std::move(movedFrom);
  63. CHECK(guard.get() == 3);
  64. }
  65. TEST_CASE("move-construction with copy", "[UniqueResource]")
  66. {
  67. REQUIRE_CALL(m, deleter(7));
  68. auto d = [](auto) { deleter(7); };
  69. const CopyMock copyMock;
  70. sr::unique_resource movedFrom{copyMock, d};
  71. auto guard = std::move(movedFrom);
  72. static_cast<void>(guard);
  73. }
  74. TEST_CASE("move assignment calls deleter", "[UniqueResource]")
  75. {
  76. auto moveFrom = sr::unique_resource{Handle{3}, deleter};
  77. REQUIRE_CALL(m, deleter(4));
  78. {
  79. REQUIRE_CALL(m, deleter(3));
  80. auto guard = sr::unique_resource{Handle{4}, deleter};
  81. guard = std::move(moveFrom);
  82. }
  83. }
  84. TEST_CASE("deleter called on destruction", "[UniqueResource]")
  85. {
  86. REQUIRE_CALL(m, deleter(3));
  87. auto guard = sr::unique_resource{Handle{3}, deleter};
  88. static_cast<void>(guard);
  89. }
  90. TEST_CASE("reset calls deleter", "[UniqueResource]")
  91. {
  92. auto guard = sr::unique_resource{Handle{3}, deleter};
  93. {
  94. REQUIRE_CALL(m, deleter(3));
  95. guard.reset();
  96. }
  97. }
  98. TEST_CASE("reset does not call deleter if released", "[UniqueResource]")
  99. {
  100. REQUIRE_CALL(m, deleter(3)).TIMES(0);
  101. auto guard = sr::unique_resource{Handle{3}, deleter};
  102. guard.release();
  103. guard.reset();
  104. }
  105. TEST_CASE("reset sets new value and calls deleter on previous", "[UniqueResource]")
  106. {
  107. REQUIRE_CALL(m, deleter(3));
  108. REQUIRE_CALL(m, deleter(7));
  109. auto guard = sr::unique_resource{Handle{3}, deleter};
  110. guard.reset(Handle{7});
  111. }
  112. TEST_CASE("reset handles exception on assignment", "[UniqueResource]")
  113. {
  114. REQUIRE_CALL(m, deleter(3));
  115. REQUIRE_CALL(m, deleter(7));
  116. auto d = [](const auto& v) { deleter(v.m_handle); };
  117. auto guard = sr::unique_resource{ConditialThrowOnCopyMock{3, false}, d};
  118. guard.reset(ConditialThrowOnCopyMock{7, true});
  119. }
  120. TEST_CASE("release disables deleter", "[UniqueResource]")
  121. {
  122. REQUIRE_CALL(m, deleter(3)).TIMES(0);
  123. auto guard = sr::unique_resource{Handle{3}, deleter};
  124. guard.release();
  125. }
  126. TEST_CASE("get returns resource", "[UniqueResource]")
  127. {
  128. REQUIRE_CALL(m, deleter(3));
  129. auto guard = sr::unique_resource{Handle{3}, deleter};
  130. CHECK(guard.get() == 3);
  131. }
  132. TEST_CASE("pointer access returns resource" "[UniqueResource]")
  133. {
  134. const auto p = std::make_pair(3, 4);
  135. auto guard = sr::unique_resource{&p, [](auto*) { }};
  136. REQUIRE(guard->first == 3);
  137. REQUIRE(guard->second == 4);
  138. }
  139. TEST_CASE("pointer dereference returns resource" "[UniqueResource]")
  140. {
  141. Handle h{5};
  142. auto guard = sr::unique_resource{PtrHandle{&h}, [](auto*) { }};
  143. REQUIRE(*guard == 5);
  144. }
  145. TEST_CASE("deleter access", "[UniqueResource]")
  146. {
  147. auto guard = sr::unique_resource{Handle{3}, deleter};
  148. guard.release();
  149. {
  150. REQUIRE_CALL(m, deleter(8));
  151. guard.get_deleter()(8);
  152. }
  153. }
  154. TEST_CASE("swap", "[UniqueResource]")
  155. {
  156. REQUIRE_CALL(m, deleter(7));
  157. auto guard1 = sr::unique_resource(Handle{3}, deleter);
  158. {
  159. REQUIRE_CALL(m, deleter(3));
  160. auto guard2 = sr::unique_resource{Handle{7}, deleter};
  161. guard2.swap(guard1);
  162. REQUIRE(guard1.get() == 7);
  163. REQUIRE(guard2.get() == 3);
  164. }
  165. }
  166. TEST_CASE("make unique resource", "[UniqueResource]")
  167. {
  168. REQUIRE_CALL(m, deleter(7));
  169. auto guard = sr::unique_resource{Handle{7}, deleter};
  170. static_cast<void>(guard);
  171. }
  172. TEST_CASE("make unique resource with reference wrapper", "[UniqueResource]")
  173. {
  174. REQUIRE_CALL(m, deleter(3));
  175. Handle h{3};
  176. auto guard = sr::unique_resource{std::ref(h), deleter};
  177. static_cast<void>(guard);
  178. }
  179. TEST_CASE("make unique resource checked", "[UniqueResource]")
  180. {
  181. REQUIRE_CALL(m, deleter(4));
  182. auto guard = sr::make_unique_resource_checked(Handle{4}, Handle{-1}, deleter);
  183. static_cast<void>(guard);
  184. }
  185. TEST_CASE("make unique resource checked releases if invalid", "[UniqueResource]")
  186. {
  187. auto guard = sr::make_unique_resource_checked(Handle{-1}, Handle{-1}, deleter);
  188. static_cast<void>(guard);
  189. }