Add unit tests for optional and result helper types
This commit is contained in:
parent
b705afba69
commit
906784284f
@ -60,19 +60,19 @@ namespace detail {
|
||||
}
|
||||
|
||||
NODISCARD optional<T> value() const & {
|
||||
return has_value() ? value_ : nullopt;
|
||||
return has_value() ? optional<T>(value_) : nullopt;
|
||||
}
|
||||
|
||||
NODISCARD optional<E> error() const & {
|
||||
return is_error() ? error_ : nullopt;
|
||||
return is_error() ? optional<E>(error_) : nullopt;
|
||||
}
|
||||
|
||||
NODISCARD optional<T> value() && {
|
||||
return has_value() ? std::move(value_) : nullopt;
|
||||
return has_value() ? optional<T>(std::move(value_)) : nullopt;
|
||||
}
|
||||
|
||||
NODISCARD optional<E> error() && {
|
||||
return is_error() ? std::move(error_) : nullopt;
|
||||
return is_error() ? optional<E>(std::move(error_)) : nullopt;
|
||||
}
|
||||
|
||||
NODISCARD T& unwrap_value() & {
|
||||
|
||||
@ -81,12 +81,14 @@ if(NOT CPPTRACE_SKIP_UNIT)
|
||||
add_executable(
|
||||
unittest
|
||||
unit/main.cpp
|
||||
unit/raw_trace.cpp
|
||||
unit/object_trace.cpp
|
||||
unit/stacktrace.cpp
|
||||
unit/from_current.cpp
|
||||
unit/from_current_z.cpp
|
||||
unit/traced_exception.cpp
|
||||
unit/tracing/raw_trace.cpp
|
||||
unit/tracing/object_trace.cpp
|
||||
unit/tracing/stacktrace.cpp
|
||||
unit/tracing/from_current.cpp
|
||||
unit/tracing/from_current_z.cpp
|
||||
unit/tracing/traced_exception.cpp
|
||||
unit/internals/optional.cpp
|
||||
unit/internals/result.cpp
|
||||
)
|
||||
target_compile_features(unittest PRIVATE cxx_std_20)
|
||||
target_link_libraries(unittest PRIVATE ${target_name} GTest::gtest_main GTest::gmock_main)
|
||||
@ -101,5 +103,6 @@ if(NOT CPPTRACE_SKIP_UNIT)
|
||||
if(CPPTRACE_SANITIZER_BUILD)
|
||||
target_compile_definitions(unittest PRIVATE CPPTRACE_SANITIZER_BUILD)
|
||||
endif()
|
||||
target_include_directories(unittest PRIVATE ../src)
|
||||
add_test(NAME unittest COMMAND unittest)
|
||||
endif()
|
||||
|
||||
119
test/unit/internals/optional.cpp
Normal file
119
test/unit/internals/optional.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "utils/optional.hpp"
|
||||
|
||||
using namespace cpptrace::detail;
|
||||
|
||||
TEST(OptionalTest, DefaultConstructor) {
|
||||
optional<int> o;
|
||||
EXPECT_FALSE(o.has_value());
|
||||
EXPECT_FALSE(static_cast<bool>(o));
|
||||
}
|
||||
|
||||
TEST(OptionalTest, ConstructWithNullopt) {
|
||||
optional<int> o(nullopt);
|
||||
EXPECT_FALSE(o.has_value());
|
||||
}
|
||||
|
||||
TEST(OptionalTest, ValueConstructor) {
|
||||
optional<int> o(42);
|
||||
EXPECT_TRUE(o.has_value());
|
||||
EXPECT_EQ(o.unwrap(), 42);
|
||||
|
||||
int x = 100;
|
||||
optional<int> o2(x);
|
||||
EXPECT_TRUE(o2.has_value());
|
||||
EXPECT_EQ(o2.unwrap(), 100);
|
||||
}
|
||||
|
||||
TEST(OptionalTest, CopyConstructor) {
|
||||
optional<int> o1(42);
|
||||
optional<int> o2(o1);
|
||||
EXPECT_TRUE(o2.has_value());
|
||||
EXPECT_EQ(o2.unwrap(), 42);
|
||||
|
||||
optional<int> o3(nullopt);
|
||||
optional<int> o4(o3);
|
||||
EXPECT_FALSE(o4.has_value());
|
||||
}
|
||||
|
||||
TEST(OptionalTest, MoveConstructor) {
|
||||
optional<int> o1(42);
|
||||
optional<int> o2(std::move(o1));
|
||||
EXPECT_TRUE(o2.has_value());
|
||||
EXPECT_EQ(o2.unwrap(), 42);
|
||||
|
||||
optional<int> o3(nullopt);
|
||||
optional<int> o4(std::move(o3));
|
||||
EXPECT_FALSE(o4.has_value());
|
||||
}
|
||||
|
||||
TEST(OptionalTest, CopyAssignmentOperator) {
|
||||
optional<int> o1(42);
|
||||
optional<int> o2;
|
||||
o2 = o1;
|
||||
EXPECT_TRUE(o2.has_value());
|
||||
EXPECT_EQ(o2.unwrap(), 42);
|
||||
|
||||
optional<int> o3(nullopt);
|
||||
optional<int> o4(100);
|
||||
o4 = o3;
|
||||
EXPECT_FALSE(o4.has_value());
|
||||
}
|
||||
|
||||
TEST(OptionalTest, MoveAssignmentOperator) {
|
||||
optional<int> o1(42);
|
||||
optional<int> o2;
|
||||
o2 = std::move(o1);
|
||||
EXPECT_TRUE(o2.has_value());
|
||||
EXPECT_EQ(o2.unwrap(), 42);
|
||||
|
||||
optional<int> o3(nullopt);
|
||||
optional<int> o4(99);
|
||||
o4 = std::move(o3);
|
||||
EXPECT_FALSE(o4.has_value());
|
||||
}
|
||||
|
||||
TEST(OptionalTest, AssignmentFromValue) {
|
||||
optional<int> o;
|
||||
o = 123;
|
||||
EXPECT_TRUE(o.has_value());
|
||||
EXPECT_EQ(o.unwrap(), 123);
|
||||
|
||||
o = nullopt;
|
||||
EXPECT_FALSE(o.has_value());
|
||||
}
|
||||
|
||||
TEST(OptionalTest, Reset) {
|
||||
optional<int> o(42);
|
||||
EXPECT_TRUE(o.has_value());
|
||||
o.reset();
|
||||
EXPECT_FALSE(o.has_value());
|
||||
}
|
||||
|
||||
TEST(OptionalTest, Swap) {
|
||||
optional<int> o1(42);
|
||||
optional<int> o2(100);
|
||||
|
||||
o1.swap(o2);
|
||||
EXPECT_TRUE(o1.has_value());
|
||||
EXPECT_TRUE(o2.has_value());
|
||||
EXPECT_EQ(o1.unwrap(), 100);
|
||||
EXPECT_EQ(o2.unwrap(), 42);
|
||||
|
||||
// Swap a value-holding optional with an empty optional
|
||||
optional<int> o3(7);
|
||||
optional<int> o4(nullopt);
|
||||
o3.swap(o4);
|
||||
EXPECT_FALSE(o3.has_value());
|
||||
EXPECT_TRUE(o4.has_value());
|
||||
EXPECT_EQ(o4.unwrap(), 7);
|
||||
}
|
||||
|
||||
TEST(OptionalTest, ValueOr) {
|
||||
optional<int> o1(42);
|
||||
EXPECT_EQ(o1.value_or(100), 42);
|
||||
|
||||
optional<int> o2(nullopt);
|
||||
EXPECT_EQ(o2.value_or(100), 100);
|
||||
}
|
||||
98
test/unit/internals/result.cpp
Normal file
98
test/unit/internals/result.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "utils/result.hpp"
|
||||
|
||||
using namespace cpptrace::detail;
|
||||
|
||||
// A simple custom error type that behaves like a standard exception.
|
||||
struct error {
|
||||
int x;
|
||||
const char* what() const {
|
||||
return "error...";
|
||||
}
|
||||
};
|
||||
|
||||
class ResultFixture : public testing::Test {
|
||||
public:
|
||||
ResultFixture() {
|
||||
cpptrace::absorb_trace_exceptions(true);
|
||||
}
|
||||
|
||||
~ResultFixture() override {
|
||||
cpptrace::absorb_trace_exceptions(false);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ResultFixture, ConstructWithValueRValue) {
|
||||
cpptrace::detail::Result<std::string, error> result("test");
|
||||
EXPECT_TRUE(result.has_value());
|
||||
EXPECT_FALSE(result.is_error());
|
||||
EXPECT_TRUE(static_cast<bool>(result));
|
||||
|
||||
EXPECT_EQ(result.unwrap_value(), "test");
|
||||
EXPECT_FALSE(result.error().has_value());
|
||||
}
|
||||
|
||||
TEST_F(ResultFixture, ConstructWithValueLValue) {
|
||||
std::string s = "test";
|
||||
cpptrace::detail::Result<std::string, error> result(s);
|
||||
|
||||
EXPECT_TRUE(result.has_value());
|
||||
EXPECT_FALSE(result.is_error());
|
||||
EXPECT_EQ(result.unwrap_value(), "test");
|
||||
|
||||
s = "x";
|
||||
EXPECT_EQ(result.unwrap_value(), "test");
|
||||
}
|
||||
|
||||
TEST_F(ResultFixture, ConstructWithErrorRValue) {
|
||||
cpptrace::detail::Result<std::string, error> result(error{1});
|
||||
EXPECT_FALSE(result.has_value());
|
||||
EXPECT_TRUE(result.is_error());
|
||||
EXPECT_FALSE(static_cast<bool>(result));
|
||||
|
||||
EXPECT_EQ(result.unwrap_error().x, 1);
|
||||
|
||||
// Check that value() returns nullopt in this scenario
|
||||
EXPECT_FALSE(result.value().has_value());
|
||||
}
|
||||
|
||||
TEST_F(ResultFixture, ConstructWithErrorLValue) {
|
||||
error e{1};
|
||||
cpptrace::detail::Result<std::string, error> result(e);
|
||||
|
||||
EXPECT_FALSE(result.has_value());
|
||||
EXPECT_TRUE(result.is_error());
|
||||
EXPECT_EQ(result.unwrap_error().x, 1);
|
||||
}
|
||||
|
||||
TEST_F(ResultFixture, MoveConstructorValue) {
|
||||
cpptrace::detail::Result<std::string, error> original(std::string("move"));
|
||||
cpptrace::detail::Result<std::string, error> moved(std::move(original));
|
||||
|
||||
EXPECT_TRUE(moved.has_value());
|
||||
EXPECT_EQ(moved.unwrap_value(), "move");
|
||||
EXPECT_TRUE(original.has_value());
|
||||
}
|
||||
|
||||
TEST_F(ResultFixture, MoveConstructorError) {
|
||||
cpptrace::detail::Result<std::string, error> original(error{1});
|
||||
cpptrace::detail::Result<std::string, error> moved(std::move(original));
|
||||
|
||||
EXPECT_TRUE(moved.is_error());
|
||||
EXPECT_EQ(moved.unwrap_error().x, 1);
|
||||
EXPECT_TRUE(original.is_error());
|
||||
}
|
||||
|
||||
TEST_F(ResultFixture, ValueOr) {
|
||||
{
|
||||
cpptrace::detail::Result<int, error> res_with_value(42);
|
||||
EXPECT_EQ(res_with_value.value_or(-1), 42);
|
||||
EXPECT_EQ(std::move(res_with_value).value_or(-1), 42);
|
||||
}
|
||||
{
|
||||
cpptrace::detail::Result<int, error> res_with_error(error{});
|
||||
EXPECT_EQ(res_with_error.value_or(-1), -1);
|
||||
EXPECT_EQ(std::move(res_with_error).value_or(-1), -1);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user