TestOptional.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Daniel Bertalan <dani@danielbertalan.dev>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibTest/TestCase.h>
  8. #include <AK/Optional.h>
  9. #include <AK/String.h>
  10. #include <AK/Vector.h>
  11. TEST_CASE(basic_optional)
  12. {
  13. Optional<int> x;
  14. EXPECT_EQ(x.has_value(), false);
  15. x = 3;
  16. EXPECT_EQ(x.has_value(), true);
  17. EXPECT_EQ(x.value(), 3);
  18. }
  19. TEST_CASE(move_optional)
  20. {
  21. Optional<int> x;
  22. EXPECT_EQ(x.has_value(), false);
  23. x = 3;
  24. EXPECT_EQ(x.has_value(), true);
  25. EXPECT_EQ(x.value(), 3);
  26. Optional<int> y;
  27. y = move(x);
  28. EXPECT_EQ(y.has_value(), true);
  29. EXPECT_EQ(y.value(), 3);
  30. EXPECT_EQ(x.has_value(), false);
  31. }
  32. TEST_CASE(optional_rvalue_ref_qualified_getters)
  33. {
  34. struct DontCopyMe {
  35. DontCopyMe() { }
  36. ~DontCopyMe() = default;
  37. DontCopyMe(DontCopyMe&&) = default;
  38. DontCopyMe& operator=(DontCopyMe&&) = default;
  39. DontCopyMe(DontCopyMe const&) = delete;
  40. DontCopyMe& operator=(DontCopyMe const&) = delete;
  41. int x { 13 };
  42. };
  43. auto make_an_optional = []() -> Optional<DontCopyMe> {
  44. return DontCopyMe {};
  45. };
  46. EXPECT_EQ(make_an_optional().value().x, 13);
  47. EXPECT_EQ(make_an_optional().value_or(DontCopyMe {}).x, 13);
  48. }
  49. TEST_CASE(optional_leak_1)
  50. {
  51. struct Structure {
  52. Optional<String> str;
  53. };
  54. // This used to leak, it does not anymore.
  55. Vector<Structure> vec;
  56. vec.append({ "foo" });
  57. EXPECT_EQ(vec[0].str.has_value(), true);
  58. EXPECT_EQ(vec[0].str.value(), "foo");
  59. }
  60. TEST_CASE(short_notation)
  61. {
  62. Optional<StringView> value = "foo";
  63. EXPECT_EQ(value->length(), 3u);
  64. EXPECT_EQ(*value, "foo");
  65. }
  66. TEST_CASE(comparison_without_values)
  67. {
  68. Optional<StringView> opt0;
  69. Optional<StringView> opt1;
  70. Optional<String> opt2;
  71. EXPECT_EQ(opt0, opt1);
  72. EXPECT_EQ(opt0, opt2);
  73. }
  74. TEST_CASE(comparison_with_values)
  75. {
  76. Optional<StringView> opt0;
  77. Optional<StringView> opt1 = "foo";
  78. Optional<String> opt2 = "foo";
  79. Optional<StringView> opt3 = "bar";
  80. EXPECT_NE(opt0, opt1);
  81. EXPECT_EQ(opt1, opt2);
  82. EXPECT_NE(opt1, opt3);
  83. }
  84. TEST_CASE(comparison_to_underlying_types)
  85. {
  86. Optional<String> opt0;
  87. EXPECT_NE(opt0, String());
  88. EXPECT_NE(opt0, "foo");
  89. Optional<StringView> opt1 = "foo";
  90. EXPECT_EQ(opt1, "foo");
  91. EXPECT_NE(opt1, "bar");
  92. EXPECT_EQ(opt1, String("foo"));
  93. }
  94. TEST_CASE(comparison_with_numeric_types)
  95. {
  96. Optional<u8> opt0;
  97. EXPECT_NE(opt0, 0);
  98. Optional<u8> opt1 = 7;
  99. EXPECT_EQ(opt1, 7);
  100. EXPECT_EQ(opt1, 7.0);
  101. EXPECT_EQ(opt1, 7u);
  102. EXPECT_NE(opt1, -2);
  103. }
  104. TEST_CASE(test_copy_ctor_and_dtor_called)
  105. {
  106. #ifdef AK_HAVE_CONDITIONALLY_TRIVIAL
  107. static_assert(IsTriviallyDestructible<Optional<u8>>);
  108. static_assert(IsTriviallyCopyable<Optional<u8>>);
  109. static_assert(IsTriviallyCopyConstructible<Optional<u8>>);
  110. static_assert(IsTriviallyCopyAssignable<Optional<u8>>);
  111. // These can't be trivial as we have to clear the original object.
  112. static_assert(!IsTriviallyMoveConstructible<Optional<u8>>);
  113. static_assert(!IsTriviallyMoveAssignable<Optional<u8>>);
  114. #endif
  115. struct DestructionChecker {
  116. explicit DestructionChecker(bool& was_destroyed)
  117. : m_was_destroyed(was_destroyed)
  118. {
  119. }
  120. ~DestructionChecker()
  121. {
  122. m_was_destroyed = true;
  123. }
  124. bool& m_was_destroyed;
  125. };
  126. static_assert(!IsTriviallyDestructible<Optional<DestructionChecker>>);
  127. bool was_destroyed = false;
  128. {
  129. Optional<DestructionChecker> test_optional = DestructionChecker { was_destroyed };
  130. }
  131. EXPECT(was_destroyed);
  132. struct CopyChecker {
  133. explicit CopyChecker(bool& was_copy_constructed)
  134. : m_was_copy_constructed(was_copy_constructed)
  135. {
  136. }
  137. CopyChecker(CopyChecker const& other)
  138. : m_was_copy_constructed(other.m_was_copy_constructed)
  139. {
  140. m_was_copy_constructed = true;
  141. }
  142. bool& m_was_copy_constructed;
  143. };
  144. static_assert(IsCopyConstructible<Optional<CopyChecker>>);
  145. static_assert(!IsTriviallyCopyConstructible<Optional<CopyChecker>>);
  146. bool was_copy_constructed = false;
  147. Optional<CopyChecker> copy1 = CopyChecker { was_copy_constructed };
  148. Optional<CopyChecker> copy2 = copy1;
  149. EXPECT(was_copy_constructed);
  150. struct MoveChecker {
  151. explicit MoveChecker(bool& was_move_constructed)
  152. : m_was_move_constructed(was_move_constructed)
  153. {
  154. }
  155. MoveChecker(MoveChecker const& other)
  156. : m_was_move_constructed(other.m_was_move_constructed)
  157. {
  158. EXPECT(false);
  159. };
  160. MoveChecker(MoveChecker&& other)
  161. : m_was_move_constructed(other.m_was_move_constructed)
  162. {
  163. m_was_move_constructed = true;
  164. };
  165. bool& m_was_move_constructed;
  166. };
  167. static_assert(IsMoveConstructible<Optional<MoveChecker>>);
  168. static_assert(!IsTriviallyMoveConstructible<Optional<MoveChecker>>);
  169. bool was_moved = false;
  170. Optional<MoveChecker> move1 = MoveChecker { was_moved };
  171. Optional<MoveChecker> move2 = move(move1);
  172. EXPECT(was_moved);
  173. #ifdef AK_HAVE_CONDITIONALLY_TRIVIAL
  174. struct NonDestructible {
  175. ~NonDestructible() = delete;
  176. };
  177. static_assert(!IsDestructible<Optional<NonDestructible>>);
  178. #endif
  179. }
  180. TEST_CASE(basic_optional_reference)
  181. {
  182. Optional<int&> x;
  183. EXPECT_EQ(x.has_value(), false);
  184. int a = 3;
  185. x = a;
  186. EXPECT_EQ(x.has_value(), true);
  187. EXPECT_EQ(x.value(), 3);
  188. EXPECT_EQ(&x.value(), &a);
  189. Optional<int const&> y;
  190. EXPECT_EQ(y.has_value(), false);
  191. int b = 3;
  192. y = b;
  193. EXPECT_EQ(y.has_value(), true);
  194. EXPECT_EQ(y.value(), 3);
  195. EXPECT_EQ(&y.value(), &b);
  196. static_assert(IsConst<RemoveReference<decltype(y.value())>>);
  197. }
  198. TEST_CASE(move_optional_reference)
  199. {
  200. Optional<int&> x;
  201. EXPECT_EQ(x.has_value(), false);
  202. int b = 3;
  203. x = b;
  204. EXPECT_EQ(x.has_value(), true);
  205. EXPECT_EQ(x.value(), 3);
  206. Optional<int&> y;
  207. y = move(x);
  208. EXPECT_EQ(y.has_value(), true);
  209. EXPECT_EQ(y.value(), 3);
  210. EXPECT_EQ(x.has_value(), false);
  211. }
  212. TEST_CASE(short_notation_reference)
  213. {
  214. StringView test = "foo";
  215. Optional<StringView&> value = test;
  216. EXPECT_EQ(value->length(), 3u);
  217. EXPECT_EQ(*value, "foo");
  218. }
  219. TEST_CASE(comparison_reference)
  220. {
  221. StringView test = "foo";
  222. Optional<StringView&> opt0;
  223. Optional<StringView const&> opt1 = test;
  224. Optional<String> opt2 = "foo";
  225. Optional<StringView> opt3 = "bar";
  226. EXPECT_NE(opt0, opt1);
  227. EXPECT_EQ(opt1, opt2);
  228. EXPECT_NE(opt1, opt3);
  229. }