/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "utils/ErrorsMacros.h" #include #include using namespace android; using android::base::Error; using android::base::Result; status_t success_or_fail(bool success) { if (success) return OK; else return PERMISSION_DENIED; } TEST(errors, unwrap_or_return) { auto f = [](bool success, int* val) -> status_t { OR_RETURN(success_or_fail(success)); *val = 10; return OK; }; int val; status_t s = f(true, &val); EXPECT_EQ(OK, s); EXPECT_EQ(10, val); val = 0; // reset status_t q = f(false, &val); EXPECT_EQ(PERMISSION_DENIED, q); EXPECT_EQ(0, val); } TEST(errors, unwrap_or_return_result) { auto f = [](bool success) -> Result { OR_RETURN(success_or_fail(success)); return "hello"; }; auto r = f(true); EXPECT_TRUE(r.ok()); EXPECT_EQ("hello", *r); auto s = f(false); EXPECT_FALSE(s.ok()); EXPECT_EQ(PERMISSION_DENIED, s.error().code()); EXPECT_EQ("PERMISSION_DENIED", s.error().message()); } TEST(errors, unwrap_or_return_result_int) { auto f = [](bool success) -> Result { OR_RETURN(success_or_fail(success)); return 10; }; auto r = f(true); EXPECT_TRUE(r.ok()); EXPECT_EQ(10, *r); auto s = f(false); EXPECT_FALSE(s.ok()); EXPECT_EQ(PERMISSION_DENIED, s.error().code()); EXPECT_EQ("PERMISSION_DENIED", s.error().message()); } TEST(errors, unwrap_or_fatal) { OR_FATAL(success_or_fail(true)); EXPECT_DEATH(OR_FATAL(success_or_fail(false)), "PERMISSION_DENIED"); } TEST(errors, result_in_status) { auto f = [](bool success) -> Result { if (success) return "OK"; else return Error(PERMISSION_DENIED) << "custom error message"; }; auto g = [&](bool success) -> status_t { std::string val = OR_RETURN(f(success)); EXPECT_EQ("OK", val); return OK; }; status_t a = g(true); EXPECT_EQ(OK, a); status_t b = g(false); EXPECT_EQ(PERMISSION_DENIED, b); } TEST(errors, conversion_promotion) { constexpr size_t successVal = 10ull; auto f = [&](bool success) -> Result { OR_RETURN(success_or_fail(success)); return successVal; }; auto s = f(true); ASSERT_TRUE(s.ok()); EXPECT_EQ(s.value(), successVal); auto r = f(false); EXPECT_TRUE(!r.ok()); EXPECT_EQ(PERMISSION_DENIED, r.error().code()); } TEST(errors, conversion_promotion_bool) { constexpr size_t successVal = true; auto f = [&](bool success) -> Result { OR_RETURN(success_or_fail(success)); return successVal; }; auto s = f(true); ASSERT_TRUE(s.ok()); EXPECT_EQ(s.value(), successVal); auto r = f(false); EXPECT_TRUE(!r.ok()); EXPECT_EQ(PERMISSION_DENIED, r.error().code()); } TEST(errors, conversion_promotion_char) { constexpr char successVal = 'a'; auto f = [&](bool success) -> Result { OR_RETURN(success_or_fail(success)); return successVal; }; auto s = f(true); ASSERT_TRUE(s.ok()); EXPECT_EQ(s.value(), successVal); auto r = f(false); EXPECT_TRUE(!r.ok()); EXPECT_EQ(PERMISSION_DENIED, r.error().code()); } struct IntContainer { // Implicit conversion from int is desired IntContainer(int val) : val_(val) {} int val_; }; TEST(errors, conversion_construct) { constexpr int successVal = 10; auto f = [&](bool success) -> Result { OR_RETURN(success_or_fail(success)); return successVal; }; auto s = f(true); ASSERT_TRUE(s.ok()); EXPECT_EQ(s.value().val_, successVal); auto r = f(false); EXPECT_TRUE(!r.ok()); EXPECT_EQ(PERMISSION_DENIED, r.error().code()); }