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 
suppressErrorMessages(const llvm::SMDiagnostic &,void *)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> {
mappingllvm::yaml::MappingTraits57     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> {
mappingllvm::yaml::MappingTraits64     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 //
TEST(YAMLIO,TestMapRead)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 
TEST(YAMLIO,TestMalformedMapRead)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 //
TEST(YAMLIO,TestSequenceMapRead)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 //
TEST(YAMLIO,TestContainerSequenceMapRead)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 //
TEST(YAMLIO,TestMalformedContainerSequenceMapRead)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 //
TEST(YAMLIO,TestSequenceMapWriteAndRead)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> {
mappingllvm::yaml::MappingTraits265     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 //
TEST(YAMLIO,TestReadBuiltInTypes)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 //
TEST(YAMLIO,TestReadWriteBuiltInTypes)339 TEST(YAMLIO, TestReadWriteBuiltInTypes) {
340   std::string intermediate;
341   {
342     BuiltInTypes map;
343     map.str = "one two";
344     map.stdstr = "three four";
345     map.u64 = 6000000000ULL;
346     map.u32 = 3000000000U;
347     map.u16 = 50000;
348     map.u8  = 254;
349     map.b   = true;
350     map.s64 = -6000000000LL;
351     map.s32 = -2000000000;
352     map.s16 = -32000;
353     map.s8  = -128;
354     map.f   = 3.25;
355     map.d   = -2.8625;
356     map.h8  = 254;
357     map.h16 = 50000;
358     map.h32 = 3000000000U;
359     map.h64 = 6000000000LL;
360 
361     llvm::raw_string_ostream ostr(intermediate);
362     Output yout(ostr);
363     yout << map;
364   }
365 
366   {
367     Input yin(intermediate);
368     BuiltInTypes map;
369     yin >> map;
370 
371     EXPECT_FALSE(yin.error());
372     EXPECT_TRUE(map.str.equals("one two"));
373     EXPECT_TRUE(map.stdstr == "three four");
374     EXPECT_EQ(map.u64,      6000000000ULL);
375     EXPECT_EQ(map.u32,      3000000000U);
376     EXPECT_EQ(map.u16,      50000);
377     EXPECT_EQ(map.u8,       254);
378     EXPECT_EQ(map.b,        true);
379     EXPECT_EQ(map.s64,      -6000000000LL);
380     EXPECT_EQ(map.s32,      -2000000000L);
381     EXPECT_EQ(map.s16,      -32000);
382     EXPECT_EQ(map.s8,       -128);
383     EXPECT_EQ(map.f,        3.25);
384     EXPECT_EQ(map.d,        -2.8625);
385     EXPECT_EQ(map.h8,       Hex8(254));
386     EXPECT_EQ(map.h16,      Hex16(50000));
387     EXPECT_EQ(map.h32,      Hex32(3000000000U));
388     EXPECT_EQ(map.h64,      Hex64(6000000000LL));
389   }
390 }
391 
392 struct StringTypes {
393   llvm::StringRef str1;
394   llvm::StringRef str2;
395   llvm::StringRef str3;
396   llvm::StringRef str4;
397   llvm::StringRef str5;
398   llvm::StringRef str6;
399   llvm::StringRef str7;
400   llvm::StringRef str8;
401   llvm::StringRef str9;
402   llvm::StringRef str10;
403   llvm::StringRef str11;
404   std::string stdstr1;
405   std::string stdstr2;
406   std::string stdstr3;
407   std::string stdstr4;
408   std::string stdstr5;
409   std::string stdstr6;
410   std::string stdstr7;
411   std::string stdstr8;
412   std::string stdstr9;
413   std::string stdstr10;
414   std::string stdstr11;
415 };
416 
417 namespace llvm {
418 namespace yaml {
419   template <>
420   struct MappingTraits<StringTypes> {
mappingllvm::yaml::MappingTraits421     static void mapping(IO &io, StringTypes& st) {
422       io.mapRequired("str1",      st.str1);
423       io.mapRequired("str2",      st.str2);
424       io.mapRequired("str3",      st.str3);
425       io.mapRequired("str4",      st.str4);
426       io.mapRequired("str5",      st.str5);
427       io.mapRequired("str6",      st.str6);
428       io.mapRequired("str7",      st.str7);
429       io.mapRequired("str8",      st.str8);
430       io.mapRequired("str9",      st.str9);
431       io.mapRequired("str10",     st.str10);
432       io.mapRequired("str11",     st.str11);
433       io.mapRequired("stdstr1",   st.stdstr1);
434       io.mapRequired("stdstr2",   st.stdstr2);
435       io.mapRequired("stdstr3",   st.stdstr3);
436       io.mapRequired("stdstr4",   st.stdstr4);
437       io.mapRequired("stdstr5",   st.stdstr5);
438       io.mapRequired("stdstr6",   st.stdstr6);
439       io.mapRequired("stdstr7",   st.stdstr7);
440       io.mapRequired("stdstr8",   st.stdstr8);
441       io.mapRequired("stdstr9",   st.stdstr9);
442       io.mapRequired("stdstr10",  st.stdstr10);
443       io.mapRequired("stdstr11",  st.stdstr11);
444     }
445   };
446 }
447 }
448 
TEST(YAMLIO,TestReadWriteStringTypes)449 TEST(YAMLIO, TestReadWriteStringTypes) {
450   std::string intermediate;
451   {
452     StringTypes map;
453     map.str1 = "'aaa";
454     map.str2 = "\"bbb";
455     map.str3 = "`ccc";
456     map.str4 = "@ddd";
457     map.str5 = "";
458     map.str6 = "0000000004000000";
459     map.str7 = "true";
460     map.str8 = "FALSE";
461     map.str9 = "~";
462     map.str10 = "0.2e20";
463     map.str11 = "0x30";
464     map.stdstr1 = "'eee";
465     map.stdstr2 = "\"fff";
466     map.stdstr3 = "`ggg";
467     map.stdstr4 = "@hhh";
468     map.stdstr5 = "";
469     map.stdstr6 = "0000000004000000";
470     map.stdstr7 = "true";
471     map.stdstr8 = "FALSE";
472     map.stdstr9 = "~";
473     map.stdstr10 = "0.2e20";
474     map.stdstr11 = "0x30";
475 
476     llvm::raw_string_ostream ostr(intermediate);
477     Output yout(ostr);
478     yout << map;
479   }
480 
481   llvm::StringRef flowOut(intermediate);
482   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
483   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
484   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
485   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
486   EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
487   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n"));
488   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n"));
489   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n"));
490   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n"));
491   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n"));
492   EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n"));
493   EXPECT_NE(std::string::npos, flowOut.find("'''eee"));
494   EXPECT_NE(std::string::npos, flowOut.find("'\"fff'"));
495   EXPECT_NE(std::string::npos, flowOut.find("'`ggg'"));
496   EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
497   EXPECT_NE(std::string::npos, flowOut.find("''\n"));
498   EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n"));
499 
500   {
501     Input yin(intermediate);
502     StringTypes map;
503     yin >> map;
504 
505     EXPECT_FALSE(yin.error());
506     EXPECT_TRUE(map.str1.equals("'aaa"));
507     EXPECT_TRUE(map.str2.equals("\"bbb"));
508     EXPECT_TRUE(map.str3.equals("`ccc"));
509     EXPECT_TRUE(map.str4.equals("@ddd"));
510     EXPECT_TRUE(map.str5.equals(""));
511     EXPECT_TRUE(map.str6.equals("0000000004000000"));
512     EXPECT_TRUE(map.stdstr1 == "'eee");
513     EXPECT_TRUE(map.stdstr2 == "\"fff");
514     EXPECT_TRUE(map.stdstr3 == "`ggg");
515     EXPECT_TRUE(map.stdstr4 == "@hhh");
516     EXPECT_TRUE(map.stdstr5 == "");
517     EXPECT_TRUE(map.stdstr6 == "0000000004000000");
518   }
519 }
520 
521 //===----------------------------------------------------------------------===//
522 //  Test ScalarEnumerationTraits
523 //===----------------------------------------------------------------------===//
524 
525 enum Colors {
526     cRed,
527     cBlue,
528     cGreen,
529     cYellow
530 };
531 
532 struct ColorMap {
533   Colors      c1;
534   Colors      c2;
535   Colors      c3;
536   Colors      c4;
537   Colors      c5;
538   Colors      c6;
539 };
540 
541 namespace llvm {
542 namespace yaml {
543   template <>
544   struct ScalarEnumerationTraits<Colors> {
enumerationllvm::yaml::ScalarEnumerationTraits545     static void enumeration(IO &io, Colors &value) {
546       io.enumCase(value, "red",   cRed);
547       io.enumCase(value, "blue",  cBlue);
548       io.enumCase(value, "green", cGreen);
549       io.enumCase(value, "yellow",cYellow);
550     }
551   };
552   template <>
553   struct MappingTraits<ColorMap> {
mappingllvm::yaml::MappingTraits554     static void mapping(IO &io, ColorMap& c) {
555       io.mapRequired("c1", c.c1);
556       io.mapRequired("c2", c.c2);
557       io.mapRequired("c3", c.c3);
558       io.mapOptional("c4", c.c4, cBlue);   // supplies default
559       io.mapOptional("c5", c.c5, cYellow); // supplies default
560       io.mapOptional("c6", c.c6, cRed);    // supplies default
561     }
562   };
563 }
564 }
565 
566 
567 //
568 // Test reading enumerated scalars
569 //
TEST(YAMLIO,TestEnumRead)570 TEST(YAMLIO, TestEnumRead) {
571   ColorMap map;
572   Input yin("---\n"
573             "c1:  blue\n"
574             "c2:  red\n"
575             "c3:  green\n"
576             "c5:  yellow\n"
577             "...\n");
578   yin >> map;
579 
580   EXPECT_FALSE(yin.error());
581   EXPECT_EQ(cBlue,  map.c1);
582   EXPECT_EQ(cRed,   map.c2);
583   EXPECT_EQ(cGreen, map.c3);
584   EXPECT_EQ(cBlue,  map.c4);  // tests default
585   EXPECT_EQ(cYellow,map.c5);  // tests overridden
586   EXPECT_EQ(cRed,   map.c6);  // tests default
587 }
588 
589 
590 
591 //===----------------------------------------------------------------------===//
592 //  Test ScalarBitSetTraits
593 //===----------------------------------------------------------------------===//
594 
595 enum MyFlags {
596   flagNone    = 0,
597   flagBig     = 1 << 0,
598   flagFlat    = 1 << 1,
599   flagRound   = 1 << 2,
600   flagPointy  = 1 << 3
601 };
operator |(MyFlags a,MyFlags b)602 inline MyFlags operator|(MyFlags a, MyFlags b) {
603   return static_cast<MyFlags>(
604                       static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
605 }
606 
607 struct FlagsMap {
608   MyFlags     f1;
609   MyFlags     f2;
610   MyFlags     f3;
611   MyFlags     f4;
612 };
613 
614 
615 namespace llvm {
616 namespace yaml {
617   template <>
618   struct ScalarBitSetTraits<MyFlags> {
bitsetllvm::yaml::ScalarBitSetTraits619     static void bitset(IO &io, MyFlags &value) {
620       io.bitSetCase(value, "big",   flagBig);
621       io.bitSetCase(value, "flat",  flagFlat);
622       io.bitSetCase(value, "round", flagRound);
623       io.bitSetCase(value, "pointy",flagPointy);
624     }
625   };
626   template <>
627   struct MappingTraits<FlagsMap> {
mappingllvm::yaml::MappingTraits628     static void mapping(IO &io, FlagsMap& c) {
629       io.mapRequired("f1", c.f1);
630       io.mapRequired("f2", c.f2);
631       io.mapRequired("f3", c.f3);
632       io.mapOptional("f4", c.f4, MyFlags(flagRound));
633      }
634   };
635 }
636 }
637 
638 
639 //
640 // Test reading flow sequence representing bit-mask values
641 //
TEST(YAMLIO,TestFlagsRead)642 TEST(YAMLIO, TestFlagsRead) {
643   FlagsMap map;
644   Input yin("---\n"
645             "f1:  [ big ]\n"
646             "f2:  [ round, flat ]\n"
647             "f3:  []\n"
648             "...\n");
649   yin >> map;
650 
651   EXPECT_FALSE(yin.error());
652   EXPECT_EQ(flagBig,              map.f1);
653   EXPECT_EQ(flagRound|flagFlat,   map.f2);
654   EXPECT_EQ(flagNone,             map.f3);  // check empty set
655   EXPECT_EQ(flagRound,            map.f4);  // check optional key
656 }
657 
658 
659 //
660 // Test writing then reading back bit-mask values
661 //
TEST(YAMLIO,TestReadWriteFlags)662 TEST(YAMLIO, TestReadWriteFlags) {
663   std::string intermediate;
664   {
665     FlagsMap map;
666     map.f1 = flagBig;
667     map.f2 = flagRound | flagFlat;
668     map.f3 = flagNone;
669     map.f4 = flagNone;
670 
671     llvm::raw_string_ostream ostr(intermediate);
672     Output yout(ostr);
673     yout << map;
674   }
675 
676   {
677     Input yin(intermediate);
678     FlagsMap map2;
679     yin >> map2;
680 
681     EXPECT_FALSE(yin.error());
682     EXPECT_EQ(flagBig,              map2.f1);
683     EXPECT_EQ(flagRound|flagFlat,   map2.f2);
684     EXPECT_EQ(flagNone,             map2.f3);
685     //EXPECT_EQ(flagRound,            map2.f4);  // check optional key
686   }
687 }
688 
689 
690 
691 //===----------------------------------------------------------------------===//
692 //  Test ScalarTraits
693 //===----------------------------------------------------------------------===//
694 
695 struct MyCustomType {
696   int length;
697   int width;
698 };
699 
700 struct MyCustomTypeMap {
701   MyCustomType     f1;
702   MyCustomType     f2;
703   int              f3;
704 };
705 
706 
707 namespace llvm {
708 namespace yaml {
709   template <>
710   struct MappingTraits<MyCustomTypeMap> {
mappingllvm::yaml::MappingTraits711     static void mapping(IO &io, MyCustomTypeMap& s) {
712       io.mapRequired("f1", s.f1);
713       io.mapRequired("f2", s.f2);
714       io.mapRequired("f3", s.f3);
715      }
716   };
717   // MyCustomType is formatted as a yaml scalar.  A value of
718   // {length=3, width=4} would be represented in yaml as "3 by 4".
719   template<>
720   struct ScalarTraits<MyCustomType> {
outputllvm::yaml::ScalarTraits721     static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) {
722       out << llvm::format("%d by %d", value.length, value.width);
723     }
inputllvm::yaml::ScalarTraits724     static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) {
725       size_t byStart = scalar.find("by");
726       if ( byStart != StringRef::npos ) {
727         StringRef lenStr = scalar.slice(0, byStart);
728         lenStr = lenStr.rtrim();
729         if ( lenStr.getAsInteger(0, value.length) ) {
730           return "malformed length";
731         }
732         StringRef widthStr = scalar.drop_front(byStart+2);
733         widthStr = widthStr.ltrim();
734         if ( widthStr.getAsInteger(0, value.width) ) {
735           return "malformed width";
736         }
737         return StringRef();
738       }
739       else {
740           return "malformed by";
741       }
742     }
mustQuotellvm::yaml::ScalarTraits743     static bool mustQuote(StringRef) { return true; }
744   };
745 }
746 }
747 
748 
749 //
750 // Test writing then reading back custom values
751 //
TEST(YAMLIO,TestReadWriteMyCustomType)752 TEST(YAMLIO, TestReadWriteMyCustomType) {
753   std::string intermediate;
754   {
755     MyCustomTypeMap map;
756     map.f1.length = 1;
757     map.f1.width  = 4;
758     map.f2.length = 100;
759     map.f2.width  = 400;
760     map.f3 = 10;
761 
762     llvm::raw_string_ostream ostr(intermediate);
763     Output yout(ostr);
764     yout << map;
765   }
766 
767   {
768     Input yin(intermediate);
769     MyCustomTypeMap map2;
770     yin >> map2;
771 
772     EXPECT_FALSE(yin.error());
773     EXPECT_EQ(1,      map2.f1.length);
774     EXPECT_EQ(4,      map2.f1.width);
775     EXPECT_EQ(100,    map2.f2.length);
776     EXPECT_EQ(400,    map2.f2.width);
777     EXPECT_EQ(10,     map2.f3);
778   }
779 }
780 
781 
782 //===----------------------------------------------------------------------===//
783 //  Test flow sequences
784 //===----------------------------------------------------------------------===//
785 
786 LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
787 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
788 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef)
789 
790 namespace llvm {
791 namespace yaml {
792   template<>
793   struct ScalarTraits<MyNumber> {
outputllvm::yaml::ScalarTraits794     static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
795       out << value;
796     }
797 
inputllvm::yaml::ScalarTraits798     static StringRef input(StringRef scalar, void *, MyNumber &value) {
799       long long n;
800       if ( getAsSignedInteger(scalar, 0, n) )
801         return "invalid number";
802       value = n;
803       return StringRef();
804     }
805 
mustQuotellvm::yaml::ScalarTraits806     static bool mustQuote(StringRef) { return false; }
807   };
808 }
809 }
810 
811 struct NameAndNumbers {
812   llvm::StringRef               name;
813   std::vector<llvm::StringRef>  strings;
814   std::vector<MyNumber>         single;
815   std::vector<MyNumber>         numbers;
816 };
817 
818 namespace llvm {
819 namespace yaml {
820   template <>
821   struct MappingTraits<NameAndNumbers> {
mappingllvm::yaml::MappingTraits822     static void mapping(IO &io, NameAndNumbers& nn) {
823       io.mapRequired("name",     nn.name);
824       io.mapRequired("strings",  nn.strings);
825       io.mapRequired("single",   nn.single);
826       io.mapRequired("numbers",  nn.numbers);
827     }
828   };
829 }
830 }
831 
832 
833 //
834 // Test writing then reading back custom values
835 //
TEST(YAMLIO,TestReadWriteMyFlowSequence)836 TEST(YAMLIO, TestReadWriteMyFlowSequence) {
837   std::string intermediate;
838   {
839     NameAndNumbers map;
840     map.name  = "hello";
841     map.strings.push_back(llvm::StringRef("one"));
842     map.strings.push_back(llvm::StringRef("two"));
843     map.single.push_back(1);
844     map.numbers.push_back(10);
845     map.numbers.push_back(-30);
846     map.numbers.push_back(1024);
847 
848     llvm::raw_string_ostream ostr(intermediate);
849     Output yout(ostr);
850     yout << map;
851 
852     // Verify sequences were written in flow style
853     ostr.flush();
854     llvm::StringRef flowOut(intermediate);
855     EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
856     EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
857   }
858 
859   {
860     Input yin(intermediate);
861     NameAndNumbers map2;
862     yin >> map2;
863 
864     EXPECT_FALSE(yin.error());
865     EXPECT_TRUE(map2.name.equals("hello"));
866     EXPECT_EQ(map2.strings.size(), 2UL);
867     EXPECT_TRUE(map2.strings[0].equals("one"));
868     EXPECT_TRUE(map2.strings[1].equals("two"));
869     EXPECT_EQ(map2.single.size(), 1UL);
870     EXPECT_EQ(1,       map2.single[0]);
871     EXPECT_EQ(map2.numbers.size(), 3UL);
872     EXPECT_EQ(10,      map2.numbers[0]);
873     EXPECT_EQ(-30,     map2.numbers[1]);
874     EXPECT_EQ(1024,    map2.numbers[2]);
875   }
876 }
877 
878 
879 //===----------------------------------------------------------------------===//
880 //  Test normalizing/denormalizing
881 //===----------------------------------------------------------------------===//
882 
883 LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
884 
885 typedef std::vector<TotalSeconds> SecondsSequence;
886 
887 LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
888 
889 
890 namespace llvm {
891 namespace yaml {
892   template <>
893   struct MappingTraits<TotalSeconds> {
894 
895     class NormalizedSeconds {
896     public:
NormalizedSeconds(IO & io)897       NormalizedSeconds(IO &io)
898         : hours(0), minutes(0), seconds(0) {
899       }
NormalizedSeconds(IO &,TotalSeconds & secs)900       NormalizedSeconds(IO &, TotalSeconds &secs)
901         : hours(secs/3600),
902           minutes((secs - (hours*3600))/60),
903           seconds(secs % 60) {
904       }
denormalize(IO &)905       TotalSeconds denormalize(IO &) {
906         return TotalSeconds(hours*3600 + minutes*60 + seconds);
907       }
908 
909       uint32_t     hours;
910       uint8_t      minutes;
911       uint8_t      seconds;
912     };
913 
mappingllvm::yaml::MappingTraits914     static void mapping(IO &io, TotalSeconds &secs) {
915       MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
916 
917       io.mapOptional("hours",    keys->hours,    (uint32_t)0);
918       io.mapOptional("minutes",  keys->minutes,  (uint8_t)0);
919       io.mapRequired("seconds",  keys->seconds);
920     }
921   };
922 }
923 }
924 
925 
926 //
927 // Test the reading of a yaml sequence of mappings
928 //
TEST(YAMLIO,TestReadMySecondsSequence)929 TEST(YAMLIO, TestReadMySecondsSequence) {
930   SecondsSequence seq;
931   Input yin("---\n - hours:  1\n   seconds:  5\n - seconds:  59\n...\n");
932   yin >> seq;
933 
934   EXPECT_FALSE(yin.error());
935   EXPECT_EQ(seq.size(), 2UL);
936   EXPECT_EQ(seq[0], 3605U);
937   EXPECT_EQ(seq[1], 59U);
938 }
939 
940 
941 //
942 // Test writing then reading back custom values
943 //
TEST(YAMLIO,TestReadWriteMySecondsSequence)944 TEST(YAMLIO, TestReadWriteMySecondsSequence) {
945   std::string intermediate;
946   {
947     SecondsSequence seq;
948     seq.push_back(4000);
949     seq.push_back(500);
950     seq.push_back(59);
951 
952     llvm::raw_string_ostream ostr(intermediate);
953     Output yout(ostr);
954     yout << seq;
955   }
956   {
957     Input yin(intermediate);
958     SecondsSequence seq2;
959     yin >> seq2;
960 
961     EXPECT_FALSE(yin.error());
962     EXPECT_EQ(seq2.size(), 3UL);
963     EXPECT_EQ(seq2[0], 4000U);
964     EXPECT_EQ(seq2[1], 500U);
965     EXPECT_EQ(seq2[2], 59U);
966   }
967 }
968 
969 
970 //===----------------------------------------------------------------------===//
971 //  Test dynamic typing
972 //===----------------------------------------------------------------------===//
973 
974 enum AFlags {
975     a1,
976     a2,
977     a3
978 };
979 
980 enum BFlags {
981     b1,
982     b2,
983     b3
984 };
985 
986 enum Kind {
987     kindA,
988     kindB
989 };
990 
991 struct KindAndFlags {
KindAndFlagsKindAndFlags992   KindAndFlags() : kind(kindA), flags(0) { }
KindAndFlagsKindAndFlags993   KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
994   Kind        kind;
995   uint32_t    flags;
996 };
997 
998 typedef std::vector<KindAndFlags> KindAndFlagsSequence;
999 
1000 LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
1001 
1002 namespace llvm {
1003 namespace yaml {
1004   template <>
1005   struct ScalarEnumerationTraits<AFlags> {
enumerationllvm::yaml::ScalarEnumerationTraits1006     static void enumeration(IO &io, AFlags &value) {
1007       io.enumCase(value, "a1",  a1);
1008       io.enumCase(value, "a2",  a2);
1009       io.enumCase(value, "a3",  a3);
1010     }
1011   };
1012   template <>
1013   struct ScalarEnumerationTraits<BFlags> {
enumerationllvm::yaml::ScalarEnumerationTraits1014     static void enumeration(IO &io, BFlags &value) {
1015       io.enumCase(value, "b1",  b1);
1016       io.enumCase(value, "b2",  b2);
1017       io.enumCase(value, "b3",  b3);
1018     }
1019   };
1020   template <>
1021   struct ScalarEnumerationTraits<Kind> {
enumerationllvm::yaml::ScalarEnumerationTraits1022     static void enumeration(IO &io, Kind &value) {
1023       io.enumCase(value, "A",  kindA);
1024       io.enumCase(value, "B",  kindB);
1025     }
1026   };
1027   template <>
1028   struct MappingTraits<KindAndFlags> {
mappingllvm::yaml::MappingTraits1029     static void mapping(IO &io, KindAndFlags& kf) {
1030       io.mapRequired("kind",  kf.kind);
1031       // Type of "flags" field varies depending on "kind" field.
1032       // Use memcpy here to avoid breaking strict aliasing rules.
1033       if (kf.kind == kindA) {
1034         AFlags aflags = static_cast<AFlags>(kf.flags);
1035         io.mapRequired("flags", aflags);
1036         kf.flags = aflags;
1037       } else {
1038         BFlags bflags = static_cast<BFlags>(kf.flags);
1039         io.mapRequired("flags", bflags);
1040         kf.flags = bflags;
1041       }
1042     }
1043   };
1044 }
1045 }
1046 
1047 
1048 //
1049 // Test the reading of a yaml sequence dynamic types
1050 //
TEST(YAMLIO,TestReadKindAndFlagsSequence)1051 TEST(YAMLIO, TestReadKindAndFlagsSequence) {
1052   KindAndFlagsSequence seq;
1053   Input yin("---\n - kind:  A\n   flags:  a2\n - kind:  B\n   flags:  b1\n...\n");
1054   yin >> seq;
1055 
1056   EXPECT_FALSE(yin.error());
1057   EXPECT_EQ(seq.size(), 2UL);
1058   EXPECT_EQ(seq[0].kind,  kindA);
1059   EXPECT_EQ(seq[0].flags, (uint32_t)a2);
1060   EXPECT_EQ(seq[1].kind,  kindB);
1061   EXPECT_EQ(seq[1].flags, (uint32_t)b1);
1062 }
1063 
1064 //
1065 // Test writing then reading back dynamic types
1066 //
TEST(YAMLIO,TestReadWriteKindAndFlagsSequence)1067 TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
1068   std::string intermediate;
1069   {
1070     KindAndFlagsSequence seq;
1071     seq.push_back(KindAndFlags(kindA,a1));
1072     seq.push_back(KindAndFlags(kindB,b1));
1073     seq.push_back(KindAndFlags(kindA,a2));
1074     seq.push_back(KindAndFlags(kindB,b2));
1075     seq.push_back(KindAndFlags(kindA,a3));
1076 
1077     llvm::raw_string_ostream ostr(intermediate);
1078     Output yout(ostr);
1079     yout << seq;
1080   }
1081   {
1082     Input yin(intermediate);
1083     KindAndFlagsSequence seq2;
1084     yin >> seq2;
1085 
1086     EXPECT_FALSE(yin.error());
1087     EXPECT_EQ(seq2.size(), 5UL);
1088     EXPECT_EQ(seq2[0].kind,  kindA);
1089     EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
1090     EXPECT_EQ(seq2[1].kind,  kindB);
1091     EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
1092     EXPECT_EQ(seq2[2].kind,  kindA);
1093     EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
1094     EXPECT_EQ(seq2[3].kind,  kindB);
1095     EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
1096     EXPECT_EQ(seq2[4].kind,  kindA);
1097     EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
1098   }
1099 }
1100 
1101 
1102 //===----------------------------------------------------------------------===//
1103 //  Test document list
1104 //===----------------------------------------------------------------------===//
1105 
1106 struct FooBarMap {
1107   int foo;
1108   int bar;
1109 };
1110 typedef std::vector<FooBarMap> FooBarMapDocumentList;
1111 
1112 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
1113 
1114 
1115 namespace llvm {
1116 namespace yaml {
1117   template <>
1118   struct MappingTraits<FooBarMap> {
mappingllvm::yaml::MappingTraits1119     static void mapping(IO &io, FooBarMap& fb) {
1120       io.mapRequired("foo",    fb.foo);
1121       io.mapRequired("bar",    fb.bar);
1122     }
1123   };
1124 }
1125 }
1126 
1127 
1128 //
1129 // Test the reading of a yaml mapping
1130 //
TEST(YAMLIO,TestDocRead)1131 TEST(YAMLIO, TestDocRead) {
1132   FooBarMap doc;
1133   Input yin("---\nfoo:  3\nbar:  5\n...\n");
1134   yin >> doc;
1135 
1136   EXPECT_FALSE(yin.error());
1137   EXPECT_EQ(doc.foo, 3);
1138   EXPECT_EQ(doc.bar,5);
1139 }
1140 
1141 
1142 
1143 //
1144 // Test writing then reading back a sequence of mappings
1145 //
TEST(YAMLIO,TestSequenceDocListWriteAndRead)1146 TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
1147   std::string intermediate;
1148   {
1149     FooBarMap doc1;
1150     doc1.foo = 10;
1151     doc1.bar = -3;
1152     FooBarMap doc2;
1153     doc2.foo = 257;
1154     doc2.bar = 0;
1155     std::vector<FooBarMap> docList;
1156     docList.push_back(doc1);
1157     docList.push_back(doc2);
1158 
1159     llvm::raw_string_ostream ostr(intermediate);
1160     Output yout(ostr);
1161     yout << docList;
1162   }
1163 
1164 
1165   {
1166     Input yin(intermediate);
1167     std::vector<FooBarMap> docList2;
1168     yin >> docList2;
1169 
1170     EXPECT_FALSE(yin.error());
1171     EXPECT_EQ(docList2.size(), 2UL);
1172     FooBarMap& map1 = docList2[0];
1173     FooBarMap& map2 = docList2[1];
1174     EXPECT_EQ(map1.foo, 10);
1175     EXPECT_EQ(map1.bar, -3);
1176     EXPECT_EQ(map2.foo, 257);
1177     EXPECT_EQ(map2.bar, 0);
1178   }
1179 }
1180 
1181 //===----------------------------------------------------------------------===//
1182 //  Test document tags
1183 //===----------------------------------------------------------------------===//
1184 
1185 struct MyDouble {
MyDoubleMyDouble1186   MyDouble() : value(0.0) { }
MyDoubleMyDouble1187   MyDouble(double x) : value(x) { }
1188   double value;
1189 };
1190 
1191 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
1192 
1193 
1194 namespace llvm {
1195 namespace yaml {
1196   template <>
1197   struct MappingTraits<MyDouble> {
mappingllvm::yaml::MappingTraits1198     static void mapping(IO &io, MyDouble &d) {
1199       if (io.mapTag("!decimal", true)) {
1200         mappingDecimal(io, d);
1201       } else if (io.mapTag("!fraction")) {
1202         mappingFraction(io, d);
1203       }
1204     }
mappingDecimalllvm::yaml::MappingTraits1205     static void mappingDecimal(IO &io, MyDouble &d) {
1206       io.mapRequired("value", d.value);
1207     }
mappingFractionllvm::yaml::MappingTraits1208     static void mappingFraction(IO &io, MyDouble &d) {
1209         double num, denom;
1210         io.mapRequired("numerator",      num);
1211         io.mapRequired("denominator",    denom);
1212         // convert fraction to double
1213         d.value = num/denom;
1214     }
1215   };
1216  }
1217 }
1218 
1219 
1220 //
1221 // Test the reading of two different tagged yaml documents.
1222 //
TEST(YAMLIO,TestTaggedDocuments)1223 TEST(YAMLIO, TestTaggedDocuments) {
1224   std::vector<MyDouble> docList;
1225   Input yin("--- !decimal\nvalue:  3.0\n"
1226             "--- !fraction\nnumerator:  9.0\ndenominator:  2\n...\n");
1227   yin >> docList;
1228   EXPECT_FALSE(yin.error());
1229   EXPECT_EQ(docList.size(), 2UL);
1230   EXPECT_EQ(docList[0].value, 3.0);
1231   EXPECT_EQ(docList[1].value, 4.5);
1232 }
1233 
1234 
1235 
1236 //
1237 // Test writing then reading back tagged documents
1238 //
TEST(YAMLIO,TestTaggedDocumentsWriteAndRead)1239 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1240   std::string intermediate;
1241   {
1242     MyDouble a(10.25);
1243     MyDouble b(-3.75);
1244     std::vector<MyDouble> docList;
1245     docList.push_back(a);
1246     docList.push_back(b);
1247 
1248     llvm::raw_string_ostream ostr(intermediate);
1249     Output yout(ostr);
1250     yout << docList;
1251   }
1252 
1253   {
1254     Input yin(intermediate);
1255     std::vector<MyDouble> docList2;
1256     yin >> docList2;
1257 
1258     EXPECT_FALSE(yin.error());
1259     EXPECT_EQ(docList2.size(), 2UL);
1260     EXPECT_EQ(docList2[0].value, 10.25);
1261     EXPECT_EQ(docList2[1].value, -3.75);
1262   }
1263 }
1264 
1265 
1266 //===----------------------------------------------------------------------===//
1267 //  Test mapping validation
1268 //===----------------------------------------------------------------------===//
1269 
1270 struct MyValidation {
1271   double value;
1272 };
1273 
1274 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
1275 
1276 namespace llvm {
1277 namespace yaml {
1278   template <>
1279   struct MappingTraits<MyValidation> {
mappingllvm::yaml::MappingTraits1280     static void mapping(IO &io, MyValidation &d) {
1281         io.mapRequired("value", d.value);
1282     }
validatellvm::yaml::MappingTraits1283     static StringRef validate(IO &io, MyValidation &d) {
1284         if (d.value < 0)
1285           return "negative value";
1286         return StringRef();
1287     }
1288   };
1289  }
1290 }
1291 
1292 
1293 //
1294 // Test that validate() is called and complains about the negative value.
1295 //
TEST(YAMLIO,TestValidatingInput)1296 TEST(YAMLIO, TestValidatingInput) {
1297   std::vector<MyValidation> docList;
1298   Input yin("--- \nvalue:  3.0\n"
1299             "--- \nvalue:  -1.0\n...\n",
1300             nullptr, suppressErrorMessages);
1301   yin >> docList;
1302   EXPECT_TRUE(!!yin.error());
1303 }
1304 
1305 
1306 //===----------------------------------------------------------------------===//
1307 //  Test error handling
1308 //===----------------------------------------------------------------------===//
1309 
1310 //
1311 // Test error handling of unknown enumerated scalar
1312 //
TEST(YAMLIO,TestColorsReadError)1313 TEST(YAMLIO, TestColorsReadError) {
1314   ColorMap map;
1315   Input yin("---\n"
1316             "c1:  blue\n"
1317             "c2:  purple\n"
1318             "c3:  green\n"
1319             "...\n",
1320             /*Ctxt=*/nullptr,
1321             suppressErrorMessages);
1322   yin >> map;
1323   EXPECT_TRUE(!!yin.error());
1324 }
1325 
1326 
1327 //
1328 // Test error handling of flow sequence with unknown value
1329 //
TEST(YAMLIO,TestFlagsReadError)1330 TEST(YAMLIO, TestFlagsReadError) {
1331   FlagsMap map;
1332   Input yin("---\n"
1333             "f1:  [ big ]\n"
1334             "f2:  [ round, hollow ]\n"
1335             "f3:  []\n"
1336             "...\n",
1337             /*Ctxt=*/nullptr,
1338             suppressErrorMessages);
1339   yin >> map;
1340 
1341   EXPECT_TRUE(!!yin.error());
1342 }
1343 
1344 
1345 //
1346 // Test error handling reading built-in uint8_t type
1347 //
1348 LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
TEST(YAMLIO,TestReadBuiltInTypesUint8Error)1349 TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
1350   std::vector<uint8_t> seq;
1351   Input yin("---\n"
1352             "- 255\n"
1353             "- 0\n"
1354             "- 257\n"
1355             "...\n",
1356             /*Ctxt=*/nullptr,
1357             suppressErrorMessages);
1358   yin >> seq;
1359 
1360   EXPECT_TRUE(!!yin.error());
1361 }
1362 
1363 
1364 //
1365 // Test error handling reading built-in uint16_t type
1366 //
1367 LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
TEST(YAMLIO,TestReadBuiltInTypesUint16Error)1368 TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
1369   std::vector<uint16_t> seq;
1370   Input yin("---\n"
1371             "- 65535\n"
1372             "- 0\n"
1373             "- 66000\n"
1374             "...\n",
1375             /*Ctxt=*/nullptr,
1376             suppressErrorMessages);
1377   yin >> seq;
1378 
1379   EXPECT_TRUE(!!yin.error());
1380 }
1381 
1382 
1383 //
1384 // Test error handling reading built-in uint32_t type
1385 //
1386 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
TEST(YAMLIO,TestReadBuiltInTypesUint32Error)1387 TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
1388   std::vector<uint32_t> seq;
1389   Input yin("---\n"
1390             "- 4000000000\n"
1391             "- 0\n"
1392             "- 5000000000\n"
1393             "...\n",
1394             /*Ctxt=*/nullptr,
1395             suppressErrorMessages);
1396   yin >> seq;
1397 
1398   EXPECT_TRUE(!!yin.error());
1399 }
1400 
1401 
1402 //
1403 // Test error handling reading built-in uint64_t type
1404 //
1405 LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
TEST(YAMLIO,TestReadBuiltInTypesUint64Error)1406 TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
1407   std::vector<uint64_t> seq;
1408   Input yin("---\n"
1409             "- 18446744073709551615\n"
1410             "- 0\n"
1411             "- 19446744073709551615\n"
1412             "...\n",
1413             /*Ctxt=*/nullptr,
1414             suppressErrorMessages);
1415   yin >> seq;
1416 
1417   EXPECT_TRUE(!!yin.error());
1418 }
1419 
1420 
1421 //
1422 // Test error handling reading built-in int8_t type
1423 //
1424 LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
TEST(YAMLIO,TestReadBuiltInTypesint8OverError)1425 TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
1426   std::vector<int8_t> seq;
1427   Input yin("---\n"
1428             "- -128\n"
1429             "- 0\n"
1430             "- 127\n"
1431             "- 128\n"
1432            "...\n",
1433             /*Ctxt=*/nullptr,
1434             suppressErrorMessages);
1435   yin >> seq;
1436 
1437   EXPECT_TRUE(!!yin.error());
1438 }
1439 
1440 //
1441 // Test error handling reading built-in int8_t type
1442 //
TEST(YAMLIO,TestReadBuiltInTypesint8UnderError)1443 TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
1444   std::vector<int8_t> seq;
1445   Input yin("---\n"
1446             "- -128\n"
1447             "- 0\n"
1448             "- 127\n"
1449             "- -129\n"
1450             "...\n",
1451             /*Ctxt=*/nullptr,
1452             suppressErrorMessages);
1453   yin >> seq;
1454 
1455   EXPECT_TRUE(!!yin.error());
1456 }
1457 
1458 
1459 //
1460 // Test error handling reading built-in int16_t type
1461 //
1462 LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
TEST(YAMLIO,TestReadBuiltInTypesint16UnderError)1463 TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
1464   std::vector<int16_t> seq;
1465   Input yin("---\n"
1466             "- 32767\n"
1467             "- 0\n"
1468             "- -32768\n"
1469             "- -32769\n"
1470             "...\n",
1471             /*Ctxt=*/nullptr,
1472             suppressErrorMessages);
1473   yin >> seq;
1474 
1475   EXPECT_TRUE(!!yin.error());
1476 }
1477 
1478 
1479 //
1480 // Test error handling reading built-in int16_t type
1481 //
TEST(YAMLIO,TestReadBuiltInTypesint16OverError)1482 TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
1483   std::vector<int16_t> seq;
1484   Input yin("---\n"
1485             "- 32767\n"
1486             "- 0\n"
1487             "- -32768\n"
1488             "- 32768\n"
1489             "...\n",
1490             /*Ctxt=*/nullptr,
1491             suppressErrorMessages);
1492   yin >> seq;
1493 
1494   EXPECT_TRUE(!!yin.error());
1495 }
1496 
1497 
1498 //
1499 // Test error handling reading built-in int32_t type
1500 //
1501 LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
TEST(YAMLIO,TestReadBuiltInTypesint32UnderError)1502 TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
1503   std::vector<int32_t> seq;
1504   Input yin("---\n"
1505             "- 2147483647\n"
1506             "- 0\n"
1507             "- -2147483648\n"
1508             "- -2147483649\n"
1509             "...\n",
1510             /*Ctxt=*/nullptr,
1511             suppressErrorMessages);
1512   yin >> seq;
1513 
1514   EXPECT_TRUE(!!yin.error());
1515 }
1516 
1517 //
1518 // Test error handling reading built-in int32_t type
1519 //
TEST(YAMLIO,TestReadBuiltInTypesint32OverError)1520 TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
1521   std::vector<int32_t> seq;
1522   Input yin("---\n"
1523             "- 2147483647\n"
1524             "- 0\n"
1525             "- -2147483648\n"
1526             "- 2147483649\n"
1527             "...\n",
1528             /*Ctxt=*/nullptr,
1529             suppressErrorMessages);
1530   yin >> seq;
1531 
1532   EXPECT_TRUE(!!yin.error());
1533 }
1534 
1535 
1536 //
1537 // Test error handling reading built-in int64_t type
1538 //
1539 LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
TEST(YAMLIO,TestReadBuiltInTypesint64UnderError)1540 TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
1541   std::vector<int64_t> seq;
1542   Input yin("---\n"
1543             "- -9223372036854775808\n"
1544             "- 0\n"
1545             "- 9223372036854775807\n"
1546             "- -9223372036854775809\n"
1547             "...\n",
1548             /*Ctxt=*/nullptr,
1549             suppressErrorMessages);
1550   yin >> seq;
1551 
1552   EXPECT_TRUE(!!yin.error());
1553 }
1554 
1555 //
1556 // Test error handling reading built-in int64_t type
1557 //
TEST(YAMLIO,TestReadBuiltInTypesint64OverError)1558 TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
1559   std::vector<int64_t> seq;
1560   Input yin("---\n"
1561             "- -9223372036854775808\n"
1562             "- 0\n"
1563             "- 9223372036854775807\n"
1564             "- 9223372036854775809\n"
1565             "...\n",
1566             /*Ctxt=*/nullptr,
1567             suppressErrorMessages);
1568   yin >> seq;
1569 
1570   EXPECT_TRUE(!!yin.error());
1571 }
1572 
1573 //
1574 // Test error handling reading built-in float type
1575 //
1576 LLVM_YAML_IS_SEQUENCE_VECTOR(float)
TEST(YAMLIO,TestReadBuiltInTypesFloatError)1577 TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
1578   std::vector<float> seq;
1579   Input yin("---\n"
1580             "- 0.0\n"
1581             "- 1000.1\n"
1582             "- -123.456\n"
1583             "- 1.2.3\n"
1584             "...\n",
1585             /*Ctxt=*/nullptr,
1586             suppressErrorMessages);
1587   yin >> seq;
1588 
1589   EXPECT_TRUE(!!yin.error());
1590 }
1591 
1592 //
1593 // Test error handling reading built-in float type
1594 //
1595 LLVM_YAML_IS_SEQUENCE_VECTOR(double)
TEST(YAMLIO,TestReadBuiltInTypesDoubleError)1596 TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
1597   std::vector<double> seq;
1598   Input yin("---\n"
1599             "- 0.0\n"
1600             "- 1000.1\n"
1601             "- -123.456\n"
1602             "- 1.2.3\n"
1603             "...\n",
1604             /*Ctxt=*/nullptr,
1605             suppressErrorMessages);
1606   yin >> seq;
1607 
1608   EXPECT_TRUE(!!yin.error());
1609 }
1610 
1611 //
1612 // Test error handling reading built-in Hex8 type
1613 //
1614 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
TEST(YAMLIO,TestReadBuiltInTypesHex8Error)1615 TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
1616   std::vector<Hex8> seq;
1617   Input yin("---\n"
1618             "- 0x12\n"
1619             "- 0xFE\n"
1620             "- 0x123\n"
1621             "...\n",
1622             /*Ctxt=*/nullptr,
1623             suppressErrorMessages);
1624   yin >> seq;
1625 
1626   EXPECT_TRUE(!!yin.error());
1627 }
1628 
1629 
1630 //
1631 // Test error handling reading built-in Hex16 type
1632 //
1633 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
TEST(YAMLIO,TestReadBuiltInTypesHex16Error)1634 TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
1635   std::vector<Hex16> seq;
1636   Input yin("---\n"
1637             "- 0x0012\n"
1638             "- 0xFEFF\n"
1639             "- 0x12345\n"
1640             "...\n",
1641             /*Ctxt=*/nullptr,
1642             suppressErrorMessages);
1643   yin >> seq;
1644 
1645   EXPECT_TRUE(!!yin.error());
1646 }
1647 
1648 //
1649 // Test error handling reading built-in Hex32 type
1650 //
1651 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
TEST(YAMLIO,TestReadBuiltInTypesHex32Error)1652 TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
1653   std::vector<Hex32> seq;
1654   Input yin("---\n"
1655             "- 0x0012\n"
1656             "- 0xFEFF0000\n"
1657             "- 0x1234556789\n"
1658             "...\n",
1659             /*Ctxt=*/nullptr,
1660             suppressErrorMessages);
1661   yin >> seq;
1662 
1663   EXPECT_TRUE(!!yin.error());
1664 }
1665 
1666 //
1667 // Test error handling reading built-in Hex64 type
1668 //
1669 LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
TEST(YAMLIO,TestReadBuiltInTypesHex64Error)1670 TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
1671   std::vector<Hex64> seq;
1672   Input yin("---\n"
1673             "- 0x0012\n"
1674             "- 0xFFEEDDCCBBAA9988\n"
1675             "- 0x12345567890ABCDEF0\n"
1676             "...\n",
1677             /*Ctxt=*/nullptr,
1678             suppressErrorMessages);
1679   yin >> seq;
1680 
1681   EXPECT_TRUE(!!yin.error());
1682 }
1683 
TEST(YAMLIO,TestMalformedMapFailsGracefully)1684 TEST(YAMLIO, TestMalformedMapFailsGracefully) {
1685   FooBar doc;
1686   {
1687     // We pass the suppressErrorMessages handler to handle the error
1688     // message generated in the constructor of Input.
1689     Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages);
1690     yin >> doc;
1691     EXPECT_TRUE(!!yin.error());
1692   }
1693 
1694   {
1695     Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
1696     yin >> doc;
1697     EXPECT_TRUE(!!yin.error());
1698   }
1699 }
1700 
1701 struct OptionalTest {
1702   std::vector<int> Numbers;
1703 };
1704 
1705 struct OptionalTestSeq {
1706   std::vector<OptionalTest> Tests;
1707 };
1708 
1709 LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
1710 namespace llvm {
1711 namespace yaml {
1712   template <>
1713   struct MappingTraits<OptionalTest> {
mappingllvm::yaml::MappingTraits1714     static void mapping(IO& IO, OptionalTest &OT) {
1715       IO.mapOptional("Numbers", OT.Numbers);
1716     }
1717   };
1718 
1719   template <>
1720   struct MappingTraits<OptionalTestSeq> {
mappingllvm::yaml::MappingTraits1721     static void mapping(IO &IO, OptionalTestSeq &OTS) {
1722       IO.mapOptional("Tests", OTS.Tests);
1723     }
1724   };
1725 }
1726 }
1727 
TEST(YAMLIO,SequenceElideTest)1728 TEST(YAMLIO, SequenceElideTest) {
1729   // Test that writing out a purely optional structure with its fields set to
1730   // default followed by other data is properly read back in.
1731   OptionalTestSeq Seq;
1732   OptionalTest One, Two, Three, Four;
1733   int N[] = {1, 2, 3};
1734   Three.Numbers.assign(N, N + 3);
1735   Seq.Tests.push_back(One);
1736   Seq.Tests.push_back(Two);
1737   Seq.Tests.push_back(Three);
1738   Seq.Tests.push_back(Four);
1739 
1740   std::string intermediate;
1741   {
1742     llvm::raw_string_ostream ostr(intermediate);
1743     Output yout(ostr);
1744     yout << Seq;
1745   }
1746 
1747   Input yin(intermediate);
1748   OptionalTestSeq Seq2;
1749   yin >> Seq2;
1750 
1751   EXPECT_FALSE(yin.error());
1752 
1753   EXPECT_EQ(4UL, Seq2.Tests.size());
1754 
1755   EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
1756   EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
1757 
1758   EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
1759   EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
1760   EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
1761 
1762   EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
1763 }
1764 
TEST(YAMLIO,TestEmptyStringFailsForMapWithRequiredFields)1765 TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
1766   FooBar doc;
1767   Input yin("");
1768   yin >> doc;
1769   EXPECT_TRUE(!!yin.error());
1770 }
1771 
TEST(YAMLIO,TestEmptyStringSucceedsForMapWithOptionalFields)1772 TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
1773   OptionalTest doc;
1774   Input yin("");
1775   yin >> doc;
1776   EXPECT_FALSE(yin.error());
1777 }
1778 
TEST(YAMLIO,TestEmptyStringSucceedsForSequence)1779 TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
1780   std::vector<uint8_t> seq;
1781   Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
1782   yin >> seq;
1783 
1784   EXPECT_FALSE(yin.error());
1785   EXPECT_TRUE(seq.empty());
1786 }
1787