You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

364 lines
12 KiB

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