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