blob: 75e954df41122375f23cfd002c9c185d6dcbe8a0 [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"
15#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
16#include "gtest/gtest.h"
17
18using namespace llvm;
19using namespace llvm::codeview;
20using namespace llvm::pdb;
21
22namespace {
23
24#define EXPECT_NO_ERROR(Err) \
25 { \
Zachary Turnerd665a7f2016-06-01 18:18:55 +000026 auto E = Err; \
Zachary Turner90b8b8d2016-05-31 22:41:52 +000027 EXPECT_FALSE(static_cast<bool>(E)); \
28 if (E) \
29 consumeError(std::move(E)); \
30 }
31
32#define EXPECT_ERROR(Err) \
33 { \
Zachary Turnerd665a7f2016-06-01 18:18:55 +000034 auto E = Err; \
Zachary Turner90b8b8d2016-05-31 22:41:52 +000035 EXPECT_TRUE(static_cast<bool>(E)); \
36 if (E) \
37 consumeError(std::move(E)); \
38 }
39
NAKAMURA Takumi47d1e372016-06-01 14:26:54 +000040static const uint32_t BlocksAry[] = {0, 1, 2, 5, 4, 3, 6, 7, 8, 9};
41static const char DataAry[] = {'A', 'B', 'C', 'F', 'E',
42 'D', 'G', 'H', 'I', 'J'};
43
Zachary Turner90b8b8d2016-05-31 22:41:52 +000044class DiscontiguousFile : public IPDBFile {
45public:
46 DiscontiguousFile()
NAKAMURA Takumif021d262016-06-01 22:59:06 +000047 : Blocks(std::begin(BlocksAry), std::end(BlocksAry)),
NAKAMURA Takumi7f48be02016-06-01 23:03:46 +000048 Data(std::begin(DataAry), std::end(DataAry)) {}
Zachary Turner90b8b8d2016-05-31 22:41:52 +000049
50 virtual uint32_t getBlockSize() const override { return 1; }
51 virtual uint32_t getBlockCount() const override { return 10; }
52 virtual uint32_t getNumStreams() const override { return 1; }
53 virtual uint32_t getStreamByteSize(uint32_t StreamIndex) const override {
54 return getBlockCount() * getBlockSize();
55 }
56 virtual ArrayRef<uint32_t>
57 getStreamBlockList(uint32_t StreamIndex) const override {
58 if (StreamIndex != 0)
59 return ArrayRef<uint32_t>();
60 return Blocks;
61 }
62 virtual StringRef getBlockData(uint32_t BlockIndex,
63 uint32_t NumBytes) const override {
64 return StringRef(&Data[BlockIndex], NumBytes);
65 }
66
67private:
68 std::vector<uint32_t> Blocks;
69 std::vector<char> Data;
70};
71
72// Tests that a read which is entirely contained within a single block works
73// and does not allocate.
David Majnemerb6aa8752016-06-01 18:13:06 +000074TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
Zachary Turner90b8b8d2016-05-31 22:41:52 +000075 DiscontiguousFile F;
76 MappedBlockStream S(0, F);
77 StreamReader R(S);
David Majnemerb6aa8752016-06-01 18:13:06 +000078 StreamRef SR;
79 EXPECT_NO_ERROR(R.readStreamRef(SR, 0U));
80 ArrayRef<uint8_t> Buffer;
81 EXPECT_ERROR(SR.readBytes(0U, 1U, Buffer));
David Majnemer8c79db12016-06-02 06:21:44 +000082 EXPECT_NO_ERROR(R.readStreamRef(SR, 1U));
83 EXPECT_ERROR(SR.readBytes(1U, 1U, Buffer));
Zachary Turner90b8b8d2016-05-31 22:41:52 +000084}
85
86// Tests that a read which outputs into a full destination buffer works and
87// does not fail due to the length of the output buffer.
88TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
89 DiscontiguousFile F;
90 MappedBlockStream S(0, F);
91 StreamReader R(S);
92 StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
93 EXPECT_NO_ERROR(R.readFixedString(Str, 1));
94 EXPECT_EQ(Str, StringRef("A"));
David Majnemerc0113052016-06-01 18:13:02 +000095 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +000096}
97
98// Tests that a read which crosses a block boundary, but where the subsequent
99// blocks are still contiguous in memory to the previous block works and does
100// not allocate memory.
101TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
102 DiscontiguousFile F;
103 MappedBlockStream S(0, F);
104 StreamReader R(S);
105 StringRef Str;
106 EXPECT_NO_ERROR(R.readFixedString(Str, 2));
107 EXPECT_EQ(Str, StringRef("AB"));
David Majnemerc0113052016-06-01 18:13:02 +0000108 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000109
110 R.setOffset(6);
111 EXPECT_NO_ERROR(R.readFixedString(Str, 4));
112 EXPECT_EQ(Str, StringRef("GHIJ"));
David Majnemerc0113052016-06-01 18:13:02 +0000113 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000114}
115
116// Tests that a read which crosses a block boundary and cannot be referenced
117// contiguously works and allocates only the precise amount of bytes
118// requested.
119TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
120 DiscontiguousFile F;
121 MappedBlockStream S(0, F);
122 StreamReader R(S);
123 StringRef Str;
124 EXPECT_NO_ERROR(R.readFixedString(Str, 10));
125 EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
David Majnemerc0113052016-06-01 18:13:02 +0000126 EXPECT_EQ(10U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000127}
128
129// Test that an out of bounds read which doesn't cross a block boundary
130// fails and allocates no memory.
131TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
132 DiscontiguousFile F;
133 MappedBlockStream S(0, F);
134 StreamReader R(S);
135 StringRef Str;
136
137 R.setOffset(10);
138 EXPECT_ERROR(R.readFixedString(Str, 1));
David Majnemerc0113052016-06-01 18:13:02 +0000139 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000140}
141
142// Test that an out of bounds read which crosses a contiguous block boundary
143// fails and allocates no memory.
144TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
145 DiscontiguousFile F;
146 MappedBlockStream S(0, F);
147 StreamReader R(S);
148 StringRef Str;
149
150 R.setOffset(6);
151 EXPECT_ERROR(R.readFixedString(Str, 5));
David Majnemerc0113052016-06-01 18:13:02 +0000152 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000153}
154
155// Test that an out of bounds read which crosses a discontiguous block
156// boundary fails and allocates no memory.
157TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
158 DiscontiguousFile F;
159 MappedBlockStream S(0, F);
160 StreamReader R(S);
161 StringRef Str;
162
163 EXPECT_ERROR(R.readFixedString(Str, 11));
David Majnemerc0113052016-06-01 18:13:02 +0000164 EXPECT_EQ(0U, S.getNumBytesCopied());
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000165}
166
David Majnemerb6aa8752016-06-01 18:13:06 +0000167// Tests that a read which is entirely contained within a single block but
168// beyond the end of a StreamRef fails.
169TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
170 DiscontiguousFile F;
171 MappedBlockStream S(0, F);
172 StreamReader R(S);
173 StringRef Str;
174 EXPECT_NO_ERROR(R.readFixedString(Str, 1));
175 EXPECT_EQ(Str, StringRef("A"));
176 EXPECT_EQ(0U, S.getNumBytesCopied());
177}
178
Zachary Turner90b8b8d2016-05-31 22:41:52 +0000179} // end anonymous namespace