YAML I/O - Added default trait support for std:string. Making another attempt at...
[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 //  Test dyn_cast<> on IO object 
1120 //===----------------------------------------------------------------------===//
1121
1122 struct DynCast {
1123   int value;
1124 };
1125 typedef std::vector<DynCast> DynCastSequence;
1126
1127 LLVM_YAML_IS_SEQUENCE_VECTOR(DynCast)
1128
1129 namespace llvm {
1130 namespace yaml {
1131   template <>
1132   struct MappingTraits<DynCast> {
1133     static void mapping(IO &io, DynCast& info) {
1134       // Change 10 to 13 when writing yaml.
1135       if (Output *output = dyn_cast<Output>(&io)) {
1136         (void)output;
1137         if (info.value == 10)
1138           info.value = 13;
1139       }
1140       io.mapRequired("value", info.value);
1141       // Change 20 to 23 when parsing yaml.
1142       if (Input *input = dyn_cast<Input>(&io)) {
1143         (void)input;
1144         if (info.value == 20)
1145           info.value = 23;
1146       }
1147     }
1148   };
1149 }
1150 }
1151
1152 //
1153 // Test writing then reading back a sequence of mappings
1154 //
1155 TEST(YAMLIO, TestDynCast) {
1156   std::string intermediate;
1157   {
1158     DynCast entry1;
1159     entry1.value = 10;
1160     DynCast entry2;
1161     entry2.value = 20;
1162     DynCast entry3;
1163     entry3.value = 30;
1164     DynCastSequence seq;
1165     seq.push_back(entry1);
1166     seq.push_back(entry2);
1167     seq.push_back(entry3);
1168
1169     llvm::raw_string_ostream ostr(intermediate);
1170     Output yout(ostr);
1171     yout << seq;
1172   }
1173
1174   {
1175     Input yin(intermediate);
1176     DynCastSequence seq2;
1177     yin >> seq2;
1178
1179     EXPECT_FALSE(yin.error());
1180     EXPECT_EQ(seq2.size(), 3UL);
1181     EXPECT_EQ(seq2[0].value, 13);   // Verify changed to 13.
1182     EXPECT_EQ(seq2[1].value, 23);   // Verify changed to 23.
1183     EXPECT_EQ(seq2[2].value, 30);   // Verify stays same.
1184   }
1185 }
1186
1187
1188
1189 //===----------------------------------------------------------------------===//
1190 //  Test error handling
1191 //===----------------------------------------------------------------------===//
1192
1193
1194
1195 static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
1196 }
1197
1198
1199 //
1200 // Test error handling of unknown enumerated scalar
1201 //
1202 TEST(YAMLIO, TestColorsReadError) {
1203   ColorMap map;
1204   Input yin("---\n"
1205             "c1:  blue\n"
1206             "c2:  purple\n"
1207             "c3:  green\n"
1208             "...\n",
1209             /*Ctxt=*/NULL,
1210             suppressErrorMessages);
1211   yin >> map;
1212   EXPECT_TRUE(yin.error());
1213 }
1214
1215
1216 //
1217 // Test error handling of flow sequence with unknown value
1218 //
1219 TEST(YAMLIO, TestFlagsReadError) {
1220   FlagsMap map;
1221   Input yin("---\n"
1222             "f1:  [ big ]\n"
1223             "f2:  [ round, hollow ]\n"
1224             "f3:  []\n"
1225             "...\n",
1226             /*Ctxt=*/NULL,
1227             suppressErrorMessages);
1228   yin >> map;
1229
1230   EXPECT_TRUE(yin.error());
1231 }
1232
1233
1234 //
1235 // Test error handling reading built-in uint8_t type
1236 //
1237 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
1238 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1239   std::vector<uint8_t> seq;
1240   Input yin("---\n"
1241             "- 255\n"
1242             "- 0\n"
1243             "- 257\n"
1244             "...\n",
1245             /*Ctxt=*/NULL,
1246             suppressErrorMessages);
1247   yin >> seq;
1248
1249   EXPECT_TRUE(yin.error());
1250 }
1251
1252
1253 //
1254 // Test error handling reading built-in uint16_t type
1255 //
1256 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
1257 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1258   std::vector<uint16_t> seq;
1259   Input yin("---\n"
1260             "- 65535\n"
1261             "- 0\n"
1262             "- 66000\n"
1263             "...\n",
1264             /*Ctxt=*/NULL,
1265             suppressErrorMessages);
1266   yin >> seq;
1267
1268   EXPECT_TRUE(yin.error());
1269 }
1270
1271
1272 //
1273 // Test error handling reading built-in uint32_t type
1274 //
1275 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
1276 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1277   std::vector<uint32_t> seq;
1278   Input yin("---\n"
1279             "- 4000000000\n"
1280             "- 0\n"
1281             "- 5000000000\n"
1282             "...\n",
1283             /*Ctxt=*/NULL,
1284             suppressErrorMessages);
1285   yin >> seq;
1286
1287   EXPECT_TRUE(yin.error());
1288 }
1289
1290
1291 //
1292 // Test error handling reading built-in uint64_t type
1293 //
1294 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
1295 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1296   std::vector<uint64_t> seq;
1297   Input yin("---\n"
1298             "- 18446744073709551615\n"
1299             "- 0\n"
1300             "- 19446744073709551615\n"
1301             "...\n",
1302             /*Ctxt=*/NULL,
1303             suppressErrorMessages);
1304   yin >> seq;
1305
1306   EXPECT_TRUE(yin.error());
1307 }
1308
1309
1310 //
1311 // Test error handling reading built-in int8_t type
1312 //
1313 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
1314 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1315   std::vector<int8_t> seq;
1316   Input yin("---\n"
1317             "- -128\n"
1318             "- 0\n"
1319             "- 127\n"
1320             "- 128\n"
1321            "...\n",
1322             /*Ctxt=*/NULL,
1323             suppressErrorMessages);
1324   yin >> seq;
1325
1326   EXPECT_TRUE(yin.error());
1327 }
1328
1329 //
1330 // Test error handling reading built-in int8_t type
1331 //
1332 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1333   std::vector<int8_t> seq;
1334   Input yin("---\n"
1335             "- -128\n"
1336             "- 0\n"
1337             "- 127\n"
1338             "- -129\n"
1339             "...\n",
1340             /*Ctxt=*/NULL,
1341             suppressErrorMessages);
1342   yin >> seq;
1343
1344   EXPECT_TRUE(yin.error());
1345 }
1346
1347
1348 //
1349 // Test error handling reading built-in int16_t type
1350 //
1351 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
1352 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1353   std::vector<int16_t> seq;
1354   Input yin("---\n"
1355             "- 32767\n"
1356             "- 0\n"
1357             "- -32768\n"
1358             "- -32769\n"
1359             "...\n",
1360             /*Ctxt=*/NULL,
1361             suppressErrorMessages);
1362   yin >> seq;
1363
1364   EXPECT_TRUE(yin.error());
1365 }
1366
1367
1368 //
1369 // Test error handling reading built-in int16_t type
1370 //
1371 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1372   std::vector<int16_t> seq;
1373   Input yin("---\n"
1374             "- 32767\n"
1375             "- 0\n"
1376             "- -32768\n"
1377             "- 32768\n"
1378             "...\n",
1379             /*Ctxt=*/NULL,
1380             suppressErrorMessages);
1381   yin >> seq;
1382
1383   EXPECT_TRUE(yin.error());
1384 }
1385
1386
1387 //
1388 // Test error handling reading built-in int32_t type
1389 //
1390 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
1391 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1392   std::vector<int32_t> seq;
1393   Input yin("---\n"
1394             "- 2147483647\n"
1395             "- 0\n"
1396             "- -2147483648\n"
1397             "- -2147483649\n"
1398             "...\n",
1399             /*Ctxt=*/NULL,
1400             suppressErrorMessages);
1401   yin >> seq;
1402
1403   EXPECT_TRUE(yin.error());
1404 }
1405
1406 //
1407 // Test error handling reading built-in int32_t type
1408 //
1409 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
1410   std::vector<int32_t> seq;
1411   Input yin("---\n"
1412             "- 2147483647\n"
1413             "- 0\n"
1414             "- -2147483648\n"
1415             "- 2147483649\n"
1416             "...\n",
1417             /*Ctxt=*/NULL,
1418             suppressErrorMessages);
1419   yin >> seq;
1420
1421   EXPECT_TRUE(yin.error());
1422 }
1423
1424
1425 //
1426 // Test error handling reading built-in int64_t type
1427 //
1428 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
1429 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
1430   std::vector<int64_t> seq;
1431   Input yin("---\n"
1432             "- -9223372036854775808\n"
1433             "- 0\n"
1434             "- 9223372036854775807\n"
1435             "- -9223372036854775809\n"
1436             "...\n",
1437             /*Ctxt=*/NULL,
1438             suppressErrorMessages);
1439   yin >> seq;
1440
1441   EXPECT_TRUE(yin.error());
1442 }
1443
1444 //
1445 // Test error handling reading built-in int64_t type
1446 //
1447 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
1448   std::vector<int64_t> seq;
1449   Input yin("---\n"
1450             "- -9223372036854775808\n"
1451             "- 0\n"
1452             "- 9223372036854775807\n"
1453             "- 9223372036854775809\n"
1454             "...\n",
1455             /*Ctxt=*/NULL,
1456             suppressErrorMessages);
1457   yin >> seq;
1458
1459   EXPECT_TRUE(yin.error());
1460 }
1461
1462 //
1463 // Test error handling reading built-in float type
1464 //
1465 LLVM_YAML_IS_SEQUENCE_VECTOR(float)
1466 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
1467   std::vector<float> seq;
1468   Input yin("---\n"
1469             "- 0.0\n"
1470             "- 1000.1\n"
1471             "- -123.456\n"
1472             "- 1.2.3\n"
1473             "...\n",
1474             /*Ctxt=*/NULL,
1475             suppressErrorMessages);
1476   yin >> seq;
1477
1478   EXPECT_TRUE(yin.error());
1479 }
1480
1481 //
1482 // Test error handling reading built-in float type
1483 //
1484 LLVM_YAML_IS_SEQUENCE_VECTOR(double)
1485 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
1486   std::vector<double> seq;
1487   Input yin("---\n"
1488             "- 0.0\n"
1489             "- 1000.1\n"
1490             "- -123.456\n"
1491             "- 1.2.3\n"
1492             "...\n",
1493             /*Ctxt=*/NULL,
1494             suppressErrorMessages);
1495   yin >> seq;
1496
1497   EXPECT_TRUE(yin.error());
1498 }
1499
1500 //
1501 // Test error handling reading built-in Hex8 type
1502 //
1503 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
1504 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
1505   std::vector<Hex8> seq;
1506   Input yin("---\n"
1507             "- 0x12\n"
1508             "- 0xFE\n"
1509             "- 0x123\n"
1510             "...\n",
1511             /*Ctxt=*/NULL,
1512             suppressErrorMessages);
1513   yin >> seq;
1514
1515   EXPECT_TRUE(yin.error());
1516 }
1517
1518
1519 //
1520 // Test error handling reading built-in Hex16 type
1521 //
1522 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
1523 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
1524   std::vector<Hex16> seq;
1525   Input yin("---\n"
1526             "- 0x0012\n"
1527             "- 0xFEFF\n"
1528             "- 0x12345\n"
1529             "...\n",
1530             /*Ctxt=*/NULL,
1531             suppressErrorMessages);
1532   yin >> seq;
1533
1534   EXPECT_TRUE(yin.error());
1535 }
1536
1537 //
1538 // Test error handling reading built-in Hex32 type
1539 //
1540 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
1541 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
1542   std::vector<Hex32> seq;
1543   Input yin("---\n"
1544             "- 0x0012\n"
1545             "- 0xFEFF0000\n"
1546             "- 0x1234556789\n"
1547             "...\n",
1548             /*Ctxt=*/NULL,
1549             suppressErrorMessages);
1550   yin >> seq;
1551
1552   EXPECT_TRUE(yin.error());
1553 }
1554
1555 //
1556 // Test error handling reading built-in Hex64 type
1557 //
1558 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
1559 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
1560   std::vector<Hex64> seq;
1561   Input yin("---\n"
1562             "- 0x0012\n"
1563             "- 0xFFEEDDCCBBAA9988\n"
1564             "- 0x12345567890ABCDEF0\n"
1565             "...\n",
1566             /*Ctxt=*/NULL,
1567             suppressErrorMessages);
1568   yin >> seq;
1569
1570   EXPECT_TRUE(yin.error());
1571 }
1572
1573 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
1574   FooBar doc;
1575   {
1576     // We pass the suppressErrorMessages handler to handle the error
1577     // message generated in the constructor of Input.
1578     Input yin("{foo:3, bar: 5}", /*Ctxt=*/NULL, suppressErrorMessages);
1579     yin >> doc;
1580     EXPECT_TRUE(yin.error());
1581   }
1582
1583   {
1584     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/NULL, suppressErrorMessages);
1585     yin >> doc;
1586     EXPECT_TRUE(yin.error());
1587   }
1588 }
1589
1590 struct OptionalTest {
1591   std::vector<int> Numbers;
1592 };
1593
1594 struct OptionalTestSeq {
1595   std::vector<OptionalTest> Tests;
1596 };
1597
1598 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
1599 namespace llvm {
1600 namespace yaml {
1601   template <>
1602   struct MappingTraits<OptionalTest> {
1603     static void mapping(IO& IO, OptionalTest &OT) {
1604       IO.mapOptional("Numbers", OT.Numbers);
1605     }
1606   };
1607
1608   template <>
1609   struct MappingTraits<OptionalTestSeq> {
1610     static void mapping(IO &IO, OptionalTestSeq &OTS) {
1611       IO.mapOptional("Tests", OTS.Tests);
1612     }
1613   };
1614 }
1615 }
1616
1617 TEST(YAMLIO, SequenceElideTest) {
1618   // Test that writing out a purely optional structure with its fields set to
1619   // default followed by other data is properly read back in.
1620   OptionalTestSeq Seq;
1621   OptionalTest One, Two, Three, Four;
1622   int N[] = {1, 2, 3};
1623   Three.Numbers.assign(N, N + 3);
1624   Seq.Tests.push_back(One);
1625   Seq.Tests.push_back(Two);
1626   Seq.Tests.push_back(Three);
1627   Seq.Tests.push_back(Four);
1628
1629   std::string intermediate;
1630   {
1631     llvm::raw_string_ostream ostr(intermediate);
1632     Output yout(ostr);
1633     yout << Seq;
1634   }
1635
1636   Input yin(intermediate);
1637   OptionalTestSeq Seq2;
1638   yin >> Seq2;
1639
1640   EXPECT_FALSE(yin.error());
1641
1642   EXPECT_EQ(4UL, Seq2.Tests.size());
1643
1644   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
1645   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
1646
1647   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
1648   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
1649   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
1650
1651   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
1652 }
1653
1654 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
1655   FooBar doc;
1656   Input yin("");
1657   yin >> doc;
1658   EXPECT_TRUE(yin.error());
1659 }
1660
1661 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
1662   OptionalTest doc;
1663   Input yin("");
1664   yin >> doc;
1665   EXPECT_FALSE(yin.error());
1666 }
1667
1668 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
1669   std::vector<uint8_t> seq;
1670   Input yin("", /*Ctxt=*/NULL, suppressErrorMessages);
1671   yin >> seq;
1672
1673   EXPECT_FALSE(yin.error());
1674   EXPECT_TRUE(seq.empty());
1675 }