summaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-05-31 22:41:52 +0000
committerZachary Turner <zturner@google.com>2016-05-31 22:41:52 +0000
commite781066bc293cef5f6453995a8d1de4e684cf697 (patch)
treec638e903481d81ff3f3b42f4ed5212845a9ad609 /unittests
parent1cd242fe11b7851fd1a3e8f39ca36f04719dede6 (diff)
[pdb] Add unit tests for PDB MappedBlockStream and zero copy
Differential Revision: http://reviews.llvm.org/D20837 Reviewed By: ruiu git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271346 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests')
-rw-r--r--unittests/DebugInfo/PDB/CMakeLists.txt1
-rw-r--r--unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp161
2 files changed, 162 insertions, 0 deletions
diff --git a/unittests/DebugInfo/PDB/CMakeLists.txt b/unittests/DebugInfo/PDB/CMakeLists.txt
index 91924a5a875..4cc7b0d1a80 100644
--- a/unittests/DebugInfo/PDB/CMakeLists.txt
+++ b/unittests/DebugInfo/PDB/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS
)
set(DebugInfoPDBSources
+ MappedBlockStreamTest.cpp
PDBApiTest.cpp
)
diff --git a/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp b/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
new file mode 100644
index 00000000000..b98a3c81ed6
--- /dev/null
+++ b/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
@@ -0,0 +1,161 @@
+//===- 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/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 = std::move(Err); \
+ EXPECT_FALSE(static_cast<bool>(E)); \
+ if (E) \
+ consumeError(std::move(E)); \
+ }
+
+#define EXPECT_ERROR(Err) \
+ { \
+ auto E = std::move(Err); \
+ EXPECT_TRUE(static_cast<bool>(E)); \
+ if (E) \
+ consumeError(std::move(E)); \
+ }
+
+class DiscontiguousFile : public IPDBFile {
+public:
+ DiscontiguousFile()
+ : Blocks{0, 1, 2, 5, 4, 3, 6, 7, 8, 9},
+ Data{'A', 'B', 'C', 'F', 'E', 'D', 'G', 'H', 'I', 'J'} {}
+
+ 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<uint32_t>
+ getStreamBlockList(uint32_t StreamIndex) const override {
+ if (StreamIndex != 0)
+ return ArrayRef<uint32_t>();
+ return Blocks;
+ }
+ virtual StringRef getBlockData(uint32_t BlockIndex,
+ uint32_t NumBytes) const override {
+ return StringRef(&Data[BlockIndex], NumBytes);
+ }
+
+private:
+ std::vector<uint32_t> Blocks;
+ std::vector<char> Data;
+};
+
+// Tests that a read which is entirely contained within a single block works
+// and does not allocate.
+TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
+ DiscontiguousFile F;
+ MappedBlockStream S(0, F);
+ StreamReader R(S);
+ StringRef Str;
+ EXPECT_NO_ERROR(R.readFixedString(Str, 1));
+ EXPECT_EQ(Str, StringRef("A"));
+ EXPECT_EQ(0, S.getNumBytesCopied());
+}
+
+// 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;
+ MappedBlockStream S(0, F);
+ StreamReader R(S);
+ StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
+ EXPECT_NO_ERROR(R.readFixedString(Str, 1));
+ EXPECT_EQ(Str, StringRef("A"));
+ EXPECT_EQ(0, 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;
+ MappedBlockStream S(0, F);
+ StreamReader R(S);
+ StringRef Str;
+ EXPECT_NO_ERROR(R.readFixedString(Str, 2));
+ EXPECT_EQ(Str, StringRef("AB"));
+ EXPECT_EQ(0, S.getNumBytesCopied());
+
+ R.setOffset(6);
+ EXPECT_NO_ERROR(R.readFixedString(Str, 4));
+ EXPECT_EQ(Str, StringRef("GHIJ"));
+ EXPECT_EQ(0, 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;
+ MappedBlockStream S(0, F);
+ StreamReader R(S);
+ StringRef Str;
+ EXPECT_NO_ERROR(R.readFixedString(Str, 10));
+ EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
+ EXPECT_EQ(10, 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;
+ MappedBlockStream S(0, F);
+ StreamReader R(S);
+ StringRef Str;
+
+ R.setOffset(10);
+ EXPECT_ERROR(R.readFixedString(Str, 1));
+ EXPECT_EQ(0, 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;
+ MappedBlockStream S(0, F);
+ StreamReader R(S);
+ StringRef Str;
+
+ R.setOffset(6);
+ EXPECT_ERROR(R.readFixedString(Str, 5));
+ EXPECT_EQ(0, 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;
+ MappedBlockStream S(0, F);
+ StreamReader R(S);
+ StringRef Str;
+
+ EXPECT_ERROR(R.readFixedString(Str, 11));
+ EXPECT_EQ(0, S.getNumBytesCopied());
+}
+
+} // end anonymous namespace