1 //===- unittest/Support/YAMLIOTest.cpp ------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/ADT/StringMap.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/Support/Casting.h"
14 #include "llvm/Support/Endian.h"
15 #include "llvm/Support/Format.h"
16 #include "llvm/Support/YAMLTraits.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 
20 using llvm::yaml::Hex16;
21 using llvm::yaml::Hex32;
22 using llvm::yaml::Hex64;
23 using llvm::yaml::Hex8;
24 using llvm::yaml::Input;
25 using llvm::yaml::IO;
26 using llvm::yaml::isNumeric;
27 using llvm::yaml::MappingNormalization;
28 using llvm::yaml::MappingTraits;
29 using llvm::yaml::Output;
30 using llvm::yaml::ScalarTraits;
31 using ::testing::StartsWith;
32 
33 
34 
35 
36 static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
37 }
38 
39 
40 
41 //===----------------------------------------------------------------------===//
42 //  Test MappingTraits
43 //===----------------------------------------------------------------------===//
44 
45 struct FooBar {
46   int foo;
47   int bar;
48 };
49 typedef std::vector<FooBar> FooBarSequence;
50 
51 LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar)
52 
53 struct FooBarContainer {
54   FooBarSequence fbs;
55 };
56 
57 namespace llvm {
58 namespace yaml {
59   template <>
60   struct MappingTraits<FooBar> {
61     static void mapping(IO &io, FooBar& fb) {
62       io.mapRequired("foo",    fb.foo);
63       io.mapRequired("bar",    fb.bar);
64     }
65   };
66 
67   template <> struct MappingTraits<FooBarContainer> {
68     static void mapping(IO &io, FooBarContainer &fb) {
69       io.mapRequired("fbs", fb.fbs);
70     }
71   };
72 }
73 }
74 
75 
76 //
77 // Test the reading of a yaml mapping
78 //
79 TEST(YAMLIO, TestMapRead) {
80   FooBar doc;
81   {
82     Input yin("---\nfoo:  3\nbar:  5\n...\n");
83     yin >> doc;
84 
85     EXPECT_FALSE(yin.error());
86     EXPECT_EQ(doc.foo, 3);
87     EXPECT_EQ(doc.bar, 5);
88   }
89 
90   {
91     Input yin("{foo: 3, bar: 5}");
92     yin >> doc;
93 
94     EXPECT_FALSE(yin.error());
95     EXPECT_EQ(doc.foo, 3);
96     EXPECT_EQ(doc.bar, 5);
97   }
98 }
99 
100 TEST(YAMLIO, TestMalformedMapRead) {
101   FooBar doc;
102   Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages);
103   yin >> doc;
104   EXPECT_TRUE(!!yin.error());
105 }
106 
107 //
108 // Test the reading of a yaml sequence of mappings
109 //
110 TEST(YAMLIO, TestSequenceMapRead) {
111   FooBarSequence seq;
112   Input yin("---\n - foo:  3\n   bar:  5\n - foo:  7\n   bar:  9\n...\n");
113   yin >> seq;
114 
115   EXPECT_FALSE(yin.error());
116   EXPECT_EQ(seq.size(), 2UL);
117   FooBar& map1 = seq[0];
118   FooBar& map2 = seq[1];
119   EXPECT_EQ(map1.foo, 3);
120   EXPECT_EQ(map1.bar, 5);
121   EXPECT_EQ(map2.foo, 7);
122   EXPECT_EQ(map2.bar, 9);
123 }
124 
125 //
126 // Test the reading of a map containing a yaml sequence of mappings
127 //
128 TEST(YAMLIO, TestContainerSequenceMapRead) {
129   {
130     FooBarContainer cont;
131     Input yin2("---\nfbs:\n - foo: 3\n   bar: 5\n - foo: 7\n   bar: 9\n...\n");
132     yin2 >> cont;
133 
134     EXPECT_FALSE(yin2.error());
135     EXPECT_EQ(cont.fbs.size(), 2UL);
136     EXPECT_EQ(cont.fbs[0].foo, 3);
137     EXPECT_EQ(cont.fbs[0].bar, 5);
138     EXPECT_EQ(cont.fbs[1].foo, 7);
139     EXPECT_EQ(cont.fbs[1].bar, 9);
140   }
141 
142   {
143     FooBarContainer cont;
144     Input yin("---\nfbs:\n...\n");
145     yin >> cont;
146     // Okay: Empty node represents an empty array.
147     EXPECT_FALSE(yin.error());
148     EXPECT_EQ(cont.fbs.size(), 0UL);
149   }
150 
151   {
152     FooBarContainer cont;
153     Input yin("---\nfbs: !!null null\n...\n");
154     yin >> cont;
155     // Okay: null represents an empty array.
156     EXPECT_FALSE(yin.error());
157     EXPECT_EQ(cont.fbs.size(), 0UL);
158   }
159 
160   {
161     FooBarContainer cont;
162     Input yin("---\nfbs: ~\n...\n");
163     yin >> cont;
164     // Okay: null represents an empty array.
165     EXPECT_FALSE(yin.error());
166     EXPECT_EQ(cont.fbs.size(), 0UL);
167   }
168 
169   {
170     FooBarContainer cont;
171     Input yin("---\nfbs: null\n...\n");
172     yin >> cont;
173     // Okay: null represents an empty array.
174     EXPECT_FALSE(yin.error());
175     EXPECT_EQ(cont.fbs.size(), 0UL);
176   }
177 }
178 
179 //
180 // Test the reading of a map containing a malformed yaml sequence
181 //
182 TEST(YAMLIO, TestMalformedContainerSequenceMapRead) {
183   {
184     FooBarContainer cont;
185     Input yin("---\nfbs:\n   foo: 3\n   bar: 5\n...\n", nullptr,
186               suppressErrorMessages);
187     yin >> cont;
188     // Error: fbs is not a sequence.
189     EXPECT_TRUE(!!yin.error());
190     EXPECT_EQ(cont.fbs.size(), 0UL);
191   }
192 
193   {
194     FooBarContainer cont;
195     Input yin("---\nfbs: 'scalar'\n...\n", nullptr, suppressErrorMessages);
196     yin >> cont;
197     // This should be an error.
198     EXPECT_TRUE(!!yin.error());
199     EXPECT_EQ(cont.fbs.size(), 0UL);
200   }
201 }
202 
203 //
204 // Test writing then reading back a sequence of mappings
205 //
206 TEST(YAMLIO, TestSequenceMapWriteAndRead) {
207   std::string intermediate;
208   {
209     FooBar entry1;
210     entry1.foo = 10;
211     entry1.bar = -3;
212     FooBar entry2;
213     entry2.foo = 257;
214     entry2.bar = 0;
215     FooBarSequence seq;
216     seq.push_back(entry1);
217     seq.push_back(entry2);
218 
219     llvm::raw_string_ostream ostr(intermediate);
220     Output yout(ostr);
221     yout << seq;
222   }
223 
224   {
225     Input yin(intermediate);
226     FooBarSequence seq2;
227     yin >> seq2;
228 
229     EXPECT_FALSE(yin.error());
230     EXPECT_EQ(seq2.size(), 2UL);
231     FooBar& map1 = seq2[0];
232     FooBar& map2 = seq2[1];
233     EXPECT_EQ(map1.foo, 10);
234     EXPECT_EQ(map1.bar, -3);
235     EXPECT_EQ(map2.foo, 257);
236     EXPECT_EQ(map2.bar, 0);
237   }
238 }
239 
240 //
241 // Test YAML filename handling.
242 //
243 static void testErrorFilename(const llvm::SMDiagnostic &Error, void *) {
244   EXPECT_EQ(Error.getFilename(), "foo.yaml");
245 }
246 
247 TEST(YAMLIO, TestGivenFilename) {
248   auto Buffer = llvm::MemoryBuffer::getMemBuffer("{ x: 42 }", "foo.yaml");
249   Input yin(*Buffer, nullptr, testErrorFilename);
250   FooBar Value;
251   yin >> Value;
252 
253   EXPECT_TRUE(!!yin.error());
254 }
255 
256 struct WithStringField {
257   std::string str1;
258   std::string str2;
259   std::string str3;
260 };
261 
262 namespace llvm {
263 namespace yaml {
264 template <> struct MappingTraits<WithStringField> {
265   static void mapping(IO &io, WithStringField &fb) {
266     io.mapRequired("str1", fb.str1);
267     io.mapRequired("str2", fb.str2);
268     io.mapRequired("str3", fb.str3);
269   }
270 };
271 } // namespace yaml
272 } // namespace llvm
273 
274 TEST(YAMLIO, MultilineStrings) {
275   WithStringField Original;
276   Original.str1 = "a multiline string\nfoobarbaz";
277   Original.str2 = "another one\rfoobarbaz";
278   Original.str3 = "a one-line string";
279 
280   std::string Serialized;
281   {
282     llvm::raw_string_ostream OS(Serialized);
283     Output YOut(OS);
284     YOut << Original;
285   }
286   auto Expected = "---\n"
287                   "str1:            'a multiline string\n"
288                   "foobarbaz'\n"
289                   "str2:            'another one\r"
290                   "foobarbaz'\n"
291                   "str3:            a one-line string\n"
292                   "...\n";
293   ASSERT_EQ(Serialized, Expected);
294 
295   // Also check it parses back without the errors.
296   WithStringField Deserialized;
297   {
298     Input YIn(Serialized);
299     YIn >> Deserialized;
300     ASSERT_FALSE(YIn.error())
301         << "Parsing error occurred during deserialization. Serialized string:\n"
302         << Serialized;
303   }
304   EXPECT_EQ(Original.str1, Deserialized.str1);
305   EXPECT_EQ(Original.str2, Deserialized.str2);
306   EXPECT_EQ(Original.str3, Deserialized.str3);
307 }
308 
309 TEST(YAMLIO, NoQuotesForTab) {
310   WithStringField WithTab;
311   WithTab.str1 = "aba\tcaba";
312   std::string Serialized;
313   {
314     llvm::raw_string_ostream OS(Serialized);
315     Output YOut(OS);
316     YOut << WithTab;
317   }
318   auto ExpectedPrefix = "---\n"
319                         "str1:            aba\tcaba\n";
320   EXPECT_THAT(Serialized, StartsWith(ExpectedPrefix));
321 }
322 
323 //===----------------------------------------------------------------------===//
324 //  Test built-in types
325 //===----------------------------------------------------------------------===//
326 
327 struct BuiltInTypes {
328   llvm::StringRef str;
329   std::string stdstr;
330   uint64_t        u64;
331   uint32_t        u32;
332   uint16_t        u16;
333   uint8_t         u8;
334   bool            b;
335   int64_t         s64;
336   int32_t         s32;
337   int16_t         s16;
338   int8_t          s8;
339   float           f;
340   double          d;
341   Hex8            h8;
342   Hex16           h16;
343   Hex32           h32;
344   Hex64           h64;
345 };
346 
347 namespace llvm {
348 namespace yaml {
349   template <>
350   struct MappingTraits<BuiltInTypes> {
351     static void mapping(IO &io, BuiltInTypes& bt) {
352       io.mapRequired("str",      bt.str);
353       io.mapRequired("stdstr",   bt.stdstr);
354       io.mapRequired("u64",      bt.u64);
355       io.mapRequired("u32",      bt.u32);
356       io.mapRequired("u16",      bt.u16);
357       io.mapRequired("u8",       bt.u8);
358       io.mapRequired("b",        bt.b);
359       io.mapRequired("s64",      bt.s64);
360       io.mapRequired("s32",      bt.s32);
361       io.mapRequired("s16",      bt.s16);
362       io.mapRequired("s8",       bt.s8);
363       io.mapRequired("f",        bt.f);
364       io.mapRequired("d",        bt.d);
365       io.mapRequired("h8",       bt.h8);
366       io.mapRequired("h16",      bt.h16);
367       io.mapRequired("h32",      bt.h32);
368       io.mapRequired("h64",      bt.h64);
369     }
370   };
371 }
372 }
373 
374 
375 //
376 // Test the reading of all built-in scalar conversions
377 //
378 TEST(YAMLIO, TestReadBuiltInTypes) {
379   BuiltInTypes map;
380   Input yin("---\n"
381             "str:      hello there\n"
382             "stdstr:   hello where?\n"
383             "u64:      5000000000\n"
384             "u32:      4000000000\n"
385             "u16:      65000\n"
386             "u8:       255\n"
387             "b:        false\n"
388             "s64:      -5000000000\n"
389             "s32:      -2000000000\n"
390             "s16:      -32000\n"
391             "s8:       -127\n"
392             "f:        137.125\n"
393             "d:        -2.8625\n"
394             "h8:       0xFF\n"
395             "h16:      0x8765\n"
396             "h32:      0xFEDCBA98\n"
397             "h64:      0xFEDCBA9876543210\n"
398            "...\n");
399   yin >> map;
400 
401   EXPECT_FALSE(yin.error());
402   EXPECT_TRUE(map.str.equals("hello there"));
403   EXPECT_TRUE(map.stdstr == "hello where?");
404   EXPECT_EQ(map.u64, 5000000000ULL);
405   EXPECT_EQ(map.u32, 4000000000U);
406   EXPECT_EQ(map.u16, 65000);
407   EXPECT_EQ(map.u8,  255);
408   EXPECT_EQ(map.b,   false);
409   EXPECT_EQ(map.s64, -5000000000LL);
410   EXPECT_EQ(map.s32, -2000000000L);
411   EXPECT_EQ(map.s16, -32000);
412   EXPECT_EQ(map.s8,  -127);
413   EXPECT_EQ(map.f,   137.125);
414   EXPECT_EQ(map.d,   -2.8625);
415   EXPECT_EQ(map.h8,  Hex8(255));
416   EXPECT_EQ(map.h16, Hex16(0x8765));
417   EXPECT_EQ(map.h32, Hex32(0xFEDCBA98));
418   EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL));
419 }
420 
421 
422 //
423 // Test writing then reading back all built-in scalar types
424 //
425 TEST(YAMLIO, TestReadWriteBuiltInTypes) {
426   std::string intermediate;
427   {
428     BuiltInTypes map;
429     map.str = "one two";
430     map.stdstr = "three four";
431     map.u64 = 6000000000ULL;
432     map.u32 = 3000000000U;
433     map.u16 = 50000;
434     map.u8  = 254;
435     map.b   = true;
436     map.s64 = -6000000000LL;
437     map.s32 = -2000000000;
438     map.s16 = -32000;
439     map.s8  = -128;
440     map.f   = 3.25;
441     map.d   = -2.8625;
442     map.h8  = 254;
443     map.h16 = 50000;
444     map.h32 = 3000000000U;
445     map.h64 = 6000000000LL;
446 
447     llvm::raw_string_ostream ostr(intermediate);
448     Output yout(ostr);
449     yout << map;
450   }
451 
452   {
453     Input yin(intermediate);
454     BuiltInTypes map;
455     yin >> map;
456 
457     EXPECT_FALSE(yin.error());
458     EXPECT_TRUE(map.str.equals("one two"));
459     EXPECT_TRUE(map.stdstr == "three four");
460     EXPECT_EQ(map.u64,      6000000000ULL);
461     EXPECT_EQ(map.u32,      3000000000U);
462     EXPECT_EQ(map.u16,      50000);
463     EXPECT_EQ(map.u8,       254);
464     EXPECT_EQ(map.b,        true);
465     EXPECT_EQ(map.s64,      -6000000000LL);
466     EXPECT_EQ(map.s32,      -2000000000L);
467     EXPECT_EQ(map.s16,      -32000);
468     EXPECT_EQ(map.s8,       -128);
469     EXPECT_EQ(map.f,        3.25);
470     EXPECT_EQ(map.d,        -2.8625);
471     EXPECT_EQ(map.h8,       Hex8(254));
472     EXPECT_EQ(map.h16,      Hex16(50000));
473     EXPECT_EQ(map.h32,      Hex32(3000000000U));
474     EXPECT_EQ(map.h64,      Hex64(6000000000LL));
475   }
476 }
477 
478 //===----------------------------------------------------------------------===//
479 //  Test endian-aware types
480 //===----------------------------------------------------------------------===//
481 
482 struct EndianTypes {
483   typedef llvm::support::detail::packed_endian_specific_integral<
484       float, llvm::support::little, llvm::support::unaligned>
485       ulittle_float;
486   typedef llvm::support::detail::packed_endian_specific_integral<
487       double, llvm::support::little, llvm::support::unaligned>
488       ulittle_double;
489 
490   llvm::support::ulittle64_t u64;
491   llvm::support::ulittle32_t u32;
492   llvm::support::ulittle16_t u16;
493   llvm::support::little64_t s64;
494   llvm::support::little32_t s32;
495   llvm::support::little16_t s16;
496   ulittle_float f;
497   ulittle_double d;
498 };
499 
500 namespace llvm {
501 namespace yaml {
502 template <> struct MappingTraits<EndianTypes> {
503   static void mapping(IO &io, EndianTypes &et) {
504     io.mapRequired("u64", et.u64);
505     io.mapRequired("u32", et.u32);
506     io.mapRequired("u16", et.u16);
507     io.mapRequired("s64", et.s64);
508     io.mapRequired("s32", et.s32);
509     io.mapRequired("s16", et.s16);
510     io.mapRequired("f", et.f);
511     io.mapRequired("d", et.d);
512   }
513 };
514 }
515 }
516 
517 //
518 // Test the reading of all endian scalar conversions
519 //
520 TEST(YAMLIO, TestReadEndianTypes) {
521   EndianTypes map;
522   Input yin("---\n"
523             "u64:      5000000000\n"
524             "u32:      4000000000\n"
525             "u16:      65000\n"
526             "s64:      -5000000000\n"
527             "s32:      -2000000000\n"
528             "s16:      -32000\n"
529             "f:        3.25\n"
530             "d:        -2.8625\n"
531             "...\n");
532   yin >> map;
533 
534   EXPECT_FALSE(yin.error());
535   EXPECT_EQ(map.u64, 5000000000ULL);
536   EXPECT_EQ(map.u32, 4000000000U);
537   EXPECT_EQ(map.u16, 65000);
538   EXPECT_EQ(map.s64, -5000000000LL);
539   EXPECT_EQ(map.s32, -2000000000L);
540   EXPECT_EQ(map.s16, -32000);
541   EXPECT_EQ(map.f, 3.25f);
542   EXPECT_EQ(map.d, -2.8625);
543 }
544 
545 //
546 // Test writing then reading back all endian-aware scalar types
547 //
548 TEST(YAMLIO, TestReadWriteEndianTypes) {
549   std::string intermediate;
550   {
551     EndianTypes map;
552     map.u64 = 6000000000ULL;
553     map.u32 = 3000000000U;
554     map.u16 = 50000;
555     map.s64 = -6000000000LL;
556     map.s32 = -2000000000;
557     map.s16 = -32000;
558     map.f = 3.25f;
559     map.d = -2.8625;
560 
561     llvm::raw_string_ostream ostr(intermediate);
562     Output yout(ostr);
563     yout << map;
564   }
565 
566   {
567     Input yin(intermediate);
568     EndianTypes map;
569     yin >> map;
570 
571     EXPECT_FALSE(yin.error());
572     EXPECT_EQ(map.u64, 6000000000ULL);
573     EXPECT_EQ(map.u32, 3000000000U);
574     EXPECT_EQ(map.u16, 50000);
575     EXPECT_EQ(map.s64, -6000000000LL);
576     EXPECT_EQ(map.s32, -2000000000L);
577     EXPECT_EQ(map.s16, -32000);
578     EXPECT_EQ(map.f, 3.25f);
579     EXPECT_EQ(map.d, -2.8625);
580   }
581 }
582 
583 struct StringTypes {
584   llvm::StringRef str1;
585   llvm::StringRef str2;
586   llvm::StringRef str3;
587   llvm::StringRef str4;
588   llvm::StringRef str5;
589   llvm::StringRef str6;
590   llvm::StringRef str7;
591   llvm::StringRef str8;
592   llvm::StringRef str9;
593   llvm::StringRef str10;
594   llvm::StringRef str11;
595   std::string stdstr1;
596   std::string stdstr2;
597   std::string stdstr3;
598   std::string stdstr4;
599   std::string stdstr5;
600   std::string stdstr6;
601   std::string stdstr7;
602   std::string stdstr8;
603   std::string stdstr9;
604   std::string stdstr10;
605   std::string stdstr11;
606   std::string stdstr12;
607 };
608 
609 namespace llvm {
610 namespace yaml {
611   template <>
612   struct MappingTraits<StringTypes> {
613     static void mapping(IO &io, StringTypes& st) {
614       io.mapRequired("str1",      st.str1);
615       io.mapRequired("str2",      st.str2);
616       io.mapRequired("str3",      st.str3);
617       io.mapRequired("str4",      st.str4);
618       io.mapRequired("str5",      st.str5);
619       io.mapRequired("str6",      st.str6);
620       io.mapRequired("str7",      st.str7);
621       io.mapRequired("str8",      st.str8);
622       io.mapRequired("str9",      st.str9);
623       io.mapRequired("str10",     st.str10);
624       io.mapRequired("str11",     st.str11);
625       io.mapRequired("stdstr1",   st.stdstr1);
626       io.mapRequired("stdstr2",   st.stdstr2);
627       io.mapRequired("stdstr3",   st.stdstr3);
628       io.mapRequired("stdstr4",   st.stdstr4);
629       io.mapRequired("stdstr5",   st.stdstr5);
630       io.mapRequired("stdstr6",   st.stdstr6);
631       io.mapRequired("stdstr7",   st.stdstr7);
632       io.mapRequired("stdstr8",   st.stdstr8);
633       io.mapRequired("stdstr9",   st.stdstr9);
634       io.mapRequired("stdstr10",  st.stdstr10);
635       io.mapRequired("stdstr11",  st.stdstr11);
636       io.mapRequired("stdstr12",  st.stdstr12);
637     }
638   };
639 }
640 }
641 
642 TEST(YAMLIO, TestReadWriteStringTypes) {
643   std::string intermediate;
644   {
645     StringTypes map;
646     map.str1 = "'aaa";
647     map.str2 = "\"bbb";
648     map.str3 = "`ccc";
649     map.str4 = "@ddd";
650     map.str5 = "";
651     map.str6 = "0000000004000000";
652     map.str7 = "true";
653     map.str8 = "FALSE";
654     map.str9 = "~";
655     map.str10 = "0.2e20";
656     map.str11 = "0x30";
657     map.stdstr1 = "'eee";
658     map.stdstr2 = "\"fff";
659     map.stdstr3 = "`ggg";
660     map.stdstr4 = "@hhh";
661     map.stdstr5 = "";
662     map.stdstr6 = "0000000004000000";
663     map.stdstr7 = "true";
664     map.stdstr8 = "FALSE";
665     map.stdstr9 = "~";
666     map.stdstr10 = "0.2e20";
667     map.stdstr11 = "0x30";
668     map.stdstr12 = "- match";
669 
670     llvm::raw_string_ostream ostr(intermediate);
671     Output yout(ostr);
672     yout << map;
673   }
674 
675   llvm::StringRef flowOut(intermediate);
676   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
677   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
678   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
679   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
680   EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
681   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n"));
682   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n"));
683   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n"));
684   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n"));
685   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n"));
686   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n"));
687   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'- match'\n"));
688   EXPECT_NE(std::string::npos, flowOut.find("'''eee"));
689   EXPECT_NE(std::string::npos, flowOut.find("'\"fff'"));
690   EXPECT_NE(std::string::npos, flowOut.find("'`ggg'"));
691   EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
692   EXPECT_NE(std::string::npos, flowOut.find("''\n"));
693   EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n"));
694 
695   {
696     Input yin(intermediate);
697     StringTypes map;
698     yin >> map;
699 
700     EXPECT_FALSE(yin.error());
701     EXPECT_TRUE(map.str1.equals("'aaa"));
702     EXPECT_TRUE(map.str2.equals("\"bbb"));
703     EXPECT_TRUE(map.str3.equals("`ccc"));
704     EXPECT_TRUE(map.str4.equals("@ddd"));
705     EXPECT_TRUE(map.str5.equals(""));
706     EXPECT_TRUE(map.str6.equals("0000000004000000"));
707     EXPECT_TRUE(map.stdstr1 == "'eee");
708     EXPECT_TRUE(map.stdstr2 == "\"fff");
709     EXPECT_TRUE(map.stdstr3 == "`ggg");
710     EXPECT_TRUE(map.stdstr4 == "@hhh");
711     EXPECT_TRUE(map.stdstr5 == "");
712     EXPECT_TRUE(map.stdstr6 == "0000000004000000");
713   }
714 }
715 
716 //===----------------------------------------------------------------------===//
717 //  Test ScalarEnumerationTraits
718 //===----------------------------------------------------------------------===//
719 
720 enum Colors {
721     cRed,
722     cBlue,
723     cGreen,
724     cYellow
725 };
726 
727 struct ColorMap {
728   Colors      c1;
729   Colors      c2;
730   Colors      c3;
731   Colors      c4;
732   Colors      c5;
733   Colors      c6;
734 };
735 
736 namespace llvm {
737 namespace yaml {
738   template <>
739   struct ScalarEnumerationTraits<Colors> {
740     static void enumeration(IO &io, Colors &value) {
741       io.enumCase(value, "red",   cRed);
742       io.enumCase(value, "blue",  cBlue);
743       io.enumCase(value, "green", cGreen);
744       io.enumCase(value, "yellow",cYellow);
745     }
746   };
747   template <>
748   struct MappingTraits<ColorMap> {
749     static void mapping(IO &io, ColorMap& c) {
750       io.mapRequired("c1", c.c1);
751       io.mapRequired("c2", c.c2);
752       io.mapRequired("c3", c.c3);
753       io.mapOptional("c4", c.c4, cBlue);   // supplies default
754       io.mapOptional("c5", c.c5, cYellow); // supplies default
755       io.mapOptional("c6", c.c6, cRed);    // supplies default
756     }
757   };
758 }
759 }
760 
761 
762 //
763 // Test reading enumerated scalars
764 //
765 TEST(YAMLIO, TestEnumRead) {
766   ColorMap map;
767   Input yin("---\n"
768             "c1:  blue\n"
769             "c2:  red\n"
770             "c3:  green\n"
771             "c5:  yellow\n"
772             "...\n");
773   yin >> map;
774 
775   EXPECT_FALSE(yin.error());
776   EXPECT_EQ(cBlue,  map.c1);
777   EXPECT_EQ(cRed,   map.c2);
778   EXPECT_EQ(cGreen, map.c3);
779   EXPECT_EQ(cBlue,  map.c4);  // tests default
780   EXPECT_EQ(cYellow,map.c5);  // tests overridden
781   EXPECT_EQ(cRed,   map.c6);  // tests default
782 }
783 
784 
785 
786 //===----------------------------------------------------------------------===//
787 //  Test ScalarBitSetTraits
788 //===----------------------------------------------------------------------===//
789 
790 enum MyFlags {
791   flagNone    = 0,
792   flagBig     = 1 << 0,
793   flagFlat    = 1 << 1,
794   flagRound   = 1 << 2,
795   flagPointy  = 1 << 3
796 };
797 inline MyFlags operator|(MyFlags a, MyFlags b) {
798   return static_cast<MyFlags>(
799                       static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
800 }
801 
802 struct FlagsMap {
803   MyFlags     f1;
804   MyFlags     f2;
805   MyFlags     f3;
806   MyFlags     f4;
807 };
808 
809 
810 namespace llvm {
811 namespace yaml {
812   template <>
813   struct ScalarBitSetTraits<MyFlags> {
814     static void bitset(IO &io, MyFlags &value) {
815       io.bitSetCase(value, "big",   flagBig);
816       io.bitSetCase(value, "flat",  flagFlat);
817       io.bitSetCase(value, "round", flagRound);
818       io.bitSetCase(value, "pointy",flagPointy);
819     }
820   };
821   template <>
822   struct MappingTraits<FlagsMap> {
823     static void mapping(IO &io, FlagsMap& c) {
824       io.mapRequired("f1", c.f1);
825       io.mapRequired("f2", c.f2);
826       io.mapRequired("f3", c.f3);
827       io.mapOptional("f4", c.f4, MyFlags(flagRound));
828      }
829   };
830 }
831 }
832 
833 
834 //
835 // Test reading flow sequence representing bit-mask values
836 //
837 TEST(YAMLIO, TestFlagsRead) {
838   FlagsMap map;
839   Input yin("---\n"
840             "f1:  [ big ]\n"
841             "f2:  [ round, flat ]\n"
842             "f3:  []\n"
843             "...\n");
844   yin >> map;
845 
846   EXPECT_FALSE(yin.error());
847   EXPECT_EQ(flagBig,              map.f1);
848   EXPECT_EQ(flagRound|flagFlat,   map.f2);
849   EXPECT_EQ(flagNone,             map.f3);  // check empty set
850   EXPECT_EQ(flagRound,            map.f4);  // check optional key
851 }
852 
853 
854 //
855 // Test writing then reading back bit-mask values
856 //
857 TEST(YAMLIO, TestReadWriteFlags) {
858   std::string intermediate;
859   {
860     FlagsMap map;
861     map.f1 = flagBig;
862     map.f2 = flagRound | flagFlat;
863     map.f3 = flagNone;
864     map.f4 = flagNone;
865 
866     llvm::raw_string_ostream ostr(intermediate);
867     Output yout(ostr);
868     yout << map;
869   }
870 
871   {
872     Input yin(intermediate);
873     FlagsMap map2;
874     yin >> map2;
875 
876     EXPECT_FALSE(yin.error());
877     EXPECT_EQ(flagBig,              map2.f1);
878     EXPECT_EQ(flagRound|flagFlat,   map2.f2);
879     EXPECT_EQ(flagNone,             map2.f3);
880     //EXPECT_EQ(flagRound,            map2.f4);  // check optional key
881   }
882 }
883 
884 
885 
886 //===----------------------------------------------------------------------===//
887 //  Test ScalarTraits
888 //===----------------------------------------------------------------------===//
889 
890 struct MyCustomType {
891   int length;
892   int width;
893 };
894 
895 struct MyCustomTypeMap {
896   MyCustomType     f1;
897   MyCustomType     f2;
898   int              f3;
899 };
900 
901 
902 namespace llvm {
903 namespace yaml {
904   template <>
905   struct MappingTraits<MyCustomTypeMap> {
906     static void mapping(IO &io, MyCustomTypeMap& s) {
907       io.mapRequired("f1", s.f1);
908       io.mapRequired("f2", s.f2);
909       io.mapRequired("f3", s.f3);
910      }
911   };
912   // MyCustomType is formatted as a yaml scalar.  A value of
913   // {length=3, width=4} would be represented in yaml as "3 by 4".
914   template<>
915   struct ScalarTraits<MyCustomType> {
916     static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) {
917       out << llvm::format("%d by %d", value.length, value.width);
918     }
919     static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) {
920       size_t byStart = scalar.find("by");
921       if ( byStart != StringRef::npos ) {
922         StringRef lenStr = scalar.slice(0, byStart);
923         lenStr = lenStr.rtrim();
924         if ( lenStr.getAsInteger(0, value.length) ) {
925           return "malformed length";
926         }
927         StringRef widthStr = scalar.drop_front(byStart+2);
928         widthStr = widthStr.ltrim();
929         if ( widthStr.getAsInteger(0, value.width) ) {
930           return "malformed width";
931         }
932         return StringRef();
933       }
934       else {
935           return "malformed by";
936       }
937     }
938     static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
939   };
940 }
941 }
942 
943 
944 //
945 // Test writing then reading back custom values
946 //
947 TEST(YAMLIO, TestReadWriteMyCustomType) {
948   std::string intermediate;
949   {
950     MyCustomTypeMap map;
951     map.f1.length = 1;
952     map.f1.width  = 4;
953     map.f2.length = 100;
954     map.f2.width  = 400;
955     map.f3 = 10;
956 
957     llvm::raw_string_ostream ostr(intermediate);
958     Output yout(ostr);
959     yout << map;
960   }
961 
962   {
963     Input yin(intermediate);
964     MyCustomTypeMap map2;
965     yin >> map2;
966 
967     EXPECT_FALSE(yin.error());
968     EXPECT_EQ(1,      map2.f1.length);
969     EXPECT_EQ(4,      map2.f1.width);
970     EXPECT_EQ(100,    map2.f2.length);
971     EXPECT_EQ(400,    map2.f2.width);
972     EXPECT_EQ(10,     map2.f3);
973   }
974 }
975 
976 
977 //===----------------------------------------------------------------------===//
978 //  Test BlockScalarTraits
979 //===----------------------------------------------------------------------===//
980 
981 struct MultilineStringType {
982   std::string str;
983 };
984 
985 struct MultilineStringTypeMap {
986   MultilineStringType name;
987   MultilineStringType description;
988   MultilineStringType ingredients;
989   MultilineStringType recipes;
990   MultilineStringType warningLabels;
991   MultilineStringType documentation;
992   int price;
993 };
994 
995 namespace llvm {
996 namespace yaml {
997   template <>
998   struct MappingTraits<MultilineStringTypeMap> {
999     static void mapping(IO &io, MultilineStringTypeMap& s) {
1000       io.mapRequired("name", s.name);
1001       io.mapRequired("description", s.description);
1002       io.mapRequired("ingredients", s.ingredients);
1003       io.mapRequired("recipes", s.recipes);
1004       io.mapRequired("warningLabels", s.warningLabels);
1005       io.mapRequired("documentation", s.documentation);
1006       io.mapRequired("price", s.price);
1007      }
1008   };
1009 
1010   // MultilineStringType is formatted as a yaml block literal scalar. A value of
1011   // "Hello\nWorld" would be represented in yaml as
1012   //  |
1013   //    Hello
1014   //    World
1015   template <>
1016   struct BlockScalarTraits<MultilineStringType> {
1017     static void output(const MultilineStringType &value, void *ctxt,
1018                        llvm::raw_ostream &out) {
1019       out << value.str;
1020     }
1021     static StringRef input(StringRef scalar, void *ctxt,
1022                            MultilineStringType &value) {
1023       value.str = scalar.str();
1024       return StringRef();
1025     }
1026   };
1027 }
1028 }
1029 
1030 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType)
1031 
1032 //
1033 // Test writing then reading back custom values
1034 //
1035 TEST(YAMLIO, TestReadWriteMultilineStringType) {
1036   std::string intermediate;
1037   {
1038     MultilineStringTypeMap map;
1039     map.name.str = "An Item";
1040     map.description.str = "Hello\nWorld";
1041     map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n";
1042     map.recipes.str = "\n\nTest 1\n\n\n";
1043     map.warningLabels.str = "";
1044     map.documentation.str = "\n\n";
1045     map.price = 350;
1046 
1047     llvm::raw_string_ostream ostr(intermediate);
1048     Output yout(ostr);
1049     yout << map;
1050   }
1051   {
1052     Input yin(intermediate);
1053     MultilineStringTypeMap map2;
1054     yin >> map2;
1055 
1056     EXPECT_FALSE(yin.error());
1057     EXPECT_EQ(map2.name.str, "An Item\n");
1058     EXPECT_EQ(map2.description.str, "Hello\nWorld\n");
1059     EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n");
1060     EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n");
1061     EXPECT_TRUE(map2.warningLabels.str.empty());
1062     EXPECT_TRUE(map2.documentation.str.empty());
1063     EXPECT_EQ(map2.price, 350);
1064   }
1065 }
1066 
1067 //
1068 // Test writing then reading back custom values
1069 //
1070 TEST(YAMLIO, TestReadWriteBlockScalarDocuments) {
1071   std::string intermediate;
1072   {
1073     std::vector<MultilineStringType> documents;
1074     MultilineStringType doc;
1075     doc.str = "Hello\nWorld";
1076     documents.push_back(doc);
1077 
1078     llvm::raw_string_ostream ostr(intermediate);
1079     Output yout(ostr);
1080     yout << documents;
1081 
1082     // Verify that the block scalar header was written out on the same line
1083     // as the document marker.
1084     EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |"));
1085   }
1086   {
1087     Input yin(intermediate);
1088     std::vector<MultilineStringType> documents2;
1089     yin >> documents2;
1090 
1091     EXPECT_FALSE(yin.error());
1092     EXPECT_EQ(documents2.size(), size_t(1));
1093     EXPECT_EQ(documents2[0].str, "Hello\nWorld\n");
1094   }
1095 }
1096 
1097 TEST(YAMLIO, TestReadWriteBlockScalarValue) {
1098   std::string intermediate;
1099   {
1100     MultilineStringType doc;
1101     doc.str = "Just a block\nscalar doc";
1102 
1103     llvm::raw_string_ostream ostr(intermediate);
1104     Output yout(ostr);
1105     yout << doc;
1106   }
1107   {
1108     Input yin(intermediate);
1109     MultilineStringType doc;
1110     yin >> doc;
1111 
1112     EXPECT_FALSE(yin.error());
1113     EXPECT_EQ(doc.str, "Just a block\nscalar doc\n");
1114   }
1115 }
1116 
1117 //===----------------------------------------------------------------------===//
1118 //  Test flow sequences
1119 //===----------------------------------------------------------------------===//
1120 
1121 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
1122 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
1123 LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, MyString)
1124 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyString)
1125 
1126 namespace llvm {
1127 namespace yaml {
1128   template<>
1129   struct ScalarTraits<MyNumber> {
1130     static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
1131       out << value;
1132     }
1133 
1134     static StringRef input(StringRef scalar, void *, MyNumber &value) {
1135       long long n;
1136       if ( getAsSignedInteger(scalar, 0, n) )
1137         return "invalid number";
1138       value = n;
1139       return StringRef();
1140     }
1141 
1142     static QuotingType mustQuote(StringRef) { return QuotingType::None; }
1143   };
1144 
1145   template <> struct ScalarTraits<MyString> {
1146     using Impl = ScalarTraits<StringRef>;
1147     static void output(const MyString &V, void *Ctx, raw_ostream &OS) {
1148       Impl::output(V, Ctx, OS);
1149     }
1150     static StringRef input(StringRef S, void *Ctx, MyString &V) {
1151       return Impl::input(S, Ctx, V.value);
1152     }
1153     static QuotingType mustQuote(StringRef S) {
1154       return Impl::mustQuote(S);
1155     }
1156   };
1157 }
1158 }
1159 
1160 struct NameAndNumbers {
1161   llvm::StringRef               name;
1162   std::vector<MyString>         strings;
1163   std::vector<MyNumber>         single;
1164   std::vector<MyNumber>         numbers;
1165 };
1166 
1167 namespace llvm {
1168 namespace yaml {
1169   template <>
1170   struct MappingTraits<NameAndNumbers> {
1171     static void mapping(IO &io, NameAndNumbers& nn) {
1172       io.mapRequired("name",     nn.name);
1173       io.mapRequired("strings",  nn.strings);
1174       io.mapRequired("single",   nn.single);
1175       io.mapRequired("numbers",  nn.numbers);
1176     }
1177   };
1178 }
1179 }
1180 
1181 typedef std::vector<MyNumber> MyNumberFlowSequence;
1182 
1183 LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence)
1184 
1185 struct NameAndNumbersFlow {
1186   llvm::StringRef                    name;
1187   std::vector<MyNumberFlowSequence>  sequenceOfNumbers;
1188 };
1189 
1190 namespace llvm {
1191 namespace yaml {
1192   template <>
1193   struct MappingTraits<NameAndNumbersFlow> {
1194     static void mapping(IO &io, NameAndNumbersFlow& nn) {
1195       io.mapRequired("name",     nn.name);
1196       io.mapRequired("sequenceOfNumbers",  nn.sequenceOfNumbers);
1197     }
1198   };
1199 }
1200 }
1201 
1202 //
1203 // Test writing then reading back custom values
1204 //
1205 TEST(YAMLIO, TestReadWriteMyFlowSequence) {
1206   std::string intermediate;
1207   {
1208     NameAndNumbers map;
1209     map.name  = "hello";
1210     map.strings.push_back(llvm::StringRef("one"));
1211     map.strings.push_back(llvm::StringRef("two"));
1212     map.single.push_back(1);
1213     map.numbers.push_back(10);
1214     map.numbers.push_back(-30);
1215     map.numbers.push_back(1024);
1216 
1217     llvm::raw_string_ostream ostr(intermediate);
1218     Output yout(ostr);
1219     yout << map;
1220 
1221     // Verify sequences were written in flow style
1222     ostr.flush();
1223     llvm::StringRef flowOut(intermediate);
1224     EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
1225     EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
1226   }
1227 
1228   {
1229     Input yin(intermediate);
1230     NameAndNumbers map2;
1231     yin >> map2;
1232 
1233     EXPECT_FALSE(yin.error());
1234     EXPECT_TRUE(map2.name.equals("hello"));
1235     EXPECT_EQ(map2.strings.size(), 2UL);
1236     EXPECT_TRUE(map2.strings[0].value.equals("one"));
1237     EXPECT_TRUE(map2.strings[1].value.equals("two"));
1238     EXPECT_EQ(map2.single.size(), 1UL);
1239     EXPECT_EQ(1,       map2.single[0]);
1240     EXPECT_EQ(map2.numbers.size(), 3UL);
1241     EXPECT_EQ(10,      map2.numbers[0]);
1242     EXPECT_EQ(-30,     map2.numbers[1]);
1243     EXPECT_EQ(1024,    map2.numbers[2]);
1244   }
1245 }
1246 
1247 
1248 //
1249 // Test writing then reading back a sequence of flow sequences.
1250 //
1251 TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) {
1252   std::string intermediate;
1253   {
1254     NameAndNumbersFlow map;
1255     map.name  = "hello";
1256     MyNumberFlowSequence single = { 0 };
1257     MyNumberFlowSequence numbers = { 12, 1, -512 };
1258     map.sequenceOfNumbers.push_back(single);
1259     map.sequenceOfNumbers.push_back(numbers);
1260     map.sequenceOfNumbers.push_back(MyNumberFlowSequence());
1261 
1262     llvm::raw_string_ostream ostr(intermediate);
1263     Output yout(ostr);
1264     yout << map;
1265 
1266     // Verify sequences were written in flow style
1267     // and that the parent sequence used '-'.
1268     ostr.flush();
1269     llvm::StringRef flowOut(intermediate);
1270     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]"));
1271     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]"));
1272     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [  ]"));
1273   }
1274 
1275   {
1276     Input yin(intermediate);
1277     NameAndNumbersFlow map2;
1278     yin >> map2;
1279 
1280     EXPECT_FALSE(yin.error());
1281     EXPECT_TRUE(map2.name.equals("hello"));
1282     EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL);
1283     EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL);
1284     EXPECT_EQ(0,    map2.sequenceOfNumbers[0][0]);
1285     EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL);
1286     EXPECT_EQ(12,   map2.sequenceOfNumbers[1][0]);
1287     EXPECT_EQ(1,    map2.sequenceOfNumbers[1][1]);
1288     EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]);
1289     EXPECT_TRUE(map2.sequenceOfNumbers[2].empty());
1290   }
1291 }
1292 
1293 //===----------------------------------------------------------------------===//
1294 //  Test normalizing/denormalizing
1295 //===----------------------------------------------------------------------===//
1296 
1297 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
1298 
1299 typedef std::vector<TotalSeconds> SecondsSequence;
1300 
1301 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
1302 
1303 
1304 namespace llvm {
1305 namespace yaml {
1306   template <>
1307   struct MappingTraits<TotalSeconds> {
1308 
1309     class NormalizedSeconds {
1310     public:
1311       NormalizedSeconds(IO &io)
1312         : hours(0), minutes(0), seconds(0) {
1313       }
1314       NormalizedSeconds(IO &, TotalSeconds &secs)
1315         : hours(secs/3600),
1316           minutes((secs - (hours*3600))/60),
1317           seconds(secs % 60) {
1318       }
1319       TotalSeconds denormalize(IO &) {
1320         return TotalSeconds(hours*3600 + minutes*60 + seconds);
1321       }
1322 
1323       uint32_t     hours;
1324       uint8_t      minutes;
1325       uint8_t      seconds;
1326     };
1327 
1328     static void mapping(IO &io, TotalSeconds &secs) {
1329       MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
1330 
1331       io.mapOptional("hours",    keys->hours,    (uint32_t)0);
1332       io.mapOptional("minutes",  keys->minutes,  (uint8_t)0);
1333       io.mapRequired("seconds",  keys->seconds);
1334     }
1335   };
1336 }
1337 }
1338 
1339 
1340 //
1341 // Test the reading of a yaml sequence of mappings
1342 //
1343 TEST(YAMLIO, TestReadMySecondsSequence) {
1344   SecondsSequence seq;
1345   Input yin("---\n - hours:  1\n   seconds:  5\n - seconds:  59\n...\n");
1346   yin >> seq;
1347 
1348   EXPECT_FALSE(yin.error());
1349   EXPECT_EQ(seq.size(), 2UL);
1350   EXPECT_EQ(seq[0], 3605U);
1351   EXPECT_EQ(seq[1], 59U);
1352 }
1353 
1354 
1355 //
1356 // Test writing then reading back custom values
1357 //
1358 TEST(YAMLIO, TestReadWriteMySecondsSequence) {
1359   std::string intermediate;
1360   {
1361     SecondsSequence seq;
1362     seq.push_back(4000);
1363     seq.push_back(500);
1364     seq.push_back(59);
1365 
1366     llvm::raw_string_ostream ostr(intermediate);
1367     Output yout(ostr);
1368     yout << seq;
1369   }
1370   {
1371     Input yin(intermediate);
1372     SecondsSequence seq2;
1373     yin >> seq2;
1374 
1375     EXPECT_FALSE(yin.error());
1376     EXPECT_EQ(seq2.size(), 3UL);
1377     EXPECT_EQ(seq2[0], 4000U);
1378     EXPECT_EQ(seq2[1], 500U);
1379     EXPECT_EQ(seq2[2], 59U);
1380   }
1381 }
1382 
1383 
1384 //===----------------------------------------------------------------------===//
1385 //  Test dynamic typing
1386 //===----------------------------------------------------------------------===//
1387 
1388 enum AFlags {
1389     a1,
1390     a2,
1391     a3
1392 };
1393 
1394 enum BFlags {
1395     b1,
1396     b2,
1397     b3
1398 };
1399 
1400 enum Kind {
1401     kindA,
1402     kindB
1403 };
1404 
1405 struct KindAndFlags {
1406   KindAndFlags() : kind(kindA), flags(0) { }
1407   KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
1408   Kind        kind;
1409   uint32_t    flags;
1410 };
1411 
1412 typedef std::vector<KindAndFlags> KindAndFlagsSequence;
1413 
1414 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
1415 
1416 namespace llvm {
1417 namespace yaml {
1418   template <>
1419   struct ScalarEnumerationTraits<AFlags> {
1420     static void enumeration(IO &io, AFlags &value) {
1421       io.enumCase(value, "a1",  a1);
1422       io.enumCase(value, "a2",  a2);
1423       io.enumCase(value, "a3",  a3);
1424     }
1425   };
1426   template <>
1427   struct ScalarEnumerationTraits<BFlags> {
1428     static void enumeration(IO &io, BFlags &value) {
1429       io.enumCase(value, "b1",  b1);
1430       io.enumCase(value, "b2",  b2);
1431       io.enumCase(value, "b3",  b3);
1432     }
1433   };
1434   template <>
1435   struct ScalarEnumerationTraits<Kind> {
1436     static void enumeration(IO &io, Kind &value) {
1437       io.enumCase(value, "A",  kindA);
1438       io.enumCase(value, "B",  kindB);
1439     }
1440   };
1441   template <>
1442   struct MappingTraits<KindAndFlags> {
1443     static void mapping(IO &io, KindAndFlags& kf) {
1444       io.mapRequired("kind",  kf.kind);
1445       // Type of "flags" field varies depending on "kind" field.
1446       // Use memcpy here to avoid breaking strict aliasing rules.
1447       if (kf.kind == kindA) {
1448         AFlags aflags = static_cast<AFlags>(kf.flags);
1449         io.mapRequired("flags", aflags);
1450         kf.flags = aflags;
1451       } else {
1452         BFlags bflags = static_cast<BFlags>(kf.flags);
1453         io.mapRequired("flags", bflags);
1454         kf.flags = bflags;
1455       }
1456     }
1457   };
1458 }
1459 }
1460 
1461 
1462 //
1463 // Test the reading of a yaml sequence dynamic types
1464 //
1465 TEST(YAMLIO, TestReadKindAndFlagsSequence) {
1466   KindAndFlagsSequence seq;
1467   Input yin("---\n - kind:  A\n   flags:  a2\n - kind:  B\n   flags:  b1\n...\n");
1468   yin >> seq;
1469 
1470   EXPECT_FALSE(yin.error());
1471   EXPECT_EQ(seq.size(), 2UL);
1472   EXPECT_EQ(seq[0].kind,  kindA);
1473   EXPECT_EQ(seq[0].flags, (uint32_t)a2);
1474   EXPECT_EQ(seq[1].kind,  kindB);
1475   EXPECT_EQ(seq[1].flags, (uint32_t)b1);
1476 }
1477 
1478 //
1479 // Test writing then reading back dynamic types
1480 //
1481 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
1482   std::string intermediate;
1483   {
1484     KindAndFlagsSequence seq;
1485     seq.push_back(KindAndFlags(kindA,a1));
1486     seq.push_back(KindAndFlags(kindB,b1));
1487     seq.push_back(KindAndFlags(kindA,a2));
1488     seq.push_back(KindAndFlags(kindB,b2));
1489     seq.push_back(KindAndFlags(kindA,a3));
1490 
1491     llvm::raw_string_ostream ostr(intermediate);
1492     Output yout(ostr);
1493     yout << seq;
1494   }
1495   {
1496     Input yin(intermediate);
1497     KindAndFlagsSequence seq2;
1498     yin >> seq2;
1499 
1500     EXPECT_FALSE(yin.error());
1501     EXPECT_EQ(seq2.size(), 5UL);
1502     EXPECT_EQ(seq2[0].kind,  kindA);
1503     EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
1504     EXPECT_EQ(seq2[1].kind,  kindB);
1505     EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
1506     EXPECT_EQ(seq2[2].kind,  kindA);
1507     EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
1508     EXPECT_EQ(seq2[3].kind,  kindB);
1509     EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
1510     EXPECT_EQ(seq2[4].kind,  kindA);
1511     EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
1512   }
1513 }
1514 
1515 
1516 //===----------------------------------------------------------------------===//
1517 //  Test document list
1518 //===----------------------------------------------------------------------===//
1519 
1520 struct FooBarMap {
1521   int foo;
1522   int bar;
1523 };
1524 typedef std::vector<FooBarMap> FooBarMapDocumentList;
1525 
1526 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
1527 
1528 
1529 namespace llvm {
1530 namespace yaml {
1531   template <>
1532   struct MappingTraits<FooBarMap> {
1533     static void mapping(IO &io, FooBarMap& fb) {
1534       io.mapRequired("foo",    fb.foo);
1535       io.mapRequired("bar",    fb.bar);
1536     }
1537   };
1538 }
1539 }
1540 
1541 
1542 //
1543 // Test the reading of a yaml mapping
1544 //
1545 TEST(YAMLIO, TestDocRead) {
1546   FooBarMap doc;
1547   Input yin("---\nfoo:  3\nbar:  5\n...\n");
1548   yin >> doc;
1549 
1550   EXPECT_FALSE(yin.error());
1551   EXPECT_EQ(doc.foo, 3);
1552   EXPECT_EQ(doc.bar,5);
1553 }
1554 
1555 
1556 
1557 //
1558 // Test writing then reading back a sequence of mappings
1559 //
1560 TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
1561   std::string intermediate;
1562   {
1563     FooBarMap doc1;
1564     doc1.foo = 10;
1565     doc1.bar = -3;
1566     FooBarMap doc2;
1567     doc2.foo = 257;
1568     doc2.bar = 0;
1569     std::vector<FooBarMap> docList;
1570     docList.push_back(doc1);
1571     docList.push_back(doc2);
1572 
1573     llvm::raw_string_ostream ostr(intermediate);
1574     Output yout(ostr);
1575     yout << docList;
1576   }
1577 
1578 
1579   {
1580     Input yin(intermediate);
1581     std::vector<FooBarMap> docList2;
1582     yin >> docList2;
1583 
1584     EXPECT_FALSE(yin.error());
1585     EXPECT_EQ(docList2.size(), 2UL);
1586     FooBarMap& map1 = docList2[0];
1587     FooBarMap& map2 = docList2[1];
1588     EXPECT_EQ(map1.foo, 10);
1589     EXPECT_EQ(map1.bar, -3);
1590     EXPECT_EQ(map2.foo, 257);
1591     EXPECT_EQ(map2.bar, 0);
1592   }
1593 }
1594 
1595 //===----------------------------------------------------------------------===//
1596 //  Test document tags
1597 //===----------------------------------------------------------------------===//
1598 
1599 struct MyDouble {
1600   MyDouble() : value(0.0) { }
1601   MyDouble(double x) : value(x) { }
1602   double value;
1603 };
1604 
1605 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
1606 
1607 
1608 namespace llvm {
1609 namespace yaml {
1610   template <>
1611   struct MappingTraits<MyDouble> {
1612     static void mapping(IO &io, MyDouble &d) {
1613       if (io.mapTag("!decimal", true)) {
1614         mappingDecimal(io, d);
1615       } else if (io.mapTag("!fraction")) {
1616         mappingFraction(io, d);
1617       }
1618     }
1619     static void mappingDecimal(IO &io, MyDouble &d) {
1620       io.mapRequired("value", d.value);
1621     }
1622     static void mappingFraction(IO &io, MyDouble &d) {
1623         double num, denom;
1624         io.mapRequired("numerator",      num);
1625         io.mapRequired("denominator",    denom);
1626         // convert fraction to double
1627         d.value = num/denom;
1628     }
1629   };
1630  }
1631 }
1632 
1633 
1634 //
1635 // Test the reading of two different tagged yaml documents.
1636 //
1637 TEST(YAMLIO, TestTaggedDocuments) {
1638   std::vector<MyDouble> docList;
1639   Input yin("--- !decimal\nvalue:  3.0\n"
1640             "--- !fraction\nnumerator:  9.0\ndenominator:  2\n...\n");
1641   yin >> docList;
1642   EXPECT_FALSE(yin.error());
1643   EXPECT_EQ(docList.size(), 2UL);
1644   EXPECT_EQ(docList[0].value, 3.0);
1645   EXPECT_EQ(docList[1].value, 4.5);
1646 }
1647 
1648 
1649 
1650 //
1651 // Test writing then reading back tagged documents
1652 //
1653 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1654   std::string intermediate;
1655   {
1656     MyDouble a(10.25);
1657     MyDouble b(-3.75);
1658     std::vector<MyDouble> docList;
1659     docList.push_back(a);
1660     docList.push_back(b);
1661 
1662     llvm::raw_string_ostream ostr(intermediate);
1663     Output yout(ostr);
1664     yout << docList;
1665   }
1666 
1667   {
1668     Input yin(intermediate);
1669     std::vector<MyDouble> docList2;
1670     yin >> docList2;
1671 
1672     EXPECT_FALSE(yin.error());
1673     EXPECT_EQ(docList2.size(), 2UL);
1674     EXPECT_EQ(docList2[0].value, 10.25);
1675     EXPECT_EQ(docList2[1].value, -3.75);
1676   }
1677 }
1678 
1679 
1680 //===----------------------------------------------------------------------===//
1681 //  Test mapping validation
1682 //===----------------------------------------------------------------------===//
1683 
1684 struct MyValidation {
1685   double value;
1686 };
1687 
1688 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
1689 
1690 namespace llvm {
1691 namespace yaml {
1692   template <>
1693   struct MappingTraits<MyValidation> {
1694     static void mapping(IO &io, MyValidation &d) {
1695         io.mapRequired("value", d.value);
1696     }
1697     static StringRef validate(IO &io, MyValidation &d) {
1698         if (d.value < 0)
1699           return "negative value";
1700         return StringRef();
1701     }
1702   };
1703  }
1704 }
1705 
1706 
1707 //
1708 // Test that validate() is called and complains about the negative value.
1709 //
1710 TEST(YAMLIO, TestValidatingInput) {
1711   std::vector<MyValidation> docList;
1712   Input yin("--- \nvalue:  3.0\n"
1713             "--- \nvalue:  -1.0\n...\n",
1714             nullptr, suppressErrorMessages);
1715   yin >> docList;
1716   EXPECT_TRUE(!!yin.error());
1717 }
1718 
1719 //===----------------------------------------------------------------------===//
1720 //  Test flow mapping
1721 //===----------------------------------------------------------------------===//
1722 
1723 struct FlowFooBar {
1724   int foo;
1725   int bar;
1726 
1727   FlowFooBar() : foo(0), bar(0) {}
1728   FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {}
1729 };
1730 
1731 typedef std::vector<FlowFooBar> FlowFooBarSequence;
1732 
1733 LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar)
1734 
1735 struct FlowFooBarDoc {
1736   FlowFooBar attribute;
1737   FlowFooBarSequence seq;
1738 };
1739 
1740 namespace llvm {
1741 namespace yaml {
1742   template <>
1743   struct MappingTraits<FlowFooBar> {
1744     static void mapping(IO &io, FlowFooBar &fb) {
1745       io.mapRequired("foo", fb.foo);
1746       io.mapRequired("bar", fb.bar);
1747     }
1748 
1749     static const bool flow = true;
1750   };
1751 
1752   template <>
1753   struct MappingTraits<FlowFooBarDoc> {
1754     static void mapping(IO &io, FlowFooBarDoc &fb) {
1755       io.mapRequired("attribute", fb.attribute);
1756       io.mapRequired("seq", fb.seq);
1757     }
1758   };
1759 }
1760 }
1761 
1762 //
1763 // Test writing then reading back custom mappings
1764 //
1765 TEST(YAMLIO, TestReadWriteMyFlowMapping) {
1766   std::string intermediate;
1767   {
1768     FlowFooBarDoc doc;
1769     doc.attribute = FlowFooBar(42, 907);
1770     doc.seq.push_back(FlowFooBar(1, 2));
1771     doc.seq.push_back(FlowFooBar(0, 0));
1772     doc.seq.push_back(FlowFooBar(-1, 1024));
1773 
1774     llvm::raw_string_ostream ostr(intermediate);
1775     Output yout(ostr);
1776     yout << doc;
1777 
1778     // Verify that mappings were written in flow style
1779     ostr.flush();
1780     llvm::StringRef flowOut(intermediate);
1781     EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }"));
1782     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }"));
1783     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }"));
1784     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }"));
1785   }
1786 
1787   {
1788     Input yin(intermediate);
1789     FlowFooBarDoc doc2;
1790     yin >> doc2;
1791 
1792     EXPECT_FALSE(yin.error());
1793     EXPECT_EQ(doc2.attribute.foo, 42);
1794     EXPECT_EQ(doc2.attribute.bar, 907);
1795     EXPECT_EQ(doc2.seq.size(), 3UL);
1796     EXPECT_EQ(doc2.seq[0].foo, 1);
1797     EXPECT_EQ(doc2.seq[0].bar, 2);
1798     EXPECT_EQ(doc2.seq[1].foo, 0);
1799     EXPECT_EQ(doc2.seq[1].bar, 0);
1800     EXPECT_EQ(doc2.seq[2].foo, -1);
1801     EXPECT_EQ(doc2.seq[2].bar, 1024);
1802   }
1803 }
1804 
1805 //===----------------------------------------------------------------------===//
1806 //  Test error handling
1807 //===----------------------------------------------------------------------===//
1808 
1809 //
1810 // Test error handling of unknown enumerated scalar
1811 //
1812 TEST(YAMLIO, TestColorsReadError) {
1813   ColorMap map;
1814   Input yin("---\n"
1815             "c1:  blue\n"
1816             "c2:  purple\n"
1817             "c3:  green\n"
1818             "...\n",
1819             /*Ctxt=*/nullptr,
1820             suppressErrorMessages);
1821   yin >> map;
1822   EXPECT_TRUE(!!yin.error());
1823 }
1824 
1825 
1826 //
1827 // Test error handling of flow sequence with unknown value
1828 //
1829 TEST(YAMLIO, TestFlagsReadError) {
1830   FlagsMap map;
1831   Input yin("---\n"
1832             "f1:  [ big ]\n"
1833             "f2:  [ round, hollow ]\n"
1834             "f3:  []\n"
1835             "...\n",
1836             /*Ctxt=*/nullptr,
1837             suppressErrorMessages);
1838   yin >> map;
1839 
1840   EXPECT_TRUE(!!yin.error());
1841 }
1842 
1843 
1844 //
1845 // Test error handling reading built-in uint8_t type
1846 //
1847 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1848   std::vector<uint8_t> seq;
1849   Input yin("---\n"
1850             "- 255\n"
1851             "- 0\n"
1852             "- 257\n"
1853             "...\n",
1854             /*Ctxt=*/nullptr,
1855             suppressErrorMessages);
1856   yin >> seq;
1857 
1858   EXPECT_TRUE(!!yin.error());
1859 }
1860 
1861 
1862 //
1863 // Test error handling reading built-in uint16_t type
1864 //
1865 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1866   std::vector<uint16_t> seq;
1867   Input yin("---\n"
1868             "- 65535\n"
1869             "- 0\n"
1870             "- 66000\n"
1871             "...\n",
1872             /*Ctxt=*/nullptr,
1873             suppressErrorMessages);
1874   yin >> seq;
1875 
1876   EXPECT_TRUE(!!yin.error());
1877 }
1878 
1879 
1880 //
1881 // Test error handling reading built-in uint32_t type
1882 //
1883 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1884   std::vector<uint32_t> seq;
1885   Input yin("---\n"
1886             "- 4000000000\n"
1887             "- 0\n"
1888             "- 5000000000\n"
1889             "...\n",
1890             /*Ctxt=*/nullptr,
1891             suppressErrorMessages);
1892   yin >> seq;
1893 
1894   EXPECT_TRUE(!!yin.error());
1895 }
1896 
1897 
1898 //
1899 // Test error handling reading built-in uint64_t type
1900 //
1901 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1902   std::vector<uint64_t> seq;
1903   Input yin("---\n"
1904             "- 18446744073709551615\n"
1905             "- 0\n"
1906             "- 19446744073709551615\n"
1907             "...\n",
1908             /*Ctxt=*/nullptr,
1909             suppressErrorMessages);
1910   yin >> seq;
1911 
1912   EXPECT_TRUE(!!yin.error());
1913 }
1914 
1915 
1916 //
1917 // Test error handling reading built-in int8_t type
1918 //
1919 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1920   std::vector<int8_t> seq;
1921   Input yin("---\n"
1922             "- -128\n"
1923             "- 0\n"
1924             "- 127\n"
1925             "- 128\n"
1926            "...\n",
1927             /*Ctxt=*/nullptr,
1928             suppressErrorMessages);
1929   yin >> seq;
1930 
1931   EXPECT_TRUE(!!yin.error());
1932 }
1933 
1934 //
1935 // Test error handling reading built-in int8_t type
1936 //
1937 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1938   std::vector<int8_t> seq;
1939   Input yin("---\n"
1940             "- -128\n"
1941             "- 0\n"
1942             "- 127\n"
1943             "- -129\n"
1944             "...\n",
1945             /*Ctxt=*/nullptr,
1946             suppressErrorMessages);
1947   yin >> seq;
1948 
1949   EXPECT_TRUE(!!yin.error());
1950 }
1951 
1952 
1953 //
1954 // Test error handling reading built-in int16_t type
1955 //
1956 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1957   std::vector<int16_t> seq;
1958   Input yin("---\n"
1959             "- 32767\n"
1960             "- 0\n"
1961             "- -32768\n"
1962             "- -32769\n"
1963             "...\n",
1964             /*Ctxt=*/nullptr,
1965             suppressErrorMessages);
1966   yin >> seq;
1967 
1968   EXPECT_TRUE(!!yin.error());
1969 }
1970 
1971 
1972 //
1973 // Test error handling reading built-in int16_t type
1974 //
1975 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1976   std::vector<int16_t> seq;
1977   Input yin("---\n"
1978             "- 32767\n"
1979             "- 0\n"
1980             "- -32768\n"
1981             "- 32768\n"
1982             "...\n",
1983             /*Ctxt=*/nullptr,
1984             suppressErrorMessages);
1985   yin >> seq;
1986 
1987   EXPECT_TRUE(!!yin.error());
1988 }
1989 
1990 
1991 //
1992 // Test error handling reading built-in int32_t type
1993 //
1994 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1995   std::vector<int32_t> seq;
1996   Input yin("---\n"
1997             "- 2147483647\n"
1998             "- 0\n"
1999             "- -2147483648\n"
2000             "- -2147483649\n"
2001             "...\n",
2002             /*Ctxt=*/nullptr,
2003             suppressErrorMessages);
2004   yin >> seq;
2005 
2006   EXPECT_TRUE(!!yin.error());
2007 }
2008 
2009 //
2010 // Test error handling reading built-in int32_t type
2011 //
2012 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
2013   std::vector<int32_t> seq;
2014   Input yin("---\n"
2015             "- 2147483647\n"
2016             "- 0\n"
2017             "- -2147483648\n"
2018             "- 2147483649\n"
2019             "...\n",
2020             /*Ctxt=*/nullptr,
2021             suppressErrorMessages);
2022   yin >> seq;
2023 
2024   EXPECT_TRUE(!!yin.error());
2025 }
2026 
2027 
2028 //
2029 // Test error handling reading built-in int64_t type
2030 //
2031 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
2032   std::vector<int64_t> seq;
2033   Input yin("---\n"
2034             "- -9223372036854775808\n"
2035             "- 0\n"
2036             "- 9223372036854775807\n"
2037             "- -9223372036854775809\n"
2038             "...\n",
2039             /*Ctxt=*/nullptr,
2040             suppressErrorMessages);
2041   yin >> seq;
2042 
2043   EXPECT_TRUE(!!yin.error());
2044 }
2045 
2046 //
2047 // Test error handling reading built-in int64_t type
2048 //
2049 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
2050   std::vector<int64_t> seq;
2051   Input yin("---\n"
2052             "- -9223372036854775808\n"
2053             "- 0\n"
2054             "- 9223372036854775807\n"
2055             "- 9223372036854775809\n"
2056             "...\n",
2057             /*Ctxt=*/nullptr,
2058             suppressErrorMessages);
2059   yin >> seq;
2060 
2061   EXPECT_TRUE(!!yin.error());
2062 }
2063 
2064 //
2065 // Test error handling reading built-in float type
2066 //
2067 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
2068   std::vector<float> seq;
2069   Input yin("---\n"
2070             "- 0.0\n"
2071             "- 1000.1\n"
2072             "- -123.456\n"
2073             "- 1.2.3\n"
2074             "...\n",
2075             /*Ctxt=*/nullptr,
2076             suppressErrorMessages);
2077   yin >> seq;
2078 
2079   EXPECT_TRUE(!!yin.error());
2080 }
2081 
2082 //
2083 // Test error handling reading built-in float type
2084 //
2085 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
2086   std::vector<double> seq;
2087   Input yin("---\n"
2088             "- 0.0\n"
2089             "- 1000.1\n"
2090             "- -123.456\n"
2091             "- 1.2.3\n"
2092             "...\n",
2093             /*Ctxt=*/nullptr,
2094             suppressErrorMessages);
2095   yin >> seq;
2096 
2097   EXPECT_TRUE(!!yin.error());
2098 }
2099 
2100 //
2101 // Test error handling reading built-in Hex8 type
2102 //
2103 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
2104 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
2105   std::vector<Hex8> seq;
2106   Input yin("---\n"
2107             "- 0x12\n"
2108             "- 0xFE\n"
2109             "- 0x123\n"
2110             "...\n",
2111             /*Ctxt=*/nullptr,
2112             suppressErrorMessages);
2113   yin >> seq;
2114 
2115   EXPECT_TRUE(!!yin.error());
2116 }
2117 
2118 
2119 //
2120 // Test error handling reading built-in Hex16 type
2121 //
2122 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
2123 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
2124   std::vector<Hex16> seq;
2125   Input yin("---\n"
2126             "- 0x0012\n"
2127             "- 0xFEFF\n"
2128             "- 0x12345\n"
2129             "...\n",
2130             /*Ctxt=*/nullptr,
2131             suppressErrorMessages);
2132   yin >> seq;
2133 
2134   EXPECT_TRUE(!!yin.error());
2135 }
2136 
2137 //
2138 // Test error handling reading built-in Hex32 type
2139 //
2140 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
2141 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
2142   std::vector<Hex32> seq;
2143   Input yin("---\n"
2144             "- 0x0012\n"
2145             "- 0xFEFF0000\n"
2146             "- 0x1234556789\n"
2147             "...\n",
2148             /*Ctxt=*/nullptr,
2149             suppressErrorMessages);
2150   yin >> seq;
2151 
2152   EXPECT_TRUE(!!yin.error());
2153 }
2154 
2155 //
2156 // Test error handling reading built-in Hex64 type
2157 //
2158 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
2159 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
2160   std::vector<Hex64> seq;
2161   Input yin("---\n"
2162             "- 0x0012\n"
2163             "- 0xFFEEDDCCBBAA9988\n"
2164             "- 0x12345567890ABCDEF0\n"
2165             "...\n",
2166             /*Ctxt=*/nullptr,
2167             suppressErrorMessages);
2168   yin >> seq;
2169 
2170   EXPECT_TRUE(!!yin.error());
2171 }
2172 
2173 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
2174   FooBar doc;
2175   {
2176     // We pass the suppressErrorMessages handler to handle the error
2177     // message generated in the constructor of Input.
2178     Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages);
2179     yin >> doc;
2180     EXPECT_TRUE(!!yin.error());
2181   }
2182 
2183   {
2184     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
2185     yin >> doc;
2186     EXPECT_TRUE(!!yin.error());
2187   }
2188 }
2189 
2190 struct OptionalTest {
2191   std::vector<int> Numbers;
2192 };
2193 
2194 struct OptionalTestSeq {
2195   std::vector<OptionalTest> Tests;
2196 };
2197 
2198 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
2199 namespace llvm {
2200 namespace yaml {
2201   template <>
2202   struct MappingTraits<OptionalTest> {
2203     static void mapping(IO& IO, OptionalTest &OT) {
2204       IO.mapOptional("Numbers", OT.Numbers);
2205     }
2206   };
2207 
2208   template <>
2209   struct MappingTraits<OptionalTestSeq> {
2210     static void mapping(IO &IO, OptionalTestSeq &OTS) {
2211       IO.mapOptional("Tests", OTS.Tests);
2212     }
2213   };
2214 }
2215 }
2216 
2217 TEST(YAMLIO, SequenceElideTest) {
2218   // Test that writing out a purely optional structure with its fields set to
2219   // default followed by other data is properly read back in.
2220   OptionalTestSeq Seq;
2221   OptionalTest One, Two, Three, Four;
2222   int N[] = {1, 2, 3};
2223   Three.Numbers.assign(N, N + 3);
2224   Seq.Tests.push_back(One);
2225   Seq.Tests.push_back(Two);
2226   Seq.Tests.push_back(Three);
2227   Seq.Tests.push_back(Four);
2228 
2229   std::string intermediate;
2230   {
2231     llvm::raw_string_ostream ostr(intermediate);
2232     Output yout(ostr);
2233     yout << Seq;
2234   }
2235 
2236   Input yin(intermediate);
2237   OptionalTestSeq Seq2;
2238   yin >> Seq2;
2239 
2240   EXPECT_FALSE(yin.error());
2241 
2242   EXPECT_EQ(4UL, Seq2.Tests.size());
2243 
2244   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
2245   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
2246 
2247   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
2248   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
2249   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
2250 
2251   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
2252 }
2253 
2254 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
2255   FooBar doc;
2256   Input yin("");
2257   yin >> doc;
2258   EXPECT_TRUE(!!yin.error());
2259 }
2260 
2261 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
2262   OptionalTest doc;
2263   Input yin("");
2264   yin >> doc;
2265   EXPECT_FALSE(yin.error());
2266 }
2267 
2268 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
2269   std::vector<uint8_t> seq;
2270   Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
2271   yin >> seq;
2272 
2273   EXPECT_FALSE(yin.error());
2274   EXPECT_TRUE(seq.empty());
2275 }
2276 
2277 struct FlowMap {
2278   llvm::StringRef str1, str2, str3;
2279   FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3)
2280     : str1(str1), str2(str2), str3(str3) {}
2281 };
2282 
2283 struct FlowSeq {
2284   llvm::StringRef str;
2285   FlowSeq(llvm::StringRef S) : str(S) {}
2286   FlowSeq() = default;
2287 };
2288 
2289 namespace llvm {
2290 namespace yaml {
2291   template <>
2292   struct MappingTraits<FlowMap> {
2293     static void mapping(IO &io, FlowMap &fm) {
2294       io.mapRequired("str1", fm.str1);
2295       io.mapRequired("str2", fm.str2);
2296       io.mapRequired("str3", fm.str3);
2297     }
2298 
2299     static const bool flow = true;
2300   };
2301 
2302 template <>
2303 struct ScalarTraits<FlowSeq> {
2304   static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) {
2305     out << value.str;
2306   }
2307   static StringRef input(StringRef scalar, void*, FlowSeq &value) {
2308     value.str = scalar;
2309     return "";
2310   }
2311 
2312   static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
2313 };
2314 }
2315 }
2316 
2317 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq)
2318 
2319 TEST(YAMLIO, TestWrapFlow) {
2320   std::string out;
2321   llvm::raw_string_ostream ostr(out);
2322   FlowMap Map("This is str1", "This is str2", "This is str3");
2323   std::vector<FlowSeq> Seq;
2324   Seq.emplace_back("This is str1");
2325   Seq.emplace_back("This is str2");
2326   Seq.emplace_back("This is str3");
2327 
2328   {
2329     // 20 is just bellow the total length of the first mapping field.
2330     // We should wreap at every element.
2331     Output yout(ostr, nullptr, 15);
2332 
2333     yout << Map;
2334     ostr.flush();
2335     EXPECT_EQ(out,
2336               "---\n"
2337               "{ str1: This is str1, \n"
2338               "  str2: This is str2, \n"
2339               "  str3: This is str3 }\n"
2340               "...\n");
2341     out.clear();
2342 
2343     yout << Seq;
2344     ostr.flush();
2345     EXPECT_EQ(out,
2346               "---\n"
2347               "[ This is str1, \n"
2348               "  This is str2, \n"
2349               "  This is str3 ]\n"
2350               "...\n");
2351     out.clear();
2352   }
2353   {
2354     // 25 will allow the second field to be output on the first line.
2355     Output yout(ostr, nullptr, 25);
2356 
2357     yout << Map;
2358     ostr.flush();
2359     EXPECT_EQ(out,
2360               "---\n"
2361               "{ str1: This is str1, str2: This is str2, \n"
2362               "  str3: This is str3 }\n"
2363               "...\n");
2364     out.clear();
2365 
2366     yout << Seq;
2367     ostr.flush();
2368     EXPECT_EQ(out,
2369               "---\n"
2370               "[ This is str1, This is str2, \n"
2371               "  This is str3 ]\n"
2372               "...\n");
2373     out.clear();
2374   }
2375   {
2376     // 0 means no wrapping.
2377     Output yout(ostr, nullptr, 0);
2378 
2379     yout << Map;
2380     ostr.flush();
2381     EXPECT_EQ(out,
2382               "---\n"
2383               "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n"
2384               "...\n");
2385     out.clear();
2386 
2387     yout << Seq;
2388     ostr.flush();
2389     EXPECT_EQ(out,
2390               "---\n"
2391               "[ This is str1, This is str2, This is str3 ]\n"
2392               "...\n");
2393     out.clear();
2394   }
2395 }
2396 
2397 struct MappingContext {
2398   int A = 0;
2399 };
2400 struct SimpleMap {
2401   int B = 0;
2402   int C = 0;
2403 };
2404 
2405 struct NestedMap {
2406   NestedMap(MappingContext &Context) : Context(Context) {}
2407   SimpleMap Simple;
2408   MappingContext &Context;
2409 };
2410 
2411 namespace llvm {
2412 namespace yaml {
2413 template <> struct MappingContextTraits<SimpleMap, MappingContext> {
2414   static void mapping(IO &io, SimpleMap &sm, MappingContext &Context) {
2415     io.mapRequired("B", sm.B);
2416     io.mapRequired("C", sm.C);
2417     ++Context.A;
2418     io.mapRequired("Context", Context.A);
2419   }
2420 };
2421 
2422 template <> struct MappingTraits<NestedMap> {
2423   static void mapping(IO &io, NestedMap &nm) {
2424     io.mapRequired("Simple", nm.Simple, nm.Context);
2425   }
2426 };
2427 }
2428 }
2429 
2430 TEST(YAMLIO, TestMapWithContext) {
2431   MappingContext Context;
2432   NestedMap Nested(Context);
2433   std::string out;
2434   llvm::raw_string_ostream ostr(out);
2435 
2436   Output yout(ostr, nullptr, 15);
2437 
2438   yout << Nested;
2439   ostr.flush();
2440   EXPECT_EQ(1, Context.A);
2441   EXPECT_EQ("---\n"
2442             "Simple:          \n"
2443             "  B:               0\n"
2444             "  C:               0\n"
2445             "  Context:         1\n"
2446             "...\n",
2447             out);
2448 
2449   out.clear();
2450 
2451   Nested.Simple.B = 2;
2452   Nested.Simple.C = 3;
2453   yout << Nested;
2454   ostr.flush();
2455   EXPECT_EQ(2, Context.A);
2456   EXPECT_EQ("---\n"
2457             "Simple:          \n"
2458             "  B:               2\n"
2459             "  C:               3\n"
2460             "  Context:         2\n"
2461             "...\n",
2462             out);
2463   out.clear();
2464 }
2465 
2466 LLVM_YAML_IS_STRING_MAP(int)
2467 
2468 TEST(YAMLIO, TestCustomMapping) {
2469   std::map<std::string, int> x;
2470   x["foo"] = 1;
2471   x["bar"] = 2;
2472 
2473   std::string out;
2474   llvm::raw_string_ostream ostr(out);
2475   Output xout(ostr, nullptr, 0);
2476 
2477   xout << x;
2478   ostr.flush();
2479   EXPECT_EQ("---\n"
2480             "bar:             2\n"
2481             "foo:             1\n"
2482             "...\n",
2483             out);
2484 
2485   Input yin(out);
2486   std::map<std::string, int> y;
2487   yin >> y;
2488   EXPECT_EQ(2ul, y.size());
2489   EXPECT_EQ(1, y["foo"]);
2490   EXPECT_EQ(2, y["bar"]);
2491 }
2492 
2493 LLVM_YAML_IS_STRING_MAP(FooBar)
2494 
2495 TEST(YAMLIO, TestCustomMappingStruct) {
2496   std::map<std::string, FooBar> x;
2497   x["foo"].foo = 1;
2498   x["foo"].bar = 2;
2499   x["bar"].foo = 3;
2500   x["bar"].bar = 4;
2501 
2502   std::string out;
2503   llvm::raw_string_ostream ostr(out);
2504   Output xout(ostr, nullptr, 0);
2505 
2506   xout << x;
2507   ostr.flush();
2508   EXPECT_EQ("---\n"
2509             "bar:             \n"
2510             "  foo:             3\n"
2511             "  bar:             4\n"
2512             "foo:             \n"
2513             "  foo:             1\n"
2514             "  bar:             2\n"
2515             "...\n",
2516             out);
2517 
2518   Input yin(out);
2519   std::map<std::string, FooBar> y;
2520   yin >> y;
2521   EXPECT_EQ(2ul, y.size());
2522   EXPECT_EQ(1, y["foo"].foo);
2523   EXPECT_EQ(2, y["foo"].bar);
2524   EXPECT_EQ(3, y["bar"].foo);
2525   EXPECT_EQ(4, y["bar"].bar);
2526 }
2527 
2528 static void TestEscaped(llvm::StringRef Input, llvm::StringRef Expected) {
2529   std::string out;
2530   llvm::raw_string_ostream ostr(out);
2531   Output xout(ostr, nullptr, 0);
2532 
2533   llvm::yaml::EmptyContext Ctx;
2534   yamlize(xout, Input, true, Ctx);
2535 
2536   ostr.flush();
2537 
2538   // Make a separate StringRef so we get nice byte-by-byte output.
2539   llvm::StringRef Got(out);
2540   EXPECT_EQ(Expected, Got);
2541 }
2542 
2543 TEST(YAMLIO, TestEscaped) {
2544   // Single quote
2545   TestEscaped("@abc@", "'@abc@'");
2546   // No quote
2547   TestEscaped("abc", "abc");
2548   // Forward slash quoted
2549   TestEscaped("abc/", "'abc/'");
2550   // Double quote non-printable
2551   TestEscaped("\01@abc@", "\"\\x01@abc@\"");
2552   // Double quote inside single quote
2553   TestEscaped("abc\"fdf", "'abc\"fdf'");
2554   // Double quote inside double quote
2555   TestEscaped("\01bc\"fdf", "\"\\x01bc\\\"fdf\"");
2556   // Single quote inside single quote
2557   TestEscaped("abc'fdf", "'abc''fdf'");
2558   // UTF8
2559   TestEscaped("/*параметр*/", "\"/*параметр*/\"");
2560   // UTF8 with single quote inside double quote
2561   TestEscaped("parameter 'параметр' is unused",
2562               "\"parameter 'параметр' is unused\"");
2563 
2564   // String with embedded non-printable multibyte UTF-8 sequence (U+200B
2565   // zero-width space). The thing to test here is that we emit a
2566   // unicode-scalar level escape like \uNNNN (at the YAML level), and don't
2567   // just pass the UTF-8 byte sequence through as with quoted printables.
2568   {
2569     const unsigned char foobar[10] = {'f', 'o', 'o',
2570                                       0xE2, 0x80, 0x8B, // UTF-8 of U+200B
2571                                       'b', 'a', 'r',
2572                                       0x0};
2573     TestEscaped((char const *)foobar, "\"foo\\u200Bbar\"");
2574   }
2575 }
2576 
2577 TEST(YAMLIO, Numeric) {
2578   EXPECT_TRUE(isNumeric(".inf"));
2579   EXPECT_TRUE(isNumeric(".INF"));
2580   EXPECT_TRUE(isNumeric(".Inf"));
2581   EXPECT_TRUE(isNumeric("-.inf"));
2582   EXPECT_TRUE(isNumeric("+.inf"));
2583 
2584   EXPECT_TRUE(isNumeric(".nan"));
2585   EXPECT_TRUE(isNumeric(".NaN"));
2586   EXPECT_TRUE(isNumeric(".NAN"));
2587 
2588   EXPECT_TRUE(isNumeric("0"));
2589   EXPECT_TRUE(isNumeric("0."));
2590   EXPECT_TRUE(isNumeric("0.0"));
2591   EXPECT_TRUE(isNumeric("-0.0"));
2592   EXPECT_TRUE(isNumeric("+0.0"));
2593 
2594   EXPECT_TRUE(isNumeric("12345"));
2595   EXPECT_TRUE(isNumeric("012345"));
2596   EXPECT_TRUE(isNumeric("+12.0"));
2597   EXPECT_TRUE(isNumeric(".5"));
2598   EXPECT_TRUE(isNumeric("+.5"));
2599   EXPECT_TRUE(isNumeric("-1.0"));
2600 
2601   EXPECT_TRUE(isNumeric("2.3e4"));
2602   EXPECT_TRUE(isNumeric("-2E+05"));
2603   EXPECT_TRUE(isNumeric("+12e03"));
2604   EXPECT_TRUE(isNumeric("6.8523015e+5"));
2605 
2606   EXPECT_TRUE(isNumeric("1.e+1"));
2607   EXPECT_TRUE(isNumeric(".0e+1"));
2608 
2609   EXPECT_TRUE(isNumeric("0x2aF3"));
2610   EXPECT_TRUE(isNumeric("0o01234567"));
2611 
2612   EXPECT_FALSE(isNumeric("not a number"));
2613   EXPECT_FALSE(isNumeric("."));
2614   EXPECT_FALSE(isNumeric(".e+1"));
2615   EXPECT_FALSE(isNumeric(".1e"));
2616   EXPECT_FALSE(isNumeric(".1e+"));
2617   EXPECT_FALSE(isNumeric(".1e++1"));
2618 
2619   EXPECT_FALSE(isNumeric("ABCD"));
2620   EXPECT_FALSE(isNumeric("+0x2AF3"));
2621   EXPECT_FALSE(isNumeric("-0x2AF3"));
2622   EXPECT_FALSE(isNumeric("0x2AF3Z"));
2623   EXPECT_FALSE(isNumeric("0o012345678"));
2624   EXPECT_FALSE(isNumeric("0xZ"));
2625   EXPECT_FALSE(isNumeric("-0o012345678"));
2626   EXPECT_FALSE(isNumeric("000003A8229434B839616A25C16B0291F77A438B"));
2627 
2628   EXPECT_FALSE(isNumeric(""));
2629   EXPECT_FALSE(isNumeric("."));
2630   EXPECT_FALSE(isNumeric(".e+1"));
2631   EXPECT_FALSE(isNumeric(".e+"));
2632   EXPECT_FALSE(isNumeric(".e"));
2633   EXPECT_FALSE(isNumeric("e1"));
2634 
2635   // Deprecated formats: as for YAML 1.2 specification, the following are not
2636   // valid numbers anymore:
2637   //
2638   // * Sexagecimal numbers
2639   // * Decimal numbers with comma s the delimiter
2640   // * "inf", "nan" without '.' prefix
2641   EXPECT_FALSE(isNumeric("3:25:45"));
2642   EXPECT_FALSE(isNumeric("+12,345"));
2643   EXPECT_FALSE(isNumeric("-inf"));
2644   EXPECT_FALSE(isNumeric("1,230.15"));
2645 }
2646 
2647 //===----------------------------------------------------------------------===//
2648 //  Test PolymorphicTraits and TaggedScalarTraits
2649 //===----------------------------------------------------------------------===//
2650 
2651 struct Poly {
2652   enum NodeKind {
2653     NK_Scalar,
2654     NK_Seq,
2655     NK_Map,
2656   } Kind;
2657 
2658   Poly(NodeKind Kind) : Kind(Kind) {}
2659 
2660   virtual ~Poly() = default;
2661 
2662   NodeKind getKind() const { return Kind; }
2663 };
2664 
2665 struct Scalar : Poly {
2666   enum ScalarKind {
2667     SK_Unknown,
2668     SK_Double,
2669     SK_Bool,
2670   } SKind;
2671 
2672   union {
2673     double DoubleValue;
2674     bool BoolValue;
2675   };
2676 
2677   Scalar() : Poly(NK_Scalar), SKind(SK_Unknown) {}
2678   Scalar(double DoubleValue)
2679       : Poly(NK_Scalar), SKind(SK_Double), DoubleValue(DoubleValue) {}
2680   Scalar(bool BoolValue)
2681       : Poly(NK_Scalar), SKind(SK_Bool), BoolValue(BoolValue) {}
2682 
2683   static bool classof(const Poly *N) { return N->getKind() == NK_Scalar; }
2684 };
2685 
2686 struct Seq : Poly, std::vector<std::unique_ptr<Poly>> {
2687   Seq() : Poly(NK_Seq) {}
2688 
2689   static bool classof(const Poly *N) { return N->getKind() == NK_Seq; }
2690 };
2691 
2692 struct Map : Poly, llvm::StringMap<std::unique_ptr<Poly>> {
2693   Map() : Poly(NK_Map) {}
2694 
2695   static bool classof(const Poly *N) { return N->getKind() == NK_Map; }
2696 };
2697 
2698 namespace llvm {
2699 namespace yaml {
2700 
2701 template <> struct PolymorphicTraits<std::unique_ptr<Poly>> {
2702   static NodeKind getKind(const std::unique_ptr<Poly> &N) {
2703     if (isa<Scalar>(*N))
2704       return NodeKind::Scalar;
2705     if (isa<Seq>(*N))
2706       return NodeKind::Sequence;
2707     if (isa<Map>(*N))
2708       return NodeKind::Map;
2709     llvm_unreachable("unsupported node type");
2710   }
2711 
2712   static Scalar &getAsScalar(std::unique_ptr<Poly> &N) {
2713     if (!N || !isa<Scalar>(*N))
2714       N = llvm::make_unique<Scalar>();
2715     return *cast<Scalar>(N.get());
2716   }
2717 
2718   static Seq &getAsSequence(std::unique_ptr<Poly> &N) {
2719     if (!N || !isa<Seq>(*N))
2720       N = llvm::make_unique<Seq>();
2721     return *cast<Seq>(N.get());
2722   }
2723 
2724   static Map &getAsMap(std::unique_ptr<Poly> &N) {
2725     if (!N || !isa<Map>(*N))
2726       N = llvm::make_unique<Map>();
2727     return *cast<Map>(N.get());
2728   }
2729 };
2730 
2731 template <> struct TaggedScalarTraits<Scalar> {
2732   static void output(const Scalar &S, void *Ctxt, raw_ostream &ScalarOS,
2733                      raw_ostream &TagOS) {
2734     switch (S.SKind) {
2735     case Scalar::SK_Unknown:
2736       report_fatal_error("output unknown scalar");
2737       break;
2738     case Scalar::SK_Double:
2739       TagOS << "!double";
2740       ScalarTraits<double>::output(S.DoubleValue, Ctxt, ScalarOS);
2741       break;
2742     case Scalar::SK_Bool:
2743       TagOS << "!bool";
2744       ScalarTraits<bool>::output(S.BoolValue, Ctxt, ScalarOS);
2745       break;
2746     }
2747   }
2748 
2749   static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt,
2750                          Scalar &S) {
2751     S.SKind = StringSwitch<Scalar::ScalarKind>(Tag)
2752                   .Case("!double", Scalar::SK_Double)
2753                   .Case("!bool", Scalar::SK_Bool)
2754                   .Default(Scalar::SK_Unknown);
2755     switch (S.SKind) {
2756     case Scalar::SK_Unknown:
2757       return StringRef("unknown scalar tag");
2758     case Scalar::SK_Double:
2759       return ScalarTraits<double>::input(ScalarStr, Ctxt, S.DoubleValue);
2760     case Scalar::SK_Bool:
2761       return ScalarTraits<bool>::input(ScalarStr, Ctxt, S.BoolValue);
2762     }
2763     llvm_unreachable("unknown scalar kind");
2764   }
2765 
2766   static QuotingType mustQuote(const Scalar &S, StringRef Str) {
2767     switch (S.SKind) {
2768     case Scalar::SK_Unknown:
2769       report_fatal_error("quote unknown scalar");
2770     case Scalar::SK_Double:
2771       return ScalarTraits<double>::mustQuote(Str);
2772     case Scalar::SK_Bool:
2773       return ScalarTraits<bool>::mustQuote(Str);
2774     }
2775     llvm_unreachable("unknown scalar kind");
2776   }
2777 };
2778 
2779 template <> struct CustomMappingTraits<Map> {
2780   static void inputOne(IO &IO, StringRef Key, Map &M) {
2781     IO.mapRequired(Key.str().c_str(), M[Key]);
2782   }
2783 
2784   static void output(IO &IO, Map &M) {
2785     for (auto &N : M)
2786       IO.mapRequired(N.getKey().str().c_str(), N.getValue());
2787   }
2788 };
2789 
2790 template <> struct SequenceTraits<Seq> {
2791   static size_t size(IO &IO, Seq &A) { return A.size(); }
2792 
2793   static std::unique_ptr<Poly> &element(IO &IO, Seq &A, size_t Index) {
2794     if (Index >= A.size())
2795       A.resize(Index + 1);
2796     return A[Index];
2797   }
2798 };
2799 
2800 } // namespace yaml
2801 } // namespace llvm
2802 
2803 TEST(YAMLIO, TestReadWritePolymorphicScalar) {
2804   std::string intermediate;
2805   std::unique_ptr<Poly> node = llvm::make_unique<Scalar>(true);
2806 
2807   llvm::raw_string_ostream ostr(intermediate);
2808   Output yout(ostr);
2809 #ifdef GTEST_HAS_DEATH_TEST
2810 #ifndef NDEBUG
2811   EXPECT_DEATH(yout << node, "plain scalar documents are not supported");
2812 #endif
2813 #endif
2814 }
2815 
2816 TEST(YAMLIO, TestReadWritePolymorphicSeq) {
2817   std::string intermediate;
2818   {
2819     auto seq = llvm::make_unique<Seq>();
2820     seq->push_back(llvm::make_unique<Scalar>(true));
2821     seq->push_back(llvm::make_unique<Scalar>(1.0));
2822     auto node = llvm::unique_dyn_cast<Poly>(seq);
2823 
2824     llvm::raw_string_ostream ostr(intermediate);
2825     Output yout(ostr);
2826     yout << node;
2827   }
2828   {
2829     Input yin(intermediate);
2830     std::unique_ptr<Poly> node;
2831     yin >> node;
2832 
2833     EXPECT_FALSE(yin.error());
2834     auto seq = llvm::dyn_cast<Seq>(node.get());
2835     ASSERT_TRUE(seq);
2836     ASSERT_EQ(seq->size(), 2u);
2837     auto first = llvm::dyn_cast<Scalar>((*seq)[0].get());
2838     ASSERT_TRUE(first);
2839     EXPECT_EQ(first->SKind, Scalar::SK_Bool);
2840     EXPECT_TRUE(first->BoolValue);
2841     auto second = llvm::dyn_cast<Scalar>((*seq)[1].get());
2842     ASSERT_TRUE(second);
2843     EXPECT_EQ(second->SKind, Scalar::SK_Double);
2844     EXPECT_EQ(second->DoubleValue, 1.0);
2845   }
2846 }
2847 
2848 TEST(YAMLIO, TestReadWritePolymorphicMap) {
2849   std::string intermediate;
2850   {
2851     auto map = llvm::make_unique<Map>();
2852     (*map)["foo"] = llvm::make_unique<Scalar>(false);
2853     (*map)["bar"] = llvm::make_unique<Scalar>(2.0);
2854     std::unique_ptr<Poly> node = llvm::unique_dyn_cast<Poly>(map);
2855 
2856     llvm::raw_string_ostream ostr(intermediate);
2857     Output yout(ostr);
2858     yout << node;
2859   }
2860   {
2861     Input yin(intermediate);
2862     std::unique_ptr<Poly> node;
2863     yin >> node;
2864 
2865     EXPECT_FALSE(yin.error());
2866     auto map = llvm::dyn_cast<Map>(node.get());
2867     ASSERT_TRUE(map);
2868     auto foo = llvm::dyn_cast<Scalar>((*map)["foo"].get());
2869     ASSERT_TRUE(foo);
2870     EXPECT_EQ(foo->SKind, Scalar::SK_Bool);
2871     EXPECT_FALSE(foo->BoolValue);
2872     auto bar = llvm::dyn_cast<Scalar>((*map)["bar"].get());
2873     ASSERT_TRUE(bar);
2874     EXPECT_EQ(bar->SKind, Scalar::SK_Double);
2875     EXPECT_EQ(bar->DoubleValue, 2.0);
2876   }
2877 }
2878