TestResultExtensions.cpp (9451B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "Common.h" 8 #include "gtest/gtest.h" 9 #include "mozilla/dom/QMResult.h" 10 #include "mozilla/dom/quota/ResultExtensions.h" 11 12 using namespace mozilla; 13 using namespace mozilla::dom::quota; 14 15 namespace { 16 class TestClass { 17 public: 18 static constexpr int kTestValue = 42; 19 20 nsresult NonOverloadedNoInputComplex(std::pair<int, int>* aOut) { 21 *aOut = std::pair{kTestValue, kTestValue}; 22 return NS_OK; 23 } 24 nsresult NonOverloadedNoInputFailsComplex(std::pair<int, int>* aOut) { 25 return NS_ERROR_FAILURE; 26 } 27 }; 28 } // namespace 29 30 class DOM_Quota_ResultExtensions_ToResult : public DOM_Quota_Test {}; 31 class DOM_Quota_ResultExtensions_GenericErrorResult : public DOM_Quota_Test {}; 32 33 TEST_F(DOM_Quota_ResultExtensions_ToResult, FromBool) { 34 // success 35 { 36 auto res = ToResult(true); 37 static_assert(std::is_same_v<decltype(res), Result<Ok, nsresult>>); 38 EXPECT_TRUE(res.isOk()); 39 } 40 41 // failure 42 { 43 auto res = ToResult(false); 44 static_assert(std::is_same_v<decltype(res), Result<Ok, nsresult>>); 45 EXPECT_TRUE(res.isErr()); 46 EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); 47 } 48 } 49 50 TEST_F(DOM_Quota_ResultExtensions_ToResult, FromQMResult_Failure) { 51 // copy 52 { 53 const auto res = ToQMResult(NS_ERROR_FAILURE); 54 auto okOrErr = ToResult<QMResult>(res); 55 static_assert(std::is_same_v<decltype(okOrErr), OkOrErr>); 56 ASSERT_TRUE(okOrErr.isErr()); 57 auto err = okOrErr.unwrapErr(); 58 59 #ifdef QM_ERROR_STACKS_ENABLED 60 IncreaseExpectedStackId(); 61 62 ASSERT_EQ(err.StackId(), ExpectedStackId()); 63 ASSERT_EQ(err.FrameId(), 1u); 64 ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE); 65 #else 66 ASSERT_EQ(err, NS_ERROR_FAILURE); 67 #endif 68 } 69 70 // move 71 { 72 auto res = ToQMResult(NS_ERROR_FAILURE); 73 auto okOrErr = ToResult<QMResult>(std::move(res)); 74 static_assert(std::is_same_v<decltype(okOrErr), OkOrErr>); 75 ASSERT_TRUE(okOrErr.isErr()); 76 auto err = okOrErr.unwrapErr(); 77 78 #ifdef QM_ERROR_STACKS_ENABLED 79 IncreaseExpectedStackId(); 80 81 ASSERT_EQ(err.StackId(), ExpectedStackId()); 82 ASSERT_EQ(err.FrameId(), 1u); 83 ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE); 84 #else 85 ASSERT_EQ(err, NS_ERROR_FAILURE); 86 #endif 87 } 88 } 89 90 TEST_F(DOM_Quota_ResultExtensions_ToResult, FromNSResult_Failure_Macro) { 91 auto okOrErr = QM_TO_RESULT(NS_ERROR_FAILURE); 92 static_assert(std::is_same_v<decltype(okOrErr), OkOrErr>); 93 ASSERT_TRUE(okOrErr.isErr()); 94 auto err = okOrErr.unwrapErr(); 95 96 #ifdef QM_ERROR_STACKS_ENABLED 97 IncreaseExpectedStackId(); 98 99 ASSERT_EQ(err.StackId(), ExpectedStackId()); 100 ASSERT_EQ(err.FrameId(), 1u); 101 ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE); 102 #else 103 ASSERT_EQ(err, NS_ERROR_FAILURE); 104 #endif 105 } 106 107 TEST_F(DOM_Quota_ResultExtensions_GenericErrorResult, ErrorPropagation) { 108 OkOrErr okOrErr1 = ToResult<QMResult>(ToQMResult(NS_ERROR_FAILURE)); 109 const auto& err1 = okOrErr1.inspectErr(); 110 111 #ifdef QM_ERROR_STACKS_ENABLED 112 IncreaseExpectedStackId(); 113 114 ASSERT_EQ(err1.StackId(), ExpectedStackId()); 115 ASSERT_EQ(err1.FrameId(), 1u); 116 ASSERT_EQ(err1.NSResult(), NS_ERROR_FAILURE); 117 #else 118 ASSERT_EQ(err1, NS_ERROR_FAILURE); 119 #endif 120 121 OkOrErr okOrErr2 = okOrErr1.propagateErr(); 122 const auto& err2 = okOrErr2.inspectErr(); 123 124 #ifdef QM_ERROR_STACKS_ENABLED 125 ASSERT_EQ(err2.StackId(), ExpectedStackId()); 126 ASSERT_EQ(err2.FrameId(), 2u); 127 ASSERT_EQ(err2.NSResult(), NS_ERROR_FAILURE); 128 #else 129 ASSERT_EQ(err2, NS_ERROR_FAILURE); 130 #endif 131 132 OkOrErr okOrErr3 = okOrErr2.propagateErr(); 133 const auto& err3 = okOrErr3.inspectErr(); 134 135 #ifdef QM_ERROR_STACKS_ENABLED 136 ASSERT_EQ(err3.StackId(), ExpectedStackId()); 137 ASSERT_EQ(err3.FrameId(), 3u); 138 ASSERT_EQ(err3.NSResult(), NS_ERROR_FAILURE); 139 #else 140 ASSERT_EQ(err3, NS_ERROR_FAILURE); 141 #endif 142 } 143 144 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput) 145 { 146 auto res = ToResultGet<int32_t>([](nsresult* aRv) -> int32_t { 147 *aRv = NS_OK; 148 return 42; 149 }); 150 151 static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>); 152 153 EXPECT_TRUE(res.isOk()); 154 EXPECT_EQ(res.unwrap(), 42); 155 } 156 157 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Err) 158 { 159 auto res = ToResultGet<int32_t>([](nsresult* aRv) -> int32_t { 160 *aRv = NS_ERROR_FAILURE; 161 return -1; 162 }); 163 164 static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>); 165 166 EXPECT_TRUE(res.isErr()); 167 EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); 168 } 169 170 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput) 171 { 172 auto res = ToResultGet<int32_t>( 173 [](int32_t aValue, nsresult* aRv) -> int32_t { 174 *aRv = NS_OK; 175 return aValue * 2; 176 }, 177 42); 178 179 static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>); 180 181 EXPECT_TRUE(res.isOk()); 182 EXPECT_EQ(res.unwrap(), 84); 183 } 184 185 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput_Err) 186 { 187 auto res = ToResultGet<int32_t>( 188 [](int32_t aValue, nsresult* aRv) -> int32_t { 189 *aRv = NS_ERROR_FAILURE; 190 return -1; 191 }, 192 42); 193 194 static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>); 195 196 EXPECT_TRUE(res.isErr()); 197 EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); 198 } 199 200 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Macro_Typed) 201 { 202 auto res = MOZ_TO_RESULT_GET_TYPED(int32_t, [](nsresult* aRv) -> int32_t { 203 *aRv = NS_OK; 204 return 42; 205 }); 206 207 static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>); 208 209 EXPECT_TRUE(res.isOk()); 210 EXPECT_EQ(res.unwrap(), 42); 211 } 212 213 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Macro_Typed_Parens) 214 { 215 auto res = 216 MOZ_TO_RESULT_GET_TYPED((std::pair<int32_t, int32_t>), 217 [](nsresult* aRv) -> std::pair<int32_t, int32_t> { 218 *aRv = NS_OK; 219 return std::pair{42, 42}; 220 }); 221 222 static_assert(std::is_same_v<decltype(res), 223 Result<std::pair<int32_t, int32_t>, nsresult>>); 224 225 EXPECT_TRUE(res.isOk()); 226 EXPECT_EQ(res.unwrap(), (std::pair{42, 42})); 227 } 228 229 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_NoInput_Err_Macro_Typed) 230 { 231 auto res = MOZ_TO_RESULT_GET_TYPED(int32_t, [](nsresult* aRv) -> int32_t { 232 *aRv = NS_ERROR_FAILURE; 233 return -1; 234 }); 235 236 static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>); 237 238 EXPECT_TRUE(res.isErr()); 239 EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); 240 } 241 242 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput_Macro_Typed) 243 { 244 auto res = MOZ_TO_RESULT_GET_TYPED( 245 int32_t, 246 [](int32_t aValue, nsresult* aRv) -> int32_t { 247 *aRv = NS_OK; 248 return aValue * 2; 249 }, 250 42); 251 252 static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>); 253 254 EXPECT_TRUE(res.isOk()); 255 EXPECT_EQ(res.unwrap(), 84); 256 } 257 258 TEST(DOM_Quota_ResultExtensions_ToResultGet, Lambda_WithInput_Err_Macro_Typed) 259 { 260 auto res = MOZ_TO_RESULT_GET_TYPED( 261 int32_t, 262 [](int32_t aValue, nsresult* aRv) -> int32_t { 263 *aRv = NS_ERROR_FAILURE; 264 return -1; 265 }, 266 42); 267 268 static_assert(std::is_same_v<decltype(res), Result<int32_t, nsresult>>); 269 270 EXPECT_TRUE(res.isErr()); 271 EXPECT_EQ(res.unwrapErr(), NS_ERROR_FAILURE); 272 } 273 274 TEST(DOM_Quota_ResultExtensions_ToResultInvoke, Lambda_NoInput_Complex) 275 { 276 TestClass foo; 277 278 // success 279 { 280 auto valOrErr = 281 ToResultInvoke<std::pair<int, int>>([&foo](std::pair<int, int>* out) { 282 return foo.NonOverloadedNoInputComplex(out); 283 }); 284 static_assert(std::is_same_v<decltype(valOrErr), 285 Result<std::pair<int, int>, nsresult>>); 286 ASSERT_TRUE(valOrErr.isOk()); 287 ASSERT_EQ((std::pair{TestClass::kTestValue, TestClass::kTestValue}), 288 valOrErr.unwrap()); 289 } 290 291 // failure 292 { 293 auto valOrErr = 294 ToResultInvoke<std::pair<int, int>>([&foo](std::pair<int, int>* out) { 295 return foo.NonOverloadedNoInputFailsComplex(out); 296 }); 297 static_assert(std::is_same_v<decltype(valOrErr), 298 Result<std::pair<int, int>, nsresult>>); 299 ASSERT_TRUE(valOrErr.isErr()); 300 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 301 } 302 } 303 304 TEST(DOM_Quota_ResultExtensions_ToResultInvoke, 305 Lambda_NoInput_Complex_Macro_Typed) 306 { 307 TestClass foo; 308 309 // success 310 { 311 auto valOrErr = MOZ_TO_RESULT_INVOKE_TYPED( 312 (std::pair<int, int>), [&foo](std::pair<int, int>* out) { 313 return foo.NonOverloadedNoInputComplex(out); 314 }); 315 static_assert(std::is_same_v<decltype(valOrErr), 316 Result<std::pair<int, int>, nsresult>>); 317 ASSERT_TRUE(valOrErr.isOk()); 318 ASSERT_EQ((std::pair{TestClass::kTestValue, TestClass::kTestValue}), 319 valOrErr.unwrap()); 320 } 321 322 // failure 323 { 324 auto valOrErr = MOZ_TO_RESULT_INVOKE_TYPED( 325 (std::pair<int, int>), [&foo](std::pair<int, int>* out) { 326 return foo.NonOverloadedNoInputFailsComplex(out); 327 }); 328 static_assert(std::is_same_v<decltype(valOrErr), 329 Result<std::pair<int, int>, nsresult>>); 330 ASSERT_TRUE(valOrErr.isErr()); 331 ASSERT_EQ(NS_ERROR_FAILURE, valOrErr.unwrapErr()); 332 } 333 }