llvm-mirror/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
Zachary Turner 0a756c9656 [pdb] Fix build errors in PDB unit tests.
llvm-svn: 272174
2016-06-08 17:32:25 +00:00

189 lines
6.8 KiB
C++

//===- llvm/unittest/DebugInfo/PDB/MappedBlockStreamTest.cpp --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <unordered_map>
#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/PDB/Raw/IPDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
namespace {
#define EXPECT_NO_ERROR(Err) \
{ \
auto E = Err; \
EXPECT_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)); \
}
static const uint32_t BlocksAry[] = {0, 1, 2, 5, 4, 3, 6, 7, 8, 9};
static const char DataAry[] = {'A', 'B', 'C', 'F', 'E',
'D', 'G', 'H', 'I', 'J'};
class DiscontiguousFile : public IPDBFile {
public:
DiscontiguousFile()
: Blocks(std::begin(BlocksAry), std::end(BlocksAry)),
Data(std::begin(DataAry), std::end(DataAry)) {}
virtual uint32_t getBlockSize() const override { return 1; }
virtual uint32_t getBlockCount() const override { return 10; }
virtual uint32_t getNumStreams() const override { return 1; }
virtual uint32_t getStreamByteSize(uint32_t StreamIndex) const override {
return getBlockCount() * getBlockSize();
}
virtual ArrayRef<support::ulittle32_t>
getStreamBlockList(uint32_t StreamIndex) const override {
if (StreamIndex != 0)
return ArrayRef<support::ulittle32_t>();
return Blocks;
}
virtual ArrayRef<uint8_t> getBlockData(uint32_t BlockIndex,
uint32_t NumBytes) const override {
return ArrayRef<uint8_t>(&Data[BlockIndex], NumBytes);
}
private:
std::vector<support::ulittle32_t> Blocks;
std::vector<uint8_t> Data;
};
class MappedBlockStreamImpl : public MappedBlockStream {
public:
MappedBlockStreamImpl(std::unique_ptr<IPDBStreamData> Data,
const IPDBFile &File)
: MappedBlockStream(std::move(Data), File) {}
};
// Tests that a read which is entirely contained within a single block works
// and does not allocate.
TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
DiscontiguousFile F;
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
StreamRef SR;
EXPECT_NO_ERROR(R.readStreamRef(SR, 0U));
ArrayRef<uint8_t> Buffer;
EXPECT_ERROR(SR.readBytes(0U, 1U, Buffer));
EXPECT_NO_ERROR(R.readStreamRef(SR, 1U));
EXPECT_ERROR(SR.readBytes(1U, 1U, Buffer));
}
// Tests that a read which outputs into a full destination buffer works and
// does not fail due to the length of the output buffer.
TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
DiscontiguousFile F;
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
EXPECT_EQ(Str, StringRef("A"));
EXPECT_EQ(0U, S.getNumBytesCopied());
}
// Tests that a read which crosses a block boundary, but where the subsequent
// blocks are still contiguous in memory to the previous block works and does
// not allocate memory.
TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
DiscontiguousFile F;
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
StringRef Str;
EXPECT_NO_ERROR(R.readFixedString(Str, 2));
EXPECT_EQ(Str, StringRef("AB"));
EXPECT_EQ(0U, S.getNumBytesCopied());
R.setOffset(6);
EXPECT_NO_ERROR(R.readFixedString(Str, 4));
EXPECT_EQ(Str, StringRef("GHIJ"));
EXPECT_EQ(0U, S.getNumBytesCopied());
}
// Tests that a read which crosses a block boundary and cannot be referenced
// contiguously works and allocates only the precise amount of bytes
// requested.
TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
DiscontiguousFile F;
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
StringRef Str;
EXPECT_NO_ERROR(R.readFixedString(Str, 10));
EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
EXPECT_EQ(10U, S.getNumBytesCopied());
}
// Test that an out of bounds read which doesn't cross a block boundary
// fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
DiscontiguousFile F;
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
StringRef Str;
R.setOffset(10);
EXPECT_ERROR(R.readFixedString(Str, 1));
EXPECT_EQ(0U, S.getNumBytesCopied());
}
// Test that an out of bounds read which crosses a contiguous block boundary
// fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
DiscontiguousFile F;
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
StringRef Str;
R.setOffset(6);
EXPECT_ERROR(R.readFixedString(Str, 5));
EXPECT_EQ(0U, S.getNumBytesCopied());
}
// Test that an out of bounds read which crosses a discontiguous block
// boundary fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
DiscontiguousFile F;
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
StringRef Str;
EXPECT_ERROR(R.readFixedString(Str, 11));
EXPECT_EQ(0U, S.getNumBytesCopied());
}
// Tests that a read which is entirely contained within a single block but
// beyond the end of a StreamRef fails.
TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
DiscontiguousFile F;
MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
StreamReader R(S);
StringRef Str;
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
EXPECT_EQ(Str, StringRef("A"));
EXPECT_EQ(0U, S.getNumBytesCopied());
}
} // end anonymous namespace