yaml-cpp

FORK: A YAML parser and emitter in C++
git clone https://git.neptards.moe/neptards/yaml-cpp.git
Log | Files | Refs | README | LICENSE

load_node_test.cpp (12104B)


      1 #include "yaml-cpp/yaml.h"  // IWYU pragma: keep
      2 
      3 #include "gtest/gtest.h"
      4 
      5 namespace YAML {
      6 namespace {
      7 TEST(LoadNodeTest, Reassign) {
      8   Node node = Load("foo");
      9   node = Node();
     10   EXPECT_TRUE(node.IsNull());
     11 }
     12 
     13 TEST(LoadNodeTest, FallbackValues) {
     14   Node node = Load("foo: bar\nx: 2");
     15   EXPECT_EQ("bar", node["foo"].as<std::string>());
     16   EXPECT_EQ("bar", node["foo"].as<std::string>("hello"));
     17   EXPECT_EQ("hello", node["baz"].as<std::string>("hello"));
     18   EXPECT_EQ(2, node["x"].as<int>());
     19   EXPECT_EQ(2, node["x"].as<int>(5));
     20   EXPECT_EQ(5, node["y"].as<int>(5));
     21 }
     22 
     23 TEST(LoadNodeTest, NumericConversion) {
     24   EXPECT_EQ(1.5f, Load("1.5").as<float>());
     25   EXPECT_EQ(1.5, Load("1.5").as<double>());
     26   EXPECT_THROW(Load("1.5").as<int>(), TypedBadConversion<int>);
     27   EXPECT_EQ(1, Load("1").as<int>());
     28   EXPECT_EQ(1.0f, Load("1").as<float>());
     29   EXPECT_NE(Load(".nan").as<float>(), Load(".nan").as<float>());
     30   EXPECT_EQ(std::numeric_limits<float>::infinity(), Load(".inf").as<float>());
     31   EXPECT_EQ(-std::numeric_limits<float>::infinity(), Load("-.inf").as<float>());
     32   EXPECT_EQ(21, Load("0x15").as<int>());
     33   EXPECT_EQ(13, Load("015").as<int>());
     34   EXPECT_EQ(-128, +Load("-128").as<int8_t>());
     35   EXPECT_EQ(127, +Load("127").as<int8_t>());
     36   EXPECT_THROW(Load("128").as<int8_t>(), TypedBadConversion<signed char>);
     37   EXPECT_EQ(255, +Load("255").as<uint8_t>());
     38   EXPECT_THROW(Load("256").as<uint8_t>(), TypedBadConversion<unsigned char>);
     39   // test as<char>/as<uint8_t> with ‘a’,"ab",'1',"127"
     40   EXPECT_EQ('a', Load("a").as<char>());
     41   EXPECT_THROW(Load("ab").as<char>(), TypedBadConversion<char>);
     42   EXPECT_EQ('1', Load("1").as<char>());
     43   EXPECT_THROW(Load("127").as<char>(), TypedBadConversion<char>);
     44   EXPECT_THROW(Load("a").as<uint8_t>(), TypedBadConversion<unsigned char>);
     45   EXPECT_THROW(Load("ab").as<uint8_t>(), TypedBadConversion<unsigned char>);
     46   EXPECT_EQ(1, +Load("1").as<uint8_t>());
     47   // Throw exception: convert a negative number to an unsigned number.
     48   EXPECT_THROW(Load("-128").as<unsigned>(), TypedBadConversion<unsigned int>);
     49   EXPECT_THROW(Load("-128").as<unsigned short>(), TypedBadConversion<unsigned short>);
     50   EXPECT_THROW(Load("-128").as<unsigned long>(), TypedBadConversion<unsigned long>);
     51   EXPECT_THROW(Load("-128").as<unsigned long long>(), TypedBadConversion<unsigned long long>);
     52   EXPECT_THROW(Load("-128").as<uint8_t>(), TypedBadConversion<unsigned char>);
     53 }
     54 
     55 TEST(LoadNodeTest, Binary) {
     56   Node node = Load(
     57       "[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary "
     58       "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS"
     59       "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG"
     60       "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi"
     61       "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG"
     62       "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS"
     63       "4K\"]");
     64   EXPECT_EQ(Binary(reinterpret_cast<const unsigned char*>("Hello, World!"), 13),
     65             node[0].as<Binary>());
     66   EXPECT_EQ(Binary(reinterpret_cast<const unsigned char*>(
     67                        "Man is distinguished, not only by his reason, "
     68                        "but by this singular passion from other "
     69                        "animals, which is a lust of the mind, that by "
     70                        "a perseverance of delight in the continued and "
     71                        "indefatigable generation of knowledge, exceeds "
     72                        "the short vehemence of any carnal pleasure.\n"),
     73                    270),
     74             node[1].as<Binary>());
     75 }
     76 
     77 TEST(LoadNodeTest, BinaryWithWhitespaces) {
     78   Node node = Load(
     79       "binaryText: !binary |-\n"
     80       "  TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS\n"
     81       "  B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG\n"
     82       "  x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi\n"
     83       "  B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG\n"
     84       "  dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS\n"
     85       "  4K");
     86   EXPECT_EQ(Binary(reinterpret_cast<const unsigned char*>(
     87                        "Man is distinguished, not only by his reason, "
     88                        "but by this singular passion from other "
     89                        "animals, which is a lust of the mind, that by "
     90                        "a perseverance of delight in the continued and "
     91                        "indefatigable generation of knowledge, exceeds "
     92                        "the short vehemence of any carnal pleasure.\n"),
     93                    270),
     94             node["binaryText"].as<Binary>());
     95 }
     96 
     97 TEST(LoadNodeTest, IterateSequence) {
     98   Node node = Load("[1, 3, 5, 7]");
     99   int seq[] = {1, 3, 5, 7};
    100   int i = 0;
    101   for (const_iterator it = node.begin(); it != node.end(); ++it) {
    102     EXPECT_TRUE(i < 4);
    103     int x = seq[i++];
    104     EXPECT_EQ(x, it->as<int>());
    105   }
    106   EXPECT_EQ(4, i);
    107 }
    108 
    109 TEST(LoadNodeTest, IterateMap) {
    110   Node node = Load("{a: A, b: B, c: C}");
    111   int i = 0;
    112   for (const_iterator it = node.begin(); it != node.end(); ++it) {
    113     EXPECT_TRUE(i < 3);
    114     i++;
    115     EXPECT_EQ(it->second.as<char>(), it->first.as<char>() + 'A' - 'a');
    116   }
    117   EXPECT_EQ(3, i);
    118 }
    119 
    120 #ifdef BOOST_FOREACH
    121 TEST(LoadNodeTest, ForEach) {
    122   Node node = Load("[1, 3, 5, 7]");
    123   int seq[] = {1, 3, 5, 7};
    124   int i = 0;
    125   BOOST_FOREACH (const Node& item, node) {
    126     int x = seq[i++];
    127     EXPECT_EQ(x, item.as<int>());
    128   }
    129 }
    130 
    131 TEST(LoadNodeTest, ForEachMap) {
    132   Node node = Load("{a: A, b: B, c: C}");
    133   BOOST_FOREACH (const const_iterator::value_type& p, node) {
    134     EXPECT_EQ(p.second.as<char>(), p.first.as<char>() + 'A' - 'a');
    135   }
    136 }
    137 #endif
    138 
    139 TEST(LoadNodeTest, CloneScalar) {
    140   Node node = Load("!foo monkey");
    141   Node clone = Clone(node);
    142   EXPECT_FALSE(clone == node);
    143   EXPECT_EQ(clone.as<std::string>(), node.as<std::string>());
    144   EXPECT_EQ(clone.Tag(), node.Tag());
    145 }
    146 
    147 TEST(LoadNodeTest, CloneSeq) {
    148   Node node = Load("[1, 3, 5, 7]");
    149   Node clone = Clone(node);
    150   EXPECT_FALSE(clone == node);
    151   EXPECT_EQ(NodeType::Sequence, clone.Type());
    152   EXPECT_EQ(clone.size(), node.size());
    153   for (std::size_t i = 0; i < node.size(); i++) {
    154     EXPECT_EQ(clone[i].as<int>(), node[i].as<int>());
    155   }
    156 }
    157 
    158 TEST(LoadNodeTest, CloneMap) {
    159   Node node = Load("{foo: bar}");
    160   Node clone = Clone(node);
    161   EXPECT_FALSE(clone == node);
    162   EXPECT_EQ(NodeType::Map, clone.Type());
    163   EXPECT_EQ(clone.size(), node.size());
    164   EXPECT_EQ(clone["foo"].as<std::string>(), node["foo"].as<std::string>());
    165 }
    166 
    167 TEST(LoadNodeTest, CloneAlias) {
    168   Node node = Load("&foo [*foo]");
    169   Node clone = Clone(node);
    170   EXPECT_FALSE(clone == node);
    171   EXPECT_EQ(NodeType::Sequence, clone.Type());
    172   EXPECT_EQ(clone.size(), node.size());
    173   EXPECT_EQ(clone[0], clone);
    174 }
    175 
    176 TEST(LoadNodeTest, ForceInsertIntoMap) {
    177   Node node;
    178   node["a"] = "b";
    179   node.force_insert("x", "y");
    180   node.force_insert("a", 5);
    181   EXPECT_EQ(3, node.size());
    182   EXPECT_EQ(NodeType::Map, node.Type());
    183   bool ab = false;
    184   bool a5 = false;
    185   bool xy = false;
    186   for (const_iterator it = node.begin(); it != node.end(); ++it) {
    187     if (it->first.as<std::string>() == "a") {
    188       if (it->second.as<std::string>() == "b")
    189         ab = true;
    190       else if (it->second.as<std::string>() == "5")
    191         a5 = true;
    192     } else if (it->first.as<std::string>() == "x" &&
    193                it->second.as<std::string>() == "y")
    194       xy = true;
    195   }
    196   EXPECT_TRUE(ab);
    197   EXPECT_TRUE(a5);
    198   EXPECT_TRUE(xy);
    199 }
    200 
    201 TEST(LoadNodeTest, ResetNode) {
    202   Node node = Load("[1, 2, 3]");
    203   EXPECT_TRUE(!node.IsNull());
    204   Node other = node;
    205   node.reset();
    206   EXPECT_TRUE(node.IsNull());
    207   EXPECT_TRUE(!other.IsNull());
    208   node.reset(other);
    209   EXPECT_TRUE(!node.IsNull());
    210   EXPECT_EQ(node, other);
    211 }
    212 
    213 TEST(LoadNodeTest, EmptyString) {
    214   Node node = Load("\"\"");
    215   EXPECT_TRUE(!node.IsNull());
    216 }
    217 
    218 TEST(LoadNodeTest, DereferenceIteratorError) {
    219   Node node = Load("[{a: b}, 1, 2]");
    220   EXPECT_THROW(node.begin()->first.as<int>(), InvalidNode);
    221   EXPECT_EQ(true, (*node.begin()).IsMap());
    222   EXPECT_EQ(true, node.begin()->IsMap());
    223   EXPECT_THROW((*node.begin()->begin()).Type(), InvalidNode);
    224   EXPECT_THROW(node.begin()->begin()->Type(), InvalidNode);
    225 }
    226 
    227 TEST(NodeTest, EmitEmptyNode) {
    228   Node node;
    229   Emitter emitter;
    230   emitter << node;
    231   EXPECT_EQ("", std::string(emitter.c_str()));
    232 }
    233 
    234 TEST(NodeTest, ParseNodeStyle) {
    235   EXPECT_EQ(EmitterStyle::Flow, Load("[1, 2, 3]").Style());
    236   EXPECT_EQ(EmitterStyle::Flow, Load("{foo: bar}").Style());
    237   EXPECT_EQ(EmitterStyle::Block, Load("- foo\n- bar").Style());
    238   EXPECT_EQ(EmitterStyle::Block, Load("foo: bar").Style());
    239 }
    240 
    241 struct ParserExceptionTestCase {
    242   std::string name;
    243   std::string input;
    244   std::string expected_exception;
    245 };
    246 
    247 TEST(NodeTest, IncompleteJson) {
    248   std::vector<ParserExceptionTestCase> tests = {
    249       {"JSON map without value", "{\"access\"", ErrorMsg::END_OF_MAP_FLOW},
    250       {"JSON map with colon but no value", "{\"access\":",
    251        ErrorMsg::END_OF_MAP_FLOW},
    252       {"JSON map with unclosed value quote", "{\"access\":\"",
    253        ErrorMsg::END_OF_MAP_FLOW},
    254       {"JSON map without end brace", "{\"access\":\"abc\"",
    255        ErrorMsg::END_OF_MAP_FLOW},
    256   };
    257   for (const ParserExceptionTestCase& test : tests) {
    258     try {
    259       Load(test.input);
    260       FAIL() << "Expected exception " << test.expected_exception << " for "
    261              << test.name << ", input: " << test.input;
    262     } catch (const ParserException& e) {
    263       EXPECT_EQ(test.expected_exception, e.msg);
    264     }
    265   }
    266 }
    267 
    268 struct SingleNodeTestCase {
    269   std::string input;
    270   NodeType::value nodeType;
    271   int nodeSize;
    272   std::string expected_content;
    273 };
    274 
    275 TEST(NodeTest, SpecialFlow) {
    276   std::vector<SingleNodeTestCase> tests = {
    277       {"[:]", NodeType::Sequence, 1, "[{~: ~}]"},
    278       {"[a:]", NodeType::Sequence, 1, "[{a: ~}]"},
    279       {"[:a]", NodeType::Sequence, 1, "[:a]"},
    280       {"[,]", NodeType::Sequence, 1, "[~]"},
    281       {"[a:,]", NodeType::Sequence, 1, "[{a: ~}]"},
    282       {"{:}", NodeType::Map, 1, "{~: ~}"},
    283       {"{a:}", NodeType::Map, 1, "{a: ~}"},
    284       {"{:a}", NodeType::Map, 1, "{:a: ~}"},
    285       {"{,}", NodeType::Map, 1, "{~: ~}"},
    286       {"{a:,}", NodeType::Map, 1, "{a: ~}"},
    287       //testcase for the trailing TAB of scalar
    288       {"key\t: value\t", NodeType::Map, 1, "key: value"},
    289       {"key\t: value\t #comment", NodeType::Map, 1, "key: value"},
    290       {"{key\t: value\t}", NodeType::Map, 1, "{key: value}"},
    291       {"{key\t: value\t #comment\n}", NodeType::Map, 1, "{key: value}"},
    292   };
    293   for (const SingleNodeTestCase& test : tests) {
    294     Node node = Load(test.input);
    295     Emitter emitter;
    296     emitter << node;
    297     EXPECT_EQ(test.nodeType, node.Type());
    298     EXPECT_EQ(test.nodeSize, node.size());
    299     EXPECT_EQ(test.expected_content, std::string(emitter.c_str()));
    300   }
    301 }
    302 
    303 TEST(NodeTest, IncorrectFlow) {
    304   std::vector<ParserExceptionTestCase> tests = {
    305     {"Incorrect yaml: \"{:]\"", "{:]", ErrorMsg::FLOW_END},
    306     {"Incorrect yaml: \"[:}\"", "[:}", ErrorMsg::FLOW_END},
    307   };
    308   for (const ParserExceptionTestCase test : tests) {
    309     try {
    310       Load(test.input);
    311       FAIL() << "Expected exception " << test.expected_exception << " for "
    312              << test.name << ", input: " << test.input;
    313     } catch (const ParserException& e) {
    314       EXPECT_EQ(test.expected_exception, e.msg);
    315     }
    316   }
    317 }
    318 
    319 TEST(NodeTest, LoadTildeAsNull) {
    320   Node node = Load("~");
    321   ASSERT_TRUE(node.IsNull());
    322   EXPECT_EQ(node.as<std::string>(), "null");
    323   EXPECT_EQ(node.as<std::string>("~"), "null");
    324 }
    325 
    326 TEST(NodeTest, LoadNullWithStrTag) {
    327   Node node = Load("!!str null");
    328   EXPECT_EQ(node.Tag(), "tag:yaml.org,2002:str");
    329   EXPECT_EQ(node.as<std::string>(), "null");
    330 }
    331 
    332 TEST(NodeTest, LoadQuotedNull) {
    333   Node node = Load("\"null\"");
    334   EXPECT_EQ(node.as<std::string>(), "null");
    335 }
    336 
    337 TEST(NodeTest, LoadTagWithParenthesis) {
    338     Node node = Load("!Complex(Tag) foo");
    339     EXPECT_EQ(node.Tag(), "!Complex(Tag)");
    340     EXPECT_EQ(node.as<std::string>(), "foo");
    341 }
    342 
    343 TEST(NodeTest, LoadTagWithNullScalar) {
    344   Node node = Load("!2");
    345   EXPECT_TRUE(node.IsNull());
    346 }
    347 
    348 }  // namespace
    349 }  // namespace YAML