ExpectedTests.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/std/string/fixed_string.h>
  9. #include <AzCore/std/utility/expected.h>
  10. #include <AzCore/UnitTest/TestTypes.h>
  11. namespace UnitTest
  12. {
  13. class ExpectedTest
  14. : public LeakDetectionFixture
  15. {
  16. };
  17. TEST_F(ExpectedTest, Constructors_CanConstructValueAndError)
  18. {
  19. {
  20. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  21. using VoidExpected = AZStd::expected<void, AZStd::fixed_string<32>>;
  22. TestExpected testExpected{};
  23. VoidExpected voidExpected{};
  24. EXPECT_TRUE(testExpected.has_value());
  25. EXPECT_TRUE(voidExpected.has_value());
  26. }
  27. {
  28. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  29. using VoidExpected = AZStd::expected<void, AZStd::fixed_string<32>>;
  30. TestExpected testExpected{ AZStd::in_place, 1 };
  31. VoidExpected voidExpected{ AZStd::in_place };
  32. EXPECT_TRUE(testExpected.has_value());
  33. EXPECT_EQ(1, testExpected.value());
  34. EXPECT_TRUE(voidExpected.has_value());
  35. }
  36. {
  37. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  38. using VoidExpected = AZStd::expected<void, AZStd::fixed_string<32>>;
  39. TestExpected testExpected{ AZStd::unexpect };
  40. VoidExpected voidExpected{ AZStd::unexpect, "Error" };
  41. EXPECT_FALSE(testExpected.has_value());
  42. EXPECT_TRUE(testExpected.error().empty());
  43. EXPECT_FALSE(voidExpected.has_value());
  44. EXPECT_EQ("Error", voidExpected.error());
  45. }
  46. {
  47. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  48. using InputTestExpected = AZStd::expected<short, AZStd::fixed_string<32>>;
  49. using VoidExpected = AZStd::expected<void, AZStd::fixed_string<32>>;
  50. using InputVoidExpected = AZStd::expected<void, AZStd::fixed_string<32>>;
  51. {
  52. InputTestExpected inputTestExpected{ short(2) };
  53. TestExpected testExpected(inputTestExpected);
  54. EXPECT_TRUE(testExpected.has_value());
  55. EXPECT_EQ(2, testExpected.value());
  56. }
  57. {
  58. InputTestExpected inputTestExpected{ short(3) };
  59. TestExpected testExpected{ AZStd::move(inputTestExpected) };
  60. EXPECT_TRUE(testExpected.has_value());
  61. EXPECT_EQ(3, testExpected.value());
  62. }
  63. {
  64. InputTestExpected inputTestExpected{ AZStd::unexpect, "Error" };
  65. TestExpected testExpected{ inputTestExpected };
  66. EXPECT_FALSE(testExpected.has_value());
  67. EXPECT_EQ("Error", testExpected.error());
  68. EXPECT_EQ("Error", inputTestExpected.error());
  69. }
  70. {
  71. InputTestExpected inputTestExpected{ AZStd::unexpect, "Error" };
  72. TestExpected testExpected{ AZStd::move(inputTestExpected) };
  73. EXPECT_FALSE(testExpected.has_value());
  74. EXPECT_EQ("Error", testExpected.error());
  75. EXPECT_TRUE(inputTestExpected.error().empty());
  76. }
  77. {
  78. InputVoidExpected inputVoidExpected{ AZStd::unexpect, "Error" };
  79. VoidExpected voidExpected{ inputVoidExpected };
  80. EXPECT_FALSE(voidExpected.has_value());
  81. EXPECT_EQ("Error", voidExpected.error());
  82. EXPECT_EQ("Error", inputVoidExpected.error());
  83. }
  84. {
  85. InputVoidExpected inputVoidExpected{ AZStd::unexpect, "Error" };
  86. VoidExpected voidExpected{ AZStd::move(inputVoidExpected) };
  87. EXPECT_FALSE(voidExpected.has_value());
  88. EXPECT_EQ("Error", voidExpected.error());
  89. EXPECT_TRUE(inputVoidExpected.error().empty());
  90. }
  91. }
  92. {
  93. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  94. AZStd::unexpected<AZStd::fixed_string<32>> errorValue{ "Error" };
  95. TestExpected testExpected{ errorValue };
  96. EXPECT_FALSE(testExpected.has_value());
  97. EXPECT_EQ("Error", testExpected.error());
  98. EXPECT_EQ("Error", errorValue.error());
  99. }
  100. {
  101. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  102. AZStd::unexpected<AZStd::fixed_string<32>> errorValue{ "Error" };
  103. TestExpected testExpected{ AZStd::move(errorValue) };
  104. EXPECT_FALSE(testExpected.has_value());
  105. EXPECT_EQ("Error", testExpected.error());
  106. EXPECT_TRUE(errorValue.error().empty());
  107. }
  108. }
  109. TEST_F(ExpectedTest, Constructors_ExplicitConstructorsTest)
  110. {
  111. // This validates the explicit constructors of AZStd::expected
  112. // The AZStd::fixed_string<N> template has an explicit constructor which accepts
  113. // a string_view like type, so an AZStd::string_view is used
  114. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  115. using ExplicitExpected = AZStd::expected<AZStd::string_view, AZStd::string_view>;
  116. using ExplicitUnexpected = AZStd::unexpected<AZStd::string_view>;
  117. ExplicitExpected explicitExpectedValue{ "Hello World" };
  118. ExplicitExpected explicitExpectedError{ AZStd::unexpect, "Error" };
  119. ExplicitUnexpected explicitUnexpected{ "Error2" };
  120. AZStd::string_view testValue{ "Goodbye World" };
  121. {
  122. TestExpected testExpected{ explicitExpectedValue };
  123. EXPECT_TRUE(testExpected.has_value());
  124. EXPECT_EQ("Hello World", testExpected.value());
  125. EXPECT_EQ("Hello World", explicitExpectedValue.value());
  126. }
  127. {
  128. TestExpected testExpected{ AZStd::move(explicitExpectedValue) };
  129. EXPECT_TRUE(testExpected.has_value());
  130. EXPECT_EQ("Hello World", testExpected.value());
  131. }
  132. {
  133. TestExpected testExpected{ explicitExpectedError };
  134. EXPECT_FALSE(testExpected.has_value());
  135. EXPECT_EQ("Error", testExpected.error());
  136. EXPECT_EQ("Error", explicitExpectedError.error());
  137. }
  138. {
  139. TestExpected testExpected{ AZStd::move(explicitExpectedError) };
  140. EXPECT_FALSE(testExpected.has_value());
  141. EXPECT_EQ("Error", testExpected.error());
  142. }
  143. {
  144. TestExpected testExpected{ explicitUnexpected };
  145. EXPECT_FALSE(testExpected.has_value());
  146. EXPECT_EQ("Error2", testExpected.error());
  147. EXPECT_EQ("Error2", explicitUnexpected.error());
  148. }
  149. {
  150. TestExpected testExpected{ AZStd::move(explicitUnexpected) };
  151. EXPECT_FALSE(testExpected.has_value());
  152. EXPECT_EQ("Error2", testExpected.error());
  153. }
  154. {
  155. TestExpected testExpected{ testValue };
  156. EXPECT_TRUE(testExpected.has_value());
  157. EXPECT_EQ("Goodbye World", testExpected.value());
  158. EXPECT_EQ("Goodbye World", testValue);
  159. }
  160. }
  161. TEST_F(ExpectedTest, Assignment_CanAssignValueAndError)
  162. {
  163. {
  164. // copy and move assignment of value
  165. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  166. TestExpected testExpected{ 1 };
  167. TestExpected resultExpected;
  168. resultExpected = testExpected;
  169. EXPECT_TRUE(resultExpected.has_value());
  170. EXPECT_EQ(1, resultExpected.value());
  171. resultExpected = AZStd::move(testExpected);
  172. EXPECT_TRUE(resultExpected.has_value());
  173. EXPECT_EQ(1, resultExpected.value());
  174. }
  175. {
  176. // copy and move assignment of error
  177. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  178. TestExpected testExpected{ AZStd::unexpect, "Error"};
  179. TestExpected resultExpected;
  180. resultExpected = testExpected;
  181. EXPECT_FALSE(resultExpected.has_value());
  182. EXPECT_EQ("Error", resultExpected.error());
  183. EXPECT_EQ("Error", testExpected.error());
  184. resultExpected = AZStd::move(testExpected);
  185. EXPECT_FALSE(resultExpected.has_value());
  186. EXPECT_EQ("Error", resultExpected.error());
  187. EXPECT_TRUE(testExpected.error().empty());
  188. }
  189. {
  190. // direct initialize assignment of value
  191. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  192. TestExpected resultExpected;
  193. resultExpected = 4;
  194. EXPECT_TRUE(resultExpected.has_value());
  195. EXPECT_EQ(4, resultExpected.value());
  196. }
  197. {
  198. // direct initialize assignment of error
  199. using TestExpected = AZStd::expected<int, AZStd::fixed_string<32>>;
  200. AZStd::unexpected<AZStd::fixed_string<32>> errorValue{ "Error" };
  201. TestExpected resultExpected;
  202. resultExpected = errorValue;
  203. EXPECT_FALSE(resultExpected.has_value());
  204. EXPECT_EQ("Error", resultExpected.error());
  205. EXPECT_EQ("Error", errorValue.error());
  206. resultExpected = AZStd::move(errorValue);
  207. EXPECT_FALSE(resultExpected.has_value());
  208. EXPECT_EQ("Error", resultExpected.error());
  209. EXPECT_TRUE(errorValue.error().empty());
  210. }
  211. }
  212. TEST_F(ExpectedTest, Emplace_CanAssignValue)
  213. {
  214. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  215. TestExpected testExpected;
  216. testExpected.emplace("Hello World");
  217. EXPECT_TRUE(testExpected.has_value());
  218. EXPECT_EQ("Hello World", testExpected.value());
  219. testExpected.emplace({ 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' });
  220. EXPECT_TRUE(testExpected.has_value());
  221. EXPECT_EQ("Hello World", testExpected.value());
  222. }
  223. TEST_F(ExpectedTest, OperatorArrow_CanAccessValue_Succeeds)
  224. {
  225. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  226. TestExpected testExpected;
  227. testExpected->assign("Hello World");
  228. EXPECT_EQ("Hello World", testExpected.value());
  229. }
  230. TEST_F(ExpectedTest, OperatorAsterisk_CanAccessValue_Succeeds)
  231. {
  232. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  233. TestExpected testExpected;
  234. *testExpected = "Hello World";
  235. EXPECT_EQ("Hello World", testExpected.value());
  236. }
  237. TEST_F(ExpectedTest, Value_CanModifyValue_Succeeds)
  238. {
  239. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  240. TestExpected testExpected;
  241. testExpected.value() = "Hello World";
  242. EXPECT_EQ("Hello World", testExpected.value());
  243. }
  244. TEST_F(ExpectedTest, Error_CanModifyError_Succeeds)
  245. {
  246. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  247. TestExpected testExpected{ AZStd::unexpect };
  248. testExpected.error() = "Error";
  249. EXPECT_EQ("Error", testExpected.error());
  250. }
  251. TEST_F(ExpectedTest, ValueOr_CanReturnValue_IfHasValue_Or_Default)
  252. {
  253. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  254. TestExpected testExpected{ AZStd::unexpect, "Error"};
  255. EXPECT_FALSE(testExpected);
  256. EXPECT_EQ("Hello World", testExpected.value_or("Hello World"));
  257. testExpected.emplace("Value");
  258. EXPECT_TRUE(testExpected);
  259. EXPECT_EQ("Value", testExpected.value_or("Hello World"));
  260. }
  261. TEST_F(ExpectedTest, ComparisonOperator_CanCompareExpected_Value_And_Unexpected)
  262. {
  263. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  264. using TestUnexpected = AZStd::unexpected<AZStd::fixed_string<32>>;
  265. TestExpected testExpectedValue{ "Hello World" };
  266. TestExpected testExpectedError{ AZStd::unexpect, "Error" };
  267. TestUnexpected testUnexpected{ "Error2" };
  268. AZStd::string_view testValue{ "Goodbye World" };
  269. // compare expected instance to another expected instanct
  270. EXPECT_EQ(testExpectedValue, testExpectedValue);
  271. EXPECT_NE(testExpectedValue, testExpectedError);
  272. // compare expected instance to value
  273. EXPECT_EQ(testExpectedValue, "Hello World");
  274. EXPECT_NE(testExpectedValue, testValue);
  275. // compare expected instance to error
  276. EXPECT_EQ(testExpectedError, TestUnexpected("Error"));
  277. EXPECT_NE(testExpectedValue, testUnexpected);
  278. }
  279. TEST_F(ExpectedTest, Swap_TwoExpecteds_Succeeds)
  280. {
  281. using TestExpected = AZStd::expected<AZStd::fixed_string<32>, AZStd::fixed_string<32>>;
  282. TestExpected testExpectedValue{ "Hello World" };
  283. TestExpected testExpectedError{ AZStd::unexpect, "Error" };
  284. AZStd::ranges::swap(testExpectedValue, testExpectedError);
  285. EXPECT_FALSE(testExpectedValue.has_value());
  286. EXPECT_EQ("Error", testExpectedValue.error());
  287. EXPECT_TRUE(testExpectedError.has_value());
  288. EXPECT_EQ("Hello World", testExpectedError.value());
  289. }
  290. }