fyamlcpp_ut.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #include "fyamlcpp.h"
  2. #include <contrib/libs/libfyaml/include/libfyaml.h>
  3. #include <library/cpp/testing/unittest/registar.h>
  4. #include <util/stream/str.h>
  5. Y_UNIT_TEST_SUITE(FYamlCpp) {
  6. Y_UNIT_TEST(EnumEquals) {
  7. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeType::Scalar, FYNT_SCALAR);
  8. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeType::Sequence, FYNT_SEQUENCE);
  9. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeType::Mapping, FYNT_MAPPING);
  10. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::Any, FYNS_ANY);
  11. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::Flow, FYNS_FLOW);
  12. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::Block, FYNS_BLOCK);
  13. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::Plain, FYNS_PLAIN);
  14. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::SingleQuoted, FYNS_SINGLE_QUOTED);
  15. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::DoubleQuoted, FYNS_DOUBLE_QUOTED);
  16. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::Literal, FYNS_LITERAL);
  17. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::Folded, FYNS_FOLDED);
  18. UNIT_ASSERT_EQUAL((int)NFyaml::ENodeStyle::Alias, FYNS_ALIAS);
  19. }
  20. Y_UNIT_TEST(ErrorHandling) {
  21. {
  22. const char *yaml = R"(
  23. config: a
  24. config: b
  25. )";
  26. UNIT_ASSERT_EXCEPTION_CONTAINS(
  27. NFyaml::TDocument::Parse(yaml),
  28. NFyaml::TFyamlEx,
  29. "3:1 duplicate key");
  30. }
  31. {
  32. const char *yaml = R"(
  33. anchor: *does_not_exists
  34. )";
  35. auto doc = NFyaml::TDocument::Parse(yaml);
  36. UNIT_ASSERT_EXCEPTION_CONTAINS(
  37. doc.Resolve(),
  38. NFyaml::TFyamlEx,
  39. "2:10 invalid alias");
  40. }
  41. {
  42. const char *yaml = R"(
  43. a: 1
  44. a: 2
  45. a: 3
  46. )";
  47. try {
  48. NFyaml::TDocument::Parse(yaml);
  49. UNIT_FAIL("exception must've happend");
  50. } catch (NFyaml::TFyamlEx e) {
  51. UNIT_ASSERT(TString(e.what()).Contains("3:1 duplicate key"));
  52. UNIT_ASSERT(e.Errors().ysize() == 1);
  53. }
  54. }
  55. }
  56. Y_UNIT_TEST(Out) {
  57. const char *yaml = R"(
  58. test: output
  59. )";
  60. auto doc = NFyaml::TDocument::Parse(yaml);
  61. TStringStream ss;
  62. ss << doc;
  63. UNIT_ASSERT_VALUES_EQUAL(ss.Str(), "test: output\n");
  64. }
  65. Y_UNIT_TEST(Parser) {
  66. const char *yaml = R"(
  67. test: a
  68. ---
  69. test: b
  70. )";
  71. auto parser = NFyaml::TParser::Create(yaml);
  72. TStringStream ss;
  73. auto docOpt = parser.NextDocument();
  74. UNIT_ASSERT(docOpt);
  75. ss << *docOpt;
  76. UNIT_ASSERT_VALUES_EQUAL(ss.Str(), "test: a\n");
  77. auto beginMark = docOpt->BeginMark();
  78. UNIT_ASSERT_VALUES_EQUAL(beginMark.InputPos, 1);
  79. auto endMark = docOpt->EndMark();
  80. UNIT_ASSERT_VALUES_EQUAL(endMark.InputPos, 12);
  81. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(yaml).SubStr(beginMark.InputPos, endMark.InputPos - 4), ss.Str());
  82. ss.clear();
  83. auto docOpt2 = parser.NextDocument();
  84. UNIT_ASSERT(docOpt2);
  85. ss << *docOpt2;
  86. UNIT_ASSERT_VALUES_EQUAL(ss.Str(), "---\ntest: b\n");
  87. beginMark = docOpt2->BeginMark();
  88. UNIT_ASSERT_VALUES_EQUAL(beginMark.InputPos, 9);
  89. endMark = docOpt2->EndMark();
  90. UNIT_ASSERT_VALUES_EQUAL(endMark.InputPos, 21);
  91. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(yaml).SubStr(beginMark.InputPos, endMark.InputPos), ss.Str());
  92. auto docOpt3 = parser.NextDocument();
  93. UNIT_ASSERT(!docOpt3);
  94. }
  95. Y_UNIT_TEST(Leak) {
  96. std::optional<NFyaml::TDocument> doc;
  97. {
  98. std::optional<NFyaml::TDocument> item1;
  99. std::optional<NFyaml::TDocument> item2;
  100. {
  101. const TString items = R"(
  102. item:
  103. x: 1
  104. y: 2
  105. ---
  106. test:
  107. a: noop
  108. b:
  109. - 1
  110. - 2
  111. - 3
  112. ---
  113. x: b
  114. )";
  115. auto parser = NFyaml::TParser::Create(items);
  116. item1.emplace(*parser.NextDocument());
  117. item2.emplace(*parser.NextDocument());
  118. parser.NextDocument();
  119. parser.NextDocument();
  120. }
  121. {
  122. const TString config = R"(
  123. test: a
  124. ---
  125. test: []
  126. ---
  127. x: b
  128. )";
  129. auto parser = NFyaml::TParser::Create(config);
  130. parser.NextDocument();
  131. doc.emplace(*parser.NextDocument());
  132. parser.NextDocument();
  133. parser.NextDocument();
  134. }
  135. {
  136. auto item1NodeRef = item1->Root().Map().at("item");
  137. auto item2NodeRef = item2->Root().Map().at("test");
  138. auto docNodeRef = doc->Root().Map().at("test");
  139. auto node1 = item1NodeRef.Copy(*doc);
  140. auto node2 = item2NodeRef.Copy(*doc);
  141. docNodeRef.Sequence().Append(node1);
  142. docNodeRef.Sequence().Append(node2);
  143. item1.reset();
  144. item2.reset();
  145. }
  146. }
  147. auto seq = doc->Root().Map().at("test").Sequence();
  148. UNIT_ASSERT(seq[0].Map().Has("x"));
  149. UNIT_ASSERT(!seq[0].Map().Has("xx"));
  150. UNIT_ASSERT_VALUES_EQUAL(seq[0].Map().at("x").Scalar(), "1");
  151. UNIT_ASSERT_VALUES_EQUAL(seq[0].Map().at("y").Scalar(), "2");
  152. UNIT_ASSERT_VALUES_EQUAL(seq[1].Map().at("a").Scalar(), "noop");
  153. UNIT_ASSERT_VALUES_EQUAL(seq[1].Map().at("b").Sequence().at(0).Scalar(), "1");
  154. UNIT_ASSERT_VALUES_EQUAL(seq[1].Map().at("b").Sequence().at(1).Scalar(), "2");
  155. UNIT_ASSERT_VALUES_EQUAL(seq[1].Map().at("b").Sequence().at(2).Scalar(), "3");
  156. }
  157. Y_UNIT_TEST(SimpleScalarMark) {
  158. auto check = [](const TString& str, const NFyaml::TNodeRef& node) {
  159. auto pos = str.find("123");
  160. auto endPos = pos + strlen("123");
  161. auto begin = node.BeginMark().InputPos;
  162. auto end = node.EndMark().InputPos;
  163. UNIT_ASSERT_VALUES_EQUAL(begin, pos);
  164. UNIT_ASSERT_VALUES_EQUAL(end, endPos);
  165. };
  166. {
  167. TString str = R"(obj: 123)";
  168. auto doc = NFyaml::TDocument::Parse(str);
  169. auto node = doc.Root().Map().at("obj");
  170. check(str, node);
  171. }
  172. {
  173. TString str = R"(obj: 123 # test)";
  174. auto doc = NFyaml::TDocument::Parse(str);
  175. auto node = doc.Root().Map().at("obj");
  176. check(str, node);
  177. }
  178. {
  179. TString str = R"(
  180. # test
  181. obj: 123 # test
  182. # test
  183. )";
  184. auto doc = NFyaml::TDocument::Parse(str);
  185. auto node = doc.Root().Map().at("obj");
  186. check(str, node);
  187. }
  188. {
  189. TString str = R"(
  190. ---
  191. obj: 123
  192. ...
  193. )";
  194. auto doc = NFyaml::TDocument::Parse(str);
  195. auto node = doc.Root().Map().at("obj");
  196. check(str, node);
  197. }
  198. {
  199. TString str = R"(
  200. a: foo
  201. test: [{obj: 123}]
  202. b: bar
  203. )";
  204. auto doc = NFyaml::TDocument::Parse(str);
  205. auto node = doc.Root().Map().at("test").Sequence().at(0).Map().at("obj");
  206. check(str, node);
  207. }
  208. {
  209. TString str = R"(obj: '123')";
  210. auto doc = NFyaml::TDocument::Parse(str);
  211. auto node = doc.Root().Map().at("obj");
  212. check(str, node);
  213. }
  214. {
  215. TString str = R"(obj: '123' # test)";
  216. auto doc = NFyaml::TDocument::Parse(str);
  217. auto node = doc.Root().Map().at("obj");
  218. check(str, node);
  219. }
  220. {
  221. TString str = R"(
  222. # test
  223. obj: '123' # test
  224. # test
  225. )";
  226. auto doc = NFyaml::TDocument::Parse(str);
  227. auto node = doc.Root().Map().at("obj");
  228. check(str, node);
  229. }
  230. {
  231. TString str = R"(
  232. ---
  233. obj: '123'
  234. ...
  235. )";
  236. auto doc = NFyaml::TDocument::Parse(str);
  237. auto node = doc.Root().Map().at("obj");
  238. check(str, node);
  239. }
  240. {
  241. TString str = R"(
  242. a: foo
  243. test: [{obj: "123"}]
  244. b: bar
  245. )";
  246. auto doc = NFyaml::TDocument::Parse(str);
  247. auto node = doc.Root().Map().at("test").Sequence().at(0).Map().at("obj");
  248. check(str, node);
  249. }
  250. {
  251. TString str = R"(obj: "123")";
  252. auto doc = NFyaml::TDocument::Parse(str);
  253. auto node = doc.Root().Map().at("obj");
  254. check(str, node);
  255. }
  256. {
  257. TString str = R"(obj: "123" # test)";
  258. auto doc = NFyaml::TDocument::Parse(str);
  259. auto node = doc.Root().Map().at("obj");
  260. check(str, node);
  261. }
  262. {
  263. TString str = R"(
  264. # test
  265. obj: "123" # test
  266. # test
  267. )";
  268. auto doc = NFyaml::TDocument::Parse(str);
  269. auto node = doc.Root().Map().at("obj");
  270. check(str, node);
  271. }
  272. {
  273. TString str = R"(
  274. ---
  275. obj: "123"
  276. ...
  277. )";
  278. auto doc = NFyaml::TDocument::Parse(str);
  279. auto node = doc.Root().Map().at("obj");
  280. check(str, node);
  281. }
  282. {
  283. TString str = R"(
  284. a: foo
  285. test: [{obj: "123"}]
  286. b: bar
  287. )";
  288. auto doc = NFyaml::TDocument::Parse(str);
  289. auto node = doc.Root().Map().at("test").Sequence().at(0).Map().at("obj");
  290. check(str, node);
  291. }
  292. {
  293. TString str = R"(
  294. a: foo
  295. test: [{obj: !!int "123"}]
  296. b: bar
  297. )";
  298. auto doc = NFyaml::TDocument::Parse(str);
  299. auto node = doc.Root().Map().at("test").Sequence().at(0).Map().at("obj");
  300. check(str, node);
  301. }
  302. }
  303. Y_UNIT_TEST(MultilineScalarMark) {
  304. {
  305. TString str = R"(obj: >+2
  306. some
  307. multiline
  308. scalar with couple words)";
  309. auto doc = NFyaml::TDocument::Parse(str);
  310. auto node = doc.Root().Map().at("obj");
  311. auto begin = node.BeginMark().InputPos;
  312. auto end = node.EndMark().InputPos;
  313. UNIT_ASSERT_VALUES_EQUAL(begin, 9);
  314. UNIT_ASSERT_VALUES_EQUAL(end, 55);
  315. }
  316. }
  317. Y_UNIT_TEST(MapMark) {
  318. {
  319. TString str = R"(
  320. a: foo
  321. map: !!map
  322. internal_map1: {}
  323. internal_map2:
  324. internal_map3:
  325. internal_map4:
  326. value: 1
  327. internal_map5: {
  328. internal_map6: {test1: 1, test2: 2},
  329. internal_map7: {
  330. value: 1
  331. }
  332. }
  333. # comment
  334. c: bar
  335. )";
  336. auto doc = NFyaml::TDocument::Parse(str);
  337. auto node = doc.Root().Map().at("map");
  338. auto begin = node.BeginMark().InputPos;
  339. auto end = node.EndMark().InputPos;
  340. UNIT_ASSERT_VALUES_EQUAL(begin, 21);
  341. UNIT_ASSERT_VALUES_EQUAL(end, 246);
  342. }
  343. {
  344. TString str = R"(
  345. a: foo
  346. map: !!map # comment
  347. # comment
  348. c: bar
  349. )";
  350. auto doc = NFyaml::TDocument::Parse(str);
  351. auto node = doc.Root().Map().at("map");
  352. auto begin = node.BeginMark().InputPos;
  353. auto end = node.EndMark().InputPos;
  354. UNIT_ASSERT_VALUES_EQUAL(begin, 11);
  355. UNIT_ASSERT_VALUES_EQUAL(end, 11);
  356. }
  357. {
  358. TString str = R"(
  359. a: foo
  360. map: {} # comment
  361. # comment
  362. c: bar
  363. )";
  364. auto doc = NFyaml::TDocument::Parse(str);
  365. auto node = doc.Root().Map().at("map");
  366. auto begin = node.BeginMark().InputPos;
  367. auto end = node.EndMark().InputPos;
  368. UNIT_ASSERT_VALUES_EQUAL(begin, 13);
  369. UNIT_ASSERT_VALUES_EQUAL(end, 15);
  370. }
  371. {
  372. TString str = R"(
  373. a: foo
  374. map:
  375. value: 1
  376. # comment
  377. c: bar
  378. )";
  379. auto doc = NFyaml::TDocument::Parse(str);
  380. auto node = doc.Root().Map().at("map");
  381. auto begin = node.BeginMark().InputPos;
  382. auto end = node.EndMark().InputPos;
  383. UNIT_ASSERT_VALUES_EQUAL(begin, 15);
  384. UNIT_ASSERT_VALUES_EQUAL(end, 23);
  385. }
  386. }
  387. Y_UNIT_TEST(SequenceMark) {
  388. {
  389. TString str = R"(
  390. a: foo
  391. seq: !!seq
  392. - internal_map1: {}
  393. - internal_seq2:
  394. - internal_seq3:
  395. - internal_seq4:
  396. value: 1
  397. - internal_seq5: [
  398. internal_seq6: [{test1: 1}, {test2: 2}],
  399. internal_seq7: [
  400. {value: 1}
  401. ]
  402. ]
  403. # comment
  404. c: bar
  405. )";
  406. auto doc = NFyaml::TDocument::Parse(str);
  407. auto node = doc.Root().Map().at("seq");
  408. auto begin = node.BeginMark().InputPos;
  409. auto end = node.EndMark().InputPos;
  410. UNIT_ASSERT_VALUES_EQUAL(begin, 19);
  411. UNIT_ASSERT_VALUES_EQUAL(end, 252);
  412. }
  413. {
  414. TString str = R"(
  415. a: foo
  416. seq: !!seq # comment
  417. # comment
  418. c: bar
  419. )";
  420. auto doc = NFyaml::TDocument::Parse(str);
  421. auto node = doc.Root().Map().at("seq");
  422. auto begin = node.BeginMark().InputPos;
  423. auto end = node.EndMark().InputPos;
  424. UNIT_ASSERT_VALUES_EQUAL(begin, 11);
  425. UNIT_ASSERT_VALUES_EQUAL(end, 11);
  426. }
  427. {
  428. TString str = R"(
  429. a: foo
  430. seq: [] # comment
  431. # comment
  432. c: bar
  433. )";
  434. auto doc = NFyaml::TDocument::Parse(str);
  435. auto node = doc.Root().Map().at("seq");
  436. auto begin = node.BeginMark().InputPos;
  437. auto end = node.EndMark().InputPos;
  438. UNIT_ASSERT_VALUES_EQUAL(begin, 13);
  439. UNIT_ASSERT_VALUES_EQUAL(end, 15);
  440. }
  441. {
  442. TString str = R"(
  443. a: foo
  444. seq:
  445. - value: 1
  446. # comment
  447. c: bar
  448. )";
  449. auto doc = NFyaml::TDocument::Parse(str);
  450. auto node = doc.Root().Map().at("seq");
  451. auto begin = node.BeginMark().InputPos;
  452. auto end = node.EndMark().InputPos;
  453. UNIT_ASSERT_VALUES_EQUAL(begin, 13);
  454. UNIT_ASSERT_VALUES_EQUAL(end, 23);
  455. }
  456. }
  457. }