333 lines
9.2 KiB
C++
333 lines
9.2 KiB
C++
/* -*- 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<int, int>* aOut) {
|
|
*aOut = std::pair{kTestValue, kTestValue};
|
|
return NS_OK;
|
|
}
|
|
nsresult NonOverloadedNoInputFailsComplex(std::pair<int, int>* 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<decltype(res), Result<Ok, nsresult>>);
|
|
EXPECT_TRUE(res.isOk());
|
|
}
|
|
|
|
// failure
|
|
{
|
|
auto res = ToResult(false);
|
|
static_assert(std::is_same_v<decltype(res), Result<Ok, nsresult>>);
|
|
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<QMResult>(res);
|
|
static_assert(std::is_same_v<decltype(okOrErr), OkOrErr>);
|
|
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<QMResult>(std::move(res));
|
|
static_assert(std::is_same_v<decltype(okOrErr), OkOrErr>);
|
|
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<decltype(okOrErr), OkOrErr>);
|
|
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<QMResult>(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<int32_t>([](nsresult* aRv) -> int32_t {
|
|
*aRv = NS_OK;
|
|
return 42;
|
|
});
|
|
|
|
static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>);
|
|
|
|
EXPECT_TRUE(res.isOk());
|
|
EXPECT_EQ(res.unwrap(), 42);
|
|
}
|
|
|
|
TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Err)
|
|
{
|
|
auto res = ToResultGet<int32_t>([](nsresult* aRv) -> int32_t {
|
|
*aRv = NS_ERROR_FAILURE;
|
|
return -1;
|
|
});
|
|
|
|
static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>);
|
|
|
|
EXPECT_TRUE(res.isErr());
|
|
EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE);
|
|
}
|
|
|
|
TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput)
|
|
{
|
|
auto res = ToResultGet<int32_t>(
|
|
[](int32_t aValue, nsresult* aRv) -> int32_t {
|
|
*aRv = NS_OK;
|
|
return aValue * 2;
|
|
},
|
|
42);
|
|
|
|
static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>);
|
|
|
|
EXPECT_TRUE(res.isOk());
|
|
EXPECT_EQ(res.unwrap(), 84);
|
|
}
|
|
|
|
TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput_Err)
|
|
{
|
|
auto res = ToResultGet<int32_t>(
|
|
[](int32_t aValue, nsresult* aRv) -> int32_t {
|
|
*aRv = NS_ERROR_FAILURE;
|
|
return -1;
|
|
},
|
|
42);
|
|
|
|
static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>);
|
|
|
|
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<decltype(res), Result<int32_t, nsresult>>);
|
|
|
|
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<int32_t, int32_t>),
|
|
[](nsresult* aRv) -> std::pair<int32_t, int32_t> {
|
|
*aRv = NS_OK;
|
|
return std::pair{42, 42};
|
|
});
|
|
|
|
static_assert(std::is_same_v<decltype(res),
|
|
Result<std::pair<int32_t, int32_t>, 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<decltype(res), Result<int32_t, nsresult>>);
|
|
|
|
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<decltype(res), Result<int32_t, nsresult>>);
|
|
|
|
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<decltype(res), Result<int32_t, nsresult>>);
|
|
|
|
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<std::pair<int, int>>([&foo](std::pair<int, int>* out) {
|
|
return foo.NonOverloadedNoInputComplex(out);
|
|
});
|
|
static_assert(std::is_same_v<decltype(valOrErr),
|
|
Result<std::pair<int, int>, nsresult>>);
|
|
ASSERT_TRUE(valOrErr.isOk());
|
|
ASSERT_EQ((std::pair{TestClass::kTestValue, TestClass::kTestValue}),
|
|
valOrErr.unwrap());
|
|
}
|
|
|
|
// failure
|
|
{
|
|
auto valOrErr =
|
|
ToResultInvoke<std::pair<int, int>>([&foo](std::pair<int, int>* out) {
|
|
return foo.NonOverloadedNoInputFailsComplex(out);
|
|
});
|
|
static_assert(std::is_same_v<decltype(valOrErr),
|
|
Result<std::pair<int, int>, 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<int, int>), [&foo](std::pair<int, int>* out) {
|
|
return foo.NonOverloadedNoInputComplex(out);
|
|
});
|
|
static_assert(std::is_same_v<decltype(valOrErr),
|
|
Result<std::pair<int, int>, 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<int, int>), [&foo](std::pair<int, int>* out) {
|
|
return foo.NonOverloadedNoInputFailsComplex(out);
|
|
});
|
|
static_assert(std::is_same_v<decltype(valOrErr),
|
|
Result<std::pair<int, int>, nsresult>>);
|
|
ASSERT_TRUE(valOrErr.isErr());
|
|
ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr());
|
|
}
|
|
}
|