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.

139 lines
3.5KB

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