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.

214 lines
5.3KB

  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 <functional>
  22. #include <catch.hpp>
  23. using Handle = int;
  24. TEST_CASE("deleter called on destruction", "[UniqueResource]")
  25. {
  26. std::size_t calls{0};
  27. {
  28. auto guard = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
  29. static_cast<void>(guard);
  30. }
  31. REQUIRE(calls == 1);
  32. }
  33. TEST_CASE("deleter is not called if released", "[UniqueResource]")
  34. {
  35. std::size_t calls{0};
  36. {
  37. auto guard = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
  38. guard.release();
  39. }
  40. REQUIRE(calls == 0);
  41. }
  42. TEST_CASE("release returns reference to resource", "[UniqueResource]")
  43. {
  44. auto guard = sr::unique_resource(Handle{3}, [](auto) { });
  45. const auto result = guard.release();
  46. REQUIRE(3 == result);
  47. }
  48. TEST_CASE("move releases moved-from object", "[UniqueResource]")
  49. {
  50. std::size_t calls{0};
  51. {
  52. auto movedFrom = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
  53. auto guard = std::move(movedFrom);
  54. static_cast<void>(guard);
  55. }
  56. REQUIRE(calls == 1);
  57. }
  58. TEST_CASE("move transfers state", "[UniqueResource]")
  59. {
  60. std::size_t calls{0};
  61. {
  62. auto movedFrom = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
  63. auto guard = std::move(movedFrom);
  64. static_cast<void>(guard);
  65. }
  66. REQUIRE(calls == 1);
  67. }
  68. TEST_CASE("move transfers state if released", "[UniqueResource]")
  69. {
  70. std::size_t calls{0};
  71. {
  72. auto movedFrom = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
  73. movedFrom.release();
  74. auto guard = std::move(movedFrom);
  75. static_cast<void>(guard);
  76. }
  77. REQUIRE(calls == 0);
  78. }
  79. TEST_CASE("move assignment releases moved-from object", "[UniqueResource]")
  80. {
  81. std::size_t calls{0};
  82. std::function<void(Handle)> del = [&calls](auto) { ++calls; };
  83. {
  84. auto movedFrom = sr::unique_resource(Handle{3}, del);
  85. auto guard = sr::unique_resource(Handle{3}, del);
  86. guard = std::move(movedFrom);
  87. static_cast<void>(guard);
  88. }
  89. REQUIRE(calls == 2);
  90. }
  91. TEST_CASE("move assignment transfers state", "[UniqueResource]")
  92. {
  93. std::size_t calls{0};
  94. std::function<void(Handle)> del = [&calls](auto) { ++calls; };
  95. {
  96. auto movedFrom = sr::unique_resource(Handle{3}, del);
  97. auto guard = sr::unique_resource(Handle{3}, del);
  98. guard = std::move(movedFrom);
  99. static_cast<void>(guard);
  100. }
  101. REQUIRE(calls == 2);
  102. }
  103. TEST_CASE("move assignment transfers state if released", "[UniqueResource]")
  104. {
  105. std::size_t calls{0};
  106. std::function<void(Handle)> del = [&calls](auto) { ++calls; };
  107. {
  108. auto movedFrom = sr::unique_resource(Handle{3}, del);
  109. movedFrom.release();
  110. auto guard = sr::unique_resource(Handle{3}, del);
  111. guard = std::move(movedFrom);
  112. static_cast<void>(guard);
  113. }
  114. REQUIRE(calls == 1);
  115. }
  116. TEST_CASE("no exception propagation from deleter", "[UniqueResource]")
  117. {
  118. REQUIRE_NOTHROW([] {
  119. auto guard = sr::unique_resource(Handle{3}, [](auto) { throw "Don't propagate this!"; });
  120. static_cast<void>(guard);
  121. }());
  122. }
  123. TEST_CASE("invoke executes deleter on resource", "[UniqueResource]")
  124. {
  125. std::size_t calls{0};
  126. {
  127. auto guard = sr::unique_resource(Handle{3}, [&calls](auto h)
  128. {
  129. REQUIRE(h == 3);
  130. ++calls;
  131. });
  132. guard.invoke();
  133. }
  134. REQUIRE(calls == 1);
  135. }
  136. TEST_CASE("invoke executes only multiple times if again strategy", "[UniqueResource]")
  137. {
  138. std::size_t calls{0};
  139. {
  140. auto guard = sr::unique_resource(Handle{3}, [&calls](auto h) { if( h == 3 ) { ++calls;} });
  141. guard.invoke(sr::invoke_it::again);
  142. guard.invoke(sr::invoke_it::again);
  143. }
  144. REQUIRE(calls == 3);
  145. }
  146. TEST_CASE("invoke does nothing if released", "[UniqueResource]")
  147. {
  148. std::size_t calls{0};
  149. {
  150. auto guard = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
  151. guard.release();
  152. guard.invoke(sr::invoke_it::once);
  153. }
  154. REQUIRE(calls == 0);
  155. }
  156. TEST_CASE("invoke executes after release if again strategy", "[UniqueResource]")
  157. {
  158. std::size_t calls{0};
  159. {
  160. auto guard = sr::unique_resource(Handle{3}, [&calls](auto) { ++calls; });
  161. guard.release();
  162. guard.invoke(sr::invoke_it::again);
  163. }
  164. REQUIRE(calls == 1);
  165. }
  166. TEST_CASE("invoke does not propagate exception", "[UniqueResource]")
  167. {
  168. auto guard = sr::unique_resource(Handle{3}, [](auto) { throw "Don't propagate this!"; });
  169. REQUIRE_NOTHROW(guard.invoke());
  170. }