[llvm] r296555 - [PDB] Add tests for BinaryStream.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 1 09:34:46 PST 2017


This is re-added in r296643 with the offending test disabled while I
investigate.  It doesn't look like any other tests were causing problems,
but I'm keeping an eye on the bot just in case.

On Wed, Mar 1, 2017 at 9:29 AM Zachary Turner <zturner at google.com> wrote:

> Ahh nvm, looks like you reverted.  No worries
>
> On Wed, Mar 1, 2017 at 9:26 AM Zachary Turner <zturner at google.com> wrote:
>
> I will disable this test for now.
>
> On Wed, Mar 1, 2017 at 9:22 AM Vedant Kumar <vsk at apple.com> wrote:
>
> Hi Zachary,
>
> This test causes a UBSan alignment failure on ToT. Some of our bots rely
> on UBSan for presubmission testing, so I needed to clear them up.
>
> /Users/vk/Desktop/llvm/include/llvm/DebugInfo/MSF/BinaryStreamArray.h:246:12:
> runtime error: reference binding to misaligned address 0x7f925540939a for
> type 'const int', which requires 4 byte alignment
> 0x7f925540939a: note: pointer points here
>  05 00  00 00 01 00 00 00 02 00  00 00 03 00 00 00 00 00  00 00 00 00 00
> 00 00 00  70 98 50 06 01 00
>               ^
> 0  DebugInfoPDBTests                   0x0000000106263cbd
> llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 45
> 1  DebugInfoPDBTests                   0x00000001062628ff
> llvm::sys::RunSignalHandlers() + 159
> 2  DebugInfoPDBTests                   0x0000000106264593
> SignalHandler(int) + 179
> 3  libsystem_platform.dylib            0x0000000107bb3fba _sigtramp + 26
> 4  libsystem_pthread.dylib             0x0000000107bd82c8 _pthread_keys +
> 9720
> 5  libsystem_c.dylib                   0x0000000107947f83 abort + 127
> 6  libclang_rt.ubsan_osx_dynamic.dylib 0x0000000106bb5fc2
> __sanitizer::Abort() + 66
> 7  DebugInfoPDBTests                   0x000000010613f880
> llvm::FixedStreamArrayIterator<int>::operator+=(long) + 0
> 8  DebugInfoPDBTests                   0x000000010613f615
> llvm::FixedStreamArrayIterator<int>::operator*() const + 37
> 9  DebugInfoPDBTests                   0x000000010613f3cb
> std::__1::enable_if<__is_forward_iterator<llvm::FixedStreamArrayIterator<int>
> >::value, void>::type std::__1::vector<int, std::__1::allocator<int>
> >::__construct_at_end<llvm::FixedStreamArrayIterator<int>
> >(llvm::FixedStreamArrayIterator<int>, llvm::FixedStreamArrayIterator<int>,
> unsigned long) + 251
> 10 DebugInfoPDBTests                   0x000000010613f292
> std::__1::vector<int, std::__1::allocator<int>
> >::vector<llvm::FixedStreamArrayIterator<int>
> >(llvm::FixedStreamArrayIterator<int>,
> std::__1::enable_if<(__is_forward_iterator<llvm::FixedStreamArrayIterator<int>
> >::value) && (is_constructible<int,
> std::__1::iterator_traits<llvm::FixedStreamArrayIterator<int>
> >::reference>::value), llvm::FixedStreamArrayIterator<int> >::type) + 226
> 11 DebugInfoPDBTests                   0x000000010613ddb7
> std::__1::vector<int, std::__1::allocator<int>
> >::vector<llvm::FixedStreamArrayIterator<int>
> >(llvm::FixedStreamArrayIterator<int>,
> std::__1::enable_if<(__is_forward_iterator<llvm::FixedStreamArrayIterator<int>
> >::value) && (is_constructible<int,
> std::__1::iterator_traits<llvm::FixedStreamArrayIterator<int>
> >::reference>::value), llvm::FixedStreamArrayIterator<int> >::type) + 87
> 12 DebugInfoPDBTests                   0x000000010613d4af (anonymous
> namespace)::BinaryStreamTest_StreamReaderIntegerArray_Test::TestBody() +
> 1279
> 13 DebugInfoPDBTests                   0x00000001062780f3
> testing::Test::Run() + 179
> 14 DebugInfoPDBTests                   0x0000000106279594
> testing::TestInfo::Run() + 308
> 15 DebugInfoPDBTests                   0x000000010627a6a3
> testing::TestCase::Run() + 307
> 16 DebugInfoPDBTests                   0x00000001062849d4
> testing::internal::UnitTestImpl::RunAllTests() + 756
> 17 DebugInfoPDBTests                   0x0000000106284558
> testing::UnitTest::Run() + 152
> 18 DebugInfoPDBTests                   0x0000000106266fa5 main + 117
> 19 libdyld.dylib                       0x00000001078506a5 start + 1
> zsh: abort      ./unittests/DebugInfo/PDB/DebugInfoPDBTests
>
> vedant
>
>
> > On Feb 28, 2017, at 5:03 PM, Zachary Turner via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
> >
> > Author: zturner
> > Date: Tue Feb 28 19:03:53 2017
> > New Revision: 296555
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=296555&view=rev
> > Log:
> > [PDB] Add tests for BinaryStream.
> >
> > Added:
> >    llvm/trunk/unittests/DebugInfo/PDB/BinaryStreamTest.cpp
> > Modified:
> >    llvm/trunk/unittests/DebugInfo/PDB/CMakeLists.txt
> >
> > Added: llvm/trunk/unittests/DebugInfo/PDB/BinaryStreamTest.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/PDB/BinaryStreamTest.cpp?rev=296555&view=auto
> >
> ==============================================================================
> > --- llvm/trunk/unittests/DebugInfo/PDB/BinaryStreamTest.cpp (added)
> > +++ llvm/trunk/unittests/DebugInfo/PDB/BinaryStreamTest.cpp Tue Feb 28
> 19:03:53 2017
> > @@ -0,0 +1,643 @@
> > +//===- llvm/unittest/Support/BinaryStreamTest.cpp
> -------------------------===//
> > +//
> > +//                     The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open Source
> > +// License. See LICENSE.TXT for details.
> > +//
> >
> +//===----------------------------------------------------------------------===//
> > +
> > +#include "llvm/DebugInfo/MSF/BinaryByteStream.h"
> > +#include "llvm/DebugInfo/MSF/BinaryItemStream.h"
> > +#include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
> > +#include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
> > +#include "llvm/DebugInfo/MSF/BinaryStreamRef.h"
> > +#include "llvm/DebugInfo/MSF/BinaryStreamWriter.h"
> > +#include "gtest/gtest.h"
> > +
> > +#include <unordered_map>
> > +
> > +using namespace llvm;
> > +using namespace llvm::support;
> > +
> > +#define EXPECT_NO_ERROR(Err)
>        \
> > +  {
>         \
> > +    auto E = Err;
>         \
> > +    EXPECT_FALSE(static_cast<bool>(E));
>         \
> > +    if (E)
>        \
> > +      consumeError(std::move(E));
>         \
> > +  }
> > +
> > +#define ASSERT_NO_ERROR(Err)
>        \
> > +  {
>         \
> > +    auto E = Err;
>         \
> > +    ASSERT_FALSE(static_cast<bool>(E));
>         \
> > +    if (E)
>        \
> > +      consumeError(std::move(E));
>         \
> > +  }
> > +
> > +#define EXPECT_ERROR(Err)
>         \
> > +  {
>         \
> > +    auto E = Err;
>         \
> > +    EXPECT_TRUE(static_cast<bool>(E));
>        \
> > +    if (E)
>        \
> > +      consumeError(std::move(E));
>         \
> > +  }
> > +
> > +namespace {
> > +
> > +class DiscontiguousStream : public WritableBinaryStream {
> > +public:
> > +  DiscontiguousStream(MutableArrayRef<uint8_t> Data, endianness Endian)
> > +      : Data(Data), PartitionIndex(Data.size() / 2), Endian(Endian) {}
> > +
> > +  endianness getEndian() const override { return Endian; }
> > +
> > +  Error readBytes(uint32_t Offset, uint32_t Size,
> > +                  ArrayRef<uint8_t> &Buffer) override {
> > +    if (Offset + Size > Data.size())
> > +      return
> errorCodeToError(make_error_code(std::errc::no_buffer_space));
> > +    uint32_t S = startIndex(Offset);
> > +    auto Ref = Data.drop_front(S);
> > +    if (Ref.size() >= Size) {
> > +      Buffer = Ref.take_front(Size);
> > +      return Error::success();
> > +    }
> > +
> > +    uint32_t BytesLeft = Size - Ref.size();
> > +    uint8_t *Ptr = Allocator.Allocate<uint8_t>(Size);
> > +    ::memcpy(Ptr, Ref.data(), Ref.size());
> > +    ::memcpy(Ptr + Ref.size(), Data.data(), BytesLeft);
> > +    Buffer = makeArrayRef<uint8_t>(Ptr, Size);
> > +    return Error::success();
> > +  }
> > +
> > +  Error readLongestContiguousChunk(uint32_t Offset,
> > +                                   ArrayRef<uint8_t> &Buffer) override {
> > +    if (Offset >= Data.size())
> > +      return
> errorCodeToError(make_error_code(std::errc::no_buffer_space));
> > +    uint32_t S = startIndex(Offset);
> > +    Buffer = Data.drop_front(S);
> > +    return Error::success();
> > +  }
> > +
> > +  uint32_t getLength() override { return Data.size(); }
> > +
> > +  Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> SrcData) override
> {
> > +    if (Offset + SrcData.size() > Data.size())
> > +      return
> errorCodeToError(make_error_code(std::errc::no_buffer_space));
> > +    if (SrcData.empty())
> > +      return Error::success();
> > +
> > +    uint32_t S = startIndex(Offset);
> > +    MutableArrayRef<uint8_t> Ref(Data);
> > +    Ref = Ref.drop_front(S);
> > +    if (Ref.size() >= SrcData.size()) {
> > +      ::memcpy(Ref.data(), SrcData.data(), SrcData.size());
> > +      return Error::success();
> > +    }
> > +
> > +    uint32_t BytesLeft = SrcData.size() - Ref.size();
> > +    ::memcpy(Ref.data(), SrcData.data(), Ref.size());
> > +    ::memcpy(&Data[0], SrcData.data() + Ref.size(), BytesLeft);
> > +    return Error::success();
> > +  }
> > +  Error commit() override { return Error::success(); }
> > +
> > +private:
> > +  uint32_t startIndex(uint32_t Offset) const {
> > +    return (Offset + PartitionIndex) % Data.size();
> > +  }
> > +
> > +  uint32_t endIndex(uint32_t Offset, uint32_t Size) const {
> > +    return (startIndex(Offset) + Size - 1) % Data.size();
> > +  }
> > +
> > +  // Buffer is organized like this:
> > +  // -------------------------------------------------
> > +  // | N/2 | N/2+1 | ... | N-1 | 0 | 1 | ... | N-2-1 |
> > +  // -------------------------------------------------
> > +  // So reads from the beginning actually come from the middle.
> > +  MutableArrayRef<uint8_t> Data;
> > +  uint32_t PartitionIndex = 0;
> > +  endianness Endian;
> > +  BumpPtrAllocator Allocator;
> > +};
> > +
> > +class BinaryStreamTest : public testing::Test {
> > +  static constexpr endianness Endians[] = {big, little, native};
> > +  static constexpr uint32_t NumEndians = llvm::array_lengthof(Endians);
> > +  static constexpr uint32_t NumStreams = 2 * NumEndians;
> > +
> > +public:
> > +  BinaryStreamTest() {}
> > +
> > +  void SetUp() override {
> > +    Streams.clear();
> > +    Streams.resize(NumStreams);
> > +    InputData.clear();
> > +    OutputData.clear();
> > +  }
> > +
> > +protected:
> > +  struct StreamPair {
> > +    std::unique_ptr<BinaryStream> Input;
> > +    std::unique_ptr<WritableBinaryStream> Output;
> > +  };
> > +
> > +  void initializeInput(ArrayRef<uint8_t> Input) {
> > +    InputData = Input;
> > +
> > +    BrokenInputData.resize(InputData.size());
> > +    if (!Input.empty()) {
> > +      uint32_t PartitionIndex = InputData.size() / 2;
> > +      uint32_t RightBytes = InputData.size() - PartitionIndex;
> > +      uint32_t LeftBytes = PartitionIndex;
> > +      if (RightBytes > 0)
> > +        ::memcpy(&BrokenInputData[PartitionIndex], Input.data(),
> RightBytes);
> > +      if (LeftBytes > 0)
> > +        ::memcpy(&BrokenInputData[0], Input.data() + RightBytes,
> LeftBytes);
> > +    }
> > +
> > +    for (uint32_t I = 0; I < NumEndians; ++I) {
> > +      auto InByteStream =
> > +          llvm::make_unique<BinaryByteStream>(InputData, Endians[I]);
> > +      auto InBrokenStream =
> > +          llvm::make_unique<DiscontiguousStream>(BrokenInputData,
> Endians[I]);
> > +
> > +      Streams[I * 2].Input = std::move(InByteStream);
> > +      Streams[I * 2 + 1].Input = std::move(InBrokenStream);
> > +    }
> > +  }
> > +
> > +  void initializeOutput(uint32_t Size) {
> > +    OutputData.resize(Size);
> > +    BrokenOutputData.resize(Size);
> > +
> > +    for (uint32_t I = 0; I < NumEndians; ++I) {
> > +      Streams[I * 2].Output =
> > +          llvm::make_unique<MutableBinaryByteStream>(OutputData,
> Endians[I]);
> > +      Streams[I * 2 + 1].Output =
> > +          llvm::make_unique<DiscontiguousStream>(BrokenOutputData,
> Endians[I]);
> > +    }
> > +  }
> > +
> > +  void initializeOutputFromInput() {
> > +    for (uint32_t I = 0; I < NumEndians; ++I) {
> > +      Streams[I * 2].Output =
> > +          llvm::make_unique<MutableBinaryByteStream>(InputData,
> Endians[I]);
> > +      Streams[I * 2 + 1].Output =
> > +          llvm::make_unique<DiscontiguousStream>(BrokenInputData,
> Endians[I]);
> > +    }
> > +  }
> > +
> > +  void initializeInputFromOutput() {
> > +    for (uint32_t I = 0; I < NumEndians; ++I) {
> > +      Streams[I * 2].Input =
> > +          llvm::make_unique<BinaryByteStream>(OutputData, Endians[I]);
> > +      Streams[I * 2 + 1].Input =
> > +          llvm::make_unique<DiscontiguousStream>(BrokenOutputData,
> Endians[I]);
> > +    }
> > +  }
> > +
> > +  std::vector<uint8_t> InputData;
> > +  std::vector<uint8_t> BrokenInputData;
> > +
> > +  std::vector<uint8_t> OutputData;
> > +  std::vector<uint8_t> BrokenOutputData;
> > +
> > +  std::vector<StreamPair> Streams;
> > +};
> > +
> > +// Tests that a we can read from a BinaryByteStream without a
> StreamReader.
> > +TEST_F(BinaryStreamTest, BinaryByteStreamProperties) {
> > +  std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
> > +  initializeInput(InputData);
> > +
> > +  for (auto &Stream : Streams) {
> > +    ArrayRef<uint8_t> Buffer;
> > +
> > +    // 1. If the read fits it should work.
> > +    ASSERT_EQ(InputData.size(), Stream.Input->getLength());
> > +    ASSERT_NO_ERROR(Stream.Input->readBytes(2, 1, Buffer));
> > +    EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
> > +    ASSERT_NO_ERROR(Stream.Input->readBytes(0, 4, Buffer));
> > +    EXPECT_EQ(makeArrayRef(InputData).slice(0, 4), Buffer);
> > +
> > +    // 2. Reading past the bounds of the input should fail.
> > +    EXPECT_ERROR(Stream.Input->readBytes(4, 2, Buffer));
> > +  }
> > +}
> > +
> > +// Test that we can write to a BinaryStream without a StreamWriter.
> > +TEST_F(BinaryStreamTest, MutableBinaryByteStreamProperties) {
> > +  std::vector<uint8_t> InputData = {'T', 'e', 's', 't', '\0'};
> > +  initializeInput(InputData);
> > +  initializeOutput(InputData.size());
> > +
> > +  // For every combination of input stream and output stream.
> > +  for (auto &Stream : Streams) {
> > +    MutableArrayRef<uint8_t> Buffer;
> > +    ASSERT_EQ(InputData.size(), Stream.Input->getLength());
> > +
> > +    // 1. Try two reads that are supposed to work.  One from offset 0,
> and one
> > +    // from the middle.
> > +    uint32_t Offsets[] = {0, 3};
> > +    for (auto Offset : Offsets) {
> > +      uint32_t ExpectedSize = Stream.Input->getLength() - Offset;
> > +
> > +      // Read everything from Offset until the end of the input data.
> > +      ArrayRef<uint8_t> Data;
> > +      ASSERT_NO_ERROR(Stream.Input->readBytes(Offset, ExpectedSize,
> Data));
> > +      ASSERT_EQ(ExpectedSize, Data.size());
> > +
> > +      // Then write it to the destination.
> > +      ASSERT_NO_ERROR(Stream.Output->writeBytes(0, Data));
> > +
> > +      // Then we read back what we wrote, it should match the
> corresponding
> > +      // slice of the original input data.
> > +      ArrayRef<uint8_t> Data2;
> > +      ASSERT_NO_ERROR(Stream.Output->readBytes(Offset, ExpectedSize,
> Data2));
> > +      EXPECT_EQ(makeArrayRef(InputData).drop_front(Offset), Data2);
> > +    }
> > +
> > +    std::vector<uint8_t> BigData = {0, 1, 2, 3, 4};
> > +    // 2. If the write is too big, it should fail.
> > +    EXPECT_ERROR(Stream.Output->writeBytes(3, BigData));
> > +  }
> > +}
> > +
> > +// Test that FixedStreamArray works correctly.
> > +TEST_F(BinaryStreamTest, FixedStreamArray) {
> > +  std::vector<uint32_t> Ints = {90823, 12908, 109823, 209823};
> > +  ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(Ints.data()),
> > +                             Ints.size() * sizeof(uint32_t));
> > +
> > +  initializeInput(IntBytes);
> > +
> > +  for (auto &Stream : Streams) {
> > +    MutableArrayRef<uint8_t> Buffer;
> > +    ASSERT_EQ(InputData.size(), Stream.Input->getLength());
> > +
> > +    FixedStreamArray<uint32_t> Array(*Stream.Input);
> > +    auto Iter = Array.begin();
> > +    ASSERT_EQ(Ints[0], *Iter++);
> > +    ASSERT_EQ(Ints[1], *Iter++);
> > +    ASSERT_EQ(Ints[2], *Iter++);
> > +    ASSERT_EQ(Ints[3], *Iter++);
> > +    ASSERT_EQ(Array.end(), Iter);
> > +  }
> > +}
> > +
> > +// Test that VarStreamArray works correctly.
> > +TEST_F(BinaryStreamTest, VarStreamArray) {
> > +  StringLiteral Strings("1. Test2. Longer Test3. Really Long Test4.
> Super "
> > +                        "Extra Longest Test Of All");
> > +  ArrayRef<uint8_t> StringBytes(
> > +      reinterpret_cast<const uint8_t *>(Strings.data()),
> Strings.size());
> > +  initializeInput(StringBytes);
> > +
> > +  struct StringExtractor {
> > +  public:
> > +    Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef
> &Item) {
> > +      if (Index == 0)
> > +        Len = strlen("1. Test");
> > +      else if (Index == 1)
> > +        Len = strlen("2. Longer Test");
> > +      else if (Index == 2)
> > +        Len = strlen("3. Really Long Test");
> > +      else
> > +        Len = strlen("4. Super Extra Longest Test Of All");
> > +      ArrayRef<uint8_t> Bytes;
> > +      if (auto EC = Stream.readBytes(0, Len, Bytes))
> > +        return EC;
> > +      Item =
> > +          StringRef(reinterpret_cast<const char *>(Bytes.data()),
> Bytes.size());
> > +      ++Index;
> > +      return Error::success();
> > +    }
> > +
> > +  private:
> > +    uint32_t Index = 0;
> > +  };
> > +
> > +  for (auto &Stream : Streams) {
> > +    VarStreamArray<StringRef, StringExtractor> Array(*Stream.Input);
> > +    auto Iter = Array.begin();
> > +    ASSERT_EQ("1. Test", *Iter++);
> > +    ASSERT_EQ("2. Longer Test", *Iter++);
> > +    ASSERT_EQ("3. Really Long Test", *Iter++);
> > +    ASSERT_EQ("4. Super Extra Longest Test Of All", *Iter++);
> > +    ASSERT_EQ(Array.end(), Iter);
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StreamReaderBounds) {
> > +  std::vector<uint8_t> Bytes;
> > +
> > +  initializeInput(Bytes);
> > +  for (auto &Stream : Streams) {
> > +    StringRef S;
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +    EXPECT_EQ(0U, Reader.bytesRemaining());
> > +    EXPECT_ERROR(Reader.readFixedString(S, 1));
> > +  }
> > +
> > +  Bytes.resize(5);
> > +  initializeInput(Bytes);
> > +  for (auto &Stream : Streams) {
> > +    StringRef S;
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +    EXPECT_EQ(Bytes.size(), Reader.bytesRemaining());
> > +    EXPECT_NO_ERROR(Reader.readFixedString(S, 5));
> > +    EXPECT_ERROR(Reader.readFixedString(S, 6));
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StreamReaderIntegers) {
> > +  support::ulittle64_t Little{908234};
> > +  support::ubig32_t Big{28907823};
> > +  short NS = 2897;
> > +  int NI = -89723;
> > +  unsigned long NUL = 902309023UL;
> > +  constexpr uint32_t Size =
> > +      sizeof(Little) + sizeof(Big) + sizeof(NS) + sizeof(NI) +
> sizeof(NUL);
> > +
> > +  initializeOutput(Size);
> > +  initializeInputFromOutput();
> > +
> > +  for (auto &Stream : Streams) {
> > +    BinaryStreamWriter Writer(*Stream.Output);
> > +    ASSERT_NO_ERROR(Writer.writeObject(Little));
> > +    ASSERT_NO_ERROR(Writer.writeObject(Big));
> > +    ASSERT_NO_ERROR(Writer.writeInteger(NS));
> > +    ASSERT_NO_ERROR(Writer.writeInteger(NI));
> > +    ASSERT_NO_ERROR(Writer.writeInteger(NUL));
> > +
> > +    const support::ulittle64_t *Little2;
> > +    const support::ubig32_t *Big2;
> > +    short NS2;
> > +    int NI2;
> > +    unsigned long NUL2;
> > +
> > +    // 1. Reading fields individually.
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +    ASSERT_NO_ERROR(Reader.readObject(Little2));
> > +    ASSERT_NO_ERROR(Reader.readObject(Big2));
> > +    ASSERT_NO_ERROR(Reader.readInteger(NS2));
> > +    ASSERT_NO_ERROR(Reader.readInteger(NI2));
> > +    ASSERT_NO_ERROR(Reader.readInteger(NUL2));
> > +    ASSERT_EQ(0U, Reader.bytesRemaining());
> > +
> > +    EXPECT_EQ(Little, *Little2);
> > +    EXPECT_EQ(Big, *Big2);
> > +    EXPECT_EQ(NS, NS2);
> > +    EXPECT_EQ(NI, NI2);
> > +    EXPECT_EQ(NUL, NUL2);
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StreamReaderIntegerArray) {
> > +  // 1. Arrays of integers
> > +  std::vector<int> Ints = {1, 2, 3, 4, 5};
> > +  ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(&Ints[0]),
> > +                             Ints.size() * sizeof(int));
> > +
> > +  initializeInput(IntBytes);
> > +  for (auto &Stream : Streams) {
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +    ArrayRef<int> IntsRef;
> > +    ASSERT_NO_ERROR(Reader.readArray(IntsRef, Ints.size()));
> > +    ASSERT_EQ(0U, Reader.bytesRemaining());
> > +    EXPECT_EQ(makeArrayRef(Ints), IntsRef);
> > +
> > +    Reader.setOffset(0);
> > +    FixedStreamArray<int> FixedIntsRef;
> > +    ASSERT_NO_ERROR(Reader.readArray(FixedIntsRef, Ints.size()));
> > +    ASSERT_EQ(0U, Reader.bytesRemaining());
> > +    ASSERT_EQ(Ints, std::vector<int>(FixedIntsRef.begin(),
> FixedIntsRef.end()));
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StreamReaderEnum) {
> > +  enum class MyEnum : int64_t { Foo = -10, Bar = 0, Baz = 10 };
> > +
> > +  std::vector<MyEnum> Enums = {MyEnum::Bar, MyEnum::Baz, MyEnum::Foo};
> > +
> > +  initializeOutput(Enums.size() * sizeof(MyEnum));
> > +  initializeInputFromOutput();
> > +  for (auto &Stream : Streams) {
> > +    BinaryStreamWriter Writer(*Stream.Output);
> > +    for (auto Value : Enums)
> > +      ASSERT_NO_ERROR(Writer.writeEnum(Value));
> > +
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +
> > +    ArrayRef<MyEnum> Array;
> > +    FixedStreamArray<MyEnum> FSA;
> > +
> > +    for (size_t I = 0; I < Enums.size(); ++I) {
> > +      MyEnum Value;
> > +      ASSERT_NO_ERROR(Reader.readEnum(Value));
> > +      EXPECT_EQ(Enums[I], Value);
> > +    }
> > +    ASSERT_EQ(0U, Reader.bytesRemaining());
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StreamReaderObject) {
> > +  struct Foo {
> > +    int X;
> > +    double Y;
> > +    char Z;
> > +  };
> > +
> > +  std::vector<Foo> Foos;
> > +  Foos.push_back({-42, 42.42, 42});
> > +  Foos.push_back({100, 3.1415, static_cast<char>(-89)});
> > +
> > +  const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]);
> > +
> > +  initializeInput(makeArrayRef(Bytes, 2 * sizeof(Foo)));
> > +
> > +  for (auto &Stream : Streams) {
> > +    // 1. Reading object pointers.
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +    const Foo *FPtrOut = nullptr;
> > +    const Foo *GPtrOut = nullptr;
> > +    ASSERT_NO_ERROR(Reader.readObject(FPtrOut));
> > +    ASSERT_NO_ERROR(Reader.readObject(GPtrOut));
> > +    EXPECT_EQ(0U, Reader.bytesRemaining());
> > +    EXPECT_EQ(0, ::memcmp(&Foos[0], FPtrOut, sizeof(Foo)));
> > +    EXPECT_EQ(0, ::memcmp(&Foos[1], GPtrOut, sizeof(Foo)));
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StreamReaderStrings) {
> > +  std::vector<uint8_t> Bytes = {'O',  'n', 'e', '\0', 'T', 'w', 'o',
> > +                                '\0', 'T', 'h', 'r',  'e', 'e', '\0',
> > +                                'F',  'o', 'u', 'r',  '\0'};
> > +  initializeInput(Bytes);
> > +
> > +  for (auto &Stream : Streams) {
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +
> > +    StringRef S1;
> > +    StringRef S2;
> > +    StringRef S3;
> > +    StringRef S4;
> > +    ASSERT_NO_ERROR(Reader.readCString(S1));
> > +    ASSERT_NO_ERROR(Reader.readCString(S2));
> > +    ASSERT_NO_ERROR(Reader.readCString(S3));
> > +    ASSERT_NO_ERROR(Reader.readCString(S4));
> > +    ASSERT_EQ(0U, Reader.bytesRemaining());
> > +
> > +    EXPECT_EQ("One", S1);
> > +    EXPECT_EQ("Two", S2);
> > +    EXPECT_EQ("Three", S3);
> > +    EXPECT_EQ("Four", S4);
> > +
> > +    S1 = S2 = S3 = S4 = "";
> > +    Reader.setOffset(0);
> > +    ASSERT_NO_ERROR(Reader.readFixedString(S1, 3));
> > +    ASSERT_NO_ERROR(Reader.skip(1));
> > +    ASSERT_NO_ERROR(Reader.readFixedString(S2, 3));
> > +    ASSERT_NO_ERROR(Reader.skip(1));
> > +    ASSERT_NO_ERROR(Reader.readFixedString(S3, 5));
> > +    ASSERT_NO_ERROR(Reader.skip(1));
> > +    ASSERT_NO_ERROR(Reader.readFixedString(S4, 4));
> > +    ASSERT_NO_ERROR(Reader.skip(1));
> > +    ASSERT_EQ(0U, Reader.bytesRemaining());
> > +
> > +    EXPECT_EQ("One", S1);
> > +    EXPECT_EQ("Two", S2);
> > +    EXPECT_EQ("Three", S3);
> > +    EXPECT_EQ("Four", S4);
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StreamWriterBounds) {
> > +  initializeOutput(5);
> > +
> > +  for (auto &Stream : Streams) {
> > +    BinaryStreamWriter Writer(*Stream.Output);
> > +
> > +    // 1. Can write a string that exactly fills the buffer.
> > +    EXPECT_EQ(5U, Writer.bytesRemaining());
> > +    EXPECT_NO_ERROR(Writer.writeFixedString("abcde"));
> > +    EXPECT_EQ(0U, Writer.bytesRemaining());
> > +
> > +    // 2. Can write an empty string even when you're full
> > +    EXPECT_NO_ERROR(Writer.writeFixedString(""));
> > +    EXPECT_ERROR(Writer.writeFixedString("a"));
> > +
> > +    // 3. Can't write a string that is one character too long.
> > +    Writer.setOffset(0);
> > +    EXPECT_ERROR(Writer.writeFixedString("abcdef"));
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StreamWriterIntegerArrays) {
> > +  // 3. Arrays of integers
> > +  std::vector<int> SourceInts = {1, 2, 3, 4, 5};
> > +  ArrayRef<uint8_t> SourceBytes(reinterpret_cast<uint8_t
> *>(&SourceInts[0]),
> > +                                SourceInts.size() * sizeof(int));
> > +
> > +  initializeInput(SourceBytes);
> > +  initializeOutputFromInput();
> > +
> > +  for (auto &Stream : Streams) {
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +    BinaryStreamWriter Writer(*Stream.Output);
> > +    ArrayRef<int> Ints;
> > +    ArrayRef<int> Ints2;
> > +    // First read them, then write them, then read them back.
> > +    ASSERT_NO_ERROR(Reader.readArray(Ints, SourceInts.size()));
> > +    ASSERT_NO_ERROR(Writer.writeArray(Ints));
> > +
> > +    BinaryStreamReader ReaderBacker(*Stream.Output);
> > +    ASSERT_NO_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()));
> > +
> > +    EXPECT_EQ(makeArrayRef(SourceInts), Ints2);
> > +  }
> > +}
> > +
> > +TEST_F(BinaryStreamTest, StringWriterStrings) {
> > +  StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
> > +
> > +  size_t Length = 0;
> > +  for (auto S : Strings)
> > +    Length += S.size() + 1;
> > +  initializeOutput(Length);
> > +  initializeInputFromOutput();
> > +
> > +  for (auto &Stream : Streams) {
> > +    BinaryStreamWriter Writer(*Stream.Output);
> > +    for (auto S : Strings)
> > +      ASSERT_NO_ERROR(Writer.writeCString(S));
> > +    std::vector<StringRef> InStrings;
> > +    BinaryStreamReader Reader(*Stream.Input);
> > +    while (!Reader.empty()) {
> > +      StringRef S;
> > +      ASSERT_NO_ERROR(Reader.readCString(S));
> > +      InStrings.push_back(S);
> > +    }
> > +    EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings));
> > +  }
> > +}
> > +}
> > +
> > +namespace {
> > +struct BinaryItemStreamObject {
> > +  explicit BinaryItemStreamObject(ArrayRef<uint8_t> Bytes) :
> Bytes(Bytes) {}
> > +
> > +  ArrayRef<uint8_t> Bytes;
> > +};
> > +}
> > +
> > +namespace llvm {
> > +template <> struct BinaryItemTraits<BinaryItemStreamObject> {
> > +  static size_t length(const BinaryItemStreamObject &Item) {
> > +    return Item.Bytes.size();
> > +  }
> > +
> > +  static ArrayRef<uint8_t> bytes(const BinaryItemStreamObject &Item) {
> > +    return Item.Bytes;
> > +  }
> > +};
> > +}
> > +
> > +namespace {
> > +
> > +TEST_F(BinaryStreamTest, BinaryItemStream) {
> > +  std::vector<BinaryItemStreamObject> Objects;
> > +
> > +  struct Foo {
> > +    int X;
> > +    double Y;
> > +  };
> > +  std::vector<Foo> Foos = {{1, 1.0}, {2, 2.0}, {3, 3.0}};
> > +  BumpPtrAllocator Allocator;
> > +  for (const auto &F : Foos) {
> > +    uint8_t *Ptr = Allocator.Allocate<uint8_t>(sizeof(Foo));
> > +    MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo));
> > +    MutableBinaryByteStream Stream(Buffer, llvm::support::big);
> > +    BinaryStreamWriter Writer(Stream);
> > +    ASSERT_NO_ERROR(Writer.writeObject(F));
> > +    Objects.push_back(BinaryItemStreamObject(Buffer));
> > +  }
> > +
> > +  BinaryItemStream<BinaryItemStreamObject> ItemStream(big);
> > +  ItemStream.setItems(Objects);
> > +  BinaryStreamReader Reader(ItemStream);
> > +
> > +  for (const auto &F : Foos) {
> > +    const Foo *F2;
> > +    ASSERT_NO_ERROR(Reader.readObject(F2));
> > +
> > +    EXPECT_EQ(F.X, F2->X);
> > +    EXPECT_DOUBLE_EQ(F.Y, F2->Y);
> > +  }
> > +}
> > +
> > +} // end anonymous namespace
> >
> > Modified: llvm/trunk/unittests/DebugInfo/PDB/CMakeLists.txt
> > URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/PDB/CMakeLists.txt?rev=296555&r1=296554&r2=296555&view=diff
> >
> ==============================================================================
> > --- llvm/trunk/unittests/DebugInfo/PDB/CMakeLists.txt (original)
> > +++ llvm/trunk/unittests/DebugInfo/PDB/CMakeLists.txt Tue Feb 28
> 19:03:53 2017
> > @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
> >   )
> >
> > set(DebugInfoPDBSources
> > +  BinaryStreamTest.cpp
> >   HashTableTest.cpp
> >   MappedBlockStreamTest.cpp
> >   StringTableBuilderTest.cpp
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170301/252f05e7/attachment-0001.html>


More information about the llvm-commits mailing list