Home | History | Annotate | Download | only in Support
      1 //===- llvm/unittest/Support/BinaryStreamTest.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/Support/BinaryByteStream.h"
     11 #include "llvm/Support/BinaryItemStream.h"
     12 #include "llvm/Support/BinaryStreamArray.h"
     13 #include "llvm/Support/BinaryStreamReader.h"
     14 #include "llvm/Support/BinaryStreamRef.h"
     15 #include "llvm/Support/BinaryStreamWriter.h"
     16 #include "llvm/Testing/Support/Error.h"
     17 
     18 #include "gtest/gtest.h"
     19 
     20 
     21 using namespace llvm;
     22 using namespace llvm::support;
     23 
     24 namespace {
     25 
     26 class BrokenStream : public WritableBinaryStream {
     27 public:
     28   BrokenStream(MutableArrayRef<uint8_t> Data, endianness Endian,
     29                       uint32_t Align)
     30       : Data(Data), PartitionIndex(alignDown(Data.size() / 2, Align)),
     31         Endian(Endian) {}
     32 
     33   endianness getEndian() const override { return Endian; }
     34 
     35   Error readBytes(uint32_t Offset, uint32_t Size,
     36                   ArrayRef<uint8_t> &Buffer) override {
     37     if (auto EC = checkOffsetForRead(Offset, Size))
     38       return EC;
     39     uint32_t S = startIndex(Offset);
     40     auto Ref = Data.drop_front(S);
     41     if (Ref.size() >= Size) {
     42       Buffer = Ref.take_front(Size);
     43       return Error::success();
     44     }
     45 
     46     uint32_t BytesLeft = Size - Ref.size();
     47     uint8_t *Ptr = Allocator.Allocate<uint8_t>(Size);
     48     ::memcpy(Ptr, Ref.data(), Ref.size());
     49     ::memcpy(Ptr + Ref.size(), Data.data(), BytesLeft);
     50     Buffer = makeArrayRef<uint8_t>(Ptr, Size);
     51     return Error::success();
     52   }
     53 
     54   Error readLongestContiguousChunk(uint32_t Offset,
     55                                    ArrayRef<uint8_t> &Buffer) override {
     56     if (auto EC = checkOffsetForRead(Offset, 1))
     57       return EC;
     58     uint32_t S = startIndex(Offset);
     59     Buffer = Data.drop_front(S);
     60     return Error::success();
     61   }
     62 
     63   uint32_t getLength() override { return Data.size(); }
     64 
     65   Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> SrcData) override {
     66     if (auto EC = checkOffsetForWrite(Offset, SrcData.size()))
     67       return EC;
     68     if (SrcData.empty())
     69       return Error::success();
     70 
     71     uint32_t S = startIndex(Offset);
     72     MutableArrayRef<uint8_t> Ref(Data);
     73     Ref = Ref.drop_front(S);
     74     if (Ref.size() >= SrcData.size()) {
     75       ::memcpy(Ref.data(), SrcData.data(), SrcData.size());
     76       return Error::success();
     77     }
     78 
     79     uint32_t BytesLeft = SrcData.size() - Ref.size();
     80     ::memcpy(Ref.data(), SrcData.data(), Ref.size());
     81     ::memcpy(&Data[0], SrcData.data() + Ref.size(), BytesLeft);
     82     return Error::success();
     83   }
     84   Error commit() override { return Error::success(); }
     85 
     86 private:
     87   uint32_t startIndex(uint32_t Offset) const {
     88     return (Offset + PartitionIndex) % Data.size();
     89   }
     90 
     91   uint32_t endIndex(uint32_t Offset, uint32_t Size) const {
     92     return (startIndex(Offset) + Size - 1) % Data.size();
     93   }
     94 
     95   // Buffer is organized like this:
     96   // -------------------------------------------------
     97   // | N/2 | N/2+1 | ... | N-1 | 0 | 1 | ... | N/2-1 |
     98   // -------------------------------------------------
     99   // So reads from the beginning actually come from the middle.
    100   MutableArrayRef<uint8_t> Data;
    101   uint32_t PartitionIndex = 0;
    102   endianness Endian;
    103   BumpPtrAllocator Allocator;
    104 };
    105 
    106 constexpr endianness Endians[] = {big, little, native};
    107 constexpr uint32_t NumEndians = llvm::array_lengthof(Endians);
    108 constexpr uint32_t NumStreams = 2 * NumEndians;
    109 
    110 class BinaryStreamTest : public testing::Test {
    111 
    112 public:
    113   BinaryStreamTest() {}
    114 
    115   void SetUp() override {
    116     Streams.clear();
    117     Streams.resize(NumStreams);
    118     for (uint32_t I = 0; I < NumStreams; ++I)
    119       Streams[I].IsContiguous = (I % 2 == 0);
    120 
    121     InputData.clear();
    122     OutputData.clear();
    123   }
    124 
    125 protected:
    126   struct StreamPair {
    127     bool IsContiguous;
    128     std::unique_ptr<BinaryStream> Input;
    129     std::unique_ptr<WritableBinaryStream> Output;
    130   };
    131 
    132   void initializeInput(ArrayRef<uint8_t> Input, uint32_t Align) {
    133     InputData = Input;
    134 
    135     BrokenInputData.resize(InputData.size());
    136     if (!Input.empty()) {
    137       uint32_t PartitionIndex = alignDown(InputData.size() / 2, Align);
    138       uint32_t RightBytes = InputData.size() - PartitionIndex;
    139       uint32_t LeftBytes = PartitionIndex;
    140       if (RightBytes > 0)
    141         ::memcpy(&BrokenInputData[PartitionIndex], Input.data(), RightBytes);
    142       if (LeftBytes > 0)
    143         ::memcpy(&BrokenInputData[0], Input.data() + RightBytes, LeftBytes);
    144     }
    145 
    146     for (uint32_t I = 0; I < NumEndians; ++I) {
    147       auto InByteStream =
    148           llvm::make_unique<BinaryByteStream>(InputData, Endians[I]);
    149       auto InBrokenStream = llvm::make_unique<BrokenStream>(
    150           BrokenInputData, Endians[I], Align);
    151 
    152       Streams[I * 2].Input = std::move(InByteStream);
    153       Streams[I * 2 + 1].Input = std::move(InBrokenStream);
    154     }
    155   }
    156 
    157   void initializeOutput(uint32_t Size, uint32_t Align) {
    158     OutputData.resize(Size);
    159     BrokenOutputData.resize(Size);
    160 
    161     for (uint32_t I = 0; I < NumEndians; ++I) {
    162       Streams[I * 2].Output =
    163           llvm::make_unique<MutableBinaryByteStream>(OutputData, Endians[I]);
    164       Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>(
    165           BrokenOutputData, Endians[I], Align);
    166     }
    167   }
    168 
    169   void initializeOutputFromInput(uint32_t Align) {
    170     for (uint32_t I = 0; I < NumEndians; ++I) {
    171       Streams[I * 2].Output =
    172           llvm::make_unique<MutableBinaryByteStream>(InputData, Endians[I]);
    173       Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>(
    174           BrokenInputData, Endians[I], Align);
    175     }
    176   }
    177 
    178   void initializeInputFromOutput(uint32_t Align) {
    179     for (uint32_t I = 0; I < NumEndians; ++I) {
    180       Streams[I * 2].Input =
    181           llvm::make_unique<BinaryByteStream>(OutputData, Endians[I]);
    182       Streams[I * 2 + 1].Input = llvm::make_unique<BrokenStream>(
    183           BrokenOutputData, Endians[I], Align);
    184     }
    185   }
    186 
    187   std::vector<uint8_t> InputData;
    188   std::vector<uint8_t> BrokenInputData;
    189 
    190   std::vector<uint8_t> OutputData;
    191   std::vector<uint8_t> BrokenOutputData;
    192 
    193   std::vector<StreamPair> Streams;
    194 };
    195 
    196 // Tests that a we can read from a BinaryByteStream without a StreamReader.
    197 TEST_F(BinaryStreamTest, BinaryByteStreamBounds) {
    198   std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
    199   initializeInput(InputData, 1);
    200 
    201   for (auto &Stream : Streams) {
    202     ArrayRef<uint8_t> Buffer;
    203 
    204     // 1. If the read fits it should work.
    205     ASSERT_EQ(InputData.size(), Stream.Input->getLength());
    206     ASSERT_THAT_ERROR(Stream.Input->readBytes(2, 1, Buffer), Succeeded());
    207     EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
    208     ASSERT_THAT_ERROR(Stream.Input->readBytes(0, 4, Buffer), Succeeded());
    209     EXPECT_EQ(makeArrayRef(InputData).slice(0, 4), Buffer);
    210 
    211     // 2. Reading past the bounds of the input should fail.
    212     EXPECT_THAT_ERROR(Stream.Input->readBytes(4, 2, Buffer), Failed());
    213   }
    214 }
    215 
    216 TEST_F(BinaryStreamTest, StreamRefBounds) {
    217   std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
    218   initializeInput(InputData, 1);
    219 
    220   for (const auto &Stream : Streams) {
    221     ArrayRef<uint8_t> Buffer;
    222     BinaryStreamRef Ref(*Stream.Input);
    223 
    224     // Read 1 byte from offset 2 should work
    225     ASSERT_EQ(InputData.size(), Ref.getLength());
    226     ASSERT_THAT_ERROR(Ref.readBytes(2, 1, Buffer), Succeeded());
    227     EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
    228 
    229     // Reading everything from offset 2 on.
    230     ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
    231     if (Stream.IsContiguous)
    232       EXPECT_EQ(makeArrayRef(InputData).slice(2), Buffer);
    233     else
    234       EXPECT_FALSE(Buffer.empty());
    235 
    236     // Reading 6 bytes from offset 0 is too big.
    237     EXPECT_THAT_ERROR(Ref.readBytes(0, 6, Buffer), Failed());
    238     EXPECT_THAT_ERROR(Ref.readLongestContiguousChunk(6, Buffer), Failed());
    239 
    240     // Reading 1 byte from offset 2 after dropping 1 byte is the same as reading
    241     // 1 byte from offset 3.
    242     Ref = Ref.drop_front(1);
    243     ASSERT_THAT_ERROR(Ref.readBytes(2, 1, Buffer), Succeeded());
    244     if (Stream.IsContiguous)
    245       EXPECT_EQ(makeArrayRef(InputData).slice(3, 1), Buffer);
    246     else
    247       EXPECT_FALSE(Buffer.empty());
    248 
    249     // Reading everything from offset 2 on after dropping 1 byte.
    250     ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
    251     if (Stream.IsContiguous)
    252       EXPECT_EQ(makeArrayRef(InputData).slice(3), Buffer);
    253     else
    254       EXPECT_FALSE(Buffer.empty());
    255 
    256     // Reading 2 bytes from offset 2 after dropping 2 bytes is the same as
    257     // reading 2 bytes from offset 4, and should fail.
    258     Ref = Ref.drop_front(1);
    259     EXPECT_THAT_ERROR(Ref.readBytes(2, 2, Buffer), Failed());
    260 
    261     // But if we read the longest contiguous chunk instead, we should still
    262     // get the 1 byte at the end.
    263     ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
    264     EXPECT_EQ(makeArrayRef(InputData).take_back(), Buffer);
    265   }
    266 }
    267 
    268 TEST_F(BinaryStreamTest, StreamRefDynamicSize) {
    269   StringRef Strings[] = {"1", "2", "3", "4"};
    270   AppendingBinaryByteStream Stream(support::little);
    271 
    272   BinaryStreamWriter Writer(Stream);
    273   BinaryStreamReader Reader(Stream);
    274   const uint8_t *Byte;
    275   StringRef Str;
    276 
    277   // When the stream is empty, it should report a 0 length and we should get an
    278   // error trying to read even 1 byte from it.
    279   BinaryStreamRef ConstRef(Stream);
    280   EXPECT_EQ(0U, ConstRef.getLength());
    281   EXPECT_THAT_ERROR(Reader.readObject(Byte), Failed());
    282 
    283   // But if we write to it, its size should increase and we should be able to
    284   // read not just a byte, but the string that was written.
    285   EXPECT_THAT_ERROR(Writer.writeCString(Strings[0]), Succeeded());
    286   EXPECT_EQ(2U, ConstRef.getLength());
    287   EXPECT_THAT_ERROR(Reader.readObject(Byte), Succeeded());
    288 
    289   Reader.setOffset(0);
    290   EXPECT_THAT_ERROR(Reader.readCString(Str), Succeeded());
    291   EXPECT_EQ(Str, Strings[0]);
    292 
    293   // If we drop some bytes from the front, we should still track the length as
    294   // the
    295   // underlying stream grows.
    296   BinaryStreamRef Dropped = ConstRef.drop_front(1);
    297   EXPECT_EQ(1U, Dropped.getLength());
    298 
    299   EXPECT_THAT_ERROR(Writer.writeCString(Strings[1]), Succeeded());
    300   EXPECT_EQ(4U, ConstRef.getLength());
    301   EXPECT_EQ(3U, Dropped.getLength());
    302 
    303   // If we drop zero bytes from the back, we should continue tracking the
    304   // length.
    305   Dropped = Dropped.drop_back(0);
    306   EXPECT_THAT_ERROR(Writer.writeCString(Strings[2]), Succeeded());
    307   EXPECT_EQ(6U, ConstRef.getLength());
    308   EXPECT_EQ(5U, Dropped.getLength());
    309 
    310   // If we drop non-zero bytes from the back, we should stop tracking the
    311   // length.
    312   Dropped = Dropped.drop_back(1);
    313   EXPECT_THAT_ERROR(Writer.writeCString(Strings[3]), Succeeded());
    314   EXPECT_EQ(8U, ConstRef.getLength());
    315   EXPECT_EQ(4U, Dropped.getLength());
    316 }
    317 
    318 TEST_F(BinaryStreamTest, DropOperations) {
    319   std::vector<uint8_t> InputData = {1, 2, 3, 4, 5, 4, 3, 2, 1};
    320   auto RefData = makeArrayRef(InputData);
    321   initializeInput(InputData, 1);
    322 
    323   ArrayRef<uint8_t> Result;
    324   BinaryStreamRef Original(InputData, support::little);
    325   ASSERT_EQ(InputData.size(), Original.getLength());
    326 
    327   EXPECT_THAT_ERROR(Original.readBytes(0, InputData.size(), Result),
    328                     Succeeded());
    329   EXPECT_EQ(RefData, Result);
    330 
    331   auto Dropped = Original.drop_front(2);
    332   EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
    333                     Succeeded());
    334   EXPECT_EQ(RefData.drop_front(2), Result);
    335 
    336   Dropped = Original.drop_back(2);
    337   EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
    338                     Succeeded());
    339   EXPECT_EQ(RefData.drop_back(2), Result);
    340 
    341   Dropped = Original.keep_front(2);
    342   EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
    343                     Succeeded());
    344   EXPECT_EQ(RefData.take_front(2), Result);
    345 
    346   Dropped = Original.keep_back(2);
    347   EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
    348                     Succeeded());
    349   EXPECT_EQ(RefData.take_back(2), Result);
    350 
    351   Dropped = Original.drop_symmetric(2);
    352   EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
    353                     Succeeded());
    354   EXPECT_EQ(RefData.drop_front(2).drop_back(2), Result);
    355 }
    356 
    357 // Test that we can write to a BinaryStream without a StreamWriter.
    358 TEST_F(BinaryStreamTest, MutableBinaryByteStreamBounds) {
    359   std::vector<uint8_t> InputData = {'T', 'e', 's', 't', '\0'};
    360   initializeInput(InputData, 1);
    361   initializeOutput(InputData.size(), 1);
    362 
    363   // For every combination of input stream and output stream.
    364   for (auto &Stream : Streams) {
    365     ASSERT_EQ(InputData.size(), Stream.Input->getLength());
    366 
    367     // 1. Try two reads that are supposed to work.  One from offset 0, and one
    368     // from the middle.
    369     uint32_t Offsets[] = {0, 3};
    370     for (auto Offset : Offsets) {
    371       uint32_t ExpectedSize = Stream.Input->getLength() - Offset;
    372 
    373       // Read everything from Offset until the end of the input data.
    374       ArrayRef<uint8_t> Data;
    375       ASSERT_THAT_ERROR(Stream.Input->readBytes(Offset, ExpectedSize, Data),
    376                         Succeeded());
    377       ASSERT_EQ(ExpectedSize, Data.size());
    378 
    379       // Then write it to the destination.
    380       ASSERT_THAT_ERROR(Stream.Output->writeBytes(0, Data), Succeeded());
    381 
    382       // Then we read back what we wrote, it should match the corresponding
    383       // slice of the original input data.
    384       ArrayRef<uint8_t> Data2;
    385       ASSERT_THAT_ERROR(Stream.Output->readBytes(Offset, ExpectedSize, Data2),
    386                         Succeeded());
    387       EXPECT_EQ(makeArrayRef(InputData).drop_front(Offset), Data2);
    388     }
    389 
    390     std::vector<uint8_t> BigData = {0, 1, 2, 3, 4};
    391     // 2. If the write is too big, it should fail.
    392     EXPECT_THAT_ERROR(Stream.Output->writeBytes(3, BigData), Failed());
    393   }
    394 }
    395 
    396 TEST_F(BinaryStreamTest, AppendingStream) {
    397   AppendingBinaryByteStream Stream(llvm::support::little);
    398   EXPECT_EQ(0U, Stream.getLength());
    399 
    400   std::vector<uint8_t> InputData = {'T', 'e', 's', 't', 'T', 'e', 's', 't'};
    401   auto Test = makeArrayRef(InputData).take_front(4);
    402   // Writing past the end of the stream is an error.
    403   EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Failed());
    404 
    405   // Writing exactly at the end of the stream is ok.
    406   EXPECT_THAT_ERROR(Stream.writeBytes(0, Test), Succeeded());
    407   EXPECT_EQ(Test, Stream.data());
    408 
    409   // And now that the end of the stream is where we couldn't write before, now
    410   // we can write.
    411   EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Succeeded());
    412   EXPECT_EQ(MutableArrayRef<uint8_t>(InputData), Stream.data());
    413 }
    414 
    415 // Test that FixedStreamArray works correctly.
    416 TEST_F(BinaryStreamTest, FixedStreamArray) {
    417   std::vector<uint32_t> Ints = {90823, 12908, 109823, 209823};
    418   ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(Ints.data()),
    419                              Ints.size() * sizeof(uint32_t));
    420 
    421   initializeInput(IntBytes, alignof(uint32_t));
    422 
    423   for (auto &Stream : Streams) {
    424     ASSERT_EQ(InputData.size(), Stream.Input->getLength());
    425 
    426     FixedStreamArray<uint32_t> Array(*Stream.Input);
    427     auto Iter = Array.begin();
    428     ASSERT_EQ(Ints[0], *Iter++);
    429     ASSERT_EQ(Ints[1], *Iter++);
    430     ASSERT_EQ(Ints[2], *Iter++);
    431     ASSERT_EQ(Ints[3], *Iter++);
    432     ASSERT_EQ(Array.end(), Iter);
    433   }
    434 }
    435 
    436 // Ensure FixedStreamArrayIterator::operator-> works.
    437 // Added for coverage of r302257.
    438 TEST_F(BinaryStreamTest, FixedStreamArrayIteratorArrow) {
    439   std::vector<std::pair<uint32_t, uint32_t>> Pairs = {{867, 5309}, {555, 1212}};
    440   ArrayRef<uint8_t> PairBytes(reinterpret_cast<uint8_t *>(Pairs.data()),
    441     Pairs.size() * sizeof(Pairs[0]));
    442 
    443   initializeInput(PairBytes, alignof(uint32_t));
    444 
    445   for (auto &Stream : Streams) {
    446     ASSERT_EQ(InputData.size(), Stream.Input->getLength());
    447 
    448     const FixedStreamArray<std::pair<uint32_t, uint32_t>> Array(*Stream.Input);
    449     auto Iter = Array.begin();
    450     ASSERT_EQ(Pairs[0].first, Iter->first);
    451     ASSERT_EQ(Pairs[0].second, Iter->second);
    452     ++Iter;
    453     ASSERT_EQ(Pairs[1].first, Iter->first);
    454     ASSERT_EQ(Pairs[1].second, Iter->second);
    455     ++Iter;
    456     ASSERT_EQ(Array.end(), Iter);
    457   }
    458 }
    459 
    460 // Test that VarStreamArray works correctly.
    461 TEST_F(BinaryStreamTest, VarStreamArray) {
    462   StringLiteral Strings("1. Test2. Longer Test3. Really Long Test4. Super "
    463                         "Extra Longest Test Of All");
    464   ArrayRef<uint8_t> StringBytes(
    465       reinterpret_cast<const uint8_t *>(Strings.data()), Strings.size());
    466   initializeInput(StringBytes, 1);
    467 
    468   struct StringExtractor {
    469   public:
    470     Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item) {
    471       if (Index == 0)
    472         Len = strlen("1. Test");
    473       else if (Index == 1)
    474         Len = strlen("2. Longer Test");
    475       else if (Index == 2)
    476         Len = strlen("3. Really Long Test");
    477       else
    478         Len = strlen("4. Super Extra Longest Test Of All");
    479       ArrayRef<uint8_t> Bytes;
    480       if (auto EC = Stream.readBytes(0, Len, Bytes))
    481         return EC;
    482       Item =
    483           StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
    484       ++Index;
    485       return Error::success();
    486     }
    487 
    488     uint32_t Index = 0;
    489   };
    490 
    491   for (auto &Stream : Streams) {
    492     VarStreamArray<StringRef, StringExtractor> Array(*Stream.Input);
    493     auto Iter = Array.begin();
    494     ASSERT_EQ("1. Test", *Iter++);
    495     ASSERT_EQ("2. Longer Test", *Iter++);
    496     ASSERT_EQ("3. Really Long Test", *Iter++);
    497     ASSERT_EQ("4. Super Extra Longest Test Of All", *Iter++);
    498     ASSERT_EQ(Array.end(), Iter);
    499   }
    500 }
    501 
    502 TEST_F(BinaryStreamTest, StreamReaderBounds) {
    503   std::vector<uint8_t> Bytes;
    504 
    505   initializeInput(Bytes, 1);
    506   for (auto &Stream : Streams) {
    507     StringRef S;
    508     BinaryStreamReader Reader(*Stream.Input);
    509     EXPECT_EQ(0U, Reader.bytesRemaining());
    510     EXPECT_THAT_ERROR(Reader.readFixedString(S, 1), Failed());
    511   }
    512 
    513   Bytes.resize(5);
    514   initializeInput(Bytes, 1);
    515   for (auto &Stream : Streams) {
    516     StringRef S;
    517     BinaryStreamReader Reader(*Stream.Input);
    518     EXPECT_EQ(Bytes.size(), Reader.bytesRemaining());
    519     EXPECT_THAT_ERROR(Reader.readFixedString(S, 5), Succeeded());
    520     EXPECT_THAT_ERROR(Reader.readFixedString(S, 6), Failed());
    521   }
    522 }
    523 
    524 TEST_F(BinaryStreamTest, StreamReaderIntegers) {
    525   support::ulittle64_t Little{908234};
    526   support::ubig32_t Big{28907823};
    527   short NS = 2897;
    528   int NI = -89723;
    529   unsigned long NUL = 902309023UL;
    530   constexpr uint32_t Size =
    531       sizeof(Little) + sizeof(Big) + sizeof(NS) + sizeof(NI) + sizeof(NUL);
    532 
    533   initializeOutput(Size, alignof(support::ulittle64_t));
    534   initializeInputFromOutput(alignof(support::ulittle64_t));
    535 
    536   for (auto &Stream : Streams) {
    537     BinaryStreamWriter Writer(*Stream.Output);
    538     ASSERT_THAT_ERROR(Writer.writeObject(Little), Succeeded());
    539     ASSERT_THAT_ERROR(Writer.writeObject(Big), Succeeded());
    540     ASSERT_THAT_ERROR(Writer.writeInteger(NS), Succeeded());
    541     ASSERT_THAT_ERROR(Writer.writeInteger(NI), Succeeded());
    542     ASSERT_THAT_ERROR(Writer.writeInteger(NUL), Succeeded());
    543 
    544     const support::ulittle64_t *Little2;
    545     const support::ubig32_t *Big2;
    546     short NS2;
    547     int NI2;
    548     unsigned long NUL2;
    549 
    550     // 1. Reading fields individually.
    551     BinaryStreamReader Reader(*Stream.Input);
    552     ASSERT_THAT_ERROR(Reader.readObject(Little2), Succeeded());
    553     ASSERT_THAT_ERROR(Reader.readObject(Big2), Succeeded());
    554     ASSERT_THAT_ERROR(Reader.readInteger(NS2), Succeeded());
    555     ASSERT_THAT_ERROR(Reader.readInteger(NI2), Succeeded());
    556     ASSERT_THAT_ERROR(Reader.readInteger(NUL2), Succeeded());
    557     ASSERT_EQ(0U, Reader.bytesRemaining());
    558 
    559     EXPECT_EQ(Little, *Little2);
    560     EXPECT_EQ(Big, *Big2);
    561     EXPECT_EQ(NS, NS2);
    562     EXPECT_EQ(NI, NI2);
    563     EXPECT_EQ(NUL, NUL2);
    564   }
    565 }
    566 
    567 TEST_F(BinaryStreamTest, StreamReaderIntegerArray) {
    568   // 1. Arrays of integers
    569   std::vector<int> Ints = {1, 2, 3, 4, 5};
    570   ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(&Ints[0]),
    571                              Ints.size() * sizeof(int));
    572 
    573   initializeInput(IntBytes, alignof(int));
    574   for (auto &Stream : Streams) {
    575     BinaryStreamReader Reader(*Stream.Input);
    576     ArrayRef<int> IntsRef;
    577     ASSERT_THAT_ERROR(Reader.readArray(IntsRef, Ints.size()), Succeeded());
    578     ASSERT_EQ(0U, Reader.bytesRemaining());
    579     EXPECT_EQ(makeArrayRef(Ints), IntsRef);
    580 
    581     Reader.setOffset(0);
    582     FixedStreamArray<int> FixedIntsRef;
    583     ASSERT_THAT_ERROR(Reader.readArray(FixedIntsRef, Ints.size()), Succeeded());
    584     ASSERT_EQ(0U, Reader.bytesRemaining());
    585     ASSERT_EQ(Ints, std::vector<int>(FixedIntsRef.begin(), FixedIntsRef.end()));
    586   }
    587 }
    588 
    589 TEST_F(BinaryStreamTest, StreamReaderEnum) {
    590   enum class MyEnum : int64_t { Foo = -10, Bar = 0, Baz = 10 };
    591 
    592   std::vector<MyEnum> Enums = {MyEnum::Bar, MyEnum::Baz, MyEnum::Foo};
    593 
    594   initializeOutput(Enums.size() * sizeof(MyEnum), alignof(MyEnum));
    595   initializeInputFromOutput(alignof(MyEnum));
    596   for (auto &Stream : Streams) {
    597     BinaryStreamWriter Writer(*Stream.Output);
    598     for (auto Value : Enums)
    599       ASSERT_THAT_ERROR(Writer.writeEnum(Value), Succeeded());
    600 
    601     BinaryStreamReader Reader(*Stream.Input);
    602 
    603     FixedStreamArray<MyEnum> FSA;
    604 
    605     for (size_t I = 0; I < Enums.size(); ++I) {
    606       MyEnum Value;
    607       ASSERT_THAT_ERROR(Reader.readEnum(Value), Succeeded());
    608       EXPECT_EQ(Enums[I], Value);
    609     }
    610     ASSERT_EQ(0U, Reader.bytesRemaining());
    611   }
    612 }
    613 
    614 TEST_F(BinaryStreamTest, StreamReaderObject) {
    615   struct Foo {
    616     int X;
    617     double Y;
    618     char Z;
    619 
    620     bool operator==(const Foo &Other) const {
    621       return X == Other.X && Y == Other.Y && Z == Other.Z;
    622     }
    623   };
    624 
    625   std::vector<Foo> Foos;
    626   Foos.push_back({-42, 42.42, 42});
    627   Foos.push_back({100, 3.1415, static_cast<char>(-89)});
    628   Foos.push_back({200, 2.718, static_cast<char>(-12) });
    629 
    630   const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]);
    631 
    632   initializeInput(makeArrayRef(Bytes, 3 * sizeof(Foo)), alignof(Foo));
    633 
    634   for (auto &Stream : Streams) {
    635     // 1. Reading object pointers.
    636     BinaryStreamReader Reader(*Stream.Input);
    637     const Foo *FPtrOut = nullptr;
    638     const Foo *GPtrOut = nullptr;
    639     const Foo *HPtrOut = nullptr;
    640     ASSERT_THAT_ERROR(Reader.readObject(FPtrOut), Succeeded());
    641     ASSERT_THAT_ERROR(Reader.readObject(GPtrOut), Succeeded());
    642     ASSERT_THAT_ERROR(Reader.readObject(HPtrOut), Succeeded());
    643     EXPECT_EQ(0U, Reader.bytesRemaining());
    644     EXPECT_EQ(Foos[0], *FPtrOut);
    645     EXPECT_EQ(Foos[1], *GPtrOut);
    646     EXPECT_EQ(Foos[2], *HPtrOut);
    647   }
    648 }
    649 
    650 TEST_F(BinaryStreamTest, StreamReaderStrings) {
    651   std::vector<uint8_t> Bytes = {'O',  'n', 'e', '\0', 'T', 'w', 'o',
    652                                 '\0', 'T', 'h', 'r',  'e', 'e', '\0',
    653                                 'F',  'o', 'u', 'r',  '\0'};
    654   initializeInput(Bytes, 1);
    655 
    656   for (auto &Stream : Streams) {
    657     BinaryStreamReader Reader(*Stream.Input);
    658 
    659     StringRef S1;
    660     StringRef S2;
    661     StringRef S3;
    662     StringRef S4;
    663     ASSERT_THAT_ERROR(Reader.readCString(S1), Succeeded());
    664     ASSERT_THAT_ERROR(Reader.readCString(S2), Succeeded());
    665     ASSERT_THAT_ERROR(Reader.readCString(S3), Succeeded());
    666     ASSERT_THAT_ERROR(Reader.readCString(S4), Succeeded());
    667     ASSERT_EQ(0U, Reader.bytesRemaining());
    668 
    669     EXPECT_EQ("One", S1);
    670     EXPECT_EQ("Two", S2);
    671     EXPECT_EQ("Three", S3);
    672     EXPECT_EQ("Four", S4);
    673 
    674     S1 = S2 = S3 = S4 = "";
    675     Reader.setOffset(0);
    676     ASSERT_THAT_ERROR(Reader.readFixedString(S1, 3), Succeeded());
    677     ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
    678     ASSERT_THAT_ERROR(Reader.readFixedString(S2, 3), Succeeded());
    679     ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
    680     ASSERT_THAT_ERROR(Reader.readFixedString(S3, 5), Succeeded());
    681     ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
    682     ASSERT_THAT_ERROR(Reader.readFixedString(S4, 4), Succeeded());
    683     ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
    684     ASSERT_EQ(0U, Reader.bytesRemaining());
    685 
    686     EXPECT_EQ("One", S1);
    687     EXPECT_EQ("Two", S2);
    688     EXPECT_EQ("Three", S3);
    689     EXPECT_EQ("Four", S4);
    690   }
    691 }
    692 
    693 TEST_F(BinaryStreamTest, StreamWriterBounds) {
    694   initializeOutput(5, 1);
    695 
    696   for (auto &Stream : Streams) {
    697     BinaryStreamWriter Writer(*Stream.Output);
    698 
    699     // 1. Can write a string that exactly fills the buffer.
    700     EXPECT_EQ(5U, Writer.bytesRemaining());
    701     EXPECT_THAT_ERROR(Writer.writeFixedString("abcde"), Succeeded());
    702     EXPECT_EQ(0U, Writer.bytesRemaining());
    703 
    704     // 2. Can write an empty string even when you're full
    705     EXPECT_THAT_ERROR(Writer.writeFixedString(""), Succeeded());
    706     EXPECT_THAT_ERROR(Writer.writeFixedString("a"), Failed());
    707 
    708     // 3. Can't write a string that is one character too long.
    709     Writer.setOffset(0);
    710     EXPECT_THAT_ERROR(Writer.writeFixedString("abcdef"), Failed());
    711   }
    712 }
    713 
    714 TEST_F(BinaryStreamTest, StreamWriterIntegerArrays) {
    715   // 3. Arrays of integers
    716   std::vector<int> SourceInts = {1, 2, 3, 4, 5};
    717   ArrayRef<uint8_t> SourceBytes(reinterpret_cast<uint8_t *>(&SourceInts[0]),
    718                                 SourceInts.size() * sizeof(int));
    719 
    720   initializeInput(SourceBytes, alignof(int));
    721   initializeOutputFromInput(alignof(int));
    722 
    723   for (auto &Stream : Streams) {
    724     BinaryStreamReader Reader(*Stream.Input);
    725     BinaryStreamWriter Writer(*Stream.Output);
    726     ArrayRef<int> Ints;
    727     ArrayRef<int> Ints2;
    728     // First read them, then write them, then read them back.
    729     ASSERT_THAT_ERROR(Reader.readArray(Ints, SourceInts.size()), Succeeded());
    730     ASSERT_THAT_ERROR(Writer.writeArray(Ints), Succeeded());
    731 
    732     BinaryStreamReader ReaderBacker(*Stream.Output);
    733     ASSERT_THAT_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()),
    734                       Succeeded());
    735 
    736     EXPECT_EQ(makeArrayRef(SourceInts), Ints2);
    737   }
    738 }
    739 
    740 TEST_F(BinaryStreamTest, StringWriterStrings) {
    741   StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
    742 
    743   size_t Length = 0;
    744   for (auto S : Strings)
    745     Length += S.size() + 1;
    746   initializeOutput(Length, 1);
    747   initializeInputFromOutput(1);
    748 
    749   for (auto &Stream : Streams) {
    750     BinaryStreamWriter Writer(*Stream.Output);
    751     for (auto S : Strings)
    752       ASSERT_THAT_ERROR(Writer.writeCString(S), Succeeded());
    753     std::vector<StringRef> InStrings;
    754     BinaryStreamReader Reader(*Stream.Input);
    755     while (!Reader.empty()) {
    756       StringRef S;
    757       ASSERT_THAT_ERROR(Reader.readCString(S), Succeeded());
    758       InStrings.push_back(S);
    759     }
    760     EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings));
    761   }
    762 }
    763 
    764 TEST_F(BinaryStreamTest, StreamWriterAppend) {
    765   StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
    766   AppendingBinaryByteStream Stream(support::little);
    767   BinaryStreamWriter Writer(Stream);
    768 
    769   for (auto &Str : Strings) {
    770     EXPECT_THAT_ERROR(Writer.writeCString(Str), Succeeded());
    771   }
    772 
    773   BinaryStreamReader Reader(Stream);
    774   for (auto &Str : Strings) {
    775     StringRef S;
    776     EXPECT_THAT_ERROR(Reader.readCString(S), Succeeded());
    777     EXPECT_EQ(Str, S);
    778   }
    779 }
    780 }
    781 
    782 namespace {
    783 struct BinaryItemStreamObject {
    784   explicit BinaryItemStreamObject(ArrayRef<uint8_t> Bytes) : Bytes(Bytes) {}
    785 
    786   ArrayRef<uint8_t> Bytes;
    787 };
    788 }
    789 
    790 namespace llvm {
    791 template <> struct BinaryItemTraits<BinaryItemStreamObject> {
    792   static size_t length(const BinaryItemStreamObject &Item) {
    793     return Item.Bytes.size();
    794   }
    795 
    796   static ArrayRef<uint8_t> bytes(const BinaryItemStreamObject &Item) {
    797     return Item.Bytes;
    798   }
    799 };
    800 }
    801 
    802 namespace {
    803 
    804 TEST_F(BinaryStreamTest, BinaryItemStream) {
    805   std::vector<BinaryItemStreamObject> Objects;
    806 
    807   struct Foo {
    808     int X;
    809     double Y;
    810   };
    811   std::vector<Foo> Foos = {{1, 1.0}, {2, 2.0}, {3, 3.0}};
    812   BumpPtrAllocator Allocator;
    813   for (const auto &F : Foos) {
    814     uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo),
    815                                                              alignof(Foo)));
    816     MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo));
    817     MutableBinaryByteStream Stream(Buffer, llvm::support::big);
    818     BinaryStreamWriter Writer(Stream);
    819     ASSERT_THAT_ERROR(Writer.writeObject(F), Succeeded());
    820     Objects.push_back(BinaryItemStreamObject(Buffer));
    821   }
    822 
    823   BinaryItemStream<BinaryItemStreamObject> ItemStream(big);
    824   ItemStream.setItems(Objects);
    825   BinaryStreamReader Reader(ItemStream);
    826 
    827   for (const auto &F : Foos) {
    828     const Foo *F2;
    829     ASSERT_THAT_ERROR(Reader.readObject(F2), Succeeded());
    830 
    831     EXPECT_EQ(F.X, F2->X);
    832     EXPECT_DOUBLE_EQ(F.Y, F2->Y);
    833   }
    834 }
    835 
    836 } // end anonymous namespace
    837