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.

1751 lines
42 KiB

2 months ago
  1. #include "yaml-cpp/emitterstyle.h"
  2. #include "yaml-cpp/eventhandler.h"
  3. #include "yaml-cpp/yaml.h" // IWYU pragma: keep
  4. #include "gtest/gtest.h"
  5. namespace YAML {
  6. namespace {
  7. class NullEventHandler : public EventHandler {
  8. virtual void OnDocumentStart(const Mark&) {}
  9. virtual void OnDocumentEnd() {}
  10. virtual void OnNull(const Mark&, anchor_t) {}
  11. virtual void OnAlias(const Mark&, anchor_t) {}
  12. virtual void OnScalar(const Mark&, const std::string&, anchor_t,
  13. const std::string&) {}
  14. virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t,
  15. EmitterStyle::value /* style */) {}
  16. virtual void OnSequenceEnd() {}
  17. virtual void OnMapStart(const Mark&, const std::string&, anchor_t,
  18. EmitterStyle::value /* style */) {}
  19. virtual void OnMapEnd() {}
  20. };
  21. class EmitterTest : public ::testing::Test {
  22. protected:
  23. void ExpectEmit(const std::string& expected) {
  24. EXPECT_EQ(expected, out.c_str());
  25. EXPECT_TRUE(out.good()) << "Emitter raised: " << out.GetLastError();
  26. if (expected == out.c_str()) {
  27. std::stringstream stream(expected);
  28. Parser parser;
  29. NullEventHandler handler;
  30. parser.HandleNextDocument(handler);
  31. }
  32. }
  33. Emitter out;
  34. };
  35. TEST_F(EmitterTest, SimpleScalar) {
  36. out << "Hello, World!";
  37. ExpectEmit("Hello, World!");
  38. }
  39. TEST_F(EmitterTest, SimpleQuotedScalar) {
  40. Node n(Load("\"test\""));
  41. out << n;
  42. ExpectEmit("test");
  43. }
  44. TEST_F(EmitterTest, DumpAndSize) {
  45. Node n(Load("test"));
  46. EXPECT_EQ("test", Dump(n));
  47. out << n;
  48. EXPECT_EQ(4, out.size());
  49. }
  50. TEST_F(EmitterTest, NullScalar) {
  51. Node n(Load("null"));
  52. out << n;
  53. ExpectEmit("~");
  54. }
  55. TEST_F(EmitterTest, AliasScalar) {
  56. Node n(Load("[&a str, *a]"));
  57. out << n;
  58. ExpectEmit("[&1 str, *1]");
  59. }
  60. TEST_F(EmitterTest, StringFormat) {
  61. out << BeginSeq;
  62. out.SetStringFormat(SingleQuoted);
  63. out << "string";
  64. out.SetStringFormat(DoubleQuoted);
  65. out << "string";
  66. out.SetStringFormat(Literal);
  67. out << "string";
  68. out << EndSeq;
  69. ExpectEmit("- 'string'\n- \"string\"\n- |\n string");
  70. }
  71. TEST_F(EmitterTest, IntBase) {
  72. out << BeginSeq;
  73. out.SetIntBase(Dec);
  74. out << 1024;
  75. out.SetIntBase(Hex);
  76. out << 1024;
  77. out.SetIntBase(Oct);
  78. out << 1024;
  79. out << EndSeq;
  80. ExpectEmit("- 1024\n- 0x400\n- 02000");
  81. }
  82. TEST_F(EmitterTest, NumberPrecision) {
  83. out.SetFloatPrecision(3);
  84. out.SetDoublePrecision(2);
  85. out << BeginSeq;
  86. out << 3.1425926f;
  87. out << 53.5893;
  88. out << 2384626.4338;
  89. out << EndSeq;
  90. ExpectEmit("- 3.14\n- 54\n- 2.4e+06");
  91. }
  92. TEST_F(EmitterTest, SimpleSeq) {
  93. out << BeginSeq;
  94. out << "eggs";
  95. out << "bread";
  96. out << "milk";
  97. out << EndSeq;
  98. ExpectEmit("- eggs\n- bread\n- milk");
  99. }
  100. TEST_F(EmitterTest, SimpleFlowSeq) {
  101. out << Flow;
  102. out << BeginSeq;
  103. out << "Larry";
  104. out << "Curly";
  105. out << "Moe";
  106. out << EndSeq;
  107. ExpectEmit("[Larry, Curly, Moe]");
  108. }
  109. TEST_F(EmitterTest, EmptyFlowSeq) {
  110. out << Flow;
  111. out << BeginSeq;
  112. out << EndSeq;
  113. ExpectEmit("[]");
  114. }
  115. TEST_F(EmitterTest, EmptyBlockSeqWithBegunContent) {
  116. out << BeginSeq;
  117. out << BeginSeq << Comment("comment") << EndSeq;
  118. out << BeginSeq << Newline << EndSeq;
  119. out << EndSeq;
  120. ExpectEmit(R"(-
  121. # comment
  122. []
  123. -
  124. [])");
  125. }
  126. TEST_F(EmitterTest, EmptyBlockMapWithBegunContent) {
  127. out << BeginSeq;
  128. out << BeginMap << Comment("comment") << EndMap;
  129. out << BeginMap << Newline << EndMap;
  130. out << EndSeq;
  131. ExpectEmit(R"(- # comment
  132. {}
  133. -
  134. {})");
  135. }
  136. TEST_F(EmitterTest, EmptyFlowSeqWithBegunContent) {
  137. out << Flow;
  138. out << BeginSeq;
  139. out << BeginSeq << Comment("comment") << EndSeq;
  140. out << BeginSeq << Newline << EndSeq;
  141. out << EndSeq;
  142. ExpectEmit(R"([[ # comment
  143. ], [
  144. ]])");
  145. }
  146. TEST_F(EmitterTest, EmptyFlowSeqInMap) {
  147. out << BeginMap;
  148. out << Key << Flow << BeginSeq << EndSeq;
  149. out << Value << 1;
  150. out << Key << 2;
  151. out << Value << Flow << BeginSeq << EndSeq;
  152. out << EndMap;
  153. ExpectEmit("[]: 1\n2: []");
  154. }
  155. TEST_F(EmitterTest, EmptyFlowMapWithBegunContent) {
  156. out << Flow;
  157. out << BeginSeq;
  158. out << BeginMap << Comment("comment") << EndMap;
  159. out << BeginMap << Newline << EndMap;
  160. out << EndSeq;
  161. ExpectEmit(R"([{ # comment
  162. }, {
  163. }])");
  164. }
  165. TEST_F(EmitterTest, NestedBlockSeq) {
  166. out << BeginSeq;
  167. out << "item 1";
  168. out << BeginSeq << "subitem 1"
  169. << "subitem 2" << EndSeq;
  170. out << EndSeq;
  171. ExpectEmit("- item 1\n-\n - subitem 1\n - subitem 2");
  172. }
  173. TEST_F(EmitterTest, NestedFlowSeq) {
  174. out << BeginSeq;
  175. out << "one";
  176. out << Flow << BeginSeq << "two"
  177. << "three" << EndSeq;
  178. out << EndSeq;
  179. ExpectEmit("- one\n- [two, three]");
  180. }
  181. TEST_F(EmitterTest, SimpleMap) {
  182. out << BeginMap;
  183. out << Key << "name";
  184. out << Value << "Ryan Braun";
  185. out << Key << "position";
  186. out << Value << "3B";
  187. out << EndMap;
  188. ExpectEmit("name: Ryan Braun\nposition: 3B");
  189. }
  190. TEST_F(EmitterTest, SimpleFlowMap) {
  191. out << Flow;
  192. out << BeginMap;
  193. out << Key << "shape";
  194. out << Value << "square";
  195. out << Key << "color";
  196. out << Value << "blue";
  197. out << EndMap;
  198. ExpectEmit("{shape: square, color: blue}");
  199. }
  200. TEST_F(EmitterTest, MapAndList) {
  201. out << BeginMap;
  202. out << Key << "name";
  203. out << Value << "Barack Obama";
  204. out << Key << "children";
  205. out << Value << BeginSeq << "Sasha"
  206. << "Malia" << EndSeq;
  207. out << EndMap;
  208. ExpectEmit("name: Barack Obama\nchildren:\n - Sasha\n - Malia");
  209. }
  210. TEST_F(EmitterTest, ListAndMap) {
  211. out << BeginSeq;
  212. out << "item 1";
  213. out << BeginMap;
  214. out << Key << "pens" << Value << 8;
  215. out << Key << "pencils" << Value << 14;
  216. out << EndMap;
  217. out << "item 2";
  218. out << EndSeq;
  219. ExpectEmit("- item 1\n- pens: 8\n pencils: 14\n- item 2");
  220. }
  221. TEST_F(EmitterTest, NestedBlockMap) {
  222. out << BeginMap;
  223. out << Key << "name";
  224. out << Value << "Fred";
  225. out << Key << "grades";
  226. out << Value;
  227. out << BeginMap;
  228. out << Key << "algebra" << Value << "A";
  229. out << Key << "physics" << Value << "C+";
  230. out << Key << "literature" << Value << "B";
  231. out << EndMap;
  232. out << EndMap;
  233. ExpectEmit(
  234. "name: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B");
  235. }
  236. TEST_F(EmitterTest, NestedFlowMap) {
  237. out << Flow;
  238. out << BeginMap;
  239. out << Key << "name";
  240. out << Value << "Fred";
  241. out << Key << "grades";
  242. out << Value;
  243. out << BeginMap;
  244. out << Key << "algebra" << Value << "A";
  245. out << Key << "physics" << Value << "C+";
  246. out << Key << "literature" << Value << "B";
  247. out << EndMap;
  248. out << EndMap;
  249. ExpectEmit("{name: Fred, grades: {algebra: A, physics: C+, literature: B}}");
  250. }
  251. TEST_F(EmitterTest, MapListMix) {
  252. out << BeginMap;
  253. out << Key << "name";
  254. out << Value << "Bob";
  255. out << Key << "position";
  256. out << Value;
  257. out << Flow << BeginSeq << 2 << 4 << EndSeq;
  258. out << Key << "invincible" << Value << OnOffBool << false;
  259. out << EndMap;
  260. ExpectEmit("name: Bob\nposition: [2, 4]\ninvincible: off");
  261. }
  262. TEST_F(EmitterTest, SimpleLongKey) {
  263. out << LongKey;
  264. out << BeginMap;
  265. out << Key << "height";
  266. out << Value << "5'9\"";
  267. out << Key << "weight";
  268. out << Value << 145;
  269. out << EndMap;
  270. ExpectEmit("? height\n: 5'9\"\n? weight\n: 145");
  271. }
  272. TEST_F(EmitterTest, SingleLongKey) {
  273. const std::string shortKey(1024, 'a');
  274. const std::string longKey(1025, 'a');
  275. out << BeginMap;
  276. out << Key << "age";
  277. out << Value << "24";
  278. out << LongKey << Key << "height";
  279. out << Value << "5'9\"";
  280. out << Key << "weight";
  281. out << Value << 145;
  282. out << Key << shortKey;
  283. out << Value << "1";
  284. out << Key << longKey;
  285. out << Value << "1";
  286. out << EndMap;
  287. ExpectEmit("age: 24\n? height\n: 5'9\"\nweight: 145\n" + shortKey +
  288. ": 1\n? " + longKey + "\n: 1");
  289. }
  290. TEST_F(EmitterTest, ComplexLongKey) {
  291. out << LongKey;
  292. out << BeginMap;
  293. out << Key << BeginSeq << 1 << 3 << EndSeq;
  294. out << Value << "monster";
  295. out << Key << Flow << BeginSeq << 2 << 0 << EndSeq;
  296. out << Value << "demon";
  297. out << EndMap;
  298. ExpectEmit("? - 1\n - 3\n: monster\n? [2, 0]\n: demon");
  299. }
  300. TEST_F(EmitterTest, AutoLongKey) {
  301. out << BeginMap;
  302. out << Key << BeginSeq << 1 << 3 << EndSeq;
  303. out << Value << "monster";
  304. out << Key << Flow << BeginSeq << 2 << 0 << EndSeq;
  305. out << Value << "demon";
  306. out << Key << "the origin";
  307. out << Value << "angel";
  308. out << EndMap;
  309. ExpectEmit("? - 1\n - 3\n: monster\n[2, 0]: demon\nthe origin: angel");
  310. }
  311. TEST_F(EmitterTest, ScalarFormat) {
  312. out << BeginSeq;
  313. out << "simple scalar";
  314. out << SingleQuoted << "explicit single-quoted scalar";
  315. out << DoubleQuoted << "explicit double-quoted scalar";
  316. out << "auto-detected\ndouble-quoted scalar";
  317. out << "a non-\"auto-detected\" double-quoted scalar";
  318. out << Literal
  319. << "literal scalar\nthat may span\nmany, many\nlines "
  320. "and have \"whatever\" crazy\tsymbols that we like";
  321. out << EndSeq;
  322. ExpectEmit(
  323. "- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit "
  324. "double-quoted scalar\"\n- \"auto-detected\\ndouble-quoted "
  325. "scalar\"\n- a "
  326. "non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n "
  327. " "
  328. "that may span\n many, many\n lines and have \"whatever\" "
  329. "crazy\tsymbols that we like");
  330. }
  331. TEST_F(EmitterTest, LiteralWithoutTrailingSpaces) {
  332. out << YAML::BeginMap;
  333. out << YAML::Key << "key";
  334. out << YAML::Value << YAML::Literal;
  335. out << "expect that with two newlines\n\n"
  336. "no spaces are emitted in the empty line";
  337. out << YAML::EndMap;
  338. ExpectEmit(
  339. "key: |\n"
  340. " expect that with two newlines\n\n"
  341. " no spaces are emitted in the empty line");
  342. }
  343. TEST_F(EmitterTest, AutoLongKeyScalar) {
  344. out << BeginMap;
  345. out << Key << Literal << "multi-line\nscalar";
  346. out << Value << "and its value";
  347. out << EndMap;
  348. ExpectEmit("? |\n multi-line\n scalar\n: and its value");
  349. }
  350. TEST_F(EmitterTest, LongKeyFlowMap) {
  351. out << Flow;
  352. out << BeginMap;
  353. out << Key << "simple key";
  354. out << Value << "and value";
  355. out << LongKey << Key << "long key";
  356. out << Value << "and its value";
  357. out << EndMap;
  358. ExpectEmit("{simple key: and value, ? long key: and its value}");
  359. }
  360. TEST_F(EmitterTest, BlockMapAsKey) {
  361. out << BeginMap;
  362. out << Key;
  363. out << BeginMap;
  364. out << Key << "key" << Value << "value";
  365. out << Key << "next key" << Value << "next value";
  366. out << EndMap;
  367. out << Value;
  368. out << "total value";
  369. out << EndMap;
  370. ExpectEmit("? key: value\n next key: next value\n: total value");
  371. }
  372. TEST_F(EmitterTest, TaggedBlockMapAsKey) {
  373. out << BeginMap;
  374. out << Key;
  375. out << LocalTag("innerMap");
  376. out << BeginMap;
  377. out << Key << "key" << Value << "value";
  378. out << EndMap;
  379. out << Value;
  380. out << "outerValue";
  381. out << EndMap;
  382. ExpectEmit(R"(? !innerMap
  383. key: value
  384. : outerValue)");
  385. }
  386. TEST_F(EmitterTest, TaggedBlockListAsKey) {
  387. out << BeginMap;
  388. out << Key;
  389. out << LocalTag("innerList");
  390. out << BeginSeq;
  391. out << "listItem";
  392. out << EndSeq;
  393. out << Value;
  394. out << "outerValue";
  395. out << EndMap;
  396. ExpectEmit(R"(? !innerList
  397. - listItem
  398. : outerValue)");
  399. }
  400. TEST_F(EmitterTest, AliasAndAnchor) {
  401. out << BeginSeq;
  402. out << Anchor("fred");
  403. out << BeginMap;
  404. out << Key << "name" << Value << "Fred";
  405. out << Key << "age" << Value << 42;
  406. out << EndMap;
  407. out << Alias("fred");
  408. out << EndSeq;
  409. ExpectEmit("- &fred\n name: Fred\n age: 42\n- *fred");
  410. }
  411. TEST_F(EmitterTest, AliasOnKey) {
  412. out << BeginSeq;
  413. out << Anchor("name") << "Name";
  414. out << BeginMap;
  415. out << Key << Alias("name") << Value << "Fred";
  416. out << EndMap;
  417. out << Flow << BeginMap;
  418. out << Key << Alias("name") << Value << "Mike";
  419. out << EndMap;
  420. out << EndSeq;
  421. ExpectEmit(R"(- &name Name
  422. - *name : Fred
  423. - {*name : Mike})");
  424. }
  425. TEST_F(EmitterTest, AliasAndAnchorWithNull) {
  426. out << BeginSeq;
  427. out << Anchor("fred") << Null;
  428. out << Alias("fred");
  429. out << EndSeq;
  430. ExpectEmit("- &fred ~\n- *fred");
  431. }
  432. TEST_F(EmitterTest, AliasAndAnchorInFlow) {
  433. out << Flow << BeginSeq;
  434. out << Anchor("fred");
  435. out << BeginMap;
  436. out << Key << "name" << Value << "Fred";
  437. out << Key << "age" << Value << 42;
  438. out << EndMap;
  439. out << Alias("fred");
  440. out << EndSeq;
  441. ExpectEmit("[&fred {name: Fred, age: 42}, *fred]");
  442. }
  443. TEST_F(EmitterTest, SimpleVerbatimTag) {
  444. out << VerbatimTag("!foo") << "bar";
  445. ExpectEmit("!<!foo> bar");
  446. }
  447. TEST_F(EmitterTest, VerbatimTagInBlockSeq) {
  448. out << BeginSeq;
  449. out << VerbatimTag("!foo") << "bar";
  450. out << "baz";
  451. out << EndSeq;
  452. ExpectEmit("- !<!foo> bar\n- baz");
  453. }
  454. TEST_F(EmitterTest, VerbatimTagInFlowSeq) {
  455. out << Flow << BeginSeq;
  456. out << VerbatimTag("!foo") << "bar";
  457. out << "baz";
  458. out << EndSeq;
  459. ExpectEmit("[!<!foo> bar, baz]");
  460. }
  461. TEST_F(EmitterTest, VerbatimTagInFlowSeqWithNull) {
  462. out << Flow << BeginSeq;
  463. out << VerbatimTag("!foo") << Null;
  464. out << "baz";
  465. out << EndSeq;
  466. ExpectEmit("[!<!foo> ~, baz]");
  467. }
  468. TEST_F(EmitterTest, VerbatimTagInBlockMap) {
  469. out << BeginMap;
  470. out << Key << VerbatimTag("!foo") << "bar";
  471. out << Value << VerbatimTag("!waz") << "baz";
  472. out << EndMap;
  473. ExpectEmit("? !<!foo> bar\n: !<!waz> baz");
  474. }
  475. TEST_F(EmitterTest, VerbatimTagInFlowMap) {
  476. out << Flow << BeginMap;
  477. out << Key << VerbatimTag("!foo") << "bar";
  478. out << Value << "baz";
  479. out << EndMap;
  480. ExpectEmit("{!<!foo> bar: baz}");
  481. }
  482. TEST_F(EmitterTest, VerbatimTagInFlowMapWithNull) {
  483. out << Flow << BeginMap;
  484. out << Key << VerbatimTag("!foo") << Null;
  485. out << Value << "baz";
  486. out << EndMap;
  487. ExpectEmit("{!<!foo> ~: baz}");
  488. }
  489. TEST_F(EmitterTest, VerbatimTagWithEmptySeq) {
  490. out << VerbatimTag("!foo") << BeginSeq << EndSeq;
  491. ExpectEmit("!<!foo>\n[]");
  492. }
  493. TEST_F(EmitterTest, VerbatimTagWithEmptyMap) {
  494. out << VerbatimTag("!bar") << BeginMap << EndMap;
  495. ExpectEmit("!<!bar>\n{}");
  496. }
  497. TEST_F(EmitterTest, VerbatimTagWithEmptySeqAndMap) {
  498. out << BeginSeq;
  499. out << VerbatimTag("!foo") << BeginSeq << EndSeq;
  500. out << VerbatimTag("!bar") << BeginMap << EndMap;
  501. out << EndSeq;
  502. ExpectEmit("- !<!foo>\n []\n- !<!bar>\n {}");
  503. }
  504. TEST_F(EmitterTest, ByKindTagWithScalar) {
  505. out << BeginSeq;
  506. out << DoubleQuoted << "12";
  507. out << "12";
  508. out << TagByKind << "12";
  509. out << EndSeq;
  510. ExpectEmit("- \"12\"\n- 12\n- ! 12");
  511. }
  512. TEST_F(EmitterTest, LocalTagInNameHandle) {
  513. out << LocalTag("a", "foo") << "bar";
  514. ExpectEmit("!a!foo bar");
  515. }
  516. TEST_F(EmitterTest, LocalTagWithScalar) {
  517. out << LocalTag("foo") << "bar";
  518. ExpectEmit("!foo bar");
  519. }
  520. TEST_F(EmitterTest, ComplexDoc) {
  521. out << BeginMap;
  522. out << Key << "receipt";
  523. out << Value << "Oz-Ware Purchase Invoice";
  524. out << Key << "date";
  525. out << Value << "2007-08-06";
  526. out << Key << "customer";
  527. out << Value;
  528. out << BeginMap;
  529. out << Key << "given";
  530. out << Value << "Dorothy";
  531. out << Key << "family";
  532. out << Value << "Gale";
  533. out << EndMap;
  534. out << Key << "items";
  535. out << Value;
  536. out << BeginSeq;
  537. out << BeginMap;
  538. out << Key << "part_no";
  539. out << Value << "A4786";
  540. out << Key << "descrip";
  541. out << Value << "Water Bucket (Filled)";
  542. out << Key << "price";
  543. out << Value << 1.47;
  544. out << Key << "quantity";
  545. out << Value << 4;
  546. out << EndMap;
  547. out << BeginMap;
  548. out << Key << "part_no";
  549. out << Value << "E1628";
  550. out << Key << "descrip";
  551. out << Value << "High Heeled \"Ruby\" Slippers";
  552. out << Key << "price";
  553. out << Value << 100.27;
  554. out << Key << "quantity";
  555. out << Value << 1;
  556. out << EndMap;
  557. out << EndSeq;
  558. out << Key << "bill-to";
  559. out << Value << Anchor("id001");
  560. out << BeginMap;
  561. out << Key << "street";
  562. out << Value << Literal << "123 Tornado Alley\nSuite 16";
  563. out << Key << "city";
  564. out << Value << "East Westville";
  565. out << Key << "state";
  566. out << Value << "KS";
  567. out << EndMap;
  568. out << Key << "ship-to";
  569. out << Value << Alias("id001");
  570. out << EndMap;
  571. ExpectEmit(
  572. "receipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n "
  573. "given: Dorothy\n family: Gale\nitems:\n - part_no: A4786\n "
  574. "descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n - "
  575. "part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: "
  576. "100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado "
  577. "Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: "
  578. "*id001");
  579. }
  580. TEST_F(EmitterTest, STLContainers) {
  581. out << BeginSeq;
  582. std::vector<int> primes;
  583. primes.push_back(2);
  584. primes.push_back(3);
  585. primes.push_back(5);
  586. primes.push_back(7);
  587. primes.push_back(11);
  588. primes.push_back(13);
  589. out << Flow << primes;
  590. std::map<std::string, int> ages;
  591. ages["Daniel"] = 26;
  592. ages["Jesse"] = 24;
  593. out << ages;
  594. out << EndSeq;
  595. ExpectEmit("- [2, 3, 5, 7, 11, 13]\n- Daniel: 26\n Jesse: 24");
  596. }
  597. TEST_F(EmitterTest, CommentStyle) {
  598. out.SetPreCommentIndent(1);
  599. out.SetPostCommentIndent(2);
  600. out << BeginMap;
  601. out << Key << "method";
  602. out << Value << "least squares" << Comment("should we change this method?");
  603. out << EndMap;
  604. ExpectEmit("method: least squares # should we change this method?");
  605. }
  606. TEST_F(EmitterTest, SimpleComment) {
  607. out << BeginMap;
  608. out << Key << "method";
  609. out << Value << "least squares" << Comment("should we change this method?");
  610. out << EndMap;
  611. ExpectEmit("method: least squares # should we change this method?");
  612. }
  613. TEST_F(EmitterTest, MultiLineComment) {
  614. out << BeginSeq;
  615. out << "item 1"
  616. << Comment(
  617. "really really long\ncomment that couldn't "
  618. "possibly\nfit on one line");
  619. out << "item 2";
  620. out << EndSeq;
  621. ExpectEmit(
  622. "- item 1 # really really long\n # comment that couldn't "
  623. "possibly\n # fit on one line\n- item 2");
  624. }
  625. TEST_F(EmitterTest, ComplexComments) {
  626. out << BeginMap;
  627. out << LongKey << Key << "long key" << Comment("long key");
  628. out << Value << "value";
  629. out << EndMap;
  630. ExpectEmit("? long key # long key\n: value");
  631. }
  632. TEST_F(EmitterTest, InitialComment) {
  633. out << Comment("A comment describing the purpose of the file.");
  634. out << BeginMap << Key << "key" << Value << "value" << EndMap;
  635. ExpectEmit("# A comment describing the purpose of the file.\nkey: value");
  636. }
  637. TEST_F(EmitterTest, InitialCommentWithDocIndicator) {
  638. out << BeginDoc << Comment("A comment describing the purpose of the file.");
  639. out << BeginMap << Key << "key" << Value << "value" << EndMap;
  640. ExpectEmit(
  641. "---\n# A comment describing the purpose of the file.\nkey: value");
  642. }
  643. TEST_F(EmitterTest, CommentInFlowSeq) {
  644. out << Flow << BeginSeq << "foo" << Comment("foo!") << "bar" << EndSeq;
  645. ExpectEmit("[foo, # foo!\nbar]");
  646. }
  647. TEST_F(EmitterTest, CommentInFlowMap) {
  648. out << Flow << BeginMap;
  649. out << Key << "foo" << Value << "foo value";
  650. out << Key << "bar" << Value << "bar value" << Comment("bar!");
  651. out << Key << "baz" << Value << "baz value" << Comment("baz!");
  652. out << EndMap;
  653. ExpectEmit(
  654. "{foo: foo value, bar: bar value, # bar!\nbaz: baz value, # baz!\n}");
  655. }
  656. TEST_F(EmitterTest, Indentation) {
  657. out << Indent(4);
  658. out << BeginSeq;
  659. out << BeginMap;
  660. out << Key << "key 1" << Value << "value 1";
  661. out << Key << "key 2" << Value << BeginSeq << "a"
  662. << "b"
  663. << "c" << EndSeq;
  664. out << EndMap;
  665. out << EndSeq;
  666. ExpectEmit(
  667. "- key 1: value 1\n key 2:\n - a\n - b\n - "
  668. " c");
  669. }
  670. TEST_F(EmitterTest, SimpleGlobalSettings) {
  671. out.SetIndent(4);
  672. out.SetMapFormat(LongKey);
  673. out << BeginSeq;
  674. out << BeginMap;
  675. out << Key << "key 1" << Value << "value 1";
  676. out << Key << "key 2" << Value << Flow << BeginSeq << "a"
  677. << "b"
  678. << "c" << EndSeq;
  679. out << EndMap;
  680. out << EndSeq;
  681. ExpectEmit("- ? key 1\n : value 1\n ? key 2\n : [a, b, c]");
  682. }
  683. TEST_F(EmitterTest, GlobalLongKeyOnSeq) {
  684. out.SetMapFormat(LongKey);
  685. out << BeginMap;
  686. out << Key << Anchor("key");
  687. out << BeginSeq << "a"
  688. << "b" << EndSeq;
  689. out << Value << Anchor("value");
  690. out << BeginSeq << "c"
  691. << "d" << EndSeq;
  692. out << Key << Alias("key") << Value << Alias("value");
  693. out << EndMap;
  694. ExpectEmit(R"(? &key
  695. - a
  696. - b
  697. : &value
  698. - c
  699. - d
  700. ? *key
  701. : *value)");
  702. }
  703. TEST_F(EmitterTest, GlobalLongKeyOnMap) {
  704. out.SetMapFormat(LongKey);
  705. out << BeginMap;
  706. out << Key << Anchor("key");
  707. out << BeginMap << "a"
  708. << "b" << EndMap;
  709. out << Value << Anchor("value");
  710. out << BeginMap << "c"
  711. << "d" << EndMap;
  712. out << Key << Alias("key") << Value << Alias("value");
  713. out << EndMap;
  714. ExpectEmit(R"(? &key
  715. ? a
  716. : b
  717. : &value
  718. ? c
  719. : d
  720. ? *key
  721. : *value)");
  722. }
  723. TEST_F(EmitterTest, GlobalSettingStyleOnSeqNode) {
  724. Node n(Load(R"(foo:
  725. - 1
  726. - 2
  727. - 3
  728. bar: aa)"));
  729. out.SetSeqFormat(YAML::Flow);
  730. out << n;
  731. ExpectEmit(R"(foo: [1, 2, 3]
  732. bar: aa)");
  733. }
  734. TEST_F(EmitterTest, GlobalSettingStyleOnMapNode) {
  735. Node n(Load(R"(-
  736. foo: a
  737. bar: b
  738. - 2
  739. - 3)"));
  740. out.SetMapFormat(YAML::Flow);
  741. out << n;
  742. ExpectEmit(R"(- {foo: a, bar: b}
  743. - 2
  744. - 3)");
  745. }
  746. TEST_F(EmitterTest, ComplexGlobalSettings) {
  747. out << BeginSeq;
  748. out << Block;
  749. out << BeginMap;
  750. out << Key << "key 1" << Value << "value 1";
  751. out << Key << "key 2" << Value;
  752. out.SetSeqFormat(Flow);
  753. out << BeginSeq << "a"
  754. << "b"
  755. << "c" << EndSeq;
  756. out << EndMap;
  757. out << BeginMap;
  758. out << Key << BeginSeq << 1 << 2 << EndSeq;
  759. out << Value << BeginMap << Key << "a" << Value << "b" << EndMap;
  760. out << EndMap;
  761. out << EndSeq;
  762. ExpectEmit("- key 1: value 1\n key 2: [a, b, c]\n- [1, 2]:\n a: b");
  763. }
  764. TEST_F(EmitterTest, Null) {
  765. out << BeginSeq;
  766. out << Null;
  767. out << BeginMap;
  768. out << Key << "null value" << Value << Null;
  769. out << Key << Null << Value << "null key";
  770. out << EndMap;
  771. out << EndSeq;
  772. ExpectEmit("- ~\n- null value: ~\n ~: null key");
  773. }
  774. TEST_F(EmitterTest, OutputCharset) {
  775. out << BeginSeq;
  776. out.SetOutputCharset(EmitNonAscii);
  777. out << "\x24 \xC2\xA2 \xE2\x82\xAC";
  778. out.SetOutputCharset(EscapeNonAscii);
  779. out << "\x24 \xC2\xA2 \xE2\x82\xAC";
  780. out << EndSeq;
  781. ExpectEmit("- \x24 \xC2\xA2 \xE2\x82\xAC\n- \"\x24 \\xa2 \\u20ac\"");
  782. }
  783. TEST_F(EmitterTest, EscapedUnicode) {
  784. out << EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
  785. ExpectEmit("\"$ \\xa2 \\u20ac \\U00024b62\"");
  786. }
  787. TEST_F(EmitterTest, Unicode) {
  788. out << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
  789. ExpectEmit("\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2");
  790. }
  791. TEST_F(EmitterTest, DoubleQuotedUnicode) {
  792. out << DoubleQuoted << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
  793. ExpectEmit("\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\"");
  794. }
  795. TEST_F(EmitterTest, EscapedJsonString) {
  796. out.SetStringFormat(DoubleQuoted);
  797. out.SetOutputCharset(EscapeAsJson);
  798. out << "\" \\ "
  799. "\x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0A \x0B \x0C \x0D \x0E \x0F "
  800. "\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1A \x1B \x1C \x1D \x1E \x1F "
  801. "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
  802. ExpectEmit(R"("\" \\ \u0001 \u0002 \u0003 \u0004 \u0005 \u0006 \u0007 \b \t )"
  803. R"(\n \u000b \f \r \u000e \u000f \u0010 \u0011 \u0012 \u0013 )"
  804. R"(\u0014 \u0015 \u0016 \u0017 \u0018 \u0019 \u001a \u001b )"
  805. R"(\u001c \u001d \u001e \u001f )"
  806. "$ \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\"");
  807. }
  808. TEST_F(EmitterTest, EscapedCharacters) {
  809. out << BeginSeq
  810. << '\x00'
  811. << '\x0C'
  812. << '\x0D'
  813. << EndSeq;
  814. ExpectEmit("- \"\\x00\"\n- \"\\f\"\n- \"\\r\"");
  815. }
  816. TEST_F(EmitterTest, CharactersEscapedAsJson) {
  817. out.SetOutputCharset(EscapeAsJson);
  818. out << BeginSeq
  819. << '\x00'
  820. << '\x0C'
  821. << '\x0D'
  822. << EndSeq;
  823. ExpectEmit("- \"\\u0000\"\n- \"\\f\"\n- \"\\r\"");
  824. }
  825. TEST_F(EmitterTest, DoubleQuotedString) {
  826. out << DoubleQuoted << "\" \\ \n \t \r \b \x15 \xEF\xBB\xBF \x24";
  827. ExpectEmit("\"\\\" \\\\ \\n \\t \\r \\b \\x15 \\ufeff $\"");
  828. }
  829. struct Foo {
  830. Foo() : x(0) {}
  831. Foo(int x_, const std::string& bar_) : x(x_), bar(bar_) {}
  832. int x;
  833. std::string bar;
  834. };
  835. Emitter& operator<<(Emitter& out, const Foo& foo) {
  836. out << BeginMap;
  837. out << Key << "x" << Value << foo.x;
  838. out << Key << "bar" << Value << foo.bar;
  839. out << EndMap;
  840. return out;
  841. }
  842. TEST_F(EmitterTest, UserType) {
  843. out << BeginSeq;
  844. out << Foo(5, "hello");
  845. out << Foo(3, "goodbye");
  846. out << EndSeq;
  847. ExpectEmit("- x: 5\n bar: hello\n- x: 3\n bar: goodbye");
  848. }
  849. TEST_F(EmitterTest, UserType2) {
  850. out << BeginSeq;
  851. out << Foo(5, "\r");
  852. out << EndSeq;
  853. ExpectEmit("- x: 5\n bar: \"\\r\"");
  854. }
  855. TEST_F(EmitterTest, UserTypeInContainer) {
  856. std::vector<Foo> fv;
  857. fv.push_back(Foo(5, "hello"));
  858. fv.push_back(Foo(3, "goodbye"));
  859. out << fv;
  860. ExpectEmit("- x: 5\n bar: hello\n- x: 3\n bar: goodbye");
  861. }
  862. template <typename T>
  863. Emitter& operator<<(Emitter& out, const T* v) {
  864. if (v)
  865. out << *v;
  866. else
  867. out << Null;
  868. return out;
  869. }
  870. TEST_F(EmitterTest, PointerToInt) {
  871. int foo = 5;
  872. int* bar = &foo;
  873. int* baz = 0;
  874. out << BeginSeq;
  875. out << bar << baz;
  876. out << EndSeq;
  877. ExpectEmit("- 5\n- ~");
  878. }
  879. TEST_F(EmitterTest, PointerToUserType) {
  880. Foo foo(5, "hello");
  881. Foo* bar = &foo;
  882. Foo* baz = 0;
  883. out << BeginSeq;
  884. out << bar << baz;
  885. out << EndSeq;
  886. ExpectEmit("- x: 5\n bar: hello\n- ~");
  887. }
  888. TEST_F(EmitterTest, NewlineAtEnd) {
  889. out << "Hello" << Newline << Newline;
  890. ExpectEmit("Hello\n\n");
  891. }
  892. TEST_F(EmitterTest, NewlineInBlockSequence) {
  893. out << BeginSeq;
  894. out << "a" << Newline << "b"
  895. << "c" << Newline << "d";
  896. out << EndSeq;
  897. ExpectEmit("- a\n\n- b\n- c\n\n- d");
  898. }
  899. TEST_F(EmitterTest, NewlineInFlowSequence) {
  900. out << Flow << BeginSeq;
  901. out << "a" << Newline << "b"
  902. << "c" << Newline << "d";
  903. out << EndSeq;
  904. ExpectEmit("[a,\nb, c,\nd]");
  905. }
  906. TEST_F(EmitterTest, NewlineInBlockMap) {
  907. out << BeginMap;
  908. out << Key << "a" << Value << "foo" << Newline;
  909. out << Key << "b" << Newline << Value << "bar";
  910. out << LongKey << Key << "c" << Newline << Value << "car";
  911. out << EndMap;
  912. ExpectEmit("a: foo\nb:\n bar\n? c\n\n: car");
  913. }
  914. TEST_F(EmitterTest, NewlineInFlowMap) {
  915. out << Flow << BeginMap;
  916. out << Key << "a" << Value << "foo" << Newline;
  917. out << Key << "b" << Value << "bar";
  918. out << EndMap;
  919. ExpectEmit("{a: foo,\nb: bar}");
  920. }
  921. TEST_F(EmitterTest, LotsOfNewlines) {
  922. out << BeginSeq;
  923. out << "a" << Newline;
  924. out << BeginSeq;
  925. out << "b"
  926. << "c" << Newline;
  927. out << EndSeq;
  928. out << Newline;
  929. out << BeginMap;
  930. out << Newline << Key << "d" << Value << Newline << "e";
  931. out << LongKey << Key << "f" << Newline << Value << "foo";
  932. out << EndMap;
  933. out << EndSeq;
  934. ExpectEmit("- a\n\n-\n - b\n - c\n\n\n-\n d:\n e\n ? f\n\n : foo");
  935. }
  936. TEST_F(EmitterTest, Binary) {
  937. out << Binary(reinterpret_cast<const unsigned char*>("Hello, World!"), 13);
  938. ExpectEmit("!!binary \"SGVsbG8sIFdvcmxkIQ==\"");
  939. }
  940. TEST_F(EmitterTest, LongBinary) {
  941. out << Binary(
  942. reinterpret_cast<const unsigned char*>(
  943. "Man is distinguished, not only by his reason, but by this "
  944. "singular passion from other animals, which is a lust of the "
  945. "mind, that by a perseverance of delight in the continued and "
  946. "indefatigable generation of knowledge, exceeds the short "
  947. "vehemence of any carnal pleasure.\n"),
  948. 270);
  949. ExpectEmit(
  950. "!!binary "
  951. "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS"
  952. "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG"
  953. "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi"
  954. "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG"
  955. "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS"
  956. "4K\"");
  957. }
  958. TEST_F(EmitterTest, EmptyBinary) {
  959. out << Binary(reinterpret_cast<const unsigned char*>(""), 0);
  960. ExpectEmit("!!binary \"\"");
  961. }
  962. TEST_F(EmitterTest, ColonAtEndOfScalar) {
  963. out << "a:";
  964. ExpectEmit("\"a:\"");
  965. }
  966. TEST_F(EmitterTest, ColonAsScalar) {
  967. out << BeginMap;
  968. out << Key << "apple" << Value << ":";
  969. out << Key << "banana" << Value << ":";
  970. out << EndMap;
  971. ExpectEmit("apple: \":\"\nbanana: \":\"");
  972. }
  973. TEST_F(EmitterTest, ColonAtEndOfScalarInFlow) {
  974. out << Flow << BeginMap << Key << "C:" << Value << "C:" << EndMap;
  975. ExpectEmit("{\"C:\": \"C:\"}");
  976. }
  977. TEST_F(EmitterTest, GlobalBoolFormatting) {
  978. out << BeginSeq;
  979. out.SetBoolFormat(UpperCase);
  980. out.SetBoolFormat(YesNoBool);
  981. out << true;
  982. out << false;
  983. out.SetBoolFormat(TrueFalseBool);
  984. out << true;
  985. out << false;
  986. out.SetBoolFormat(OnOffBool);
  987. out << true;
  988. out << false;
  989. out.SetBoolFormat(LowerCase);
  990. out.SetBoolFormat(YesNoBool);
  991. out << true;
  992. out << false;
  993. out.SetBoolFormat(TrueFalseBool);
  994. out << true;
  995. out << false;
  996. out.SetBoolFormat(OnOffBool);
  997. out << true;
  998. out << false;
  999. out.SetBoolFormat(CamelCase);
  1000. out.SetBoolFormat(YesNoBool);
  1001. out << true;
  1002. out << false;
  1003. out.SetBoolFormat(TrueFalseBool);
  1004. out << true;
  1005. out << false;
  1006. out.SetBoolFormat(OnOffBool);
  1007. out << true;
  1008. out << false;
  1009. out.SetBoolFormat(ShortBool);
  1010. out.SetBoolFormat(UpperCase);
  1011. out.SetBoolFormat(YesNoBool);
  1012. out << true;
  1013. out << false;
  1014. out.SetBoolFormat(TrueFalseBool);
  1015. out << true;
  1016. out << false;
  1017. out.SetBoolFormat(OnOffBool);
  1018. out << true;
  1019. out << false;
  1020. out << EndSeq;
  1021. ExpectEmit(
  1022. "- YES\n- NO\n- TRUE\n- FALSE\n- ON\n- OFF\n"
  1023. "- yes\n- no\n- true\n- false\n- on\n- off\n"
  1024. "- Yes\n- No\n- True\n- False\n- On\n- Off\n"
  1025. "- Y\n- N\n- Y\n- N\n- Y\n- N");
  1026. }
  1027. TEST_F(EmitterTest, BoolFormatting) {
  1028. out << BeginSeq;
  1029. out << TrueFalseBool << UpperCase << true;
  1030. out << TrueFalseBool << CamelCase << true;
  1031. out << TrueFalseBool << LowerCase << true;
  1032. out << TrueFalseBool << UpperCase << false;
  1033. out << TrueFalseBool << CamelCase << false;
  1034. out << TrueFalseBool << LowerCase << false;
  1035. out << YesNoBool << UpperCase << true;
  1036. out << YesNoBool << CamelCase << true;
  1037. out << YesNoBool << LowerCase << true;
  1038. out << YesNoBool << UpperCase << false;
  1039. out << YesNoBool << CamelCase << false;
  1040. out << YesNoBool << LowerCase << false;
  1041. out << OnOffBool << UpperCase << true;
  1042. out << OnOffBool << CamelCase << true;
  1043. out << OnOffBool << LowerCase << true;
  1044. out << OnOffBool << UpperCase << false;
  1045. out << OnOffBool << CamelCase << false;
  1046. out << OnOffBool << LowerCase << false;
  1047. out << ShortBool << UpperCase << true;
  1048. out << ShortBool << CamelCase << true;
  1049. out << ShortBool << LowerCase << true;
  1050. out << ShortBool << UpperCase << false;
  1051. out << ShortBool << CamelCase << false;
  1052. out << ShortBool << LowerCase << false;
  1053. out << EndSeq;
  1054. ExpectEmit(
  1055. "- TRUE\n- True\n- true\n- FALSE\n- False\n- false\n"
  1056. "- YES\n- Yes\n- yes\n- NO\n- No\n- no\n"
  1057. "- ON\n- On\n- on\n- OFF\n- Off\n- off\n"
  1058. "- Y\n- Y\n- y\n- N\n- N\n- n");
  1059. }
  1060. TEST_F(EmitterTest, GlobalNullFormatting) {
  1061. out << Flow << BeginSeq;
  1062. out.SetNullFormat(LowerNull);
  1063. out << Null;
  1064. out.SetNullFormat(UpperNull);
  1065. out << Null;
  1066. out.SetNullFormat(CamelNull);
  1067. out << Null;
  1068. out.SetNullFormat(TildeNull);
  1069. out << Null;
  1070. out << EndSeq;
  1071. ExpectEmit("[null, NULL, Null, ~]");
  1072. }
  1073. TEST_F(EmitterTest, NullFormatting) {
  1074. out << Flow << BeginSeq;
  1075. out << LowerNull << Null;
  1076. out << UpperNull << Null;
  1077. out << CamelNull << Null;
  1078. out << TildeNull << Null;
  1079. out << EndSeq;
  1080. ExpectEmit("[null, NULL, Null, ~]");
  1081. }
  1082. TEST_F(EmitterTest, NullFormattingOnNode) {
  1083. Node n(Load("null"));
  1084. out << Flow << BeginSeq;
  1085. out.SetNullFormat(LowerNull);
  1086. out << n;
  1087. out.SetNullFormat(UpperNull);
  1088. out << n;
  1089. out.SetNullFormat(CamelNull);
  1090. out << n;
  1091. out.SetNullFormat(TildeNull);
  1092. out << n;
  1093. out << EndSeq;
  1094. ExpectEmit("[null, NULL, Null, ~]");
  1095. }
  1096. // TODO: Fix this test.
  1097. // TEST_F(EmitterTest, DocStartAndEnd) {
  1098. // out << BeginDoc;
  1099. // out << BeginSeq << 1 << 2 << 3 << EndSeq;
  1100. // out << BeginDoc;
  1101. // out << "Hi there!";
  1102. // out << EndDoc;
  1103. // out << EndDoc;
  1104. // out << EndDoc;
  1105. // out << BeginDoc;
  1106. // out << VerbatimTag("foo") << "bar";
  1107. // ExpectEmit(
  1108. // "---\n- 1\n- 2\n- 3\n---\nHi there!\n...\n...\n...\n---\n!<foo> bar");
  1109. //}
  1110. TEST_F(EmitterTest, ImplicitDocStart) {
  1111. out << "Hi";
  1112. out << "Bye";
  1113. out << "Oops";
  1114. ExpectEmit("Hi\n---\nBye\n---\nOops");
  1115. }
  1116. TEST_F(EmitterTest, EmptyString) {
  1117. out << BeginMap;
  1118. out << Key << "key" << Value << "";
  1119. out << EndMap;
  1120. ExpectEmit("key: \"\"");
  1121. }
  1122. TEST_F(EmitterTest, SingleChar) {
  1123. out << BeginSeq;
  1124. out << 'a';
  1125. out << ':';
  1126. out << (char)0x10;
  1127. out << '\n';
  1128. out << ' ';
  1129. out << '\t';
  1130. out << EndSeq;
  1131. ExpectEmit("- a\n- \":\"\n- \"\\x10\"\n- \"\\n\"\n- \" \"\n- \"\\t\"");
  1132. }
  1133. TEST_F(EmitterTest, DefaultPrecision) {
  1134. out << BeginSeq;
  1135. out << 1.3125f;
  1136. out << 1.23455810546875;
  1137. out << EndSeq;
  1138. ExpectEmit("- 1.3125\n- 1.23455810546875");
  1139. }
  1140. TEST_F(EmitterTest, SetPrecision) {
  1141. out << BeginSeq;
  1142. out << FloatPrecision(3) << 1.3125f;
  1143. out << DoublePrecision(6) << 1.23455810546875;
  1144. out << EndSeq;
  1145. ExpectEmit("- 1.31\n- 1.23456");
  1146. }
  1147. TEST_F(EmitterTest, DashInBlockContext) {
  1148. out << BeginMap;
  1149. out << Key << "key" << Value << "-";
  1150. out << EndMap;
  1151. ExpectEmit("key: \"-\"");
  1152. }
  1153. TEST_F(EmitterTest, HexAndOct) {
  1154. out << Flow << BeginSeq;
  1155. out << 31;
  1156. out << Hex << 31;
  1157. out << Oct << 31;
  1158. out << EndSeq;
  1159. ExpectEmit("[31, 0x1f, 037]");
  1160. }
  1161. TEST_F(EmitterTest, CompactMapWithNewline) {
  1162. out << Comment("Characteristics");
  1163. out << BeginSeq;
  1164. out << BeginMap;
  1165. out << Key << "color" << Value << "blue";
  1166. out << Key << "height" << Value << 120;
  1167. out << EndMap;
  1168. out << Newline << Newline;
  1169. out << Comment("Skills");
  1170. out << BeginMap;
  1171. out << Key << "attack" << Value << 23;
  1172. out << Key << "intelligence" << Value << 56;
  1173. out << EndMap;
  1174. out << EndSeq;
  1175. ExpectEmit(
  1176. "# Characteristics\n"
  1177. "- color: blue\n"
  1178. " height: 120\n"
  1179. "\n"
  1180. "# Skills\n"
  1181. "- attack: 23\n"
  1182. " intelligence: 56");
  1183. }
  1184. TEST_F(EmitterTest, ForceSingleQuotedToDouble) {
  1185. out << SingleQuoted << "Hello\nWorld";
  1186. ExpectEmit("\"Hello\\nWorld\"");
  1187. }
  1188. TEST_F(EmitterTest, QuoteNull) {
  1189. out << "null";
  1190. ExpectEmit("\"null\"");
  1191. }
  1192. TEST_F(EmitterTest, ValueOfDoubleQuote) {
  1193. out << YAML::BeginMap;
  1194. out << YAML::Key << "foo" << YAML::Value << '"';
  1195. out << YAML::EndMap;
  1196. ExpectEmit("foo: \"\\\"\"");
  1197. }
  1198. TEST_F(EmitterTest, ValueOfBackslash) {
  1199. out << YAML::BeginMap;
  1200. out << YAML::Key << "foo" << YAML::Value << '\\';
  1201. out << YAML::EndMap;
  1202. ExpectEmit("foo: \"\\\\\"");
  1203. }
  1204. TEST_F(EmitterTest, Infinity) {
  1205. out << YAML::BeginMap;
  1206. out << YAML::Key << "foo" << YAML::Value
  1207. << std::numeric_limits<float>::infinity();
  1208. out << YAML::Key << "bar" << YAML::Value
  1209. << std::numeric_limits<double>::infinity();
  1210. out << YAML::EndMap;
  1211. ExpectEmit(
  1212. "foo: .inf\n"
  1213. "bar: .inf");
  1214. }
  1215. TEST_F(EmitterTest, NegInfinity) {
  1216. out << YAML::BeginMap;
  1217. out << YAML::Key << "foo" << YAML::Value
  1218. << -std::numeric_limits<float>::infinity();
  1219. out << YAML::Key << "bar" << YAML::Value
  1220. << -std::numeric_limits<double>::infinity();
  1221. out << YAML::EndMap;
  1222. ExpectEmit(
  1223. "foo: -.inf\n"
  1224. "bar: -.inf");
  1225. }
  1226. TEST_F(EmitterTest, NaN) {
  1227. out << YAML::BeginMap;
  1228. out << YAML::Key << "foo" << YAML::Value
  1229. << std::numeric_limits<float>::quiet_NaN();
  1230. out << YAML::Key << "bar" << YAML::Value
  1231. << std::numeric_limits<double>::quiet_NaN();
  1232. out << YAML::EndMap;
  1233. ExpectEmit(
  1234. "foo: .nan\n"
  1235. "bar: .nan");
  1236. }
  1237. TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapWithNewLine) {
  1238. out << YAML::BeginMap;
  1239. out << YAML::Key << "NodeA" << YAML::Value << YAML::BeginMap;
  1240. out << YAML::Key << "k" << YAML::Value << YAML::Flow << YAML::BeginSeq;
  1241. out << YAML::BeginMap << YAML::Key << "i" << YAML::Value << 0 << YAML::EndMap
  1242. << YAML::Newline;
  1243. out << YAML::BeginMap << YAML::Key << "i" << YAML::Value << 1 << YAML::EndMap
  1244. << YAML::Newline;
  1245. out << YAML::EndSeq;
  1246. out << YAML::EndMap;
  1247. out << YAML::Key << "NodeB" << YAML::Value << YAML::BeginMap;
  1248. out << YAML::Key << "k" << YAML::Value << YAML::Flow << YAML::BeginSeq;
  1249. out << YAML::BeginMap << YAML::Key << "i" << YAML::Value << 0 << YAML::EndMap
  1250. << YAML::Newline;
  1251. out << YAML::BeginMap << YAML::Key << "i" << YAML::Value << 1 << YAML::EndMap
  1252. << YAML::Newline;
  1253. out << YAML::EndSeq;
  1254. out << YAML::EndMap;
  1255. out << YAML::EndMap;
  1256. ExpectEmit(R"(NodeA:
  1257. k: [{i: 0},
  1258. {i: 1},
  1259. ]
  1260. NodeB:
  1261. k: [{i: 0},
  1262. {i: 1},
  1263. ])");
  1264. }
  1265. TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapWithNewLineUsingAliases) {
  1266. out << BeginMap;
  1267. out << Key << "Node" << Anchor("Node") << Value << BeginMap;
  1268. out << Key << "k" << Value << Flow << BeginSeq;
  1269. out << BeginMap << Key << "i" << Value << 0 << EndMap;
  1270. out << YAML::Newline;
  1271. out << BeginMap << Key << "i" << Value << 1 << EndMap;
  1272. out << YAML::Newline;
  1273. out << EndSeq << EndMap;
  1274. out << Key << "NodeA" << Alias("Node");
  1275. out << Key << "NodeB" << Alias("Node");
  1276. out << EndMap;
  1277. ExpectEmit(R"(Node: &Node
  1278. k: [{i: 0},
  1279. {i: 1},
  1280. ]
  1281. NodeA: *Node
  1282. NodeB: *Node)");
  1283. }
  1284. TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapUsingAliases) {
  1285. out << BeginMap;
  1286. out << Key << "Node" << Anchor("Node") << Value << BeginMap;
  1287. out << Key << "k" << Value << Flow << BeginSeq;
  1288. out << BeginMap << Key << "i" << Value << 0 << EndMap;
  1289. out << BeginMap << Key << "i" << Value << 1 << EndMap;
  1290. out << EndSeq << EndMap;
  1291. out << Key << "NodeA" << Alias("Node");
  1292. out << Key << "NodeB" << Alias("Node");
  1293. out << EndMap;
  1294. ExpectEmit(R"(Node: &Node
  1295. k: [{i: 0}, {i: 1}]
  1296. NodeA: *Node
  1297. NodeB: *Node)");
  1298. }
  1299. TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapWithNewLineUsingAliases2) {
  1300. out << BeginMap;
  1301. out << Key << "Seq" << Anchor("Seq") << Flow << BeginSeq;
  1302. out << BeginMap << Key << "i" << Value << 0 << EndMap;
  1303. out << YAML::Newline;
  1304. out << BeginMap << Key << "i" << Value << 1 << EndMap;
  1305. out << YAML::Newline;
  1306. out << EndSeq;
  1307. out << Key << "NodeA" << Value << BeginMap;
  1308. out << Key << "k" << Value << Alias("Seq") << EndMap;
  1309. out << Key << "NodeB" << Value << BeginMap;
  1310. out << Key << "k" << Value << Alias("Seq") << EndMap;
  1311. out << EndMap;
  1312. ExpectEmit(R"(Seq: &Seq [{i: 0},
  1313. {i: 1},
  1314. ]
  1315. NodeA:
  1316. k: *Seq
  1317. NodeB:
  1318. k: *Seq)");
  1319. }
  1320. TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapUsingAliases2) {
  1321. out << BeginMap;
  1322. out << Key << "Seq" << Anchor("Seq") << Value << Flow << BeginSeq;
  1323. out << BeginMap << Key << "i" << Value << 0 << EndMap;
  1324. out << BeginMap << Key << "i" << Value << 1 << EndMap;
  1325. out << EndSeq;
  1326. out << Key << "NodeA" << Value << BeginMap;
  1327. out << Key << "k" << Value << Alias("Seq") << EndMap;
  1328. out << Key << "NodeB" << Value << BeginMap;
  1329. out << Key << "k" << Value << Alias("Seq") << EndMap;
  1330. out << EndMap;
  1331. ExpectEmit(R"(Seq: &Seq [{i: 0}, {i: 1}]
  1332. NodeA:
  1333. k: *Seq
  1334. NodeB:
  1335. k: *Seq)");
  1336. }
  1337. TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapWithNewLineUsingAliases3) {
  1338. out << BeginMap;
  1339. out << Key << "Keys" << Value << Flow << BeginSeq;
  1340. out << Anchor("k0") << BeginMap << Key << "i" << Value << 0 << EndMap
  1341. << Newline;
  1342. out << Anchor("k1") << BeginMap << Key << "i" << Value << 1 << EndMap
  1343. << Newline;
  1344. out << EndSeq;
  1345. out << Key << "NodeA" << Value << BeginMap;
  1346. out << Key << "k" << Value << Flow << BeginSeq;
  1347. out << Alias("k0") << Newline << Alias("k1") << Newline;
  1348. out << EndSeq << EndMap;
  1349. out << Key << "NodeB" << Value << BeginMap;
  1350. out << Key << "k" << Value << Flow << BeginSeq;
  1351. out << Alias("k0") << Newline << Alias("k1") << Newline;
  1352. out << EndSeq << EndMap;
  1353. out << EndMap;
  1354. ExpectEmit(R"(Keys: [&k0 {i: 0},
  1355. &k1 {i: 1},
  1356. ]
  1357. NodeA:
  1358. k: [*k0,
  1359. *k1,
  1360. ]
  1361. NodeB:
  1362. k: [*k0,
  1363. *k1,
  1364. ])");
  1365. }
  1366. TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapUsingAliases3a) {
  1367. out << BeginMap;
  1368. out << Key << "Keys" << Value << BeginSeq;
  1369. out << Anchor("k0") << BeginMap << Key << "i" << Value << 0 << EndMap;
  1370. out << Anchor("k1") << BeginMap << Key << "i" << Value << 1 << EndMap;
  1371. out << EndSeq;
  1372. out << Key << "NodeA" << Value << BeginMap;
  1373. out << Key << "k" << Value << Flow << BeginSeq;
  1374. out << Alias("k0") << Alias("k1");
  1375. out << EndSeq << EndMap;
  1376. out << Key << "NodeB" << Value << BeginMap;
  1377. out << Key << "k" << Value << Flow << BeginSeq;
  1378. out << Alias("k0") << Alias("k1");
  1379. out << EndSeq << EndMap;
  1380. out << EndMap;
  1381. ExpectEmit(R"(Keys:
  1382. - &k0
  1383. i: 0
  1384. - &k1
  1385. i: 1
  1386. NodeA:
  1387. k: [*k0, *k1]
  1388. NodeB:
  1389. k: [*k0, *k1])");
  1390. }
  1391. TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapUsingAliases3b) {
  1392. out << BeginMap;
  1393. out << Key << "Keys" << Value << Flow << BeginSeq;
  1394. out << Anchor("k0") << BeginMap << Key << "i" << Value << 0 << EndMap;
  1395. out << Anchor("k1") << BeginMap << Key << "i" << Value << 1 << EndMap;
  1396. out << EndSeq;
  1397. out << Key << "NodeA" << Value << BeginMap;
  1398. out << Key << "k" << Value << Flow << BeginSeq;
  1399. out << Alias("k0") << Alias("k1");
  1400. out << EndSeq << EndMap;
  1401. out << Key << "NodeB" << Value << BeginMap;
  1402. out << Key << "k" << Value << Flow << BeginSeq;
  1403. out << Alias("k0") << Alias("k1");
  1404. out << EndSeq << EndMap;
  1405. out << EndMap;
  1406. ExpectEmit(R"(Keys: [&k0 {i: 0}, &k1 {i: 1}]
  1407. NodeA:
  1408. k: [*k0, *k1]
  1409. NodeB:
  1410. k: [*k0, *k1])");
  1411. }
  1412. TEST_F(EmitterTest, AnchorEncoding) {
  1413. Node node;
  1414. node["--- &$ [*$]1"] = 1;
  1415. out << node;
  1416. ExpectEmit("\"--- &$ [*$]1\": 1");
  1417. Node reparsed = YAML::Load(out.c_str());
  1418. EXPECT_EQ(reparsed["--- &$ [*$]1"].as<int>(), 1);
  1419. }
  1420. class EmitterErrorTest : public ::testing::Test {
  1421. protected:
  1422. void ExpectEmitError(const std::string& expectedError) {
  1423. ASSERT_FALSE(out.good()) << "Emitter cleanly produced: " << out.c_str();
  1424. EXPECT_EQ(expectedError, out.GetLastError());
  1425. }
  1426. Emitter out;
  1427. };
  1428. TEST_F(EmitterErrorTest, BadLocalTag) {
  1429. out << LocalTag("e!far") << "bar";
  1430. ExpectEmitError("invalid tag");
  1431. }
  1432. TEST_F(EmitterErrorTest, BadTagAndTag) {
  1433. out << VerbatimTag("!far") << VerbatimTag("!foo") << "bar";
  1434. ExpectEmitError(ErrorMsg::INVALID_TAG);
  1435. }
  1436. TEST_F(EmitterErrorTest, BadAnchorAndAnchor) {
  1437. out << Anchor("far") << Anchor("foo") << "bar";
  1438. ExpectEmitError(ErrorMsg::INVALID_ANCHOR);
  1439. }
  1440. TEST_F(EmitterErrorTest, BadEmptyAnchorOnGroup) {
  1441. out << BeginSeq << "bar" << Anchor("foo") << EndSeq;
  1442. ExpectEmitError(ErrorMsg::INVALID_ANCHOR);
  1443. }
  1444. TEST_F(EmitterErrorTest, BadEmptyTagOnGroup) {
  1445. out << BeginSeq << "bar" << VerbatimTag("!foo") << EndSeq;
  1446. ExpectEmitError(ErrorMsg::INVALID_TAG);
  1447. }
  1448. TEST_F(EmitterErrorTest, ExtraEndSeq) {
  1449. out << BeginSeq;
  1450. out << "Hello";
  1451. out << "World";
  1452. out << EndSeq;
  1453. out << EndSeq;
  1454. ExpectEmitError(ErrorMsg::UNEXPECTED_END_SEQ);
  1455. }
  1456. TEST_F(EmitterErrorTest, ExtraEndMap) {
  1457. out << BeginMap;
  1458. out << Key << "Hello" << Value << "World";
  1459. out << EndMap;
  1460. out << EndMap;
  1461. ExpectEmitError(ErrorMsg::UNEXPECTED_END_MAP);
  1462. }
  1463. TEST_F(EmitterErrorTest, InvalidAnchor) {
  1464. out << BeginSeq;
  1465. out << Anchor("new\nline") << "Test";
  1466. out << EndSeq;
  1467. ExpectEmitError(ErrorMsg::INVALID_ANCHOR);
  1468. }
  1469. TEST_F(EmitterErrorTest, InvalidAlias) {
  1470. out << BeginSeq;
  1471. out << Alias("new\nline");
  1472. out << EndSeq;
  1473. ExpectEmitError(ErrorMsg::INVALID_ALIAS);
  1474. }
  1475. } // namespace
  1476. } // namespace YAML