#include "test.h"
#include <panda/error.h>
TEST_PREFIX("error: ", "[error]");
enum MyErr {
Err1 = 1,
Err2
};
struct MyCategory : std::error_category {
const char * name() const noexcept override {return "MyCategory";}
std::string message(int ev) const override {return std::string("MyErr") + std::to_string(ev);}
};
static const MyCategory my_category;
namespace std {
template <> struct is_error_code_enum<MyErr> : std::true_type {};
}
std::error_code make_error_code (MyErr err) noexcept { return std::error_code(err, my_category); }
TEST("ErrorCode ctor") {
SECTION("default") {
ErrorCode code;
CHECK_FALSE(code);
CHECK_FALSE(code.next());
CHECK_FALSE(code.code());
CHECK_FALSE(code.next().code());
}
SECTION("val+cat") {
ErrorCode code(2, my_category);
CHECK(code);
CHECK_FALSE(code.next());
}
SECTION("enum") {
ErrorCode code(Err1);
CHECK(code);
CHECK_FALSE(code.next());
}
SECTION("nested") {
ErrorCode nested_code(Err1);
ErrorCode code(Err2, nested_code);
CHECK(code);
REQUIRE(code.next());
CHECK_FALSE(code.next().next());
CHECK(code.what() == "MyErr2 (2:MyCategory) -> MyErr1 (1:MyCategory)");
nested_code.clear();
CHECK(code.next().code() == Err1); // check it was copy and no sharing
}
}
TEST("ErrorCode methods") {
ErrorCode e1(Err1);
ErrorCode e2;
e2 = e1;
REQUIRE(e2 == e1);
}
TEST("ErrorCode defctor") {
ErrorCode orig;
ErrorCode wrap(Err1, orig);
CHECK(wrap & Err1);
CHECK(wrap.next().code().value() == 0);
}
TEST("comparisons") {
SECTION("ErrorCode to ErrorCode") {
CHECK(ErrorCode() == ErrorCode());
CHECK(ErrorCode(MyErr::Err1) == ErrorCode(MyErr::Err1));
CHECK(ErrorCode(MyErr::Err1) != ErrorCode());
(void)(ErrorCode() < ErrorCode());
}
SECTION("ErrorCode to error_code") {
CHECK(ErrorCode() & std::error_code());
CHECK(std::error_code() & ErrorCode());
(void)(ErrorCode() < std::error_code());
(void)(std::error_code() < ErrorCode());
}
SECTION("ErrorCode to error code enum") {
CHECK(ErrorCode(MyErr::Err1) & MyErr::Err1);
CHECK(MyErr::Err1 & ErrorCode(MyErr::Err1));
(void)(ErrorCode() < MyErr::Err1);
(void)(MyErr::Err1 < ErrorCode());
}
SECTION("ErrorCode to error cond enum") {
CHECK(ErrorCode(make_error_code(std::errc::operation_canceled)) & std::errc::operation_canceled);
CHECK(std::errc::operation_canceled & ErrorCode(make_error_code(std::errc::operation_canceled)));
(void)(ErrorCode() < std::errc::operation_canceled);
(void)(std::errc::operation_canceled < ErrorCode());
}
}
TEST("bad_expected_access") {
string what;
try {
expected<int, ErrorCode> exp = make_unexpected(ErrorCode(MyErr::Err1));
exp.value();
} catch (bad_expected_access<ErrorCode>& e) {
what = e.what();
}
REQUIRE(what == "MyErr1 (1:MyCategory)");
}
TEST("contains") {
REQUIRE_FALSE(ErrorCode().contains(make_error_code(MyErr::Err1)));
REQUIRE_FALSE(ErrorCode(MyErr::Err1).contains({make_error_code(MyErr::Err2)}));
REQUIRE(ErrorCode().contains({}));
REQUIRE(ErrorCode(MyErr::Err1).contains({make_error_code(MyErr::Err1)}));
ErrorCode nested_code(Err1);
ErrorCode code(Err2, nested_code);
REQUIRE(code.contains(MyErr::Err1));
REQUIRE(code.contains(MyErr::Err2));
ErrorCode triple(make_error_code(std::errc::operation_canceled), code);
REQUIRE(triple.contains(MyErr::Err1));
REQUIRE(triple.contains(MyErr::Err2));
REQUIRE(triple.contains(make_error_code(std::errc::operation_canceled)));
REQUIRE_FALSE(triple.contains(make_error_code(std::errc::broken_pipe)));
}