/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "Common.h" #include "gtest/gtest.h" #include "mozilla/dom/QMResult.h" #include "mozilla/dom/quota/ResultExtensions.h" using namespace mozilla; using namespace mozilla::dom::quota; namespace { class TestClass { public: static constexpr int kTestValue = 42; nsresult NonOverloadedNoInputComplex(std::pair* aOut) { *aOut = std::pair{kTestValue, kTestValue}; return NS_OK; } nsresult NonOverloadedNoInputFailsComplex(std::pair* aOut) { return NS_ERROR_FAILURE; } }; } // namespace class DOM_Quota_ResultExtensions_ToResult : public DOM_Quota_Test {}; class DOM_Quota_ResultExtensions_GenericErrorResult : public DOM_Quota_Test {}; TEST_F(DOM_Quota_ResultExtensions_ToResult, FromBool) { // success { auto res = ToResult(true); static_assert(std::is_same_v>); EXPECT_TRUE(res.isOk()); } // failure { auto res = ToResult(false); static_assert(std::is_same_v>); EXPECT_TRUE(res.isErr()); EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); } } TEST_F(DOM_Quota_ResultExtensions_ToResult, FromQMResult_Failure) { // copy { const auto res = ToQMResult(NS_ERROR_FAILURE); auto okOrErr = ToResult(res); static_assert(std::is_same_v); ASSERT_TRUE(okOrErr.isErr()); auto err = okOrErr.unwrapErr(); #ifdef QM_ERROR_STACKS_ENABLED IncreaseExpectedStackId(); ASSERT_EQ(err.StackId(), ExpectedStackId()); ASSERT_EQ(err.FrameId(), 1u); ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE); #else ASSERT_EQ(err, NS_ERROR_FAILURE); #endif } // move { auto res = ToQMResult(NS_ERROR_FAILURE); auto okOrErr = ToResult(std::move(res)); static_assert(std::is_same_v); ASSERT_TRUE(okOrErr.isErr()); auto err = okOrErr.unwrapErr(); #ifdef QM_ERROR_STACKS_ENABLED IncreaseExpectedStackId(); ASSERT_EQ(err.StackId(), ExpectedStackId()); ASSERT_EQ(err.FrameId(), 1u); ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE); #else ASSERT_EQ(err, NS_ERROR_FAILURE); #endif } } TEST_F(DOM_Quota_ResultExtensions_ToResult, FromNSResult_Failure_Macro) { auto okOrErr = QM_TO_RESULT(NS_ERROR_FAILURE); static_assert(std::is_same_v); ASSERT_TRUE(okOrErr.isErr()); auto err = okOrErr.unwrapErr(); #ifdef QM_ERROR_STACKS_ENABLED IncreaseExpectedStackId(); ASSERT_EQ(err.StackId(), ExpectedStackId()); ASSERT_EQ(err.FrameId(), 1u); ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE); #else ASSERT_EQ(err, NS_ERROR_FAILURE); #endif } TEST_F(DOM_Quota_ResultExtensions_GenericErrorResult, ErrorPropagation) { OkOrErr okOrErr1 = ToResult(ToQMResult(NS_ERROR_FAILURE)); const auto& err1 = okOrErr1.inspectErr(); #ifdef QM_ERROR_STACKS_ENABLED IncreaseExpectedStackId(); ASSERT_EQ(err1.StackId(), ExpectedStackId()); ASSERT_EQ(err1.FrameId(), 1u); ASSERT_EQ(err1.NSResult(), NS_ERROR_FAILURE); #else ASSERT_EQ(err1, NS_ERROR_FAILURE); #endif OkOrErr okOrErr2 = okOrErr1.propagateErr(); const auto& err2 = okOrErr2.inspectErr(); #ifdef QM_ERROR_STACKS_ENABLED ASSERT_EQ(err2.StackId(), ExpectedStackId()); ASSERT_EQ(err2.FrameId(), 2u); ASSERT_EQ(err2.NSResult(), NS_ERROR_FAILURE); #else ASSERT_EQ(err2, NS_ERROR_FAILURE); #endif OkOrErr okOrErr3 = okOrErr2.propagateErr(); const auto& err3 = okOrErr3.inspectErr(); #ifdef QM_ERROR_STACKS_ENABLED ASSERT_EQ(err3.StackId(), ExpectedStackId()); ASSERT_EQ(err3.FrameId(), 3u); ASSERT_EQ(err3.NSResult(), NS_ERROR_FAILURE); #else ASSERT_EQ(err3, NS_ERROR_FAILURE); #endif } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput) { auto res = ToResultGet([](nsresult* aRv) -> int32_t { *aRv = NS_OK; return 42; }); static_assert(std::is_same_v>); EXPECT_TRUE(res.isOk()); EXPECT_EQ(res.unwrap(), 42); } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Err) { auto res = ToResultGet([](nsresult* aRv) -> int32_t { *aRv = NS_ERROR_FAILURE; return -1; }); static_assert(std::is_same_v>); EXPECT_TRUE(res.isErr()); EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput) { auto res = ToResultGet( [](int32_t aValue, nsresult* aRv) -> int32_t { *aRv = NS_OK; return aValue * 2; }, 42); static_assert(std::is_same_v>); EXPECT_TRUE(res.isOk()); EXPECT_EQ(res.unwrap(), 84); } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput_Err) { auto res = ToResultGet( [](int32_t aValue, nsresult* aRv) -> int32_t { *aRv = NS_ERROR_FAILURE; return -1; }, 42); static_assert(std::is_same_v>); EXPECT_TRUE(res.isErr()); EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Macro_Typed) { auto res = MOZ_TO_RESULT_GET_TYPED(int32_t, [](nsresult* aRv) -> int32_t { *aRv = NS_OK; return 42; }); static_assert(std::is_same_v>); EXPECT_TRUE(res.isOk()); EXPECT_EQ(res.unwrap(), 42); } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Macro_Typed_Parens) { auto res = MOZ_TO_RESULT_GET_TYPED((std::pair), [](nsresult* aRv) -> std::pair { *aRv = NS_OK; return std::pair{42, 42}; }); static_assert(std::is_same_v, nsresult>>); EXPECT_TRUE(res.isOk()); EXPECT_EQ(res.unwrap(), (std::pair{42, 42})); } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Err_Macro_Typed) { auto res = MOZ_TO_RESULT_GET_TYPED(int32_t, [](nsresult* aRv) -> int32_t { *aRv = NS_ERROR_FAILURE; return -1; }); static_assert(std::is_same_v>); EXPECT_TRUE(res.isErr()); EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput_Macro_Typed) { auto res = MOZ_TO_RESULT_GET_TYPED( int32_t, [](int32_t aValue, nsresult* aRv) -> int32_t { *aRv = NS_OK; return aValue * 2; }, 42); static_assert(std::is_same_v>); EXPECT_TRUE(res.isOk()); EXPECT_EQ(res.unwrap(), 84); } TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput_Err_Macro_Typed) { auto res = MOZ_TO_RESULT_GET_TYPED( int32_t, [](int32_t aValue, nsresult* aRv) -> int32_t { *aRv = NS_ERROR_FAILURE; return -1; }, 42); static_assert(std::is_same_v>); EXPECT_TRUE(res.isErr()); EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); } TEST(DOM_Quota_ResultExtensions_ToResultInvoke, Lambda_NoInput_Complex) { TestClass foo; // success { auto valOrErr = ToResultInvoke>([&foo](std::pair* out) { return foo.NonOverloadedNoInputComplex(out); }); static_assert(std::is_same_v, nsresult>>); ASSERT_TRUE(valOrErr.isOk()); ASSERT_EQ((std::pair{TestClass::kTestValue, TestClass::kTestValue}), valOrErr.unwrap()); } // failure { auto valOrErr = ToResultInvoke>([&foo](std::pair* out) { return foo.NonOverloadedNoInputFailsComplex(out); }); static_assert(std::is_same_v, nsresult>>); ASSERT_TRUE(valOrErr.isErr()); ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); } } TEST(DOM_Quota_ResultExtensions_ToResultInvoke, Lambda_NoInput_Complex_Macro_Typed) { TestClass foo; // success { auto valOrErr = MOZ_TO_RESULT_INVOKE_TYPED( (std::pair), [&foo](std::pair* out) { return foo.NonOverloadedNoInputComplex(out); }); static_assert(std::is_same_v, nsresult>>); ASSERT_TRUE(valOrErr.isOk()); ASSERT_EQ((std::pair{TestClass::kTestValue, TestClass::kTestValue}), valOrErr.unwrap()); } // failure { auto valOrErr = MOZ_TO_RESULT_INVOKE_TYPED( (std::pair), [&foo](std::pair* out) { return foo.NonOverloadedNoInputFailsComplex(out); }); static_assert(std::is_same_v, nsresult>>); ASSERT_TRUE(valOrErr.isErr()); ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); } }