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