#include #include "matador/utils/identifier.hpp" #include "matador/utils/default_type_traits.hpp" #include "matador/utils/value.hpp" using namespace matador::utils; TEST_CASE("Test create identifier", "[identifier][create]") { const identifier id; REQUIRE(id.is_null()); REQUIRE(!id.is_integer()); REQUIRE(!id.is_varchar()); REQUIRE(!id.is_valid()); REQUIRE(id.str() == "null"); } TEST_CASE("Test assign value to identifier", "[identifier][assign]") { identifier id; REQUIRE(id.is_null()); REQUIRE(!id.is_valid()); REQUIRE(id.str() == "null"); id = 7; REQUIRE(!id.is_null()); REQUIRE(id.is_valid()); REQUIRE(id.is_integer()); REQUIRE(id.str() == "7"); REQUIRE(id.type() == basic_type::Int32); REQUIRE(id.type_index() == std::type_index(typeid(int))); id = std::string{"UniqueId"}; REQUIRE(!id.is_null()); REQUIRE(id.is_valid()); REQUIRE(id.is_varchar()); REQUIRE(id.str() == "UniqueId"); id = "UniqueId"; REQUIRE(!id.is_null()); REQUIRE(id.is_valid()); REQUIRE(id.is_varchar()); // REQUIRE(id == identifier{"UniqueId"}); } TEST_CASE("Test compare identifier", "[identifier][compare]") { identifier id1{6}, id2{7}; REQUIRE(id1 != id2); REQUIRE(id1 < id2); REQUIRE(id1 <= id2); REQUIRE(id2 > id1); REQUIRE(id2 >= id1); REQUIRE(id1.hash() != id2.hash()); id2 = 6; REQUIRE(id1 == id2); REQUIRE(id1.hash() == id2.hash()); } identifier create(const int id) { return identifier{id}; } TEST_CASE("Test copy identifier" "[identifier][copy]") { identifier id1{"Unique"}; REQUIRE(id1.is_valid()); REQUIRE(id1.str() == "Unique"); const identifier id2(id1); REQUIRE(id1 == id2); REQUIRE(id1.hash() == id2.hash()); id1.clear(); REQUIRE(id1.is_null()); identifier id3 = id1; REQUIRE(id1 == id3); REQUIRE(!(id1 < id3)); REQUIRE(id3.is_null()); REQUIRE(id1.hash() == id3.hash()); id3 = create(9); id3 = id1; } TEST_CASE("Test move identifier", "[identifier][move]") { identifier id1{6}; REQUIRE(id1.is_integer()); REQUIRE(!id1.is_null()); const auto id2 = std::move(id1); REQUIRE(!id1.is_null()); REQUIRE(id2.is_integer()); } TEST_CASE("identifier assignment from integer types", "[utils][identifier][assign]") { identifier id; id = int8_t{-5}; REQUIRE(id.type() == basic_type::Int8); REQUIRE(id.str() == "-5"); REQUIRE(id.is_integer()); REQUIRE(id.is_valid()); id = int16_t{42}; REQUIRE(id.type() == basic_type::Int16); REQUIRE(id.str() == "42"); REQUIRE(id.is_integer()); REQUIRE(id.is_valid()); id = uint32_t{123456u}; REQUIRE(id.type() == basic_type::UInt32); REQUIRE(id.str() == "123456"); REQUIRE(id.is_integer()); REQUIRE(id.is_valid()); } TEST_CASE("identifier assignment from string type", "[utils][identifier][assign]") { identifier id; id = std::string{"hello"}; REQUIRE(id.type() == basic_type::Varchar); REQUIRE(id.str() == "hello"); REQUIRE(id.is_varchar()); REQUIRE(id.is_valid()); id = std::string{}; REQUIRE(id.type() == basic_type::Varchar); REQUIRE(id.str().empty()); REQUIRE_FALSE(id.is_valid()); } TEST_CASE("identifier assignment from const char*", "[utils][identifier][assign]") { identifier id; id = "world"; REQUIRE(id.type() == basic_type::Varchar); REQUIRE(id.str() == "world"); REQUIRE(id.is_varchar()); REQUIRE(id.is_valid()); id = static_cast(nullptr); REQUIRE(id.type() == basic_type::Varchar); REQUIRE(id.str().empty()); REQUIRE_FALSE(id.is_valid()); } TEST_CASE("identifier assignment from nullptr", "[utils][identifier][assign]") { identifier id{42}; REQUIRE(id.is_valid()); REQUIRE_FALSE(id.is_null()); id = nullptr; REQUIRE(id.is_null()); REQUIRE(id.type() == basic_type::Null); REQUIRE(id.str() == "null"); REQUIRE_FALSE(id.is_valid()); } TEST_CASE("identifier reassignment between types", "[utils][identifier][assign]") { identifier id{uint64_t{7}}; REQUIRE(id.is_integer()); REQUIRE(id.str() == "7"); id = std::string{"abc"}; REQUIRE(id.is_varchar()); REQUIRE(id.str() == "abc"); REQUIRE(id.is_valid()); id = int64_t{99}; REQUIRE(id.is_integer()); REQUIRE(id.str() == "99"); REQUIRE(id.is_valid()); id = nullptr; REQUIRE(id.is_null()); REQUIRE(id.str() == "null"); } TEST_CASE("identifier as() returns exact integer type", "[utils][identifier][as]") { identifier id{int32_t{42}}; const auto as_i32 = id.as(); REQUIRE(as_i32.is_ok()); REQUIRE(*as_i32 == 42); const auto as_i64 = id.as(); REQUIRE(as_i64.is_error()); } TEST_CASE("identifier as() returns exact string type", "[utils][identifier][as]") { identifier id{std::string{"hello"}}; const auto as_string = id.as(); REQUIRE(as_string.is_ok()); REQUIRE(*as_string == "hello"); const auto as_i32 = id.as(); REQUIRE(as_i32.is_error()); } TEST_CASE("identifier as() returns null type failure for null identifier", "[utils][identifier][as]") { identifier id{nullptr}; const auto as_i32 = id.as(); REQUIRE(as_i32.is_error()); const auto as_string = id.as(); REQUIRE(as_string.is_error()); } TEST_CASE("identifier convert() converts between integer types", "[utils][identifier][convert]") { identifier id{int32_t{123}}; const auto as_i64 = id.convert(); REQUIRE(as_i64.is_ok()); REQUIRE(*as_i64 == 123); const auto as_u8 = id.convert(); REQUIRE(as_u8.is_ok()); REQUIRE(*as_u8 == 123); } TEST_CASE("identifier convert() rejects out of range integer conversion", "[utils][identifier][convert]") { identifier id{int32_t{300}}; const auto as_u8 = id.convert(); REQUIRE(as_u8.is_error()); } TEST_CASE("identifier convert() rejects negative to unsigned conversion", "[utils][identifier][convert]") { identifier id{int32_t{-1}}; const auto as_u32 = id.convert(); REQUIRE(as_u32.is_error()); } TEST_CASE("identifier convert() rejects non-integer source types", "[utils][identifier][convert]") { identifier id{std::string{"123"}}; const auto as_i32 = id.convert(); REQUIRE(as_i32.is_error()); identifier null_id{nullptr}; const auto null_to_i64 = null_id.convert(); REQUIRE(null_to_i64.is_error()); } TEST_CASE("identifier convert() works with unsigned integer sources", "[utils][identifier][convert]") { identifier id{uint16_t{500}}; const auto as_i32 = id.convert(); REQUIRE(as_i32.is_ok()); REQUIRE(*as_i32 == 500); const auto as_u8 = id.convert(); REQUIRE(as_u8.is_error()); } TEST_CASE("identifier as() and convert() behave consistently for same integer type", "[utils][identifier][as][convert]") { identifier id{uint64_t{77}}; const auto as_u64 = id.as(); REQUIRE(as_u64.is_ok()); REQUIRE(*as_u64 == 77); const auto conv_u64 = id.convert(); REQUIRE(conv_u64.is_ok()); REQUIRE(*conv_u64 == 77); } TEST_CASE("identifier assign from value", "[utils][identifier][assign]") { identifier id; value v1{int32_t{17}}; const auto r1 = id.assign(v1); REQUIRE(r1.is_ok()); REQUIRE(id.is_integer()); REQUIRE(id.str() == "17"); value v2{std::string{"abc"}}; const auto r2 = id.assign(v2); REQUIRE(r2.is_ok()); REQUIRE(id.is_varchar()); REQUIRE(id.str() == "abc"); value v3{basic_type::Double, 0}; const auto r3 = id.assign(v3); REQUIRE(r3.is_error()); } TEST_CASE("identifier assign from value with exact type mapping", "[utils][identifier][assign]") { identifier id; SECTION("integer types") { value v{int16_t{12}}; const auto r = id.assign(v); REQUIRE(r.is_ok()); REQUIRE(id.is_integer()); REQUIRE(id.str() == "12"); } SECTION("string types") { value v{std::string{"abc"}}; const auto r = id.assign(v); REQUIRE(r.is_ok()); REQUIRE(id.is_varchar()); REQUIRE(id.str() == "abc"); } SECTION("null") { value v{basic_type::Null, 0}; const auto r = id.assign(v); REQUIRE(r.is_ok()); REQUIRE(id.is_null()); } } TEST_CASE("identifier::to_database_type converts internal value to database_type", "[identifier]") { SECTION("null identifier becomes nullptr") { identifier id{nullptr}; const auto db_value = id.to_database_type(); REQUIRE(std::holds_alternative(db_value)); } SECTION("signed integral identifier becomes same signed database type") { identifier id{int32_t{42}}; const auto db_value = id.to_database_type(); REQUIRE(std::holds_alternative(db_value)); REQUIRE(std::get(db_value) == 42); } SECTION("unsigned integral identifier becomes same unsigned database type") { identifier id{uint64_t{123456789ULL}}; const auto db_value = id.to_database_type(); REQUIRE(std::holds_alternative(db_value)); REQUIRE(std::get(db_value) == 123456789ULL); } SECTION("string identifier becomes std::string database type") { identifier id{std::string{"customer_1"}}; const auto db_value = id.to_database_type(); REQUIRE(std::holds_alternative(db_value)); REQUIRE(std::get(db_value) == "customer_1"); } }