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