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