blob: e33490c237ecb62b6091a3b90e99ff205a8dfdbb [file] [log] [blame]
Zachary Turner90b8b8d2016-05-31 22:41:52 +00001//===- llvm/unittest/DebugInfo/PDB/MappedBlockStreamTest.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 <unordered_map>
11
12#include "llvm/DebugInfo/CodeView/StreamReader.h"
13#include "llvm/DebugInfo/CodeView/StreamRef.h"
14#include "llvm/DebugInfo/PDB/Raw/IPDBFile.h"
Zachary Turner92d9e972016-06-07 05:32:48 +000015#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
16#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
Zachary Turner90b8b8d2016-05-31 22:41:52 +000017#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
18#include "gtest/gtest.h"
19
20using namespace llvm;
21using namespace llvm::codeview;
22using namespace llvm::pdb;
23
24namespace {
25
26#define EXPECT_NO_ERROR(Err) \
27 { \
Zachary Turnerd665a7f2016-06-01 18:18:55 +000028 auto E = Err; \
Zachary Turner90b8b8d2016-05-31 22:41:52 +000029 EXPECT_FALSE(static_cast<bool>(E)); \
30 if (E) \
31 consumeError(std::move(E)); \
32 }
33
34#define EXPECT_ERROR(Err) \
35 { \
Zachary Turnerd665a7f2016-06-01 18:18:55 +000036 auto E = Err; \
Zachary Turner90b8b8d2016-05-31 22:41:52 +000037 EXPECT_TRUE(static_cast<bool>(E)); \
38 if (E) \
39 consumeError(std::move(E)); \
40 }
41
NAKAMURA Takumi47d1e372016-06-01 14:26:54 +000042static const uint32_t BlocksAry[] = {0, 1, 2, 5, 4, 3, 6, 7, 8, 9};
43static const char DataAry[] = {'A', 'B', 'C', 'F', 'E',
44 'D', 'G', 'H', 'I', 'J'};
45
Zachary Turner90b8b8d2016-05-31 22:41:52 +000046class DiscontiguousFile : public IPDBFile {
47public:
48 DiscontiguousFile()
NAKAMURA Takumif021d262016-06-01 22:59:06 +000049 : Blocks(std::begin(BlocksAry), std::end(BlocksAry)),
NAKAMURA Takumi7f48be02016-06-01 23:03:46 +000050 Data(std::begin(DataAry), std::end(DataAry)) {}
Zachary Turner90b8b8d2016-05-31 22:41:52 +000051
52 virtual uint32_t getBlockSize() const override { return 1; }
53 virtual uint32_t getBlockCount() const override { return 10; }
54 virtual uint32_t getNumStreams() const override { return 1; }
55 virtual uint32_t getStreamByteSize(uint32_t StreamIndex) const override {
56 return getBlockCount() * getBlockSize();
57 }
Zachary Turner92d9e972016-06-07 05:32:48 +000058 virtual ArrayRef<support::ulittle32_t>
Zachary Turner90b8b8d2016-05-31 22:41:52 +000059 getStreamBlockList(uint32_t StreamIndex) const override {
60 if (StreamIndex != 0)
Zachary Turner92d9e972016-06-07 05:32:48 +000061 return ArrayRef<support::ulittle32_t>();
Zachary Turner90b8b8d2016-05-31 22:41:52 +000062 return Blocks;
63 }
64 virtual StringRef getBlockData(uint32_t BlockIndex,
65 uint32_t NumBytes) const override {
66 return StringRef(&Data[BlockIndex], NumBytes);
67 }
68
69private:
Zachary Turner92d9e972016-06-07 05:32:48 +000070 std::vector<support::ulittle32_t> Blocks;
Zachary Turner90b8b8d2016-05-31 22:41:52 +000071 std::vector<char> Data;
72};
73
74// Tests that a read which is entirely contained within a single block works
75// and does not allocate.
David Majnemerb6aa8752016-06-01 18:13:06 +000076TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
Zachary Turner90b8b8d2016-05-31 22:41:52 +000077 DiscontiguousFile F;
Zachary Turner92d9e972016-06-07 05:32:48 +000078 MappedBlockStream S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +000079 StreamReader R(S);
David Majnemerb6aa8752016-06-01 18:13:06 +000080 StreamRef SR;
81 EXPECT_NO_ERROR(R.readStreamRef(SR, 0U));
82 ArrayRef<uint8_t> Buffer;
83 EXPECT_ERROR(SR.readBytes(0U, 1U, Buffer));
David Majnemer8c79db12016-06-02 06:21:44 +000084 EXPECT_NO_ERROR(R.readStreamRef(SR, 1U));
85 EXPECT_ERROR(SR.readBytes(1U, 1U, Buffer));
Zachary Turner90b8b8d2016-05-31 22:41:52 +000086}
87
88// Tests that a read which outputs into a full destination buffer works and
89// does not fail due to the length of the output buffer.
90TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
91 DiscontiguousFile F;
Zachary Turner92d9e972016-06-07 05:32:48 +000092 MappedBlockStream S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +000093 StreamReader R(S);
94 StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
95 EXPECT_NO_ERROR(R.readFixedString(Str, 1));
96 EXPECT_EQ(Str, StringRef("A"));
David Majnemerc0113052016-06-01 18:13:02 +000097 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +000098}
99
100// Tests that a read which crosses a block boundary, but where the subsequent
101// blocks are still contiguous in memory to the previous block works and does
102// not allocate memory.
103TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
104 DiscontiguousFile F;
Zachary Turner92d9e972016-06-07 05:32:48 +0000105 MappedBlockStream S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000106 StreamReader R(S);
107 StringRef Str;
108 EXPECT_NO_ERROR(R.readFixedString(Str, 2));
109 EXPECT_EQ(Str, StringRef("AB"));
David Majnemerc0113052016-06-01 18:13:02 +0000110 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000111
112 R.setOffset(6);
113 EXPECT_NO_ERROR(R.readFixedString(Str, 4));
114 EXPECT_EQ(Str, StringRef("GHIJ"));
David Majnemerc0113052016-06-01 18:13:02 +0000115 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000116}
117
118// Tests that a read which crosses a block boundary and cannot be referenced
119// contiguously works and allocates only the precise amount of bytes
120// requested.
121TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
122 DiscontiguousFile F;
Zachary Turner92d9e972016-06-07 05:32:48 +0000123 MappedBlockStream S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000124 StreamReader R(S);
125 StringRef Str;
126 EXPECT_NO_ERROR(R.readFixedString(Str, 10));
127 EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
David Majnemerc0113052016-06-01 18:13:02 +0000128 EXPECT_EQ(10U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000129}
130
131// Test that an out of bounds read which doesn't cross a block boundary
132// fails and allocates no memory.
133TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
134 DiscontiguousFile F;
Zachary Turner92d9e972016-06-07 05:32:48 +0000135 MappedBlockStream S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000136 StreamReader R(S);
137 StringRef Str;
138
139 R.setOffset(10);
140 EXPECT_ERROR(R.readFixedString(Str, 1));
David Majnemerc0113052016-06-01 18:13:02 +0000141 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000142}
143
144// Test that an out of bounds read which crosses a contiguous block boundary
145// fails and allocates no memory.
146TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
147 DiscontiguousFile F;
Zachary Turner92d9e972016-06-07 05:32:48 +0000148 MappedBlockStream S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000149 StreamReader R(S);
150 StringRef Str;
151
152 R.setOffset(6);
153 EXPECT_ERROR(R.readFixedString(Str, 5));
David Majnemerc0113052016-06-01 18:13:02 +0000154 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000155}
156
157// Test that an out of bounds read which crosses a discontiguous block
158// boundary fails and allocates no memory.
159TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
160 DiscontiguousFile F;
Zachary Turner92d9e972016-06-07 05:32:48 +0000161 MappedBlockStream S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000162 StreamReader R(S);
163 StringRef Str;
164
165 EXPECT_ERROR(R.readFixedString(Str, 11));
David Majnemerc0113052016-06-01 18:13:02 +0000166 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000167}
168
David Majnemerb6aa8752016-06-01 18:13:06 +0000169// Tests that a read which is entirely contained within a single block but
170// beyond the end of a StreamRef fails.
171TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
172 DiscontiguousFile F;
Zachary Turner92d9e972016-06-07 05:32:48 +0000173 MappedBlockStream S(llvm::make_unique<IndexedStreamData>(0, F), F);
David Majnemerb6aa8752016-06-01 18:13:06 +0000174 StreamReader R(S);
175 StringRef Str;
176 EXPECT_NO_ERROR(R.readFixedString(Str, 1));
177 EXPECT_EQ(Str, StringRef("A"));
178 EXPECT_EQ(0U, S.getNumBytesCopied());
179}
180
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000181} // end anonymous namespace