blob: f1c091805b0951c122f5358c4f70ccee1c02bfc6 [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 }
Zachary Turnerc448d652016-06-07 20:46:39 +000064 virtual ArrayRef<uint8_t> getBlockData(uint32_t BlockIndex,
65 uint32_t NumBytes) const override {
66 return ArrayRef<uint8_t>(&Data[BlockIndex], NumBytes);
Zachary Turner90b8b8d2016-05-31 22:41:52 +000067 }
68
69private:
Zachary Turner92d9e972016-06-07 05:32:48 +000070 std::vector<support::ulittle32_t> Blocks;
Zachary Turnerc448d652016-06-07 20:46:39 +000071 std::vector<uint8_t> Data;
Zachary Turner90b8b8d2016-05-31 22:41:52 +000072};
73
Zachary Turner3e65bcb2016-06-08 17:32:25 +000074class MappedBlockStreamImpl : public MappedBlockStream {
75public:
76 MappedBlockStreamImpl(std::unique_ptr<IPDBStreamData> Data,
77 const IPDBFile &File)
78 : MappedBlockStream(std::move(Data), File) {}
79};
80
Zachary Turner90b8b8d2016-05-31 22:41:52 +000081// Tests that a read which is entirely contained within a single block works
82// and does not allocate.
David Majnemerb6aa8752016-06-01 18:13:06 +000083TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
Zachary Turner90b8b8d2016-05-31 22:41:52 +000084 DiscontiguousFile F;
Zachary Turner3e65bcb2016-06-08 17:32:25 +000085 MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +000086 StreamReader R(S);
David Majnemerb6aa8752016-06-01 18:13:06 +000087 StreamRef SR;
88 EXPECT_NO_ERROR(R.readStreamRef(SR, 0U));
89 ArrayRef<uint8_t> Buffer;
90 EXPECT_ERROR(SR.readBytes(0U, 1U, Buffer));
David Majnemer8c79db12016-06-02 06:21:44 +000091 EXPECT_NO_ERROR(R.readStreamRef(SR, 1U));
92 EXPECT_ERROR(SR.readBytes(1U, 1U, Buffer));
Zachary Turner90b8b8d2016-05-31 22:41:52 +000093}
94
95// Tests that a read which outputs into a full destination buffer works and
96// does not fail due to the length of the output buffer.
97TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
98 DiscontiguousFile F;
Zachary Turner3e65bcb2016-06-08 17:32:25 +000099 MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000100 StreamReader R(S);
101 StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
102 EXPECT_NO_ERROR(R.readFixedString(Str, 1));
103 EXPECT_EQ(Str, StringRef("A"));
David Majnemerc0113052016-06-01 18:13:02 +0000104 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000105}
106
107// Tests that a read which crosses a block boundary, but where the subsequent
108// blocks are still contiguous in memory to the previous block works and does
109// not allocate memory.
110TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
111 DiscontiguousFile F;
Zachary Turner3e65bcb2016-06-08 17:32:25 +0000112 MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000113 StreamReader R(S);
114 StringRef Str;
115 EXPECT_NO_ERROR(R.readFixedString(Str, 2));
116 EXPECT_EQ(Str, StringRef("AB"));
David Majnemerc0113052016-06-01 18:13:02 +0000117 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000118
119 R.setOffset(6);
120 EXPECT_NO_ERROR(R.readFixedString(Str, 4));
121 EXPECT_EQ(Str, StringRef("GHIJ"));
David Majnemerc0113052016-06-01 18:13:02 +0000122 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000123}
124
125// Tests that a read which crosses a block boundary and cannot be referenced
126// contiguously works and allocates only the precise amount of bytes
127// requested.
128TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
129 DiscontiguousFile F;
Zachary Turner3e65bcb2016-06-08 17:32:25 +0000130 MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000131 StreamReader R(S);
132 StringRef Str;
133 EXPECT_NO_ERROR(R.readFixedString(Str, 10));
134 EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
David Majnemerc0113052016-06-01 18:13:02 +0000135 EXPECT_EQ(10U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000136}
137
138// Test that an out of bounds read which doesn't cross a block boundary
139// fails and allocates no memory.
140TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
141 DiscontiguousFile F;
Zachary Turner3e65bcb2016-06-08 17:32:25 +0000142 MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000143 StreamReader R(S);
144 StringRef Str;
145
146 R.setOffset(10);
147 EXPECT_ERROR(R.readFixedString(Str, 1));
David Majnemerc0113052016-06-01 18:13:02 +0000148 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000149}
150
151// Test that an out of bounds read which crosses a contiguous block boundary
152// fails and allocates no memory.
153TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
154 DiscontiguousFile F;
Zachary Turner3e65bcb2016-06-08 17:32:25 +0000155 MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000156 StreamReader R(S);
157 StringRef Str;
158
159 R.setOffset(6);
160 EXPECT_ERROR(R.readFixedString(Str, 5));
David Majnemerc0113052016-06-01 18:13:02 +0000161 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000162}
163
164// Test that an out of bounds read which crosses a discontiguous block
165// boundary fails and allocates no memory.
166TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
167 DiscontiguousFile F;
Zachary Turner3e65bcb2016-06-08 17:32:25 +0000168 MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000169 StreamReader R(S);
170 StringRef Str;
171
172 EXPECT_ERROR(R.readFixedString(Str, 11));
David Majnemerc0113052016-06-01 18:13:02 +0000173 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000174}
175
David Majnemerb6aa8752016-06-01 18:13:06 +0000176// Tests that a read which is entirely contained within a single block but
177// beyond the end of a StreamRef fails.
178TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
179 DiscontiguousFile F;
Zachary Turner3e65bcb2016-06-08 17:32:25 +0000180 MappedBlockStreamImpl S(llvm::make_unique<IndexedStreamData>(0, F), F);
David Majnemerb6aa8752016-06-01 18:13:06 +0000181 StreamReader R(S);
182 StringRef Str;
183 EXPECT_NO_ERROR(R.readFixedString(Str, 1));
184 EXPECT_EQ(Str, StringRef("A"));
185 EXPECT_EQ(0U, S.getNumBytesCopied());
186}
187
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000188} // end anonymous namespace