// Copyright 2018 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include namespace { struct Copyable { int data; }; struct MoveOnly { MoveOnly(const MoveOnly&) = delete; MoveOnly(MoveOnly&&) = default; MoveOnly& operator=(const MoveOnly&) = delete; MoveOnly& operator=(MoveOnly&&) = default; int data; }; bool states() { BEGIN_TEST; fit::result<> good = fit::ok(); EXPECT_EQ(fit::result_state::ok, good.state()); EXPECT_TRUE(good); EXPECT_TRUE(good.is_ok()); EXPECT_FALSE(good.is_error()); EXPECT_FALSE(good.is_pending()); fit::result<> bad = fit::error(); EXPECT_EQ(fit::result_state::error, bad.state()); EXPECT_TRUE(bad); EXPECT_FALSE(bad.is_ok()); EXPECT_TRUE(bad.is_error()); EXPECT_FALSE(bad.is_pending()); fit::result<> pending = fit::pending(); EXPECT_EQ(fit::result_state::pending, pending.state()); EXPECT_FALSE(pending); EXPECT_FALSE(pending.is_ok()); EXPECT_FALSE(pending.is_error()); EXPECT_TRUE(pending.is_pending()); fit::result<> default_init; EXPECT_EQ(fit::result_state::pending, default_init.state()); EXPECT_FALSE(default_init); EXPECT_FALSE(default_init.is_ok()); EXPECT_FALSE(default_init.is_error()); EXPECT_TRUE(default_init.is_pending()); END_TEST; } bool void_value_and_error() { BEGIN_TEST; fit::result<> good = fit::ok(); EXPECT_EQ(fit::result_state::ok, good.state()); fit::result<> bad = fit::error(); EXPECT_EQ(fit::result_state::error, bad.state()); fit::result<> tmpcopy(good); EXPECT_EQ(fit::result_state::ok, tmpcopy.state()); EXPECT_EQ(fit::result_state::ok, good.state()); tmpcopy = bad; EXPECT_EQ(fit::result_state::error, tmpcopy.state()); EXPECT_EQ(fit::result_state::error, bad.state()); fit::result<> tmpmove(std::move(good)); EXPECT_EQ(fit::result_state::ok, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, good.state()); tmpmove = std::move(bad); EXPECT_EQ(fit::result_state::error, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, bad.state()); fit::result<> tmpsrc = fit::ok(); fit::ok_result<> taken_ok_result = tmpsrc.take_ok_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); (void)taken_ok_result; tmpsrc = fit::error(); fit::error_result<> taken_error_result = tmpsrc.take_error_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); (void)taken_error_result; END_TEST; } bool copyable_value() { BEGIN_TEST; fit::result good = fit::ok({42}); EXPECT_EQ(fit::result_state::ok, good.state()); EXPECT_EQ(42, good.value().data); fit::result bad = fit::error(); EXPECT_EQ(fit::result_state::error, bad.state()); fit::result tmpcopy(good); EXPECT_EQ(fit::result_state::ok, tmpcopy.state()); EXPECT_EQ(42, tmpcopy.value().data); EXPECT_EQ(fit::result_state::ok, good.state()); tmpcopy = bad; EXPECT_EQ(fit::result_state::error, tmpcopy.state()); EXPECT_EQ(fit::result_state::error, bad.state()); fit::result tmpmove(std::move(good)); EXPECT_EQ(fit::result_state::ok, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, good.state()); EXPECT_EQ(42, tmpmove.value().data); tmpmove = std::move(bad); EXPECT_EQ(fit::result_state::error, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, bad.state()); fit::result tmpsrc = fit::ok({42}); Copyable taken_value = tmpsrc.take_value(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); EXPECT_EQ(42, taken_value.data); tmpsrc = fit::ok({42}); fit::ok_result taken_ok_result = tmpsrc.take_ok_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); EXPECT_EQ(42, taken_ok_result.value.data); tmpsrc = fit::error(); fit::error_result<> taken_error_result = tmpsrc.take_error_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); (void)taken_error_result; END_TEST; } bool copyable_error() { BEGIN_TEST; fit::result good = fit::ok(); EXPECT_EQ(fit::result_state::ok, good.state()); fit::result bad = fit::error({42}); EXPECT_EQ(fit::result_state::error, bad.state()); EXPECT_EQ(42, bad.error().data); fit::result tmpcopy(good); EXPECT_EQ(fit::result_state::ok, tmpcopy.state()); EXPECT_EQ(fit::result_state::ok, good.state()); tmpcopy = bad; EXPECT_EQ(fit::result_state::error, tmpcopy.state()); EXPECT_EQ(fit::result_state::error, bad.state()); EXPECT_EQ(42, tmpcopy.error().data); fit::result tmpmove(std::move(good)); EXPECT_EQ(fit::result_state::ok, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, good.state()); tmpmove = std::move(bad); EXPECT_EQ(fit::result_state::error, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, bad.state()); EXPECT_EQ(42, tmpmove.error().data); fit::result tmpsrc = fit::ok(); fit::ok_result<> taken_ok_result = tmpsrc.take_ok_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); (void)taken_ok_result; tmpsrc = fit::error({42}); Copyable taken_error = tmpsrc.take_error(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); EXPECT_EQ(42, taken_error.data); tmpsrc = fit::error({42}); fit::error_result taken_error_result = tmpsrc.take_error_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); EXPECT_EQ(42, taken_error_result.error.data); END_TEST; } bool moveonly_value() { BEGIN_TEST; fit::result good = fit::ok({42}); EXPECT_EQ(fit::result_state::ok, good.state()); EXPECT_EQ(42, good.value().data); fit::result bad = fit::error(); EXPECT_EQ(fit::result_state::error, bad.state()); fit::result tmpmove(std::move(good)); EXPECT_EQ(fit::result_state::ok, tmpmove.state()); EXPECT_EQ(42, tmpmove.value().data); EXPECT_EQ(fit::result_state::pending, good.state()); tmpmove = std::move(bad); EXPECT_EQ(fit::result_state::error, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, bad.state()); fit::result tmpsrc = fit::ok({42}); MoveOnly taken_value = tmpsrc.take_value(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); EXPECT_EQ(42, taken_value.data); tmpsrc = fit::ok({42}); fit::ok_result taken_ok_result = tmpsrc.take_ok_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); EXPECT_EQ(42, taken_ok_result.value.data); tmpsrc = fit::error(); fit::error_result<> taken_error_result = tmpsrc.take_error_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); (void)taken_error_result; END_TEST; } bool moveonly_error() { BEGIN_TEST; fit::result good = fit::ok(); EXPECT_EQ(fit::result_state::ok, good.state()); fit::result bad = fit::error({42}); EXPECT_EQ(fit::result_state::error, bad.state()); EXPECT_EQ(42, bad.error().data); fit::result tmpmove(std::move(good)); EXPECT_EQ(fit::result_state::ok, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, good.state()); tmpmove = std::move(bad); EXPECT_EQ(fit::result_state::error, tmpmove.state()); EXPECT_EQ(fit::result_state::pending, bad.state()); EXPECT_EQ(42, tmpmove.error().data); fit::result tmpsrc = fit::ok(); fit::ok_result<> taken_ok_result = tmpsrc.take_ok_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); (void)taken_ok_result; tmpsrc = fit::error({42}); MoveOnly taken_error = tmpsrc.take_error(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); EXPECT_EQ(42, taken_error.data); tmpsrc = fit::error({42}); fit::error_result taken_error_result = tmpsrc.take_error_result(); EXPECT_EQ(fit::result_state::pending, tmpsrc.state()); EXPECT_EQ(42, taken_error_result.error.data); END_TEST; } bool swapping() { BEGIN_TEST; fit::result a, b, c; a = fit::ok(42); b = fit::error('x'); a.swap(b); EXPECT_EQ('x', a.error()); EXPECT_EQ(42, b.value()); swap(b, c); EXPECT_EQ(42, c.value()); EXPECT_TRUE(b.is_pending()); swap(c, c); EXPECT_EQ(42, c.value()); END_TEST; } // Test constexpr behavior. namespace constexpr_test { static_assert(fit::ok(1).value == 1, ""); static_assert(fit::error(1).error == 1, ""); static_assert(fit::result<>().state() == fit::result_state::pending, ""); static_assert(fit::result<>().is_pending(), ""); static_assert(!fit::result<>().is_ok(), ""); static_assert(!fit::result<>(), ""); static_assert(!fit::result<>().is_error(), ""); static_assert(fit::result<>(fit::pending()).state() == fit::result_state::pending, ""); static_assert(fit::result<>(fit::pending()).is_pending(), ""); static_assert(!fit::result<>(fit::pending()).is_ok(), ""); static_assert(!fit::result<>(fit::pending()), ""); static_assert(!fit::result<>(fit::pending()).is_error(), ""); static_assert(fit::result<>(fit::ok()).state() == fit::result_state::ok, ""); static_assert(!fit::result<>(fit::ok()).is_pending(), ""); static_assert(fit::result<>(fit::ok()).is_ok(), ""); static_assert(fit::result<>(fit::ok()), ""); static_assert(!fit::result<>(fit::ok()).is_error(), ""); static_assert(fit::result(fit::ok(1)).state() == fit::result_state::ok, ""); static_assert(!fit::result(fit::ok(1)).is_pending(), ""); static_assert(fit::result(fit::ok(1)).is_ok(), ""); static_assert(fit::result(fit::ok(1)), ""); static_assert(!fit::result(fit::ok(1)).is_error(), ""); static_assert(fit::result(fit::ok(1)).value() == 1, ""); static_assert(fit::result<>(fit::error()).state() == fit::result_state::error, ""); static_assert(!fit::result<>(fit::error()).is_pending(), ""); static_assert(!fit::result<>(fit::error()).is_ok(), ""); static_assert(fit::result<>(fit::error()), ""); static_assert(fit::result<>(fit::error()).is_error(), ""); static_assert(fit::result(fit::error(1)).state() == fit::result_state::error, ""); static_assert(!fit::result(fit::error(1)).is_pending(), ""); static_assert(!fit::result(fit::error(1)).is_ok(), ""); static_assert(fit::result(fit::error(1)), ""); static_assert(fit::result(fit::error(1)).is_error(), ""); static_assert(fit::result(fit::error(1)).error() == 1, ""); } // namespace constexpr_test } // namespace BEGIN_TEST_CASE(result_tests) RUN_TEST(states) RUN_TEST(void_value_and_error) RUN_TEST(copyable_value) RUN_TEST(copyable_error) RUN_TEST(moveonly_value) RUN_TEST(moveonly_error) RUN_TEST(swapping) END_TEST_CASE(result_tests)