revert r194655
[oota-llvm.git] / unittests / Support / YAMLIOTest.cpp
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/SmallString.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Support/Casting.h"
13 #include "llvm/Support/Format.h"
14 #include "llvm/Support/YAMLTraits.h"
15 #include "gtest/gtest.h"
16
17
18 using llvm::yaml::Input;
19 using llvm::yaml::Output;
20 using llvm::yaml::IO;
21 using llvm::yaml::MappingTraits;
22 using llvm::yaml::MappingNormalization;
23 using llvm::yaml::ScalarTraits;
24 using llvm::yaml::Hex8;
25 using llvm::yaml::Hex16;
26 using llvm::yaml::Hex32;
27 using llvm::yaml::Hex64;
28
29
30 //===----------------------------------------------------------------------===//
31 //  Test MappingTraits
32 //===----------------------------------------------------------------------===//
33
34 struct FooBar {
35   int foo;
36   int bar;
37 };
38 typedef std::vector<FooBar> FooBarSequence;
39
40 LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar)
41
42
43 namespace llvm {
44 namespace yaml {
45   template <>
46   struct MappingTraits<FooBar> {
47     static void mapping(IO &io, FooBar& fb) {
48       io.mapRequired("foo",    fb.foo);
49       io.mapRequired("bar",    fb.bar);
50     }
51   };
52 }
53 }
54
55
56 //
57 // Test the reading of a yaml mapping
58 //
59 TEST(YAMLIO, TestMapRead) {
60   FooBar doc;
61   {
62     Input yin("---\nfoo:  3\nbar:  5\n...\n");
63     yin >> doc;
64
65     EXPECT_FALSE(yin.error());
66     EXPECT_EQ(doc.foo, 3);
67     EXPECT_EQ(doc.bar, 5);
68   }
69
70   {
71     Input yin("{foo: 3, bar: 5}");
72     yin >> doc;
73
74     EXPECT_FALSE(yin.error());
75     EXPECT_EQ(doc.foo, 3);
76     EXPECT_EQ(doc.bar, 5);
77   }
78 }
79
80 //
81 // Test the reading of a yaml sequence of mappings
82 //
83 TEST(YAMLIO, TestSequenceMapRead) {
84   FooBarSequence seq;
85   Input yin("---\n - foo:  3\n   bar:  5\n - foo:  7\n   bar:  9\n...\n");
86   yin >> seq;
87
88   EXPECT_FALSE(yin.error());
89   EXPECT_EQ(seq.size(), 2UL);
90   FooBar& map1 = seq[0];
91   FooBar& map2 = seq[1];
92   EXPECT_EQ(map1.foo, 3);
93   EXPECT_EQ(map1.bar, 5);
94   EXPECT_EQ(map2.foo, 7);
95   EXPECT_EQ(map2.bar, 9);
96 }
97
98
99 //
100 // Test writing then reading back a sequence of mappings
101 //
102 TEST(YAMLIO, TestSequenceMapWriteAndRead) {
103   std::string intermediate;
104   {
105     FooBar entry1;
106     entry1.foo = 10;
107     entry1.bar = -3;
108     FooBar entry2;
109     entry2.foo = 257;
110     entry2.bar = 0;
111     FooBarSequence seq;
112     seq.push_back(entry1);
113     seq.push_back(entry2);
114
115     llvm::raw_string_ostream ostr(intermediate);
116     Output yout(ostr);
117     yout << seq;
118   }
119
120   {
121     Input yin(intermediate);
122     FooBarSequence seq2;
123     yin >> seq2;
124
125     EXPECT_FALSE(yin.error());
126     EXPECT_EQ(seq2.size(), 2UL);
127     FooBar& map1 = seq2[0];
128     FooBar& map2 = seq2[1];
129     EXPECT_EQ(map1.foo, 10);
130     EXPECT_EQ(map1.bar, -3);
131     EXPECT_EQ(map2.foo, 257);
132     EXPECT_EQ(map2.bar, 0);
133   }
134 }
135
136
137 //===----------------------------------------------------------------------===//
138 //  Test built-in types
139 //===----------------------------------------------------------------------===//
140
141 struct BuiltInTypes {
142   llvm::StringRef str;
143   std::string stdstr;
144   uint64_t        u64;
145   uint32_t        u32;
146   uint16_t        u16;
147   uint8_t         u8;
148   bool            b;
149   int64_t         s64;
150   int32_t         s32;
151   int16_t         s16;
152   int8_t          s8;
153   float           f;
154   double          d;
155   Hex8            h8;
156   Hex16           h16;
157   Hex32           h32;
158   Hex64           h64;
159 };
160
161 namespace llvm {
162 namespace yaml {
163   template <>
164   struct MappingTraits<BuiltInTypes> {
165     static void mapping(IO &io, BuiltInTypes& bt) {
166       io.mapRequired("str",      bt.str);
167       io.mapRequired("stdstr",   bt.stdstr);
168       io.mapRequired("u64",      bt.u64);
169       io.mapRequired("u32",      bt.u32);
170       io.mapRequired("u16",      bt.u16);
171       io.mapRequired("u8",       bt.u8);
172       io.mapRequired("b",        bt.b);
173       io.mapRequired("s64",      bt.s64);
174       io.mapRequired("s32",      bt.s32);
175       io.mapRequired("s16",      bt.s16);
176       io.mapRequired("s8",       bt.s8);
177       io.mapRequired("f",        bt.f);
178       io.mapRequired("d",        bt.d);
179       io.mapRequired("h8",       bt.h8);
180       io.mapRequired("h16",      bt.h16);
181       io.mapRequired("h32",      bt.h32);
182       io.mapRequired("h64",      bt.h64);
183     }
184   };
185 }
186 }
187
188
189 //
190 // Test the reading of all built-in scalar conversions
191 //
192 TEST(YAMLIO, TestReadBuiltInTypes) {
193   BuiltInTypes map;
194   Input yin("---\n"
195             "str:      hello there\n"
196             "stdstr:   hello where?\n"
197             "u64:      5000000000\n"
198             "u32:      4000000000\n"
199             "u16:      65000\n"
200             "u8:       255\n"
201             "b:        false\n"
202             "s64:      -5000000000\n"
203             "s32:      -2000000000\n"
204             "s16:      -32000\n"
205             "s8:       -127\n"
206             "f:        137.125\n"
207             "d:        -2.8625\n"
208             "h8:       0xFF\n"
209             "h16:      0x8765\n"
210             "h32:      0xFEDCBA98\n"
211             "h64:      0xFEDCBA9876543210\n"
212            "...\n");
213   yin >> map;
214
215   EXPECT_FALSE(yin.error());
216   EXPECT_TRUE(map.str.equals("hello there"));
217   EXPECT_TRUE(map.stdstr == "hello where?");
218   EXPECT_EQ(map.u64, 5000000000ULL);
219   EXPECT_EQ(map.u32, 4000000000U);
220   EXPECT_EQ(map.u16, 65000);
221   EXPECT_EQ(map.u8,  255);
222   EXPECT_EQ(map.b,   false);
223   EXPECT_EQ(map.s64, -5000000000LL);
224   EXPECT_EQ(map.s32, -2000000000L);
225   EXPECT_EQ(map.s16, -32000);
226   EXPECT_EQ(map.s8,  -127);
227   EXPECT_EQ(map.f,   137.125);
228   EXPECT_EQ(map.d,   -2.8625);
229   EXPECT_EQ(map.h8,  Hex8(255));
230   EXPECT_EQ(map.h16, Hex16(0x8765));
231   EXPECT_EQ(map.h32, Hex32(0xFEDCBA98));
232   EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL));
233 }
234
235
236 //
237 // Test writing then reading back all built-in scalar types
238 //
239 TEST(YAMLIO, TestReadWriteBuiltInTypes) {
240   std::string intermediate;
241   {
242     BuiltInTypes map;
243     map.str = "one two";
244     map.stdstr = "three four";
245     map.u64 = 6000000000ULL;
246     map.u32 = 3000000000U;
247     map.u16 = 50000;
248     map.u8  = 254;
249     map.b   = true;
250     map.s64 = -6000000000LL;
251     map.s32 = -2000000000;
252     map.s16 = -32000;
253     map.s8  = -128;
254     map.f   = 3.25;
255     map.d   = -2.8625;
256     map.h8  = 254;
257     map.h16 = 50000;
258     map.h32 = 3000000000U;
259     map.h64 = 6000000000LL;
260
261     llvm::raw_string_ostream ostr(intermediate);
262     Output yout(ostr);
263     yout << map;
264   }
265
266   {
267     Input yin(intermediate);
268     BuiltInTypes map;
269     yin >> map;
270
271     EXPECT_FALSE(yin.error());
272     EXPECT_TRUE(map.str.equals("one two"));
273     EXPECT_TRUE(map.stdstr == "three four");
274     EXPECT_EQ(map.u64,      6000000000ULL);
275     EXPECT_EQ(map.u32,      3000000000U);
276     EXPECT_EQ(map.u16,      50000);
277     EXPECT_EQ(map.u8,       254);
278     EXPECT_EQ(map.b,        true);
279     EXPECT_EQ(map.s64,      -6000000000LL);
280     EXPECT_EQ(map.s32,      -2000000000L);
281     EXPECT_EQ(map.s16,      -32000);
282     EXPECT_EQ(map.s8,       -128);
283     EXPECT_EQ(map.f,        3.25);
284     EXPECT_EQ(map.d,        -2.8625);
285     EXPECT_EQ(map.h8,       Hex8(254));
286     EXPECT_EQ(map.h16,      Hex16(50000));
287     EXPECT_EQ(map.h32,      Hex32(3000000000U));
288     EXPECT_EQ(map.h64,      Hex64(6000000000LL));
289   }
290 }
291
292 struct StringTypes {
293   llvm::StringRef str1;
294   llvm::StringRef str2;
295   llvm::StringRef str3;
296   llvm::StringRef str4;
297   llvm::StringRef str5;
298   std::string stdstr1;
299   std::string stdstr2;
300   std::string stdstr3;
301   std::string stdstr4;
302   std::string stdstr5;
303 };
304
305 namespace llvm {
306 namespace yaml {
307   template <>
308   struct MappingTraits<StringTypes> {
309     static void mapping(IO &io, StringTypes& st) {
310       io.mapRequired("str1",      st.str1);
311       io.mapRequired("str2",      st.str2);
312       io.mapRequired("str3",      st.str3);
313       io.mapRequired("str4",      st.str4);
314       io.mapRequired("str5",      st.str5);
315       io.mapRequired("stdstr1",   st.stdstr1);
316       io.mapRequired("stdstr2",   st.stdstr2);
317       io.mapRequired("stdstr3",   st.stdstr3);
318       io.mapRequired("stdstr4",   st.stdstr4);
319       io.mapRequired("stdstr5",   st.stdstr5);
320     }
321   };
322 }
323 }
324
325 TEST(YAMLIO, TestReadWriteStringTypes) {
326   std::string intermediate;
327   {
328     StringTypes map;
329     map.str1 = "'aaa";
330     map.str2 = "\"bbb";
331     map.str3 = "`ccc";
332     map.str4 = "@ddd";
333     map.str5 = "";
334     map.stdstr1 = "'eee";
335     map.stdstr2 = "\"fff";
336     map.stdstr3 = "`ggg";
337     map.stdstr4 = "@hhh";
338     map.stdstr5 = "";
339
340     llvm::raw_string_ostream ostr(intermediate);
341     Output yout(ostr);
342     yout << map;
343   }
344
345   llvm::StringRef flowOut(intermediate);
346   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
347   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
348   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
349   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
350   EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
351   EXPECT_NE(std::string::npos, flowOut.find("'''eee"));
352   EXPECT_NE(std::string::npos, flowOut.find("'\"fff'"));
353   EXPECT_NE(std::string::npos, flowOut.find("'`ggg'"));
354   EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
355   EXPECT_NE(std::string::npos, flowOut.find("''\n"));
356
357   {
358     Input yin(intermediate);
359     StringTypes map;
360     yin >> map;
361
362     EXPECT_FALSE(yin.error());
363     EXPECT_TRUE(map.str1.equals("'aaa"));
364     EXPECT_TRUE(map.str2.equals("\"bbb"));
365     EXPECT_TRUE(map.str3.equals("`ccc"));
366     EXPECT_TRUE(map.str4.equals("@ddd"));
367     EXPECT_TRUE(map.str5.equals(""));
368     EXPECT_TRUE(map.stdstr1 == "'eee");
369     EXPECT_TRUE(map.stdstr2 == "\"fff");
370     EXPECT_TRUE(map.stdstr3 == "`ggg");
371     EXPECT_TRUE(map.stdstr4 == "@hhh");
372     EXPECT_TRUE(map.stdstr5 == "");
373   }
374 }
375
376 //===----------------------------------------------------------------------===//
377 //  Test ScalarEnumerationTraits
378 //===----------------------------------------------------------------------===//
379
380 enum Colors {
381     cRed,
382     cBlue,
383     cGreen,
384     cYellow
385 };
386
387 struct ColorMap {
388   Colors      c1;
389   Colors      c2;
390   Colors      c3;
391   Colors      c4;
392   Colors      c5;
393   Colors      c6;
394 };
395
396 namespace llvm {
397 namespace yaml {
398   template <>
399   struct ScalarEnumerationTraits<Colors> {
400     static void enumeration(IO &io, Colors &value) {
401       io.enumCase(value, "red",   cRed);
402       io.enumCase(value, "blue",  cBlue);
403       io.enumCase(value, "green", cGreen);
404       io.enumCase(value, "yellow",cYellow);
405     }
406   };
407   template <>
408   struct MappingTraits<ColorMap> {
409     static void mapping(IO &io, ColorMap& c) {
410       io.mapRequired("c1", c.c1);
411       io.mapRequired("c2", c.c2);
412       io.mapRequired("c3", c.c3);
413       io.mapOptional("c4", c.c4, cBlue);   // supplies default
414       io.mapOptional("c5", c.c5, cYellow); // supplies default
415       io.mapOptional("c6", c.c6, cRed);    // supplies default
416     }
417   };
418 }
419 }
420
421
422 //
423 // Test reading enumerated scalars
424 //
425 TEST(YAMLIO, TestEnumRead) {
426   ColorMap map;
427   Input yin("---\n"
428             "c1:  blue\n"
429             "c2:  red\n"
430             "c3:  green\n"
431             "c5:  yellow\n"
432             "...\n");
433   yin >> map;
434
435   EXPECT_FALSE(yin.error());
436   EXPECT_EQ(cBlue,  map.c1);
437   EXPECT_EQ(cRed,   map.c2);
438   EXPECT_EQ(cGreen, map.c3);
439   EXPECT_EQ(cBlue,  map.c4);  // tests default
440   EXPECT_EQ(cYellow,map.c5);  // tests overridden
441   EXPECT_EQ(cRed,   map.c6);  // tests default
442 }
443
444
445
446 //===----------------------------------------------------------------------===//
447 //  Test ScalarBitSetTraits
448 //===----------------------------------------------------------------------===//
449
450 enum MyFlags {
451   flagNone    = 0,
452   flagBig     = 1 << 0,
453   flagFlat    = 1 << 1,
454   flagRound   = 1 << 2,
455   flagPointy  = 1 << 3
456 };
457 inline MyFlags operator|(MyFlags a, MyFlags b) {
458   return static_cast<MyFlags>(
459                       static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
460 }
461
462 struct FlagsMap {
463   MyFlags     f1;
464   MyFlags     f2;
465   MyFlags     f3;
466   MyFlags     f4;
467 };
468
469
470 namespace llvm {
471 namespace yaml {
472   template <>
473   struct ScalarBitSetTraits<MyFlags> {
474     static void bitset(IO &io, MyFlags &value) {
475       io.bitSetCase(value, "big",   flagBig);
476       io.bitSetCase(value, "flat",  flagFlat);
477       io.bitSetCase(value, "round", flagRound);
478       io.bitSetCase(value, "pointy",flagPointy);
479     }
480   };
481   template <>
482   struct MappingTraits<FlagsMap> {
483     static void mapping(IO &io, FlagsMap& c) {
484       io.mapRequired("f1", c.f1);
485       io.mapRequired("f2", c.f2);
486       io.mapRequired("f3", c.f3);
487       io.mapOptional("f4", c.f4, MyFlags(flagRound));
488      }
489   };
490 }
491 }
492
493
494 //
495 // Test reading flow sequence representing bit-mask values
496 //
497 TEST(YAMLIO, TestFlagsRead) {
498   FlagsMap map;
499   Input yin("---\n"
500             "f1:  [ big ]\n"
501             "f2:  [ round, flat ]\n"
502             "f3:  []\n"
503             "...\n");
504   yin >> map;
505
506   EXPECT_FALSE(yin.error());
507   EXPECT_EQ(flagBig,              map.f1);
508   EXPECT_EQ(flagRound|flagFlat,   map.f2);
509   EXPECT_EQ(flagNone,             map.f3);  // check empty set
510   EXPECT_EQ(flagRound,            map.f4);  // check optional key
511 }
512
513
514 //
515 // Test writing then reading back bit-mask values
516 //
517 TEST(YAMLIO, TestReadWriteFlags) {
518   std::string intermediate;
519   {
520     FlagsMap map;
521     map.f1 = flagBig;
522     map.f2 = flagRound | flagFlat;
523     map.f3 = flagNone;
524     map.f4 = flagNone;
525
526     llvm::raw_string_ostream ostr(intermediate);
527     Output yout(ostr);
528     yout << map;
529   }
530
531   {
532     Input yin(intermediate);
533     FlagsMap map2;
534     yin >> map2;
535
536     EXPECT_FALSE(yin.error());
537     EXPECT_EQ(flagBig,              map2.f1);
538     EXPECT_EQ(flagRound|flagFlat,   map2.f2);
539     EXPECT_EQ(flagNone,             map2.f3);
540     //EXPECT_EQ(flagRound,            map2.f4);  // check optional key
541   }
542 }
543
544
545
546 //===----------------------------------------------------------------------===//
547 //  Test ScalarTraits
548 //===----------------------------------------------------------------------===//
549
550 struct MyCustomType {
551   int length;
552   int width;
553 };
554
555 struct MyCustomTypeMap {
556   MyCustomType     f1;
557   MyCustomType     f2;
558   int              f3;
559 };
560
561
562 namespace llvm {
563 namespace yaml {
564   template <>
565   struct MappingTraits<MyCustomTypeMap> {
566     static void mapping(IO &io, MyCustomTypeMap& s) {
567       io.mapRequired("f1", s.f1);
568       io.mapRequired("f2", s.f2);
569       io.mapRequired("f3", s.f3);
570      }
571   };
572   // MyCustomType is formatted as a yaml scalar.  A value of
573   // {length=3, width=4} would be represented in yaml as "3 by 4".
574   template<>
575   struct ScalarTraits<MyCustomType> {
576     static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) {
577       out << llvm::format("%d by %d", value.length, value.width);
578     }
579     static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) {
580       size_t byStart = scalar.find("by");
581       if ( byStart != StringRef::npos ) {
582         StringRef lenStr = scalar.slice(0, byStart);
583         lenStr = lenStr.rtrim();
584         if ( lenStr.getAsInteger(0, value.length) ) {
585           return "malformed length";
586         }
587         StringRef widthStr = scalar.drop_front(byStart+2);
588         widthStr = widthStr.ltrim();
589         if ( widthStr.getAsInteger(0, value.width) ) {
590           return "malformed width";
591         }
592         return StringRef();
593       }
594       else {
595           return "malformed by";
596       }
597     }
598   };
599 }
600 }
601
602
603 //
604 // Test writing then reading back custom values
605 //
606 TEST(YAMLIO, TestReadWriteMyCustomType) {
607   std::string intermediate;
608   {
609     MyCustomTypeMap map;
610     map.f1.length = 1;
611     map.f1.width  = 4;
612     map.f2.length = 100;
613     map.f2.width  = 400;
614     map.f3 = 10;
615
616     llvm::raw_string_ostream ostr(intermediate);
617     Output yout(ostr);
618     yout << map;
619   }
620
621   {
622     Input yin(intermediate);
623     MyCustomTypeMap map2;
624     yin >> map2;
625
626     EXPECT_FALSE(yin.error());
627     EXPECT_EQ(1,      map2.f1.length);
628     EXPECT_EQ(4,      map2.f1.width);
629     EXPECT_EQ(100,    map2.f2.length);
630     EXPECT_EQ(400,    map2.f2.width);
631     EXPECT_EQ(10,     map2.f3);
632   }
633 }
634
635
636 //===----------------------------------------------------------------------===//
637 //  Test flow sequences
638 //===----------------------------------------------------------------------===//
639
640 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
641 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
642 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef)
643
644 namespace llvm {
645 namespace yaml {
646   template<>
647   struct ScalarTraits<MyNumber> {
648     static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
649       out << value;
650     }
651
652     static StringRef input(StringRef scalar, void *, MyNumber &value) {
653       long long n;
654       if ( getAsSignedInteger(scalar, 0, n) )
655         return "invalid number";
656       value = n;
657       return StringRef();
658     }
659   };
660 }
661 }
662
663 struct NameAndNumbers {
664   llvm::StringRef               name;
665   std::vector<llvm::StringRef>  strings;
666   std::vector<MyNumber>         single;
667   std::vector<MyNumber>         numbers;
668 };
669
670 namespace llvm {
671 namespace yaml {
672   template <>
673   struct MappingTraits<NameAndNumbers> {
674     static void mapping(IO &io, NameAndNumbers& nn) {
675       io.mapRequired("name",     nn.name);
676       io.mapRequired("strings",  nn.strings);
677       io.mapRequired("single",   nn.single);
678       io.mapRequired("numbers",  nn.numbers);
679     }
680   };
681 }
682 }
683
684
685 //
686 // Test writing then reading back custom values
687 //
688 TEST(YAMLIO, TestReadWriteMyFlowSequence) {
689   std::string intermediate;
690   {
691     NameAndNumbers map;
692     map.name  = "hello";
693     map.strings.push_back(llvm::StringRef("one"));
694     map.strings.push_back(llvm::StringRef("two"));
695     map.single.push_back(1);
696     map.numbers.push_back(10);
697     map.numbers.push_back(-30);
698     map.numbers.push_back(1024);
699
700     llvm::raw_string_ostream ostr(intermediate);
701     Output yout(ostr);
702     yout << map;
703
704     // Verify sequences were written in flow style
705     ostr.flush();
706     llvm::StringRef flowOut(intermediate);
707     EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
708     EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
709   }
710
711   {
712     Input yin(intermediate);
713     NameAndNumbers map2;
714     yin >> map2;
715
716     EXPECT_FALSE(yin.error());
717     EXPECT_TRUE(map2.name.equals("hello"));
718     EXPECT_EQ(map2.strings.size(), 2UL);
719     EXPECT_TRUE(map2.strings[0].equals("one"));
720     EXPECT_TRUE(map2.strings[1].equals("two"));
721     EXPECT_EQ(map2.single.size(), 1UL);
722     EXPECT_EQ(1,       map2.single[0]);
723     EXPECT_EQ(map2.numbers.size(), 3UL);
724     EXPECT_EQ(10,      map2.numbers[0]);
725     EXPECT_EQ(-30,     map2.numbers[1]);
726     EXPECT_EQ(1024,    map2.numbers[2]);
727   }
728 }
729
730
731 //===----------------------------------------------------------------------===//
732 //  Test normalizing/denormalizing
733 //===----------------------------------------------------------------------===//
734
735 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
736
737 typedef std::vector<TotalSeconds> SecondsSequence;
738
739 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
740
741
742 namespace llvm {
743 namespace yaml {
744   template <>
745   struct MappingTraits<TotalSeconds> {
746
747     class NormalizedSeconds {
748     public:
749       NormalizedSeconds(IO &io)
750         : hours(0), minutes(0), seconds(0) {
751       }
752       NormalizedSeconds(IO &, TotalSeconds &secs)
753         : hours(secs/3600),
754           minutes((secs - (hours*3600))/60),
755           seconds(secs % 60) {
756       }
757       TotalSeconds denormalize(IO &) {
758         return TotalSeconds(hours*3600 + minutes*60 + seconds);
759       }
760
761       uint32_t     hours;
762       uint8_t      minutes;
763       uint8_t      seconds;
764     };
765
766     static void mapping(IO &io, TotalSeconds &secs) {
767       MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
768
769       io.mapOptional("hours",    keys->hours,    (uint32_t)0);
770       io.mapOptional("minutes",  keys->minutes,  (uint8_t)0);
771       io.mapRequired("seconds",  keys->seconds);
772     }
773   };
774 }
775 }
776
777
778 //
779 // Test the reading of a yaml sequence of mappings
780 //
781 TEST(YAMLIO, TestReadMySecondsSequence) {
782   SecondsSequence seq;
783   Input yin("---\n - hours:  1\n   seconds:  5\n - seconds:  59\n...\n");
784   yin >> seq;
785
786   EXPECT_FALSE(yin.error());
787   EXPECT_EQ(seq.size(), 2UL);
788   EXPECT_EQ(seq[0], 3605U);
789   EXPECT_EQ(seq[1], 59U);
790 }
791
792
793 //
794 // Test writing then reading back custom values
795 //
796 TEST(YAMLIO, TestReadWriteMySecondsSequence) {
797   std::string intermediate;
798   {
799     SecondsSequence seq;
800     seq.push_back(4000);
801     seq.push_back(500);
802     seq.push_back(59);
803
804     llvm::raw_string_ostream ostr(intermediate);
805     Output yout(ostr);
806     yout << seq;
807   }
808   {
809     Input yin(intermediate);
810     SecondsSequence seq2;
811     yin >> seq2;
812
813     EXPECT_FALSE(yin.error());
814     EXPECT_EQ(seq2.size(), 3UL);
815     EXPECT_EQ(seq2[0], 4000U);
816     EXPECT_EQ(seq2[1], 500U);
817     EXPECT_EQ(seq2[2], 59U);
818   }
819 }
820
821
822 //===----------------------------------------------------------------------===//
823 //  Test dynamic typing
824 //===----------------------------------------------------------------------===//
825
826 enum AFlags {
827     a1,
828     a2,
829     a3
830 };
831
832 enum BFlags {
833     b1,
834     b2,
835     b3
836 };
837
838 enum Kind {
839     kindA,
840     kindB
841 };
842
843 struct KindAndFlags {
844   KindAndFlags() : kind(kindA), flags(0) { }
845   KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
846   Kind        kind;
847   uint32_t    flags;
848 };
849
850 typedef std::vector<KindAndFlags> KindAndFlagsSequence;
851
852 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
853
854 namespace llvm {
855 namespace yaml {
856   template <>
857   struct ScalarEnumerationTraits<AFlags> {
858     static void enumeration(IO &io, AFlags &value) {
859       io.enumCase(value, "a1",  a1);
860       io.enumCase(value, "a2",  a2);
861       io.enumCase(value, "a3",  a3);
862     }
863   };
864   template <>
865   struct ScalarEnumerationTraits<BFlags> {
866     static void enumeration(IO &io, BFlags &value) {
867       io.enumCase(value, "b1",  b1);
868       io.enumCase(value, "b2",  b2);
869       io.enumCase(value, "b3",  b3);
870     }
871   };
872   template <>
873   struct ScalarEnumerationTraits<Kind> {
874     static void enumeration(IO &io, Kind &value) {
875       io.enumCase(value, "A",  kindA);
876       io.enumCase(value, "B",  kindB);
877     }
878   };
879   template <>
880   struct MappingTraits<KindAndFlags> {
881     static void mapping(IO &io, KindAndFlags& kf) {
882       io.mapRequired("kind",  kf.kind);
883       // Type of "flags" field varies depending on "kind" field.
884       // Use memcpy here to avoid breaking strict aliasing rules.
885       if (kf.kind == kindA) {
886         AFlags aflags = static_cast<AFlags>(kf.flags);
887         io.mapRequired("flags", aflags);
888         kf.flags = aflags;
889       } else {
890         BFlags bflags = static_cast<BFlags>(kf.flags);
891         io.mapRequired("flags", bflags);
892         kf.flags = bflags;
893       }
894     }
895   };
896 }
897 }
898
899
900 //
901 // Test the reading of a yaml sequence dynamic types
902 //
903 TEST(YAMLIO, TestReadKindAndFlagsSequence) {
904   KindAndFlagsSequence seq;
905   Input yin("---\n - kind:  A\n   flags:  a2\n - kind:  B\n   flags:  b1\n...\n");
906   yin >> seq;
907
908   EXPECT_FALSE(yin.error());
909   EXPECT_EQ(seq.size(), 2UL);
910   EXPECT_EQ(seq[0].kind,  kindA);
911   EXPECT_EQ(seq[0].flags, (uint32_t)a2);
912   EXPECT_EQ(seq[1].kind,  kindB);
913   EXPECT_EQ(seq[1].flags, (uint32_t)b1);
914 }
915
916 //
917 // Test writing then reading back dynamic types
918 //
919 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
920   std::string intermediate;
921   {
922     KindAndFlagsSequence seq;
923     seq.push_back(KindAndFlags(kindA,a1));
924     seq.push_back(KindAndFlags(kindB,b1));
925     seq.push_back(KindAndFlags(kindA,a2));
926     seq.push_back(KindAndFlags(kindB,b2));
927     seq.push_back(KindAndFlags(kindA,a3));
928
929     llvm::raw_string_ostream ostr(intermediate);
930     Output yout(ostr);
931     yout << seq;
932   }
933   {
934     Input yin(intermediate);
935     KindAndFlagsSequence seq2;
936     yin >> seq2;
937
938     EXPECT_FALSE(yin.error());
939     EXPECT_EQ(seq2.size(), 5UL);
940     EXPECT_EQ(seq2[0].kind,  kindA);
941     EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
942     EXPECT_EQ(seq2[1].kind,  kindB);
943     EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
944     EXPECT_EQ(seq2[2].kind,  kindA);
945     EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
946     EXPECT_EQ(seq2[3].kind,  kindB);
947     EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
948     EXPECT_EQ(seq2[4].kind,  kindA);
949     EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
950   }
951 }
952
953
954 //===----------------------------------------------------------------------===//
955 //  Test document list
956 //===----------------------------------------------------------------------===//
957
958 struct FooBarMap {
959   int foo;
960   int bar;
961 };
962 typedef std::vector<FooBarMap> FooBarMapDocumentList;
963
964 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
965
966
967 namespace llvm {
968 namespace yaml {
969   template <>
970   struct MappingTraits<FooBarMap> {
971     static void mapping(IO &io, FooBarMap& fb) {
972       io.mapRequired("foo",    fb.foo);
973       io.mapRequired("bar",    fb.bar);
974     }
975   };
976 }
977 }
978
979
980 //
981 // Test the reading of a yaml mapping
982 //
983 TEST(YAMLIO, TestDocRead) {
984   FooBarMap doc;
985   Input yin("---\nfoo:  3\nbar:  5\n...\n");
986   yin >> doc;
987
988   EXPECT_FALSE(yin.error());
989   EXPECT_EQ(doc.foo, 3);
990   EXPECT_EQ(doc.bar,5);
991 }
992
993
994
995 //
996 // Test writing then reading back a sequence of mappings
997 //
998 TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
999   std::string intermediate;
1000   {
1001     FooBarMap doc1;
1002     doc1.foo = 10;
1003     doc1.bar = -3;
1004     FooBarMap doc2;
1005     doc2.foo = 257;
1006     doc2.bar = 0;
1007     std::vector<FooBarMap> docList;
1008     docList.push_back(doc1);
1009     docList.push_back(doc2);
1010
1011     llvm::raw_string_ostream ostr(intermediate);
1012     Output yout(ostr);
1013     yout << docList;
1014   }
1015
1016
1017   {
1018     Input yin(intermediate);
1019     std::vector<FooBarMap> docList2;
1020     yin >> docList2;
1021
1022     EXPECT_FALSE(yin.error());
1023     EXPECT_EQ(docList2.size(), 2UL);
1024     FooBarMap& map1 = docList2[0];
1025     FooBarMap& map2 = docList2[1];
1026     EXPECT_EQ(map1.foo, 10);
1027     EXPECT_EQ(map1.bar, -3);
1028     EXPECT_EQ(map2.foo, 257);
1029     EXPECT_EQ(map2.bar, 0);
1030   }
1031 }
1032
1033 //===----------------------------------------------------------------------===//
1034 //  Test document tags
1035 //===----------------------------------------------------------------------===//
1036
1037 struct MyDouble {
1038   MyDouble() : value(0.0) { }
1039   MyDouble(double x) : value(x) { }
1040   double value;
1041 };
1042
1043 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
1044
1045
1046 namespace llvm {
1047 namespace yaml {
1048   template <>
1049   struct MappingTraits<MyDouble> {
1050     static void mapping(IO &io, MyDouble &d) {
1051       if (io.mapTag("!decimal", true)) {
1052         mappingDecimal(io, d);
1053       } else if (io.mapTag("!fraction")) {
1054         mappingFraction(io, d);
1055       }
1056     }
1057     static void mappingDecimal(IO &io, MyDouble &d) {
1058       io.mapRequired("value", d.value);
1059     }
1060     static void mappingFraction(IO &io, MyDouble &d) {
1061         double num, denom;
1062         io.mapRequired("numerator",      num);
1063         io.mapRequired("denominator",    denom);
1064         // convert fraction to double
1065         d.value = num/denom;
1066     }
1067   };
1068  }
1069 }
1070
1071
1072 //
1073 // Test the reading of two different tagged yaml documents.
1074 //
1075 TEST(YAMLIO, TestTaggedDocuments) {
1076   std::vector<MyDouble> docList;
1077   Input yin("--- !decimal\nvalue:  3.0\n"
1078             "--- !fraction\nnumerator:  9.0\ndenominator:  2\n...\n");
1079   yin >> docList;
1080   EXPECT_FALSE(yin.error());
1081   EXPECT_EQ(docList.size(), 2UL);
1082   EXPECT_EQ(docList[0].value, 3.0);
1083   EXPECT_EQ(docList[1].value, 4.5);
1084 }
1085
1086
1087
1088 //
1089 // Test writing then reading back tagged documents
1090 //
1091 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1092   std::string intermediate;
1093   {
1094     MyDouble a(10.25);
1095     MyDouble b(-3.75);
1096     std::vector<MyDouble> docList;
1097     docList.push_back(a);
1098     docList.push_back(b);
1099
1100     llvm::raw_string_ostream ostr(intermediate);
1101     Output yout(ostr);
1102     yout << docList;
1103   }
1104
1105   {
1106     Input yin(intermediate);
1107     std::vector<MyDouble> docList2;
1108     yin >> docList2;
1109
1110     EXPECT_FALSE(yin.error());
1111     EXPECT_EQ(docList2.size(), 2UL);
1112     EXPECT_EQ(docList2[0].value, 10.25);
1113     EXPECT_EQ(docList2[1].value, -3.75);
1114   }
1115 }
1116
1117
1118
1119 //===----------------------------------------------------------------------===//
1120 //  Test error handling
1121 //===----------------------------------------------------------------------===//
1122
1123
1124
1125 static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
1126 }
1127
1128
1129 //
1130 // Test error handling of unknown enumerated scalar
1131 //
1132 TEST(YAMLIO, TestColorsReadError) {
1133   ColorMap map;
1134   Input yin("---\n"
1135             "c1:  blue\n"
1136             "c2:  purple\n"
1137             "c3:  green\n"
1138             "...\n",
1139             /*Ctxt=*/NULL,
1140             suppressErrorMessages);
1141   yin >> map;
1142   EXPECT_TRUE(yin.error());
1143 }
1144
1145
1146 //
1147 // Test error handling of flow sequence with unknown value
1148 //
1149 TEST(YAMLIO, TestFlagsReadError) {
1150   FlagsMap map;
1151   Input yin("---\n"
1152             "f1:  [ big ]\n"
1153             "f2:  [ round, hollow ]\n"
1154             "f3:  []\n"
1155             "...\n",
1156             /*Ctxt=*/NULL,
1157             suppressErrorMessages);
1158   yin >> map;
1159
1160   EXPECT_TRUE(yin.error());
1161 }
1162
1163
1164 //
1165 // Test error handling reading built-in uint8_t type
1166 //
1167 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
1168 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1169   std::vector<uint8_t> seq;
1170   Input yin("---\n"
1171             "- 255\n"
1172             "- 0\n"
1173             "- 257\n"
1174             "...\n",
1175             /*Ctxt=*/NULL,
1176             suppressErrorMessages);
1177   yin >> seq;
1178
1179   EXPECT_TRUE(yin.error());
1180 }
1181
1182
1183 //
1184 // Test error handling reading built-in uint16_t type
1185 //
1186 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
1187 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1188   std::vector<uint16_t> seq;
1189   Input yin("---\n"
1190             "- 65535\n"
1191             "- 0\n"
1192             "- 66000\n"
1193             "...\n",
1194             /*Ctxt=*/NULL,
1195             suppressErrorMessages);
1196   yin >> seq;
1197
1198   EXPECT_TRUE(yin.error());
1199 }
1200
1201
1202 //
1203 // Test error handling reading built-in uint32_t type
1204 //
1205 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
1206 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1207   std::vector<uint32_t> seq;
1208   Input yin("---\n"
1209             "- 4000000000\n"
1210             "- 0\n"
1211             "- 5000000000\n"
1212             "...\n",
1213             /*Ctxt=*/NULL,
1214             suppressErrorMessages);
1215   yin >> seq;
1216
1217   EXPECT_TRUE(yin.error());
1218 }
1219
1220
1221 //
1222 // Test error handling reading built-in uint64_t type
1223 //
1224 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
1225 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1226   std::vector<uint64_t> seq;
1227   Input yin("---\n"
1228             "- 18446744073709551615\n"
1229             "- 0\n"
1230             "- 19446744073709551615\n"
1231             "...\n",
1232             /*Ctxt=*/NULL,
1233             suppressErrorMessages);
1234   yin >> seq;
1235
1236   EXPECT_TRUE(yin.error());
1237 }
1238
1239
1240 //
1241 // Test error handling reading built-in int8_t type
1242 //
1243 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
1244 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1245   std::vector<int8_t> seq;
1246   Input yin("---\n"
1247             "- -128\n"
1248             "- 0\n"
1249             "- 127\n"
1250             "- 128\n"
1251            "...\n",
1252             /*Ctxt=*/NULL,
1253             suppressErrorMessages);
1254   yin >> seq;
1255
1256   EXPECT_TRUE(yin.error());
1257 }
1258
1259 //
1260 // Test error handling reading built-in int8_t type
1261 //
1262 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1263   std::vector<int8_t> seq;
1264   Input yin("---\n"
1265             "- -128\n"
1266             "- 0\n"
1267             "- 127\n"
1268             "- -129\n"
1269             "...\n",
1270             /*Ctxt=*/NULL,
1271             suppressErrorMessages);
1272   yin >> seq;
1273
1274   EXPECT_TRUE(yin.error());
1275 }
1276
1277
1278 //
1279 // Test error handling reading built-in int16_t type
1280 //
1281 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
1282 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1283   std::vector<int16_t> seq;
1284   Input yin("---\n"
1285             "- 32767\n"
1286             "- 0\n"
1287             "- -32768\n"
1288             "- -32769\n"
1289             "...\n",
1290             /*Ctxt=*/NULL,
1291             suppressErrorMessages);
1292   yin >> seq;
1293
1294   EXPECT_TRUE(yin.error());
1295 }
1296
1297
1298 //
1299 // Test error handling reading built-in int16_t type
1300 //
1301 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1302   std::vector<int16_t> seq;
1303   Input yin("---\n"
1304             "- 32767\n"
1305             "- 0\n"
1306             "- -32768\n"
1307             "- 32768\n"
1308             "...\n",
1309             /*Ctxt=*/NULL,
1310             suppressErrorMessages);
1311   yin >> seq;
1312
1313   EXPECT_TRUE(yin.error());
1314 }
1315
1316
1317 //
1318 // Test error handling reading built-in int32_t type
1319 //
1320 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
1321 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1322   std::vector<int32_t> seq;
1323   Input yin("---\n"
1324             "- 2147483647\n"
1325             "- 0\n"
1326             "- -2147483648\n"
1327             "- -2147483649\n"
1328             "...\n",
1329             /*Ctxt=*/NULL,
1330             suppressErrorMessages);
1331   yin >> seq;
1332
1333   EXPECT_TRUE(yin.error());
1334 }
1335
1336 //
1337 // Test error handling reading built-in int32_t type
1338 //
1339 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
1340   std::vector<int32_t> seq;
1341   Input yin("---\n"
1342             "- 2147483647\n"
1343             "- 0\n"
1344             "- -2147483648\n"
1345             "- 2147483649\n"
1346             "...\n",
1347             /*Ctxt=*/NULL,
1348             suppressErrorMessages);
1349   yin >> seq;
1350
1351   EXPECT_TRUE(yin.error());
1352 }
1353
1354
1355 //
1356 // Test error handling reading built-in int64_t type
1357 //
1358 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
1359 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
1360   std::vector<int64_t> seq;
1361   Input yin("---\n"
1362             "- -9223372036854775808\n"
1363             "- 0\n"
1364             "- 9223372036854775807\n"
1365             "- -9223372036854775809\n"
1366             "...\n",
1367             /*Ctxt=*/NULL,
1368             suppressErrorMessages);
1369   yin >> seq;
1370
1371   EXPECT_TRUE(yin.error());
1372 }
1373
1374 //
1375 // Test error handling reading built-in int64_t type
1376 //
1377 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
1378   std::vector<int64_t> seq;
1379   Input yin("---\n"
1380             "- -9223372036854775808\n"
1381             "- 0\n"
1382             "- 9223372036854775807\n"
1383             "- 9223372036854775809\n"
1384             "...\n",
1385             /*Ctxt=*/NULL,
1386             suppressErrorMessages);
1387   yin >> seq;
1388
1389   EXPECT_TRUE(yin.error());
1390 }
1391
1392 //
1393 // Test error handling reading built-in float type
1394 //
1395 LLVM_YAML_IS_SEQUENCE_VECTOR(float)
1396 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
1397   std::vector<float> seq;
1398   Input yin("---\n"
1399             "- 0.0\n"
1400             "- 1000.1\n"
1401             "- -123.456\n"
1402             "- 1.2.3\n"
1403             "...\n",
1404             /*Ctxt=*/NULL,
1405             suppressErrorMessages);
1406   yin >> seq;
1407
1408   EXPECT_TRUE(yin.error());
1409 }
1410
1411 //
1412 // Test error handling reading built-in float type
1413 //
1414 LLVM_YAML_IS_SEQUENCE_VECTOR(double)
1415 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
1416   std::vector<double> seq;
1417   Input yin("---\n"
1418             "- 0.0\n"
1419             "- 1000.1\n"
1420             "- -123.456\n"
1421             "- 1.2.3\n"
1422             "...\n",
1423             /*Ctxt=*/NULL,
1424             suppressErrorMessages);
1425   yin >> seq;
1426
1427   EXPECT_TRUE(yin.error());
1428 }
1429
1430 //
1431 // Test error handling reading built-in Hex8 type
1432 //
1433 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
1434 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
1435   std::vector<Hex8> seq;
1436   Input yin("---\n"
1437             "- 0x12\n"
1438             "- 0xFE\n"
1439             "- 0x123\n"
1440             "...\n",
1441             /*Ctxt=*/NULL,
1442             suppressErrorMessages);
1443   yin >> seq;
1444
1445   EXPECT_TRUE(yin.error());
1446 }
1447
1448
1449 //
1450 // Test error handling reading built-in Hex16 type
1451 //
1452 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
1453 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
1454   std::vector<Hex16> seq;
1455   Input yin("---\n"
1456             "- 0x0012\n"
1457             "- 0xFEFF\n"
1458             "- 0x12345\n"
1459             "...\n",
1460             /*Ctxt=*/NULL,
1461             suppressErrorMessages);
1462   yin >> seq;
1463
1464   EXPECT_TRUE(yin.error());
1465 }
1466
1467 //
1468 // Test error handling reading built-in Hex32 type
1469 //
1470 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
1471 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
1472   std::vector<Hex32> seq;
1473   Input yin("---\n"
1474             "- 0x0012\n"
1475             "- 0xFEFF0000\n"
1476             "- 0x1234556789\n"
1477             "...\n",
1478             /*Ctxt=*/NULL,
1479             suppressErrorMessages);
1480   yin >> seq;
1481
1482   EXPECT_TRUE(yin.error());
1483 }
1484
1485 //
1486 // Test error handling reading built-in Hex64 type
1487 //
1488 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
1489 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
1490   std::vector<Hex64> seq;
1491   Input yin("---\n"
1492             "- 0x0012\n"
1493             "- 0xFFEEDDCCBBAA9988\n"
1494             "- 0x12345567890ABCDEF0\n"
1495             "...\n",
1496             /*Ctxt=*/NULL,
1497             suppressErrorMessages);
1498   yin >> seq;
1499
1500   EXPECT_TRUE(yin.error());
1501 }
1502
1503 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
1504   FooBar doc;
1505   {
1506     // We pass the suppressErrorMessages handler to handle the error
1507     // message generated in the constructor of Input.
1508     Input yin("{foo:3, bar: 5}", /*Ctxt=*/NULL, suppressErrorMessages);
1509     yin >> doc;
1510     EXPECT_TRUE(yin.error());
1511   }
1512
1513   {
1514     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/NULL, suppressErrorMessages);
1515     yin >> doc;
1516     EXPECT_TRUE(yin.error());
1517   }
1518 }
1519
1520 struct OptionalTest {
1521   std::vector<int> Numbers;
1522 };
1523
1524 struct OptionalTestSeq {
1525   std::vector<OptionalTest> Tests;
1526 };
1527
1528 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
1529 namespace llvm {
1530 namespace yaml {
1531   template <>
1532   struct MappingTraits<OptionalTest> {
1533     static void mapping(IO& IO, OptionalTest &OT) {
1534       IO.mapOptional("Numbers", OT.Numbers);
1535     }
1536   };
1537
1538   template <>
1539   struct MappingTraits<OptionalTestSeq> {
1540     static void mapping(IO &IO, OptionalTestSeq &OTS) {
1541       IO.mapOptional("Tests", OTS.Tests);
1542     }
1543   };
1544 }
1545 }
1546
1547 TEST(YAMLIO, SequenceElideTest) {
1548   // Test that writing out a purely optional structure with its fields set to
1549   // default followed by other data is properly read back in.
1550   OptionalTestSeq Seq;
1551   OptionalTest One, Two, Three, Four;
1552   int N[] = {1, 2, 3};
1553   Three.Numbers.assign(N, N + 3);
1554   Seq.Tests.push_back(One);
1555   Seq.Tests.push_back(Two);
1556   Seq.Tests.push_back(Three);
1557   Seq.Tests.push_back(Four);
1558
1559   std::string intermediate;
1560   {
1561     llvm::raw_string_ostream ostr(intermediate);
1562     Output yout(ostr);
1563     yout << Seq;
1564   }
1565
1566   Input yin(intermediate);
1567   OptionalTestSeq Seq2;
1568   yin >> Seq2;
1569
1570   EXPECT_FALSE(yin.error());
1571
1572   EXPECT_EQ(4UL, Seq2.Tests.size());
1573
1574   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
1575   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
1576
1577   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
1578   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
1579   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
1580
1581   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
1582 }
1583
1584 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
1585   FooBar doc;
1586   Input yin("");
1587   yin >> doc;
1588   EXPECT_TRUE(yin.error());
1589 }
1590
1591 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
1592   OptionalTest doc;
1593   Input yin("");
1594   yin >> doc;
1595   EXPECT_FALSE(yin.error());
1596 }
1597
1598 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
1599   std::vector<uint8_t> seq;
1600   Input yin("", /*Ctxt=*/NULL, suppressErrorMessages);
1601   yin >> seq;
1602
1603   EXPECT_FALSE(yin.error());
1604   EXPECT_TRUE(seq.empty());
1605 }