diff --git a/include/rfl/yaml/Reader.hpp b/include/rfl/yaml/Reader.hpp index 505339e2..12664522 100644 --- a/include/rfl/yaml/Reader.hpp +++ b/include/rfl/yaml/Reader.hpp @@ -67,7 +67,7 @@ struct Reader { } bool is_empty(const InputVarType& _var) const noexcept { - return !_var.node_ && true; + return !_var.node_ || _var.node_.IsNull(); } template diff --git a/tests/yaml/test_read_null.cpp b/tests/yaml/test_read_null.cpp new file mode 100644 index 00000000..b03fd1db --- /dev/null +++ b/tests/yaml/test_read_null.cpp @@ -0,0 +1,143 @@ +#include + +#include +#include +#include +#include +#include +#include + +namespace test_read_null { + +struct Person { + std::string first_name; + std::optional last_name; + std::optional age; + std::string city; + float weight; + double height; +}; + +TEST(yaml, test_read_null) { + const std::string yaml_str = + "first_name: Homer\n" + "last_name: null\n" + "age: ~\n" + "city: null\n" + "weight: .nan\n" + "height: .nan\n"; + + const auto res = rfl::yaml::read(yaml_str); + + ASSERT_TRUE(res && true) << "Test failed on read. Error: " + << res.error().what(); + EXPECT_EQ(res.value().first_name, "Homer"); + EXPECT_FALSE(res.value().last_name.has_value()); + EXPECT_FALSE(res.value().age.has_value()); + EXPECT_TRUE(std::isnan(res.value().weight)); + EXPECT_TRUE(std::isnan(res.value().height)); +} + +TEST(yaml, test_null_for_required_field_fails) { + const std::string yaml_str = + "first_name: Homer\n" + "last_name: null\n" + "age: ~\n" + "city: Springfield\n" + "weight: null\n" + "height: null\n"; + + const auto res = rfl::yaml::read(yaml_str); + EXPECT_FALSE(res.has_value()); +} + +// One struct per primitive type — each tested with a null value below. + +struct IntHolder { int value; }; +struct Int8Holder { int8_t value; }; +struct Int16Holder { int16_t value; }; +struct Int32Holder { int32_t value; }; +struct Int64Holder { int64_t value; }; +struct UInt8Holder { uint8_t value; }; +struct UInt16Holder { uint16_t value; }; +struct UInt32Holder { uint32_t value; }; +struct UInt64Holder { uint64_t value; }; +struct FloatHolder { float value; }; +struct DoubleHolder { double value; }; +struct BoolHolder { bool value; }; + +struct OptionalIntHolder { std::optional value; }; +struct OptionalStringHolder { std::optional value; }; + +static constexpr std::string_view kNullYaml = "value: null\n"; +static constexpr std::string_view kNaNYaml = "value: .nan\n"; + +TEST(yaml, test_null_for_int_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_int8_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_int16_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_int32_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_int64_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_uint8_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_uint16_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_uint32_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_uint64_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_float_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_nan_for_float_succeeds) { + EXPECT_TRUE(std::isnan(rfl::yaml::read(kNaNYaml).value().value)); +} + +TEST(yaml, test_null_for_double_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_nan_for_double_succeeds) { + EXPECT_TRUE(std::isnan(rfl::yaml::read(kNaNYaml).value().value)); +} + +TEST(yaml, test_null_for_bool_fails) { + EXPECT_FALSE(rfl::yaml::read(kNullYaml).has_value()); +} + +TEST(yaml, test_null_for_optional_int_is_nullopt) { + const auto res = rfl::yaml::read(kNullYaml); + ASSERT_TRUE(res.has_value()); + EXPECT_FALSE(res.value().value.has_value()); +} + +TEST(yaml, test_null_for_optional_string_is_nullopt) { + const auto res = rfl::yaml::read(kNullYaml); + ASSERT_TRUE(res.has_value()); + EXPECT_FALSE(res.value().value.has_value()); +} + +} // namespace test_read_null