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.

131 lines
3.2KB

  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 <catch.hpp>
  22. #include <trompeloeil.hpp>
  23. #include <type_traits>
  24. using namespace trompeloeil;
  25. namespace
  26. {
  27. using Handle = int;
  28. using PtrHandle = std::add_pointer_t<Handle>;
  29. struct CallMock
  30. {
  31. MAKE_MOCK1(deleter, void(Handle));
  32. };
  33. CallMock m;
  34. void deleter(Handle h)
  35. {
  36. m.deleter(h);
  37. }
  38. struct ThrowOnCopyMock
  39. {
  40. ThrowOnCopyMock() { }
  41. ThrowOnCopyMock(const ThrowOnCopyMock&)
  42. {
  43. throw std::exception{};
  44. }
  45. MAKE_CONST_MOCK1(deleter, void(ThrowOnCopyMock));
  46. ThrowOnCopyMock& operator=(const ThrowOnCopyMock&)
  47. {
  48. throw std::exception{};
  49. }
  50. };
  51. struct NotNothrowMoveMock
  52. {
  53. NotNothrowMoveMock(CallMock* mo) : m_mock(mo) { }
  54. NotNothrowMoveMock(const NotNothrowMoveMock& other) : m_mock(other.m_mock) { }
  55. NotNothrowMoveMock(NotNothrowMoveMock&& other) noexcept(false) : m_mock(other.m_mock) { }
  56. void operator()(Handle h) const
  57. {
  58. m_mock->deleter(h);
  59. }
  60. NotNothrowMoveMock& operator=(const NotNothrowMoveMock&)
  61. {
  62. throw "Not implemented";
  63. }
  64. NotNothrowMoveMock& operator=(NotNothrowMoveMock&&)
  65. {
  66. throw "Not implemented";
  67. }
  68. CallMock* m_mock;
  69. };
  70. }
  71. TEST_CASE("construction with move", "[UniqueResource]")
  72. {
  73. auto guard = sr::make_unique_resource(Handle{3}, deleter);
  74. static_cast<void>(guard);
  75. }
  76. TEST_CASE("construction with copy calls deleter and rethrows on failed copy", "[UniqueResource]")
  77. {
  78. REQUIRE_THROWS([] {
  79. const ThrowOnCopyMock noMove;
  80. const auto d = [](const auto&) { m.deleter(3); };
  81. REQUIRE_CALL(m, deleter(3));
  82. sr::unique_resource<decltype(noMove), decltype(d)> guard{noMove, d};
  83. static_cast<void>(guard);
  84. }());
  85. }
  86. TEST_CASE("move-construction with move", "[UniqueResource]")
  87. {
  88. auto movedFrom = sr::make_unique_resource(Handle{3}, deleter);
  89. auto guard = std::move(movedFrom);
  90. static_cast<void>(guard);
  91. // TODO: Check value of guard
  92. }
  93. TEST_CASE("move-construction with copy", "[UniqueResource]")
  94. {
  95. CallMock mock;
  96. const NotNothrowMoveMock notNothrow{&mock};
  97. Handle h{3};
  98. sr::unique_resource<Handle, decltype(notNothrow)> movedFrom{h, notNothrow};
  99. auto guard = std::move(movedFrom);
  100. static_cast<void>(guard);
  101. // TODO: Check value of guard
  102. }
  103. // TODO: Implement move assignment