blob: 93931f62254bb3672f7719a217f19abff2a41fb0 [file] [log] [blame]
// 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 <lib/fit/result.h>
#include <unittest/unittest.h>
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<Copyable> good = fit::ok<Copyable>({42});
EXPECT_EQ(fit::result_state::ok, good.state());
EXPECT_EQ(42, good.value().data);
fit::result<Copyable> bad = fit::error();
EXPECT_EQ(fit::result_state::error, bad.state());
fit::result<Copyable> 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<Copyable> 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<Copyable> tmpsrc = fit::ok<Copyable>({42});
Copyable taken_value = tmpsrc.take_value();
EXPECT_EQ(fit::result_state::pending, tmpsrc.state());
EXPECT_EQ(42, taken_value.data);
tmpsrc = fit::ok<Copyable>({42});
fit::ok_result<Copyable> 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<void, Copyable> good = fit::ok();
EXPECT_EQ(fit::result_state::ok, good.state());
fit::result<void, Copyable> bad = fit::error<Copyable>({42});
EXPECT_EQ(fit::result_state::error, bad.state());
EXPECT_EQ(42, bad.error().data);
fit::result<void, Copyable> 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<void, Copyable> 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<void, Copyable> 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<Copyable>({42});
Copyable taken_error = tmpsrc.take_error();
EXPECT_EQ(fit::result_state::pending, tmpsrc.state());
EXPECT_EQ(42, taken_error.data);
tmpsrc = fit::error<Copyable>({42});
fit::error_result<Copyable> 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<MoveOnly> good = fit::ok<MoveOnly>({42});
EXPECT_EQ(fit::result_state::ok, good.state());
EXPECT_EQ(42, good.value().data);
fit::result<MoveOnly> bad = fit::error();
EXPECT_EQ(fit::result_state::error, bad.state());
fit::result<MoveOnly> 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<MoveOnly> tmpsrc = fit::ok<MoveOnly>({42});
MoveOnly taken_value = tmpsrc.take_value();
EXPECT_EQ(fit::result_state::pending, tmpsrc.state());
EXPECT_EQ(42, taken_value.data);
tmpsrc = fit::ok<MoveOnly>({42});
fit::ok_result<MoveOnly> 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<void, MoveOnly> good = fit::ok();
EXPECT_EQ(fit::result_state::ok, good.state());
fit::result<void, MoveOnly> bad = fit::error<MoveOnly>({42});
EXPECT_EQ(fit::result_state::error, bad.state());
EXPECT_EQ(42, bad.error().data);
fit::result<void, MoveOnly> 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<void, MoveOnly> 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<MoveOnly>({42});
MoveOnly taken_error = tmpsrc.take_error();
EXPECT_EQ(fit::result_state::pending, tmpsrc.state());
EXPECT_EQ(42, taken_error.data);
tmpsrc = fit::error<MoveOnly>({42});
fit::error_result<MoveOnly> 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<int, char> 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<int>(fit::ok(1)).state() == fit::result_state::ok, "");
static_assert(!fit::result<int>(fit::ok(1)).is_pending(), "");
static_assert(fit::result<int>(fit::ok(1)).is_ok(), "");
static_assert(fit::result<int>(fit::ok(1)), "");
static_assert(!fit::result<int>(fit::ok(1)).is_error(), "");
static_assert(fit::result<int>(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<void, int>(fit::error(1)).state() == fit::result_state::error, "");
static_assert(!fit::result<void, int>(fit::error(1)).is_pending(), "");
static_assert(!fit::result<void, int>(fit::error(1)).is_ok(), "");
static_assert(fit::result<void, int>(fit::error(1)), "");
static_assert(fit::result<void, int>(fit::error(1)).is_error(), "");
static_assert(fit::result<void, int>(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)