#include "vdm/util/result.hpp" #include #include "vtest.hpp" using vdm::Err; using vdm::Error; using vdm::ErrorInfo; using vdm::Result; VT_TEST(result_holds_value) { Result r = 42; VT_REQUIRE(r.has_value()); VT_CHECK(static_cast(r)); VT_CHECK_EQ(r.value(), 42); VT_CHECK_EQ(*r, 42); VT_CHECK_EQ(r.code(), Error::ok); } VT_TEST(result_holds_error) { Result r = Err{Error::timeout, "HEAD stalled"}; VT_REQUIRE(!r.has_value()); VT_CHECK_EQ(r.code(), Error::timeout); VT_CHECK_EQ(r.error().code, Error::timeout); VT_CHECK(r.error().retryable); VT_CHECK_EQ(r.value_or(-1), -1); } VT_TEST(result_from_bare_error_code) { Result r = Error::not_found; VT_REQUIRE(!r.has_value()); VT_CHECK_EQ(r.error().code, Error::not_found); VT_CHECK_EQ(r.error().http_status, 0); } VT_TEST(result_void_ok) { Result r = vdm::ok(); VT_CHECK(r.has_value()); VT_CHECK_EQ(r.code(), Error::ok); } VT_TEST(result_void_error) { Result r = Err{Error::disk_full, "temp dir"}; VT_REQUIRE(!r.has_value()); VT_CHECK_EQ(r.code(), Error::disk_full); VT_CHECK(!r.error().retryable); } VT_TEST(result_transform_chains_on_success) { Result r = 21; auto doubled = r.transform([](int v) { return v * 2; }); VT_REQUIRE(doubled.has_value()); VT_CHECK_EQ(doubled.value(), 42); } VT_TEST(result_and_then_short_circuits_on_error) { Result r = Err{Error::connection_reset, "peer RST"}; int calls = 0; auto next = r.and_then([&](int v) -> std::expected { ++calls; return v + 1; }); VT_CHECK_EQ(calls, 0); VT_REQUIRE(!next.has_value()); VT_CHECK_EQ(next.error().code, Error::connection_reset); } namespace { Result parse_positive(int n) { if (n < 0) return Err{Error::internal, "negative"}; return n; } Result add_two_positives(int a, int b) { VDM_TRY_ASSIGN(auto x, parse_positive(a)); VDM_TRY_ASSIGN(auto y, parse_positive(b)); return x + y; } } // namespace VT_TEST(vdm_try_assign_propagates) { auto good = add_two_positives(2, 3); VT_REQUIRE(good.has_value()); VT_CHECK_EQ(good.value(), 5); auto bad = add_two_positives(2, -1); VT_REQUIRE(!bad.has_value()); VT_CHECK_EQ(bad.error().code, Error::internal); } VT_TEST(error_info_to_string) { ErrorInfo e{Error::http_server_error, "upstream", 503}; VT_CHECK_EQ(e.to_string(), std::string("http_server_error: upstream (HTTP 503)")); VT_CHECK(e.retryable); ErrorInfo bare{Error::canceled}; VT_CHECK_EQ(bare.to_string(), std::string("canceled")); } VT_TEST(error_name_and_retryable_cover_enum) { VT_CHECK_EQ(vdm::error_name(Error::server_file_changed), std::string_view("server_file_changed")); VT_CHECK(!vdm::is_retryable(Error::server_file_changed)); VT_CHECK(!vdm::is_retryable(Error::checksum_mismatch)); VT_CHECK(vdm::is_retryable(Error::timeout)); }