Home | History | Annotate | Download | only in Support
      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 
     32 static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
     33 }
     34 
     35 
     36 
     37 //===----------------------------------------------------------------------===//
     38 //  Test MappingTraits
     39 //===----------------------------------------------------------------------===//
     40 
     41 struct FooBar {
     42   int foo;
     43   int bar;
     44 };
     45 typedef std::vector<FooBar> FooBarSequence;
     46 
     47 LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar)
     48 
     49 struct FooBarContainer {
     50   FooBarSequence fbs;
     51 };
     52 
     53 namespace llvm {
     54 namespace yaml {
     55   template <>
     56   struct MappingTraits<FooBar> {
     57     static void mapping(IO &io, FooBar& fb) {
     58       io.mapRequired("foo",    fb.foo);
     59       io.mapRequired("bar",    fb.bar);
     60     }
     61   };
     62 
     63   template <> struct MappingTraits<FooBarContainer> {
     64     static void mapping(IO &io, FooBarContainer &fb) {
     65       io.mapRequired("fbs", fb.fbs);
     66     }
     67   };
     68 }
     69 }
     70 
     71 
     72 //
     73 // Test the reading of a yaml mapping
     74 //
     75 TEST(YAMLIO, TestMapRead) {
     76   FooBar doc;
     77   {
     78     Input yin("---\nfoo:  3\nbar:  5\n...\n");
     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     Input yin("{foo: 3, bar: 5}");
     88     yin >> doc;
     89 
     90     EXPECT_FALSE(yin.error());
     91     EXPECT_EQ(doc.foo, 3);
     92     EXPECT_EQ(doc.bar, 5);
     93   }
     94 }
     95 
     96 TEST(YAMLIO, TestMalformedMapRead) {
     97   FooBar doc;
     98   Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages);
     99   yin >> doc;
    100   EXPECT_TRUE(!!yin.error());
    101 }
    102 
    103 //
    104 // Test the reading of a yaml sequence of mappings
    105 //
    106 TEST(YAMLIO, TestSequenceMapRead) {
    107   FooBarSequence seq;
    108   Input yin("---\n - foo:  3\n   bar:  5\n - foo:  7\n   bar:  9\n...\n");
    109   yin >> seq;
    110 
    111   EXPECT_FALSE(yin.error());
    112   EXPECT_EQ(seq.size(), 2UL);
    113   FooBar& map1 = seq[0];
    114   FooBar& map2 = seq[1];
    115   EXPECT_EQ(map1.foo, 3);
    116   EXPECT_EQ(map1.bar, 5);
    117   EXPECT_EQ(map2.foo, 7);
    118   EXPECT_EQ(map2.bar, 9);
    119 }
    120 
    121 //
    122 // Test the reading of a map containing a yaml sequence of mappings
    123 //
    124 TEST(YAMLIO, TestContainerSequenceMapRead) {
    125   {
    126     FooBarContainer cont;
    127     Input yin2("---\nfbs:\n - foo: 3\n   bar: 5\n - foo: 7\n   bar: 9\n...\n");
    128     yin2 >> cont;
    129 
    130     EXPECT_FALSE(yin2.error());
    131     EXPECT_EQ(cont.fbs.size(), 2UL);
    132     EXPECT_EQ(cont.fbs[0].foo, 3);
    133     EXPECT_EQ(cont.fbs[0].bar, 5);
    134     EXPECT_EQ(cont.fbs[1].foo, 7);
    135     EXPECT_EQ(cont.fbs[1].bar, 9);
    136   }
    137 
    138   {
    139     FooBarContainer cont;
    140     Input yin("---\nfbs:\n...\n");
    141     yin >> cont;
    142     // Okay: Empty node represents an empty array.
    143     EXPECT_FALSE(yin.error());
    144     EXPECT_EQ(cont.fbs.size(), 0UL);
    145   }
    146 
    147   {
    148     FooBarContainer cont;
    149     Input yin("---\nfbs: !!null null\n...\n");
    150     yin >> cont;
    151     // Okay: null represents an empty array.
    152     EXPECT_FALSE(yin.error());
    153     EXPECT_EQ(cont.fbs.size(), 0UL);
    154   }
    155 
    156   {
    157     FooBarContainer cont;
    158     Input yin("---\nfbs: ~\n...\n");
    159     yin >> cont;
    160     // Okay: null represents an empty array.
    161     EXPECT_FALSE(yin.error());
    162     EXPECT_EQ(cont.fbs.size(), 0UL);
    163   }
    164 
    165   {
    166     FooBarContainer cont;
    167     Input yin("---\nfbs: null\n...\n");
    168     yin >> cont;
    169     // Okay: null represents an empty array.
    170     EXPECT_FALSE(yin.error());
    171     EXPECT_EQ(cont.fbs.size(), 0UL);
    172   }
    173 }
    174 
    175 //
    176 // Test the reading of a map containing a malformed yaml sequence
    177 //
    178 TEST(YAMLIO, TestMalformedContainerSequenceMapRead) {
    179   {
    180     FooBarContainer cont;
    181     Input yin("---\nfbs:\n   foo: 3\n   bar: 5\n...\n", nullptr,
    182               suppressErrorMessages);
    183     yin >> cont;
    184     // Error: fbs is not a sequence.
    185     EXPECT_TRUE(!!yin.error());
    186     EXPECT_EQ(cont.fbs.size(), 0UL);
    187   }
    188 
    189   {
    190     FooBarContainer cont;
    191     Input yin("---\nfbs: 'scalar'\n...\n", nullptr, suppressErrorMessages);
    192     yin >> cont;
    193     // This should be an error.
    194     EXPECT_TRUE(!!yin.error());
    195     EXPECT_EQ(cont.fbs.size(), 0UL);
    196   }
    197 }
    198 
    199 //
    200 // Test writing then reading back a sequence of mappings
    201 //
    202 TEST(YAMLIO, TestSequenceMapWriteAndRead) {
    203   std::string intermediate;
    204   {
    205     FooBar entry1;
    206     entry1.foo = 10;
    207     entry1.bar = -3;
    208     FooBar entry2;
    209     entry2.foo = 257;
    210     entry2.bar = 0;
    211     FooBarSequence seq;
    212     seq.push_back(entry1);
    213     seq.push_back(entry2);
    214 
    215     llvm::raw_string_ostream ostr(intermediate);
    216     Output yout(ostr);
    217     yout << seq;
    218   }
    219 
    220   {
    221     Input yin(intermediate);
    222     FooBarSequence seq2;
    223     yin >> seq2;
    224 
    225     EXPECT_FALSE(yin.error());
    226     EXPECT_EQ(seq2.size(), 2UL);
    227     FooBar& map1 = seq2[0];
    228     FooBar& map2 = seq2[1];
    229     EXPECT_EQ(map1.foo, 10);
    230     EXPECT_EQ(map1.bar, -3);
    231     EXPECT_EQ(map2.foo, 257);
    232     EXPECT_EQ(map2.bar, 0);
    233   }
    234 }
    235 
    236 
    237 //===----------------------------------------------------------------------===//
    238 //  Test built-in types
    239 //===----------------------------------------------------------------------===//
    240 
    241 struct BuiltInTypes {
    242   llvm::StringRef str;
    243   std::string stdstr;
    244   uint64_t        u64;
    245   uint32_t        u32;
    246   uint16_t        u16;
    247   uint8_t         u8;
    248   bool            b;
    249   int64_t         s64;
    250   int32_t         s32;
    251   int16_t         s16;
    252   int8_t          s8;
    253   float           f;
    254   double          d;
    255   Hex8            h8;
    256   Hex16           h16;
    257   Hex32           h32;
    258   Hex64           h64;
    259 };
    260 
    261 namespace llvm {
    262 namespace yaml {
    263   template <>
    264   struct MappingTraits<BuiltInTypes> {
    265     static void mapping(IO &io, BuiltInTypes& bt) {
    266       io.mapRequired("str",      bt.str);
    267       io.mapRequired("stdstr",   bt.stdstr);
    268       io.mapRequired("u64",      bt.u64);
    269       io.mapRequired("u32",      bt.u32);
    270       io.mapRequired("u16",      bt.u16);
    271       io.mapRequired("u8",       bt.u8);
    272       io.mapRequired("b",        bt.b);
    273       io.mapRequired("s64",      bt.s64);
    274       io.mapRequired("s32",      bt.s32);
    275       io.mapRequired("s16",      bt.s16);
    276       io.mapRequired("s8",       bt.s8);
    277       io.mapRequired("f",        bt.f);
    278       io.mapRequired("d",        bt.d);
    279       io.mapRequired("h8",       bt.h8);
    280       io.mapRequired("h16",      bt.h16);
    281       io.mapRequired("h32",      bt.h32);
    282       io.mapRequired("h64",      bt.h64);
    283     }
    284   };
    285 }
    286 }
    287 
    288 
    289 //
    290 // Test the reading of all built-in scalar conversions
    291 //
    292 TEST(YAMLIO, TestReadBuiltInTypes) {
    293   BuiltInTypes map;
    294   Input yin("---\n"
    295             "str:      hello there\n"
    296             "stdstr:   hello where?\n"
    297             "u64:      5000000000\n"
    298             "u32:      4000000000\n"
    299             "u16:      65000\n"
    300             "u8:       255\n"
    301             "b:        false\n"
    302             "s64:      -5000000000\n"
    303             "s32:      -2000000000\n"
    304             "s16:      -32000\n"
    305             "s8:       -127\n"
    306             "f:        137.125\n"
    307             "d:        -2.8625\n"
    308             "h8:       0xFF\n"
    309             "h16:      0x8765\n"
    310             "h32:      0xFEDCBA98\n"
    311             "h64:      0xFEDCBA9876543210\n"
    312            "...\n");
    313   yin >> map;
    314 
    315   EXPECT_FALSE(yin.error());
    316   EXPECT_TRUE(map.str.equals("hello there"));
    317   EXPECT_TRUE(map.stdstr == "hello where?");
    318   EXPECT_EQ(map.u64, 5000000000ULL);
    319   EXPECT_EQ(map.u32, 4000000000U);
    320   EXPECT_EQ(map.u16, 65000);
    321   EXPECT_EQ(map.u8,  255);
    322   EXPECT_EQ(map.b,   false);
    323   EXPECT_EQ(map.s64, -5000000000LL);
    324   EXPECT_EQ(map.s32, -2000000000L);
    325   EXPECT_EQ(map.s16, -32000);
    326   EXPECT_EQ(map.s8,  -127);
    327   EXPECT_EQ(map.f,   137.125);
    328   EXPECT_EQ(map.d,   -2.8625);
    329   EXPECT_EQ(map.h8,  Hex8(255));
    330   EXPECT_EQ(map.h16, Hex16(0x8765));
    331   EXPECT_EQ(map.h32, Hex32(0xFEDCBA98));
    332   EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL));
    333 }
    334 
    335 
    336 //
    337 // Test writing then reading back all built-in scalar types
    338 //
    339 TEST(YAMLIO, TestReadWriteBuiltInTypes) {
    340   std::string intermediate;
    341   {
    342     BuiltInTypes map;
    343     map.str = "one two";
    344     map.stdstr = "three four";
    345     map.u64 = 6000000000ULL;
    346     map.u32 = 3000000000U;
    347     map.u16 = 50000;
    348     map.u8  = 254;
    349     map.b   = true;
    350     map.s64 = -6000000000LL;
    351     map.s32 = -2000000000;
    352     map.s16 = -32000;
    353     map.s8  = -128;
    354     map.f   = 3.25;
    355     map.d   = -2.8625;
    356     map.h8  = 254;
    357     map.h16 = 50000;
    358     map.h32 = 3000000000U;
    359     map.h64 = 6000000000LL;
    360 
    361     llvm::raw_string_ostream ostr(intermediate);
    362     Output yout(ostr);
    363     yout << map;
    364   }
    365 
    366   {
    367     Input yin(intermediate);
    368     BuiltInTypes map;
    369     yin >> map;
    370 
    371     EXPECT_FALSE(yin.error());
    372     EXPECT_TRUE(map.str.equals("one two"));
    373     EXPECT_TRUE(map.stdstr == "three four");
    374     EXPECT_EQ(map.u64,      6000000000ULL);
    375     EXPECT_EQ(map.u32,      3000000000U);
    376     EXPECT_EQ(map.u16,      50000);
    377     EXPECT_EQ(map.u8,       254);
    378     EXPECT_EQ(map.b,        true);
    379     EXPECT_EQ(map.s64,      -6000000000LL);
    380     EXPECT_EQ(map.s32,      -2000000000L);
    381     EXPECT_EQ(map.s16,      -32000);
    382     EXPECT_EQ(map.s8,       -128);
    383     EXPECT_EQ(map.f,        3.25);
    384     EXPECT_EQ(map.d,        -2.8625);
    385     EXPECT_EQ(map.h8,       Hex8(254));
    386     EXPECT_EQ(map.h16,      Hex16(50000));
    387     EXPECT_EQ(map.h32,      Hex32(3000000000U));
    388     EXPECT_EQ(map.h64,      Hex64(6000000000LL));
    389   }
    390 }
    391 
    392 struct StringTypes {
    393   llvm::StringRef str1;
    394   llvm::StringRef str2;
    395   llvm::StringRef str3;
    396   llvm::StringRef str4;
    397   llvm::StringRef str5;
    398   llvm::StringRef str6;
    399   llvm::StringRef str7;
    400   llvm::StringRef str8;
    401   llvm::StringRef str9;
    402   llvm::StringRef str10;
    403   llvm::StringRef str11;
    404   std::string stdstr1;
    405   std::string stdstr2;
    406   std::string stdstr3;
    407   std::string stdstr4;
    408   std::string stdstr5;
    409   std::string stdstr6;
    410   std::string stdstr7;
    411   std::string stdstr8;
    412   std::string stdstr9;
    413   std::string stdstr10;
    414   std::string stdstr11;
    415 };
    416 
    417 namespace llvm {
    418 namespace yaml {
    419   template <>
    420   struct MappingTraits<StringTypes> {
    421     static void mapping(IO &io, StringTypes& st) {
    422       io.mapRequired("str1",      st.str1);
    423       io.mapRequired("str2",      st.str2);
    424       io.mapRequired("str3",      st.str3);
    425       io.mapRequired("str4",      st.str4);
    426       io.mapRequired("str5",      st.str5);
    427       io.mapRequired("str6",      st.str6);
    428       io.mapRequired("str7",      st.str7);
    429       io.mapRequired("str8",      st.str8);
    430       io.mapRequired("str9",      st.str9);
    431       io.mapRequired("str10",     st.str10);
    432       io.mapRequired("str11",     st.str11);
    433       io.mapRequired("stdstr1",   st.stdstr1);
    434       io.mapRequired("stdstr2",   st.stdstr2);
    435       io.mapRequired("stdstr3",   st.stdstr3);
    436       io.mapRequired("stdstr4",   st.stdstr4);
    437       io.mapRequired("stdstr5",   st.stdstr5);
    438       io.mapRequired("stdstr6",   st.stdstr6);
    439       io.mapRequired("stdstr7",   st.stdstr7);
    440       io.mapRequired("stdstr8",   st.stdstr8);
    441       io.mapRequired("stdstr9",   st.stdstr9);
    442       io.mapRequired("stdstr10",  st.stdstr10);
    443       io.mapRequired("stdstr11",  st.stdstr11);
    444     }
    445   };
    446 }
    447 }
    448 
    449 TEST(YAMLIO, TestReadWriteStringTypes) {
    450   std::string intermediate;
    451   {
    452     StringTypes map;
    453     map.str1 = "'aaa";
    454     map.str2 = "\"bbb";
    455     map.str3 = "`ccc";
    456     map.str4 = "@ddd";
    457     map.str5 = "";
    458     map.str6 = "0000000004000000";
    459     map.str7 = "true";
    460     map.str8 = "FALSE";
    461     map.str9 = "~";
    462     map.str10 = "0.2e20";
    463     map.str11 = "0x30";
    464     map.stdstr1 = "'eee";
    465     map.stdstr2 = "\"fff";
    466     map.stdstr3 = "`ggg";
    467     map.stdstr4 = "@hhh";
    468     map.stdstr5 = "";
    469     map.stdstr6 = "0000000004000000";
    470     map.stdstr7 = "true";
    471     map.stdstr8 = "FALSE";
    472     map.stdstr9 = "~";
    473     map.stdstr10 = "0.2e20";
    474     map.stdstr11 = "0x30";
    475 
    476     llvm::raw_string_ostream ostr(intermediate);
    477     Output yout(ostr);
    478     yout << map;
    479   }
    480 
    481   llvm::StringRef flowOut(intermediate);
    482   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
    483   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
    484   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
    485   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
    486   EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
    487   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n"));
    488   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n"));
    489   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n"));
    490   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n"));
    491   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n"));
    492   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n"));
    493   EXPECT_NE(std::string::npos, flowOut.find("'''eee"));
    494   EXPECT_NE(std::string::npos, flowOut.find("'\"fff'"));
    495   EXPECT_NE(std::string::npos, flowOut.find("'`ggg'"));
    496   EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
    497   EXPECT_NE(std::string::npos, flowOut.find("''\n"));
    498   EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n"));
    499 
    500   {
    501     Input yin(intermediate);
    502     StringTypes map;
    503     yin >> map;
    504 
    505     EXPECT_FALSE(yin.error());
    506     EXPECT_TRUE(map.str1.equals("'aaa"));
    507     EXPECT_TRUE(map.str2.equals("\"bbb"));
    508     EXPECT_TRUE(map.str3.equals("`ccc"));
    509     EXPECT_TRUE(map.str4.equals("@ddd"));
    510     EXPECT_TRUE(map.str5.equals(""));
    511     EXPECT_TRUE(map.str6.equals("0000000004000000"));
    512     EXPECT_TRUE(map.stdstr1 == "'eee");
    513     EXPECT_TRUE(map.stdstr2 == "\"fff");
    514     EXPECT_TRUE(map.stdstr3 == "`ggg");
    515     EXPECT_TRUE(map.stdstr4 == "@hhh");
    516     EXPECT_TRUE(map.stdstr5 == "");
    517     EXPECT_TRUE(map.stdstr6 == "0000000004000000");
    518   }
    519 }
    520 
    521 //===----------------------------------------------------------------------===//
    522 //  Test ScalarEnumerationTraits
    523 //===----------------------------------------------------------------------===//
    524 
    525 enum Colors {
    526     cRed,
    527     cBlue,
    528     cGreen,
    529     cYellow
    530 };
    531 
    532 struct ColorMap {
    533   Colors      c1;
    534   Colors      c2;
    535   Colors      c3;
    536   Colors      c4;
    537   Colors      c5;
    538   Colors      c6;
    539 };
    540 
    541 namespace llvm {
    542 namespace yaml {
    543   template <>
    544   struct ScalarEnumerationTraits<Colors> {
    545     static void enumeration(IO &io, Colors &value) {
    546       io.enumCase(value, "red",   cRed);
    547       io.enumCase(value, "blue",  cBlue);
    548       io.enumCase(value, "green", cGreen);
    549       io.enumCase(value, "yellow",cYellow);
    550     }
    551   };
    552   template <>
    553   struct MappingTraits<ColorMap> {
    554     static void mapping(IO &io, ColorMap& c) {
    555       io.mapRequired("c1", c.c1);
    556       io.mapRequired("c2", c.c2);
    557       io.mapRequired("c3", c.c3);
    558       io.mapOptional("c4", c.c4, cBlue);   // supplies default
    559       io.mapOptional("c5", c.c5, cYellow); // supplies default
    560       io.mapOptional("c6", c.c6, cRed);    // supplies default
    561     }
    562   };
    563 }
    564 }
    565 
    566 
    567 //
    568 // Test reading enumerated scalars
    569 //
    570 TEST(YAMLIO, TestEnumRead) {
    571   ColorMap map;
    572   Input yin("---\n"
    573             "c1:  blue\n"
    574             "c2:  red\n"
    575             "c3:  green\n"
    576             "c5:  yellow\n"
    577             "...\n");
    578   yin >> map;
    579 
    580   EXPECT_FALSE(yin.error());
    581   EXPECT_EQ(cBlue,  map.c1);
    582   EXPECT_EQ(cRed,   map.c2);
    583   EXPECT_EQ(cGreen, map.c3);
    584   EXPECT_EQ(cBlue,  map.c4);  // tests default
    585   EXPECT_EQ(cYellow,map.c5);  // tests overridden
    586   EXPECT_EQ(cRed,   map.c6);  // tests default
    587 }
    588 
    589 
    590 
    591 //===----------------------------------------------------------------------===//
    592 //  Test ScalarBitSetTraits
    593 //===----------------------------------------------------------------------===//
    594 
    595 enum MyFlags {
    596   flagNone    = 0,
    597   flagBig     = 1 << 0,
    598   flagFlat    = 1 << 1,
    599   flagRound   = 1 << 2,
    600   flagPointy  = 1 << 3
    601 };
    602 inline MyFlags operator|(MyFlags a, MyFlags b) {
    603   return static_cast<MyFlags>(
    604                       static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
    605 }
    606 
    607 struct FlagsMap {
    608   MyFlags     f1;
    609   MyFlags     f2;
    610   MyFlags     f3;
    611   MyFlags     f4;
    612 };
    613 
    614 
    615 namespace llvm {
    616 namespace yaml {
    617   template <>
    618   struct ScalarBitSetTraits<MyFlags> {
    619     static void bitset(IO &io, MyFlags &value) {
    620       io.bitSetCase(value, "big",   flagBig);
    621       io.bitSetCase(value, "flat",  flagFlat);
    622       io.bitSetCase(value, "round", flagRound);
    623       io.bitSetCase(value, "pointy",flagPointy);
    624     }
    625   };
    626   template <>
    627   struct MappingTraits<FlagsMap> {
    628     static void mapping(IO &io, FlagsMap& c) {
    629       io.mapRequired("f1", c.f1);
    630       io.mapRequired("f2", c.f2);
    631       io.mapRequired("f3", c.f3);
    632       io.mapOptional("f4", c.f4, MyFlags(flagRound));
    633      }
    634   };
    635 }
    636 }
    637 
    638 
    639 //
    640 // Test reading flow sequence representing bit-mask values
    641 //
    642 TEST(YAMLIO, TestFlagsRead) {
    643   FlagsMap map;
    644   Input yin("---\n"
    645             "f1:  [ big ]\n"
    646             "f2:  [ round, flat ]\n"
    647             "f3:  []\n"
    648             "...\n");
    649   yin >> map;
    650 
    651   EXPECT_FALSE(yin.error());
    652   EXPECT_EQ(flagBig,              map.f1);
    653   EXPECT_EQ(flagRound|flagFlat,   map.f2);
    654   EXPECT_EQ(flagNone,             map.f3);  // check empty set
    655   EXPECT_EQ(flagRound,            map.f4);  // check optional key
    656 }
    657 
    658 
    659 //
    660 // Test writing then reading back bit-mask values
    661 //
    662 TEST(YAMLIO, TestReadWriteFlags) {
    663   std::string intermediate;
    664   {
    665     FlagsMap map;
    666     map.f1 = flagBig;
    667     map.f2 = flagRound | flagFlat;
    668     map.f3 = flagNone;
    669     map.f4 = flagNone;
    670 
    671     llvm::raw_string_ostream ostr(intermediate);
    672     Output yout(ostr);
    673     yout << map;
    674   }
    675 
    676   {
    677     Input yin(intermediate);
    678     FlagsMap map2;
    679     yin >> map2;
    680 
    681     EXPECT_FALSE(yin.error());
    682     EXPECT_EQ(flagBig,              map2.f1);
    683     EXPECT_EQ(flagRound|flagFlat,   map2.f2);
    684     EXPECT_EQ(flagNone,             map2.f3);
    685     //EXPECT_EQ(flagRound,            map2.f4);  // check optional key
    686   }
    687 }
    688 
    689 
    690 
    691 //===----------------------------------------------------------------------===//
    692 //  Test ScalarTraits
    693 //===----------------------------------------------------------------------===//
    694 
    695 struct MyCustomType {
    696   int length;
    697   int width;
    698 };
    699 
    700 struct MyCustomTypeMap {
    701   MyCustomType     f1;
    702   MyCustomType     f2;
    703   int              f3;
    704 };
    705 
    706 
    707 namespace llvm {
    708 namespace yaml {
    709   template <>
    710   struct MappingTraits<MyCustomTypeMap> {
    711     static void mapping(IO &io, MyCustomTypeMap& s) {
    712       io.mapRequired("f1", s.f1);
    713       io.mapRequired("f2", s.f2);
    714       io.mapRequired("f3", s.f3);
    715      }
    716   };
    717   // MyCustomType is formatted as a yaml scalar.  A value of
    718   // {length=3, width=4} would be represented in yaml as "3 by 4".
    719   template<>
    720   struct ScalarTraits<MyCustomType> {
    721     static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) {
    722       out << llvm::format("%d by %d", value.length, value.width);
    723     }
    724     static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) {
    725       size_t byStart = scalar.find("by");
    726       if ( byStart != StringRef::npos ) {
    727         StringRef lenStr = scalar.slice(0, byStart);
    728         lenStr = lenStr.rtrim();
    729         if ( lenStr.getAsInteger(0, value.length) ) {
    730           return "malformed length";
    731         }
    732         StringRef widthStr = scalar.drop_front(byStart+2);
    733         widthStr = widthStr.ltrim();
    734         if ( widthStr.getAsInteger(0, value.width) ) {
    735           return "malformed width";
    736         }
    737         return StringRef();
    738       }
    739       else {
    740           return "malformed by";
    741       }
    742     }
    743     static bool mustQuote(StringRef) { return true; }
    744   };
    745 }
    746 }
    747 
    748 
    749 //
    750 // Test writing then reading back custom values
    751 //
    752 TEST(YAMLIO, TestReadWriteMyCustomType) {
    753   std::string intermediate;
    754   {
    755     MyCustomTypeMap map;
    756     map.f1.length = 1;
    757     map.f1.width  = 4;
    758     map.f2.length = 100;
    759     map.f2.width  = 400;
    760     map.f3 = 10;
    761 
    762     llvm::raw_string_ostream ostr(intermediate);
    763     Output yout(ostr);
    764     yout << map;
    765   }
    766 
    767   {
    768     Input yin(intermediate);
    769     MyCustomTypeMap map2;
    770     yin >> map2;
    771 
    772     EXPECT_FALSE(yin.error());
    773     EXPECT_EQ(1,      map2.f1.length);
    774     EXPECT_EQ(4,      map2.f1.width);
    775     EXPECT_EQ(100,    map2.f2.length);
    776     EXPECT_EQ(400,    map2.f2.width);
    777     EXPECT_EQ(10,     map2.f3);
    778   }
    779 }
    780 
    781 
    782 //===----------------------------------------------------------------------===//
    783 //  Test BlockScalarTraits
    784 //===----------------------------------------------------------------------===//
    785 
    786 struct MultilineStringType {
    787   std::string str;
    788 };
    789 
    790 struct MultilineStringTypeMap {
    791   MultilineStringType name;
    792   MultilineStringType description;
    793   MultilineStringType ingredients;
    794   MultilineStringType recipes;
    795   MultilineStringType warningLabels;
    796   MultilineStringType documentation;
    797   int price;
    798 };
    799 
    800 namespace llvm {
    801 namespace yaml {
    802   template <>
    803   struct MappingTraits<MultilineStringTypeMap> {
    804     static void mapping(IO &io, MultilineStringTypeMap& s) {
    805       io.mapRequired("name", s.name);
    806       io.mapRequired("description", s.description);
    807       io.mapRequired("ingredients", s.ingredients);
    808       io.mapRequired("recipes", s.recipes);
    809       io.mapRequired("warningLabels", s.warningLabels);
    810       io.mapRequired("documentation", s.documentation);
    811       io.mapRequired("price", s.price);
    812      }
    813   };
    814 
    815   // MultilineStringType is formatted as a yaml block literal scalar. A value of
    816   // "Hello\nWorld" would be represented in yaml as
    817   //  |
    818   //    Hello
    819   //    World
    820   template <>
    821   struct BlockScalarTraits<MultilineStringType> {
    822     static void output(const MultilineStringType &value, void *ctxt,
    823                        llvm::raw_ostream &out) {
    824       out << value.str;
    825     }
    826     static StringRef input(StringRef scalar, void *ctxt,
    827                            MultilineStringType &value) {
    828       value.str = scalar.str();
    829       return StringRef();
    830     }
    831   };
    832 }
    833 }
    834 
    835 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType)
    836 
    837 //
    838 // Test writing then reading back custom values
    839 //
    840 TEST(YAMLIO, TestReadWriteMultilineStringType) {
    841   std::string intermediate;
    842   {
    843     MultilineStringTypeMap map;
    844     map.name.str = "An Item";
    845     map.description.str = "Hello\nWorld";
    846     map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n";
    847     map.recipes.str = "\n\nTest 1\n\n\n";
    848     map.warningLabels.str = "";
    849     map.documentation.str = "\n\n";
    850     map.price = 350;
    851 
    852     llvm::raw_string_ostream ostr(intermediate);
    853     Output yout(ostr);
    854     yout << map;
    855   }
    856   {
    857     Input yin(intermediate);
    858     MultilineStringTypeMap map2;
    859     yin >> map2;
    860 
    861     EXPECT_FALSE(yin.error());
    862     EXPECT_EQ(map2.name.str, "An Item\n");
    863     EXPECT_EQ(map2.description.str, "Hello\nWorld\n");
    864     EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n");
    865     EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n");
    866     EXPECT_TRUE(map2.warningLabels.str.empty());
    867     EXPECT_TRUE(map2.documentation.str.empty());
    868     EXPECT_EQ(map2.price, 350);
    869   }
    870 }
    871 
    872 //
    873 // Test writing then reading back custom values
    874 //
    875 TEST(YAMLIO, TestReadWriteBlockScalarDocuments) {
    876   std::string intermediate;
    877   {
    878     std::vector<MultilineStringType> documents;
    879     MultilineStringType doc;
    880     doc.str = "Hello\nWorld";
    881     documents.push_back(doc);
    882 
    883     llvm::raw_string_ostream ostr(intermediate);
    884     Output yout(ostr);
    885     yout << documents;
    886 
    887     // Verify that the block scalar header was written out on the same line
    888     // as the document marker.
    889     EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |"));
    890   }
    891   {
    892     Input yin(intermediate);
    893     std::vector<MultilineStringType> documents2;
    894     yin >> documents2;
    895 
    896     EXPECT_FALSE(yin.error());
    897     EXPECT_EQ(documents2.size(), size_t(1));
    898     EXPECT_EQ(documents2[0].str, "Hello\nWorld\n");
    899   }
    900 }
    901 
    902 TEST(YAMLIO, TestReadWriteBlockScalarValue) {
    903   std::string intermediate;
    904   {
    905     MultilineStringType doc;
    906     doc.str = "Just a block\nscalar doc";
    907 
    908     llvm::raw_string_ostream ostr(intermediate);
    909     Output yout(ostr);
    910     yout << doc;
    911   }
    912   {
    913     Input yin(intermediate);
    914     MultilineStringType doc;
    915     yin >> doc;
    916 
    917     EXPECT_FALSE(yin.error());
    918     EXPECT_EQ(doc.str, "Just a block\nscalar doc\n");
    919   }
    920 }
    921 
    922 //===----------------------------------------------------------------------===//
    923 //  Test flow sequences
    924 //===----------------------------------------------------------------------===//
    925 
    926 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
    927 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
    928 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef)
    929 
    930 namespace llvm {
    931 namespace yaml {
    932   template<>
    933   struct ScalarTraits<MyNumber> {
    934     static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
    935       out << value;
    936     }
    937 
    938     static StringRef input(StringRef scalar, void *, MyNumber &value) {
    939       long long n;
    940       if ( getAsSignedInteger(scalar, 0, n) )
    941         return "invalid number";
    942       value = n;
    943       return StringRef();
    944     }
    945 
    946     static bool mustQuote(StringRef) { return false; }
    947   };
    948 }
    949 }
    950 
    951 struct NameAndNumbers {
    952   llvm::StringRef               name;
    953   std::vector<llvm::StringRef>  strings;
    954   std::vector<MyNumber>         single;
    955   std::vector<MyNumber>         numbers;
    956 };
    957 
    958 namespace llvm {
    959 namespace yaml {
    960   template <>
    961   struct MappingTraits<NameAndNumbers> {
    962     static void mapping(IO &io, NameAndNumbers& nn) {
    963       io.mapRequired("name",     nn.name);
    964       io.mapRequired("strings",  nn.strings);
    965       io.mapRequired("single",   nn.single);
    966       io.mapRequired("numbers",  nn.numbers);
    967     }
    968   };
    969 }
    970 }
    971 
    972 typedef std::vector<MyNumber> MyNumberFlowSequence;
    973 
    974 LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence)
    975 
    976 struct NameAndNumbersFlow {
    977   llvm::StringRef                    name;
    978   std::vector<MyNumberFlowSequence>  sequenceOfNumbers;
    979 };
    980 
    981 namespace llvm {
    982 namespace yaml {
    983   template <>
    984   struct MappingTraits<NameAndNumbersFlow> {
    985     static void mapping(IO &io, NameAndNumbersFlow& nn) {
    986       io.mapRequired("name",     nn.name);
    987       io.mapRequired("sequenceOfNumbers",  nn.sequenceOfNumbers);
    988     }
    989   };
    990 }
    991 }
    992 
    993 //
    994 // Test writing then reading back custom values
    995 //
    996 TEST(YAMLIO, TestReadWriteMyFlowSequence) {
    997   std::string intermediate;
    998   {
    999     NameAndNumbers map;
   1000     map.name  = "hello";
   1001     map.strings.push_back(llvm::StringRef("one"));
   1002     map.strings.push_back(llvm::StringRef("two"));
   1003     map.single.push_back(1);
   1004     map.numbers.push_back(10);
   1005     map.numbers.push_back(-30);
   1006     map.numbers.push_back(1024);
   1007 
   1008     llvm::raw_string_ostream ostr(intermediate);
   1009     Output yout(ostr);
   1010     yout << map;
   1011 
   1012     // Verify sequences were written in flow style
   1013     ostr.flush();
   1014     llvm::StringRef flowOut(intermediate);
   1015     EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
   1016     EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
   1017   }
   1018 
   1019   {
   1020     Input yin(intermediate);
   1021     NameAndNumbers map2;
   1022     yin >> map2;
   1023 
   1024     EXPECT_FALSE(yin.error());
   1025     EXPECT_TRUE(map2.name.equals("hello"));
   1026     EXPECT_EQ(map2.strings.size(), 2UL);
   1027     EXPECT_TRUE(map2.strings[0].equals("one"));
   1028     EXPECT_TRUE(map2.strings[1].equals("two"));
   1029     EXPECT_EQ(map2.single.size(), 1UL);
   1030     EXPECT_EQ(1,       map2.single[0]);
   1031     EXPECT_EQ(map2.numbers.size(), 3UL);
   1032     EXPECT_EQ(10,      map2.numbers[0]);
   1033     EXPECT_EQ(-30,     map2.numbers[1]);
   1034     EXPECT_EQ(1024,    map2.numbers[2]);
   1035   }
   1036 }
   1037 
   1038 
   1039 //
   1040 // Test writing then reading back a sequence of flow sequences.
   1041 //
   1042 TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) {
   1043   std::string intermediate;
   1044   {
   1045     NameAndNumbersFlow map;
   1046     map.name  = "hello";
   1047     MyNumberFlowSequence single = { 0 };
   1048     MyNumberFlowSequence numbers = { 12, 1, -512 };
   1049     map.sequenceOfNumbers.push_back(single);
   1050     map.sequenceOfNumbers.push_back(numbers);
   1051     map.sequenceOfNumbers.push_back(MyNumberFlowSequence());
   1052 
   1053     llvm::raw_string_ostream ostr(intermediate);
   1054     Output yout(ostr);
   1055     yout << map;
   1056 
   1057     // Verify sequences were written in flow style
   1058     // and that the parent sequence used '-'.
   1059     ostr.flush();
   1060     llvm::StringRef flowOut(intermediate);
   1061     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]"));
   1062     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]"));
   1063     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [  ]"));
   1064   }
   1065 
   1066   {
   1067     Input yin(intermediate);
   1068     NameAndNumbersFlow map2;
   1069     yin >> map2;
   1070 
   1071     EXPECT_FALSE(yin.error());
   1072     EXPECT_TRUE(map2.name.equals("hello"));
   1073     EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL);
   1074     EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL);
   1075     EXPECT_EQ(0,    map2.sequenceOfNumbers[0][0]);
   1076     EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL);
   1077     EXPECT_EQ(12,   map2.sequenceOfNumbers[1][0]);
   1078     EXPECT_EQ(1,    map2.sequenceOfNumbers[1][1]);
   1079     EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]);
   1080     EXPECT_TRUE(map2.sequenceOfNumbers[2].empty());
   1081   }
   1082 }
   1083 
   1084 //===----------------------------------------------------------------------===//
   1085 //  Test normalizing/denormalizing
   1086 //===----------------------------------------------------------------------===//
   1087 
   1088 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
   1089 
   1090 typedef std::vector<TotalSeconds> SecondsSequence;
   1091 
   1092 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
   1093 
   1094 
   1095 namespace llvm {
   1096 namespace yaml {
   1097   template <>
   1098   struct MappingTraits<TotalSeconds> {
   1099 
   1100     class NormalizedSeconds {
   1101     public:
   1102       NormalizedSeconds(IO &io)
   1103         : hours(0), minutes(0), seconds(0) {
   1104       }
   1105       NormalizedSeconds(IO &, TotalSeconds &secs)
   1106         : hours(secs/3600),
   1107           minutes((secs - (hours*3600))/60),
   1108           seconds(secs % 60) {
   1109       }
   1110       TotalSeconds denormalize(IO &) {
   1111         return TotalSeconds(hours*3600 + minutes*60 + seconds);
   1112       }
   1113 
   1114       uint32_t     hours;
   1115       uint8_t      minutes;
   1116       uint8_t      seconds;
   1117     };
   1118 
   1119     static void mapping(IO &io, TotalSeconds &secs) {
   1120       MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
   1121 
   1122       io.mapOptional("hours",    keys->hours,    (uint32_t)0);
   1123       io.mapOptional("minutes",  keys->minutes,  (uint8_t)0);
   1124       io.mapRequired("seconds",  keys->seconds);
   1125     }
   1126   };
   1127 }
   1128 }
   1129 
   1130 
   1131 //
   1132 // Test the reading of a yaml sequence of mappings
   1133 //
   1134 TEST(YAMLIO, TestReadMySecondsSequence) {
   1135   SecondsSequence seq;
   1136   Input yin("---\n - hours:  1\n   seconds:  5\n - seconds:  59\n...\n");
   1137   yin >> seq;
   1138 
   1139   EXPECT_FALSE(yin.error());
   1140   EXPECT_EQ(seq.size(), 2UL);
   1141   EXPECT_EQ(seq[0], 3605U);
   1142   EXPECT_EQ(seq[1], 59U);
   1143 }
   1144 
   1145 
   1146 //
   1147 // Test writing then reading back custom values
   1148 //
   1149 TEST(YAMLIO, TestReadWriteMySecondsSequence) {
   1150   std::string intermediate;
   1151   {
   1152     SecondsSequence seq;
   1153     seq.push_back(4000);
   1154     seq.push_back(500);
   1155     seq.push_back(59);
   1156 
   1157     llvm::raw_string_ostream ostr(intermediate);
   1158     Output yout(ostr);
   1159     yout << seq;
   1160   }
   1161   {
   1162     Input yin(intermediate);
   1163     SecondsSequence seq2;
   1164     yin >> seq2;
   1165 
   1166     EXPECT_FALSE(yin.error());
   1167     EXPECT_EQ(seq2.size(), 3UL);
   1168     EXPECT_EQ(seq2[0], 4000U);
   1169     EXPECT_EQ(seq2[1], 500U);
   1170     EXPECT_EQ(seq2[2], 59U);
   1171   }
   1172 }
   1173 
   1174 
   1175 //===----------------------------------------------------------------------===//
   1176 //  Test dynamic typing
   1177 //===----------------------------------------------------------------------===//
   1178 
   1179 enum AFlags {
   1180     a1,
   1181     a2,
   1182     a3
   1183 };
   1184 
   1185 enum BFlags {
   1186     b1,
   1187     b2,
   1188     b3
   1189 };
   1190 
   1191 enum Kind {
   1192     kindA,
   1193     kindB
   1194 };
   1195 
   1196 struct KindAndFlags {
   1197   KindAndFlags() : kind(kindA), flags(0) { }
   1198   KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
   1199   Kind        kind;
   1200   uint32_t    flags;
   1201 };
   1202 
   1203 typedef std::vector<KindAndFlags> KindAndFlagsSequence;
   1204 
   1205 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
   1206 
   1207 namespace llvm {
   1208 namespace yaml {
   1209   template <>
   1210   struct ScalarEnumerationTraits<AFlags> {
   1211     static void enumeration(IO &io, AFlags &value) {
   1212       io.enumCase(value, "a1",  a1);
   1213       io.enumCase(value, "a2",  a2);
   1214       io.enumCase(value, "a3",  a3);
   1215     }
   1216   };
   1217   template <>
   1218   struct ScalarEnumerationTraits<BFlags> {
   1219     static void enumeration(IO &io, BFlags &value) {
   1220       io.enumCase(value, "b1",  b1);
   1221       io.enumCase(value, "b2",  b2);
   1222       io.enumCase(value, "b3",  b3);
   1223     }
   1224   };
   1225   template <>
   1226   struct ScalarEnumerationTraits<Kind> {
   1227     static void enumeration(IO &io, Kind &value) {
   1228       io.enumCase(value, "A",  kindA);
   1229       io.enumCase(value, "B",  kindB);
   1230     }
   1231   };
   1232   template <>
   1233   struct MappingTraits<KindAndFlags> {
   1234     static void mapping(IO &io, KindAndFlags& kf) {
   1235       io.mapRequired("kind",  kf.kind);
   1236       // Type of "flags" field varies depending on "kind" field.
   1237       // Use memcpy here to avoid breaking strict aliasing rules.
   1238       if (kf.kind == kindA) {
   1239         AFlags aflags = static_cast<AFlags>(kf.flags);
   1240         io.mapRequired("flags", aflags);
   1241         kf.flags = aflags;
   1242       } else {
   1243         BFlags bflags = static_cast<BFlags>(kf.flags);
   1244         io.mapRequired("flags", bflags);
   1245         kf.flags = bflags;
   1246       }
   1247     }
   1248   };
   1249 }
   1250 }
   1251 
   1252 
   1253 //
   1254 // Test the reading of a yaml sequence dynamic types
   1255 //
   1256 TEST(YAMLIO, TestReadKindAndFlagsSequence) {
   1257   KindAndFlagsSequence seq;
   1258   Input yin("---\n - kind:  A\n   flags:  a2\n - kind:  B\n   flags:  b1\n...\n");
   1259   yin >> seq;
   1260 
   1261   EXPECT_FALSE(yin.error());
   1262   EXPECT_EQ(seq.size(), 2UL);
   1263   EXPECT_EQ(seq[0].kind,  kindA);
   1264   EXPECT_EQ(seq[0].flags, (uint32_t)a2);
   1265   EXPECT_EQ(seq[1].kind,  kindB);
   1266   EXPECT_EQ(seq[1].flags, (uint32_t)b1);
   1267 }
   1268 
   1269 //
   1270 // Test writing then reading back dynamic types
   1271 //
   1272 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
   1273   std::string intermediate;
   1274   {
   1275     KindAndFlagsSequence seq;
   1276     seq.push_back(KindAndFlags(kindA,a1));
   1277     seq.push_back(KindAndFlags(kindB,b1));
   1278     seq.push_back(KindAndFlags(kindA,a2));
   1279     seq.push_back(KindAndFlags(kindB,b2));
   1280     seq.push_back(KindAndFlags(kindA,a3));
   1281 
   1282     llvm::raw_string_ostream ostr(intermediate);
   1283     Output yout(ostr);
   1284     yout << seq;
   1285   }
   1286   {
   1287     Input yin(intermediate);
   1288     KindAndFlagsSequence seq2;
   1289     yin >> seq2;
   1290 
   1291     EXPECT_FALSE(yin.error());
   1292     EXPECT_EQ(seq2.size(), 5UL);
   1293     EXPECT_EQ(seq2[0].kind,  kindA);
   1294     EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
   1295     EXPECT_EQ(seq2[1].kind,  kindB);
   1296     EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
   1297     EXPECT_EQ(seq2[2].kind,  kindA);
   1298     EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
   1299     EXPECT_EQ(seq2[3].kind,  kindB);
   1300     EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
   1301     EXPECT_EQ(seq2[4].kind,  kindA);
   1302     EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
   1303   }
   1304 }
   1305 
   1306 
   1307 //===----------------------------------------------------------------------===//
   1308 //  Test document list
   1309 //===----------------------------------------------------------------------===//
   1310 
   1311 struct FooBarMap {
   1312   int foo;
   1313   int bar;
   1314 };
   1315 typedef std::vector<FooBarMap> FooBarMapDocumentList;
   1316 
   1317 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
   1318 
   1319 
   1320 namespace llvm {
   1321 namespace yaml {
   1322   template <>
   1323   struct MappingTraits<FooBarMap> {
   1324     static void mapping(IO &io, FooBarMap& fb) {
   1325       io.mapRequired("foo",    fb.foo);
   1326       io.mapRequired("bar",    fb.bar);
   1327     }
   1328   };
   1329 }
   1330 }
   1331 
   1332 
   1333 //
   1334 // Test the reading of a yaml mapping
   1335 //
   1336 TEST(YAMLIO, TestDocRead) {
   1337   FooBarMap doc;
   1338   Input yin("---\nfoo:  3\nbar:  5\n...\n");
   1339   yin >> doc;
   1340 
   1341   EXPECT_FALSE(yin.error());
   1342   EXPECT_EQ(doc.foo, 3);
   1343   EXPECT_EQ(doc.bar,5);
   1344 }
   1345 
   1346 
   1347 
   1348 //
   1349 // Test writing then reading back a sequence of mappings
   1350 //
   1351 TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
   1352   std::string intermediate;
   1353   {
   1354     FooBarMap doc1;
   1355     doc1.foo = 10;
   1356     doc1.bar = -3;
   1357     FooBarMap doc2;
   1358     doc2.foo = 257;
   1359     doc2.bar = 0;
   1360     std::vector<FooBarMap> docList;
   1361     docList.push_back(doc1);
   1362     docList.push_back(doc2);
   1363 
   1364     llvm::raw_string_ostream ostr(intermediate);
   1365     Output yout(ostr);
   1366     yout << docList;
   1367   }
   1368 
   1369 
   1370   {
   1371     Input yin(intermediate);
   1372     std::vector<FooBarMap> docList2;
   1373     yin >> docList2;
   1374 
   1375     EXPECT_FALSE(yin.error());
   1376     EXPECT_EQ(docList2.size(), 2UL);
   1377     FooBarMap& map1 = docList2[0];
   1378     FooBarMap& map2 = docList2[1];
   1379     EXPECT_EQ(map1.foo, 10);
   1380     EXPECT_EQ(map1.bar, -3);
   1381     EXPECT_EQ(map2.foo, 257);
   1382     EXPECT_EQ(map2.bar, 0);
   1383   }
   1384 }
   1385 
   1386 //===----------------------------------------------------------------------===//
   1387 //  Test document tags
   1388 //===----------------------------------------------------------------------===//
   1389 
   1390 struct MyDouble {
   1391   MyDouble() : value(0.0) { }
   1392   MyDouble(double x) : value(x) { }
   1393   double value;
   1394 };
   1395 
   1396 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
   1397 
   1398 
   1399 namespace llvm {
   1400 namespace yaml {
   1401   template <>
   1402   struct MappingTraits<MyDouble> {
   1403     static void mapping(IO &io, MyDouble &d) {
   1404       if (io.mapTag("!decimal", true)) {
   1405         mappingDecimal(io, d);
   1406       } else if (io.mapTag("!fraction")) {
   1407         mappingFraction(io, d);
   1408       }
   1409     }
   1410     static void mappingDecimal(IO &io, MyDouble &d) {
   1411       io.mapRequired("value", d.value);
   1412     }
   1413     static void mappingFraction(IO &io, MyDouble &d) {
   1414         double num, denom;
   1415         io.mapRequired("numerator",      num);
   1416         io.mapRequired("denominator",    denom);
   1417         // convert fraction to double
   1418         d.value = num/denom;
   1419     }
   1420   };
   1421  }
   1422 }
   1423 
   1424 
   1425 //
   1426 // Test the reading of two different tagged yaml documents.
   1427 //
   1428 TEST(YAMLIO, TestTaggedDocuments) {
   1429   std::vector<MyDouble> docList;
   1430   Input yin("--- !decimal\nvalue:  3.0\n"
   1431             "--- !fraction\nnumerator:  9.0\ndenominator:  2\n...\n");
   1432   yin >> docList;
   1433   EXPECT_FALSE(yin.error());
   1434   EXPECT_EQ(docList.size(), 2UL);
   1435   EXPECT_EQ(docList[0].value, 3.0);
   1436   EXPECT_EQ(docList[1].value, 4.5);
   1437 }
   1438 
   1439 
   1440 
   1441 //
   1442 // Test writing then reading back tagged documents
   1443 //
   1444 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
   1445   std::string intermediate;
   1446   {
   1447     MyDouble a(10.25);
   1448     MyDouble b(-3.75);
   1449     std::vector<MyDouble> docList;
   1450     docList.push_back(a);
   1451     docList.push_back(b);
   1452 
   1453     llvm::raw_string_ostream ostr(intermediate);
   1454     Output yout(ostr);
   1455     yout << docList;
   1456   }
   1457 
   1458   {
   1459     Input yin(intermediate);
   1460     std::vector<MyDouble> docList2;
   1461     yin >> docList2;
   1462 
   1463     EXPECT_FALSE(yin.error());
   1464     EXPECT_EQ(docList2.size(), 2UL);
   1465     EXPECT_EQ(docList2[0].value, 10.25);
   1466     EXPECT_EQ(docList2[1].value, -3.75);
   1467   }
   1468 }
   1469 
   1470 
   1471 //===----------------------------------------------------------------------===//
   1472 //  Test mapping validation
   1473 //===----------------------------------------------------------------------===//
   1474 
   1475 struct MyValidation {
   1476   double value;
   1477 };
   1478 
   1479 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
   1480 
   1481 namespace llvm {
   1482 namespace yaml {
   1483   template <>
   1484   struct MappingTraits<MyValidation> {
   1485     static void mapping(IO &io, MyValidation &d) {
   1486         io.mapRequired("value", d.value);
   1487     }
   1488     static StringRef validate(IO &io, MyValidation &d) {
   1489         if (d.value < 0)
   1490           return "negative value";
   1491         return StringRef();
   1492     }
   1493   };
   1494  }
   1495 }
   1496 
   1497 
   1498 //
   1499 // Test that validate() is called and complains about the negative value.
   1500 //
   1501 TEST(YAMLIO, TestValidatingInput) {
   1502   std::vector<MyValidation> docList;
   1503   Input yin("--- \nvalue:  3.0\n"
   1504             "--- \nvalue:  -1.0\n...\n",
   1505             nullptr, suppressErrorMessages);
   1506   yin >> docList;
   1507   EXPECT_TRUE(!!yin.error());
   1508 }
   1509 
   1510 //===----------------------------------------------------------------------===//
   1511 //  Test flow mapping
   1512 //===----------------------------------------------------------------------===//
   1513 
   1514 struct FlowFooBar {
   1515   int foo;
   1516   int bar;
   1517 
   1518   FlowFooBar() : foo(0), bar(0) {}
   1519   FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {}
   1520 };
   1521 
   1522 typedef std::vector<FlowFooBar> FlowFooBarSequence;
   1523 
   1524 LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar)
   1525 
   1526 struct FlowFooBarDoc {
   1527   FlowFooBar attribute;
   1528   FlowFooBarSequence seq;
   1529 };
   1530 
   1531 namespace llvm {
   1532 namespace yaml {
   1533   template <>
   1534   struct MappingTraits<FlowFooBar> {
   1535     static void mapping(IO &io, FlowFooBar &fb) {
   1536       io.mapRequired("foo", fb.foo);
   1537       io.mapRequired("bar", fb.bar);
   1538     }
   1539 
   1540     static const bool flow = true;
   1541   };
   1542 
   1543   template <>
   1544   struct MappingTraits<FlowFooBarDoc> {
   1545     static void mapping(IO &io, FlowFooBarDoc &fb) {
   1546       io.mapRequired("attribute", fb.attribute);
   1547       io.mapRequired("seq", fb.seq);
   1548     }
   1549   };
   1550 }
   1551 }
   1552 
   1553 //
   1554 // Test writing then reading back custom mappings
   1555 //
   1556 TEST(YAMLIO, TestReadWriteMyFlowMapping) {
   1557   std::string intermediate;
   1558   {
   1559     FlowFooBarDoc doc;
   1560     doc.attribute = FlowFooBar(42, 907);
   1561     doc.seq.push_back(FlowFooBar(1, 2));
   1562     doc.seq.push_back(FlowFooBar(0, 0));
   1563     doc.seq.push_back(FlowFooBar(-1, 1024));
   1564 
   1565     llvm::raw_string_ostream ostr(intermediate);
   1566     Output yout(ostr);
   1567     yout << doc;
   1568 
   1569     // Verify that mappings were written in flow style
   1570     ostr.flush();
   1571     llvm::StringRef flowOut(intermediate);
   1572     EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }"));
   1573     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }"));
   1574     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }"));
   1575     EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }"));
   1576   }
   1577 
   1578   {
   1579     Input yin(intermediate);
   1580     FlowFooBarDoc doc2;
   1581     yin >> doc2;
   1582 
   1583     EXPECT_FALSE(yin.error());
   1584     EXPECT_EQ(doc2.attribute.foo, 42);
   1585     EXPECT_EQ(doc2.attribute.bar, 907);
   1586     EXPECT_EQ(doc2.seq.size(), 3UL);
   1587     EXPECT_EQ(doc2.seq[0].foo, 1);
   1588     EXPECT_EQ(doc2.seq[0].bar, 2);
   1589     EXPECT_EQ(doc2.seq[1].foo, 0);
   1590     EXPECT_EQ(doc2.seq[1].bar, 0);
   1591     EXPECT_EQ(doc2.seq[2].foo, -1);
   1592     EXPECT_EQ(doc2.seq[2].bar, 1024);
   1593   }
   1594 }
   1595 
   1596 //===----------------------------------------------------------------------===//
   1597 //  Test error handling
   1598 //===----------------------------------------------------------------------===//
   1599 
   1600 //
   1601 // Test error handling of unknown enumerated scalar
   1602 //
   1603 TEST(YAMLIO, TestColorsReadError) {
   1604   ColorMap map;
   1605   Input yin("---\n"
   1606             "c1:  blue\n"
   1607             "c2:  purple\n"
   1608             "c3:  green\n"
   1609             "...\n",
   1610             /*Ctxt=*/nullptr,
   1611             suppressErrorMessages);
   1612   yin >> map;
   1613   EXPECT_TRUE(!!yin.error());
   1614 }
   1615 
   1616 
   1617 //
   1618 // Test error handling of flow sequence with unknown value
   1619 //
   1620 TEST(YAMLIO, TestFlagsReadError) {
   1621   FlagsMap map;
   1622   Input yin("---\n"
   1623             "f1:  [ big ]\n"
   1624             "f2:  [ round, hollow ]\n"
   1625             "f3:  []\n"
   1626             "...\n",
   1627             /*Ctxt=*/nullptr,
   1628             suppressErrorMessages);
   1629   yin >> map;
   1630 
   1631   EXPECT_TRUE(!!yin.error());
   1632 }
   1633 
   1634 
   1635 //
   1636 // Test error handling reading built-in uint8_t type
   1637 //
   1638 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
   1639 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
   1640   std::vector<uint8_t> seq;
   1641   Input yin("---\n"
   1642             "- 255\n"
   1643             "- 0\n"
   1644             "- 257\n"
   1645             "...\n",
   1646             /*Ctxt=*/nullptr,
   1647             suppressErrorMessages);
   1648   yin >> seq;
   1649 
   1650   EXPECT_TRUE(!!yin.error());
   1651 }
   1652 
   1653 
   1654 //
   1655 // Test error handling reading built-in uint16_t type
   1656 //
   1657 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
   1658 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
   1659   std::vector<uint16_t> seq;
   1660   Input yin("---\n"
   1661             "- 65535\n"
   1662             "- 0\n"
   1663             "- 66000\n"
   1664             "...\n",
   1665             /*Ctxt=*/nullptr,
   1666             suppressErrorMessages);
   1667   yin >> seq;
   1668 
   1669   EXPECT_TRUE(!!yin.error());
   1670 }
   1671 
   1672 
   1673 //
   1674 // Test error handling reading built-in uint32_t type
   1675 //
   1676 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
   1677 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
   1678   std::vector<uint32_t> seq;
   1679   Input yin("---\n"
   1680             "- 4000000000\n"
   1681             "- 0\n"
   1682             "- 5000000000\n"
   1683             "...\n",
   1684             /*Ctxt=*/nullptr,
   1685             suppressErrorMessages);
   1686   yin >> seq;
   1687 
   1688   EXPECT_TRUE(!!yin.error());
   1689 }
   1690 
   1691 
   1692 //
   1693 // Test error handling reading built-in uint64_t type
   1694 //
   1695 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
   1696 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
   1697   std::vector<uint64_t> seq;
   1698   Input yin("---\n"
   1699             "- 18446744073709551615\n"
   1700             "- 0\n"
   1701             "- 19446744073709551615\n"
   1702             "...\n",
   1703             /*Ctxt=*/nullptr,
   1704             suppressErrorMessages);
   1705   yin >> seq;
   1706 
   1707   EXPECT_TRUE(!!yin.error());
   1708 }
   1709 
   1710 
   1711 //
   1712 // Test error handling reading built-in int8_t type
   1713 //
   1714 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
   1715 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
   1716   std::vector<int8_t> seq;
   1717   Input yin("---\n"
   1718             "- -128\n"
   1719             "- 0\n"
   1720             "- 127\n"
   1721             "- 128\n"
   1722            "...\n",
   1723             /*Ctxt=*/nullptr,
   1724             suppressErrorMessages);
   1725   yin >> seq;
   1726 
   1727   EXPECT_TRUE(!!yin.error());
   1728 }
   1729 
   1730 //
   1731 // Test error handling reading built-in int8_t type
   1732 //
   1733 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
   1734   std::vector<int8_t> seq;
   1735   Input yin("---\n"
   1736             "- -128\n"
   1737             "- 0\n"
   1738             "- 127\n"
   1739             "- -129\n"
   1740             "...\n",
   1741             /*Ctxt=*/nullptr,
   1742             suppressErrorMessages);
   1743   yin >> seq;
   1744 
   1745   EXPECT_TRUE(!!yin.error());
   1746 }
   1747 
   1748 
   1749 //
   1750 // Test error handling reading built-in int16_t type
   1751 //
   1752 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
   1753 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
   1754   std::vector<int16_t> seq;
   1755   Input yin("---\n"
   1756             "- 32767\n"
   1757             "- 0\n"
   1758             "- -32768\n"
   1759             "- -32769\n"
   1760             "...\n",
   1761             /*Ctxt=*/nullptr,
   1762             suppressErrorMessages);
   1763   yin >> seq;
   1764 
   1765   EXPECT_TRUE(!!yin.error());
   1766 }
   1767 
   1768 
   1769 //
   1770 // Test error handling reading built-in int16_t type
   1771 //
   1772 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
   1773   std::vector<int16_t> seq;
   1774   Input yin("---\n"
   1775             "- 32767\n"
   1776             "- 0\n"
   1777             "- -32768\n"
   1778             "- 32768\n"
   1779             "...\n",
   1780             /*Ctxt=*/nullptr,
   1781             suppressErrorMessages);
   1782   yin >> seq;
   1783 
   1784   EXPECT_TRUE(!!yin.error());
   1785 }
   1786 
   1787 
   1788 //
   1789 // Test error handling reading built-in int32_t type
   1790 //
   1791 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
   1792 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
   1793   std::vector<int32_t> seq;
   1794   Input yin("---\n"
   1795             "- 2147483647\n"
   1796             "- 0\n"
   1797             "- -2147483648\n"
   1798             "- -2147483649\n"
   1799             "...\n",
   1800             /*Ctxt=*/nullptr,
   1801             suppressErrorMessages);
   1802   yin >> seq;
   1803 
   1804   EXPECT_TRUE(!!yin.error());
   1805 }
   1806 
   1807 //
   1808 // Test error handling reading built-in int32_t type
   1809 //
   1810 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
   1811   std::vector<int32_t> seq;
   1812   Input yin("---\n"
   1813             "- 2147483647\n"
   1814             "- 0\n"
   1815             "- -2147483648\n"
   1816             "- 2147483649\n"
   1817             "...\n",
   1818             /*Ctxt=*/nullptr,
   1819             suppressErrorMessages);
   1820   yin >> seq;
   1821 
   1822   EXPECT_TRUE(!!yin.error());
   1823 }
   1824 
   1825 
   1826 //
   1827 // Test error handling reading built-in int64_t type
   1828 //
   1829 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
   1830 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
   1831   std::vector<int64_t> seq;
   1832   Input yin("---\n"
   1833             "- -9223372036854775808\n"
   1834             "- 0\n"
   1835             "- 9223372036854775807\n"
   1836             "- -9223372036854775809\n"
   1837             "...\n",
   1838             /*Ctxt=*/nullptr,
   1839             suppressErrorMessages);
   1840   yin >> seq;
   1841 
   1842   EXPECT_TRUE(!!yin.error());
   1843 }
   1844 
   1845 //
   1846 // Test error handling reading built-in int64_t type
   1847 //
   1848 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
   1849   std::vector<int64_t> seq;
   1850   Input yin("---\n"
   1851             "- -9223372036854775808\n"
   1852             "- 0\n"
   1853             "- 9223372036854775807\n"
   1854             "- 9223372036854775809\n"
   1855             "...\n",
   1856             /*Ctxt=*/nullptr,
   1857             suppressErrorMessages);
   1858   yin >> seq;
   1859 
   1860   EXPECT_TRUE(!!yin.error());
   1861 }
   1862 
   1863 //
   1864 // Test error handling reading built-in float type
   1865 //
   1866 LLVM_YAML_IS_SEQUENCE_VECTOR(float)
   1867 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
   1868   std::vector<float> seq;
   1869   Input yin("---\n"
   1870             "- 0.0\n"
   1871             "- 1000.1\n"
   1872             "- -123.456\n"
   1873             "- 1.2.3\n"
   1874             "...\n",
   1875             /*Ctxt=*/nullptr,
   1876             suppressErrorMessages);
   1877   yin >> seq;
   1878 
   1879   EXPECT_TRUE(!!yin.error());
   1880 }
   1881 
   1882 //
   1883 // Test error handling reading built-in float type
   1884 //
   1885 LLVM_YAML_IS_SEQUENCE_VECTOR(double)
   1886 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
   1887   std::vector<double> seq;
   1888   Input yin("---\n"
   1889             "- 0.0\n"
   1890             "- 1000.1\n"
   1891             "- -123.456\n"
   1892             "- 1.2.3\n"
   1893             "...\n",
   1894             /*Ctxt=*/nullptr,
   1895             suppressErrorMessages);
   1896   yin >> seq;
   1897 
   1898   EXPECT_TRUE(!!yin.error());
   1899 }
   1900 
   1901 //
   1902 // Test error handling reading built-in Hex8 type
   1903 //
   1904 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
   1905 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
   1906   std::vector<Hex8> seq;
   1907   Input yin("---\n"
   1908             "- 0x12\n"
   1909             "- 0xFE\n"
   1910             "- 0x123\n"
   1911             "...\n",
   1912             /*Ctxt=*/nullptr,
   1913             suppressErrorMessages);
   1914   yin >> seq;
   1915 
   1916   EXPECT_TRUE(!!yin.error());
   1917 }
   1918 
   1919 
   1920 //
   1921 // Test error handling reading built-in Hex16 type
   1922 //
   1923 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
   1924 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
   1925   std::vector<Hex16> seq;
   1926   Input yin("---\n"
   1927             "- 0x0012\n"
   1928             "- 0xFEFF\n"
   1929             "- 0x12345\n"
   1930             "...\n",
   1931             /*Ctxt=*/nullptr,
   1932             suppressErrorMessages);
   1933   yin >> seq;
   1934 
   1935   EXPECT_TRUE(!!yin.error());
   1936 }
   1937 
   1938 //
   1939 // Test error handling reading built-in Hex32 type
   1940 //
   1941 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
   1942 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
   1943   std::vector<Hex32> seq;
   1944   Input yin("---\n"
   1945             "- 0x0012\n"
   1946             "- 0xFEFF0000\n"
   1947             "- 0x1234556789\n"
   1948             "...\n",
   1949             /*Ctxt=*/nullptr,
   1950             suppressErrorMessages);
   1951   yin >> seq;
   1952 
   1953   EXPECT_TRUE(!!yin.error());
   1954 }
   1955 
   1956 //
   1957 // Test error handling reading built-in Hex64 type
   1958 //
   1959 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
   1960 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
   1961   std::vector<Hex64> seq;
   1962   Input yin("---\n"
   1963             "- 0x0012\n"
   1964             "- 0xFFEEDDCCBBAA9988\n"
   1965             "- 0x12345567890ABCDEF0\n"
   1966             "...\n",
   1967             /*Ctxt=*/nullptr,
   1968             suppressErrorMessages);
   1969   yin >> seq;
   1970 
   1971   EXPECT_TRUE(!!yin.error());
   1972 }
   1973 
   1974 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
   1975   FooBar doc;
   1976   {
   1977     // We pass the suppressErrorMessages handler to handle the error
   1978     // message generated in the constructor of Input.
   1979     Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages);
   1980     yin >> doc;
   1981     EXPECT_TRUE(!!yin.error());
   1982   }
   1983 
   1984   {
   1985     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
   1986     yin >> doc;
   1987     EXPECT_TRUE(!!yin.error());
   1988   }
   1989 }
   1990 
   1991 struct OptionalTest {
   1992   std::vector<int> Numbers;
   1993 };
   1994 
   1995 struct OptionalTestSeq {
   1996   std::vector<OptionalTest> Tests;
   1997 };
   1998 
   1999 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
   2000 namespace llvm {
   2001 namespace yaml {
   2002   template <>
   2003   struct MappingTraits<OptionalTest> {
   2004     static void mapping(IO& IO, OptionalTest &OT) {
   2005       IO.mapOptional("Numbers", OT.Numbers);
   2006     }
   2007   };
   2008 
   2009   template <>
   2010   struct MappingTraits<OptionalTestSeq> {
   2011     static void mapping(IO &IO, OptionalTestSeq &OTS) {
   2012       IO.mapOptional("Tests", OTS.Tests);
   2013     }
   2014   };
   2015 }
   2016 }
   2017 
   2018 TEST(YAMLIO, SequenceElideTest) {
   2019   // Test that writing out a purely optional structure with its fields set to
   2020   // default followed by other data is properly read back in.
   2021   OptionalTestSeq Seq;
   2022   OptionalTest One, Two, Three, Four;
   2023   int N[] = {1, 2, 3};
   2024   Three.Numbers.assign(N, N + 3);
   2025   Seq.Tests.push_back(One);
   2026   Seq.Tests.push_back(Two);
   2027   Seq.Tests.push_back(Three);
   2028   Seq.Tests.push_back(Four);
   2029 
   2030   std::string intermediate;
   2031   {
   2032     llvm::raw_string_ostream ostr(intermediate);
   2033     Output yout(ostr);
   2034     yout << Seq;
   2035   }
   2036 
   2037   Input yin(intermediate);
   2038   OptionalTestSeq Seq2;
   2039   yin >> Seq2;
   2040 
   2041   EXPECT_FALSE(yin.error());
   2042 
   2043   EXPECT_EQ(4UL, Seq2.Tests.size());
   2044 
   2045   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
   2046   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
   2047 
   2048   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
   2049   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
   2050   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
   2051 
   2052   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
   2053 }
   2054 
   2055 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
   2056   FooBar doc;
   2057   Input yin("");
   2058   yin >> doc;
   2059   EXPECT_TRUE(!!yin.error());
   2060 }
   2061 
   2062 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
   2063   OptionalTest doc;
   2064   Input yin("");
   2065   yin >> doc;
   2066   EXPECT_FALSE(yin.error());
   2067 }
   2068 
   2069 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
   2070   std::vector<uint8_t> seq;
   2071   Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
   2072   yin >> seq;
   2073 
   2074   EXPECT_FALSE(yin.error());
   2075   EXPECT_TRUE(seq.empty());
   2076 }
   2077 
   2078 struct FlowMap {
   2079   llvm::StringRef str1, str2, str3;
   2080   FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3)
   2081     : str1(str1), str2(str2), str3(str3) {}
   2082 };
   2083 
   2084 struct FlowSeq {
   2085   llvm::StringRef str;
   2086   FlowSeq(llvm::StringRef S) : str(S) {}
   2087   FlowSeq() = default;
   2088 };
   2089 
   2090 namespace llvm {
   2091 namespace yaml {
   2092   template <>
   2093   struct MappingTraits<FlowMap> {
   2094     static void mapping(IO &io, FlowMap &fm) {
   2095       io.mapRequired("str1", fm.str1);
   2096       io.mapRequired("str2", fm.str2);
   2097       io.mapRequired("str3", fm.str3);
   2098     }
   2099 
   2100     static const bool flow = true;
   2101   };
   2102 
   2103 template <>
   2104 struct ScalarTraits<FlowSeq> {
   2105   static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) {
   2106     out << value.str;
   2107   }
   2108   static StringRef input(StringRef scalar, void*, FlowSeq &value) {
   2109     value.str = scalar;
   2110     return "";
   2111   }
   2112 
   2113   static bool mustQuote(StringRef S) { return false; }
   2114 };
   2115 }
   2116 }
   2117 
   2118 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq)
   2119 
   2120 TEST(YAMLIO, TestWrapFlow) {
   2121   std::string out;
   2122   llvm::raw_string_ostream ostr(out);
   2123   FlowMap Map("This is str1", "This is str2", "This is str3");
   2124   std::vector<FlowSeq> Seq;
   2125   Seq.emplace_back("This is str1");
   2126   Seq.emplace_back("This is str2");
   2127   Seq.emplace_back("This is str3");
   2128 
   2129   {
   2130     // 20 is just bellow the total length of the first mapping field.
   2131     // We should wreap at every element.
   2132     Output yout(ostr, nullptr, 15);
   2133 
   2134     yout << Map;
   2135     ostr.flush();
   2136     EXPECT_EQ(out,
   2137               "---\n"
   2138               "{ str1: This is str1, \n"
   2139               "  str2: This is str2, \n"
   2140               "  str3: This is str3 }\n"
   2141               "...\n");
   2142     out.clear();
   2143 
   2144     yout << Seq;
   2145     ostr.flush();
   2146     EXPECT_EQ(out,
   2147               "---\n"
   2148               "[ This is str1, \n"
   2149               "  This is str2, \n"
   2150               "  This is str3 ]\n"
   2151               "...\n");
   2152     out.clear();
   2153   }
   2154   {
   2155     // 25 will allow the second field to be output on the first line.
   2156     Output yout(ostr, nullptr, 25);
   2157 
   2158     yout << Map;
   2159     ostr.flush();
   2160     EXPECT_EQ(out,
   2161               "---\n"
   2162               "{ str1: This is str1, str2: This is str2, \n"
   2163               "  str3: This is str3 }\n"
   2164               "...\n");
   2165     out.clear();
   2166 
   2167     yout << Seq;
   2168     ostr.flush();
   2169     EXPECT_EQ(out,
   2170               "---\n"
   2171               "[ This is str1, This is str2, \n"
   2172               "  This is str3 ]\n"
   2173               "...\n");
   2174     out.clear();
   2175   }
   2176   {
   2177     // 0 means no wrapping.
   2178     Output yout(ostr, nullptr, 0);
   2179 
   2180     yout << Map;
   2181     ostr.flush();
   2182     EXPECT_EQ(out,
   2183               "---\n"
   2184               "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n"
   2185               "...\n");
   2186     out.clear();
   2187 
   2188     yout << Seq;
   2189     ostr.flush();
   2190     EXPECT_EQ(out,
   2191               "---\n"
   2192               "[ This is str1, This is str2, This is str3 ]\n"
   2193               "...\n");
   2194     out.clear();
   2195   }
   2196 }
   2197