diff --git a/iceoryx_hoofs/test/moduletests/test_vocabulary_expected.cpp b/iceoryx_hoofs/test/moduletests/test_vocabulary_expected.cpp index d8f1d4085ac..79d5dfb8f78 100644 --- a/iceoryx_hoofs/test/moduletests/test_vocabulary_expected.cpp +++ b/iceoryx_hoofs/test/moduletests/test_vocabulary_expected.cpp @@ -144,7 +144,7 @@ TEST_F(expected_test, CreateWithPODTypeIsSuccessful) ::testing::Test::RecordProperty("TEST_ID", "5b91db8c-5d2e-44a4-8cac-4ee436b5fe8e"); constexpr int VALUE = 123; auto sut = expected(in_place, VALUE); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut.value(), Eq(VALUE)); } @@ -152,7 +152,7 @@ TEST_F(expected_test, CreateWithVoidTypeIsSuccessful) { ::testing::Test::RecordProperty("TEST_ID", "5baee3cb-4f81-4245-b9f9-d733d14d6d4a"); auto sut = expected(in_place); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); } TEST_F(expected_test, CreateWithErrorResultsInError) @@ -194,7 +194,7 @@ TEST_F(expected_test, CreateFromConstSuccessResultsInCorrectValue) constexpr int VALUE = 424242; auto constSuccess = success(VALUE); auto sut = expected(constSuccess); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut.value(), Eq(VALUE)); } @@ -204,7 +204,7 @@ TEST_F(expected_test, CreateWithComplexTypeIsSuccessful) constexpr int VALUE_A = 12; constexpr int VALUE_B = 222; auto sut = expected(in_place, VALUE_A, VALUE_B); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut.value().m_a, Eq(VALUE_A)); EXPECT_THAT(sut.value().m_b, Eq(VALUE_B)); } @@ -259,10 +259,10 @@ TEST_F(expected_test, CreateWithValueAndMoveCtorLeadsToMovedSource) // NOLINTJUSTIFICATION we explicitly want to test the defined state of a moved expected // NOLINTBEGIN(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) - ASSERT_FALSE(sutSource.has_error()); + ASSERT_TRUE(sutSource.has_value()); EXPECT_TRUE(sutSource.value().m_moved); // NOLINTEND(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) - ASSERT_FALSE(sutDestination.has_error()); + ASSERT_TRUE(sutDestination.has_value()); EXPECT_FALSE(sutDestination.value().m_moved); EXPECT_EQ(sutDestination.value().m_a, A); EXPECT_EQ(sutDestination.value().m_b, B); @@ -297,10 +297,10 @@ TEST_F(expected_test, CreateWithValueAndMoveAssignmentLeadsToMovedSource) // NOLINTJUSTIFICATION we explicitly want to test the defined state of a moved expected // NOLINTBEGIN(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) - ASSERT_FALSE(sutSource.has_error()); + ASSERT_TRUE(sutSource.has_value()); EXPECT_TRUE(sutSource.value().m_moved); // NOLINTEND(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) - ASSERT_FALSE(sutDestination.has_error()); + ASSERT_TRUE(sutDestination.has_value()); EXPECT_FALSE(sutDestination.value().m_moved); EXPECT_EQ(sutDestination.value().m_a, A); EXPECT_EQ(sutDestination.value().m_b, B); @@ -329,7 +329,7 @@ TEST_F(expected_test, CreateWithOkFreeFunctionWithVoidValueTypeIsSuccessful) { ::testing::Test::RecordProperty("TEST_ID", "6d582b25-1c7d-4519-837c-55d151b324ff"); expected sut = ok(); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); } TEST_F(expected_test, CreateWithOkFreeFunctionByCopyIsSuccessful) @@ -337,7 +337,7 @@ TEST_F(expected_test, CreateWithOkFreeFunctionByCopyIsSuccessful) ::testing::Test::RecordProperty("TEST_ID", "d3c24c27-432d-4a4b-8d55-6e723bc88c46"); constexpr int VALUE = 111; expected sut = ok(VALUE); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut.value(), Eq(VALUE)); } @@ -348,7 +348,7 @@ TEST_F(expected_test, CreateWithOkFreeFunctionByMoveIsSuccessful) constexpr int B{55}; NonTrivialTestClass value{A, B}; expected sut = ok(std::move(value)); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut.value().m_a, Eq(A)); EXPECT_THAT(sut.value().m_b, Eq(B)); } @@ -359,7 +359,7 @@ TEST_F(expected_test, CreateWithOkFreeFunctionByForwardingIsSuccessful) constexpr int A{44}; constexpr int B{55}; expected sut = ok(A, B); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut.value().m_a, Eq(A)); EXPECT_THAT(sut.value().m_b, Eq(B)); } @@ -434,6 +434,22 @@ TEST_F(expected_test, ErrorTypeOnlyBoolOperatorReturnsNoError) ASSERT_THAT(sut.operator bool(), Eq(true)); } +TEST_F(expected_test, HasValueIsTrueWhenHasErrorIsFalse) +{ + ::testing::Test::RecordProperty("TEST_ID", "cf339ae0-bc54-4584-bef1-9471eb2d5370"); + expected sut = ok(); + ASSERT_TRUE(sut.has_value()); + ASSERT_FALSE(sut.has_error()); +} + +TEST_F(expected_test, HasValueIsFalseWhenHasErrorIsTrue) +{ + ::testing::Test::RecordProperty("TEST_ID", "28f6a33a-5264-4507-a6e3-879a297dc1e5"); + expected sut = err(TestError::ERROR1); + ASSERT_FALSE(sut.has_value()); + ASSERT_TRUE(sut.has_error()); +} + TEST_F(expected_test, ArrowOperatorWorks) { ::testing::Test::RecordProperty("TEST_ID", "39898e81-d4ad-4f27-8c45-d29c80114be2"); @@ -450,7 +466,7 @@ TEST_F(expected_test, ConstArrowOperatorWorks) constexpr int VALUE_A = 554; constexpr int VALUE_B = 811; const expected sut(success(TestClass(VALUE_A, VALUE_B))); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut->constGimme(), Eq(VALUE_A + VALUE_B)); } @@ -459,7 +475,7 @@ TEST_F(expected_test, DereferencingOperatorWorks) ::testing::Test::RecordProperty("TEST_ID", "11ddbd46-3a2f-43cd-a2d2-ebe2ad4019db"); constexpr int VALUE = 1652; expected sut = ok(VALUE); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(*sut, Eq(VALUE)); } @@ -467,7 +483,7 @@ TEST_F(expected_test, ConstDereferencingOperatorWorks) { ::testing::Test::RecordProperty("TEST_ID", "f09b9476-a4f6-4f56-9692-3c00146410fd"); const expected sut(success(981)); - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(*sut, Eq(981)); } @@ -475,7 +491,7 @@ TEST_F(expected_test, CreateFromInPlaceTypeLeadsToValidVoidValueTypeSut) { ::testing::Test::RecordProperty("TEST_ID", "91a8ad7f-4843-4bd9-a56b-0561ae6b56cb"); expected sut{in_place}; - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); } TEST_F(expected_test, CreateFromInPlaceTypeLeadsToValidSut) @@ -483,7 +499,7 @@ TEST_F(expected_test, CreateFromInPlaceTypeLeadsToValidSut) ::testing::Test::RecordProperty("TEST_ID", "3a527c62-aaea-44ae-9b99-027c19d032b5"); constexpr int VALUE = 42; expected sut{in_place, VALUE}; - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut.value(), Eq(VALUE)); } @@ -508,7 +524,7 @@ TEST_F(expected_test, CreateFromSuccessTypeLeadsToValidSut) ::testing::Test::RecordProperty("TEST_ID", "fb83b62e-4e17-480b-8425-72181e6dd55d"); constexpr int VALUE = 55; expected sut{success(VALUE)}; - ASSERT_THAT(sut.has_error(), Eq(false)); + ASSERT_THAT(sut.has_value(), Eq(true)); EXPECT_THAT(sut.value(), Eq(VALUE)); } @@ -526,7 +542,7 @@ TEST_F(expected_test, ConvertNonEmptySuccessResultToVoidValueTypeResultIsSuccess constexpr int VALUE = 91823; expected sut{success(VALUE)}; expected sut2 = sut; - EXPECT_THAT(sut2.has_error(), Eq(false)); + EXPECT_THAT(sut2.has_value(), Eq(true)); } TEST_F(expected_test, ConvertConstNonEmptySuccessResultToVoidValueTypeResultIsSuccessful) @@ -534,7 +550,7 @@ TEST_F(expected_test, ConvertConstNonEmptySuccessResultToVoidValueTypeResultIsSu ::testing::Test::RecordProperty("TEST_ID", "6ccaf1cf-1b09-4930-ad33-8f961aca4c2e"); const expected sut{success(123)}; expected sut2 = sut; - EXPECT_THAT(sut2.has_error(), Eq(false)); + EXPECT_THAT(sut2.has_value(), Eq(true)); } TEST_F(expected_test, ConvertNonEmptyErrorResultVoidValueTypeResultIsSuccessful) @@ -573,7 +589,7 @@ TEST_F(expected_test, MoveAssignmentIsNotEnforcedInMoveConstructor) auto sut = expected(in_place); /// this should compile, if not then we enforce move assignment hidden in the implementation expected destination{std::move(sut)}; - ASSERT_THAT(destination.has_error(), Eq(false)); + ASSERT_THAT(destination.has_value(), Eq(true)); } /// same test with the void value type diff --git a/iceoryx_hoofs/vocabulary/include/iox/detail/expected.inl b/iceoryx_hoofs/vocabulary/include/iox/detail/expected.inl index 04fc385faee..8a99ae116bf 100644 --- a/iceoryx_hoofs/vocabulary/include/iox/detail/expected.inl +++ b/iceoryx_hoofs/vocabulary/include/iox/detail/expected.inl @@ -125,6 +125,12 @@ inline expected::operator bool() const noexcept return !has_error(); } +template +inline bool expected::has_value() const noexcept +{ + return m_store.has_value(); +} + template inline bool expected::has_error() const noexcept { diff --git a/iceoryx_hoofs/vocabulary/include/iox/expected.hpp b/iceoryx_hoofs/vocabulary/include/iox/expected.hpp index 03f4427e87b..d3cd60717ea 100644 --- a/iceoryx_hoofs/vocabulary/include/iox/expected.hpp +++ b/iceoryx_hoofs/vocabulary/include/iox/expected.hpp @@ -209,10 +209,14 @@ class IOX_NO_DISCARD expected final : public FunctionalInterface&& errorValue) noexcept; // AXIVION Next Construct AutosarC++19_03-A13.5.3: Implementation is inspired from std::expected - /// @brief returns true if the expected does not contain an error otherwise false + /// @brief returns true if the expected contains a value type and false if it is an error type /// @return bool which contains true if the expected contains an error explicit operator bool() const noexcept; + /// @brief returns true if the expected contains a value type and false if it is an error type + /// @return bool which contains true if the expected contains an error + bool has_value() const noexcept; + /// @brief returns true if the expected contains an error otherwise false /// @return bool which contains true if the expected contains an error bool has_error() const noexcept;