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