blob: b98a3c81ed663bfbe8c9a4f474305875d70d5627 [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 { \
26 auto E = std::move(Err); \
27 EXPECT_FALSE(static_cast<bool>(E)); \
28 if (E) \
29 consumeError(std::move(E)); \
30 }
31
32#define EXPECT_ERROR(Err) \
33 { \
34 auto E = std::move(Err); \
35 EXPECT_TRUE(static_cast<bool>(E)); \
36 if (E) \
37 consumeError(std::move(E)); \
38 }
39
40class DiscontiguousFile : public IPDBFile {
41public:
42 DiscontiguousFile()
43 : Blocks{0, 1, 2, 5, 4, 3, 6, 7, 8, 9},
44 Data{'A', 'B', 'C', 'F', 'E', 'D', 'G', 'H', 'I', 'J'} {}
45
46 virtual uint32_t getBlockSize() const override { return 1; }
47 virtual uint32_t getBlockCount() const override { return 10; }
48 virtual uint32_t getNumStreams() const override { return 1; }
49 virtual uint32_t getStreamByteSize(uint32_t StreamIndex) const override {
50 return getBlockCount() * getBlockSize();
51 }
52 virtual ArrayRef<uint32_t>
53 getStreamBlockList(uint32_t StreamIndex) const override {
54 if (StreamIndex != 0)
55 return ArrayRef<uint32_t>();
56 return Blocks;
57 }
58 virtual StringRef getBlockData(uint32_t BlockIndex,
59 uint32_t NumBytes) const override {
60 return StringRef(&Data[BlockIndex], NumBytes);
61 }
62
63private:
64 std::vector<uint32_t> Blocks;
65 std::vector<char> Data;
66};
67
68// Tests that a read which is entirely contained within a single block works
69// and does not allocate.
70TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
71 DiscontiguousFile F;
72 MappedBlockStream S(0, F);
73 StreamReader R(S);
74 StringRef Str;
75 EXPECT_NO_ERROR(R.readFixedString(Str, 1));
76 EXPECT_EQ(Str, StringRef("A"));
77 EXPECT_EQ(0, S.getNumBytesCopied());
78}
79
80// Tests that a read which outputs into a full destination buffer works and
81// does not fail due to the length of the output buffer.
82TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
83 DiscontiguousFile F;
84 MappedBlockStream S(0, F);
85 StreamReader R(S);
86 StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
87 EXPECT_NO_ERROR(R.readFixedString(Str, 1));
88 EXPECT_EQ(Str, StringRef("A"));
89 EXPECT_EQ(0, S.getNumBytesCopied());
90}
91
92// Tests that a read which crosses a block boundary, but where the subsequent
93// blocks are still contiguous in memory to the previous block works and does
94// not allocate memory.
95TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
96 DiscontiguousFile F;
97 MappedBlockStream S(0, F);
98 StreamReader R(S);
99 StringRef Str;
100 EXPECT_NO_ERROR(R.readFixedString(Str, 2));
101 EXPECT_EQ(Str, StringRef("AB"));
102 EXPECT_EQ(0, S.getNumBytesCopied());
103
104 R.setOffset(6);
105 EXPECT_NO_ERROR(R.readFixedString(Str, 4));
106 EXPECT_EQ(Str, StringRef("GHIJ"));
107 EXPECT_EQ(0, S.getNumBytesCopied());
108}
109
110// Tests that a read which crosses a block boundary and cannot be referenced
111// contiguously works and allocates only the precise amount of bytes
112// requested.
113TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
114 DiscontiguousFile F;
115 MappedBlockStream S(0, F);
116 StreamReader R(S);
117 StringRef Str;
118 EXPECT_NO_ERROR(R.readFixedString(Str, 10));
119 EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
120 EXPECT_EQ(10, S.getNumBytesCopied());
121}
122
123// Test that an out of bounds read which doesn't cross a block boundary
124// fails and allocates no memory.
125TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
126 DiscontiguousFile F;
127 MappedBlockStream S(0, F);
128 StreamReader R(S);
129 StringRef Str;
130
131 R.setOffset(10);
132 EXPECT_ERROR(R.readFixedString(Str, 1));
133 EXPECT_EQ(0, S.getNumBytesCopied());
134}
135
136// Test that an out of bounds read which crosses a contiguous block boundary
137// fails and allocates no memory.
138TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
139 DiscontiguousFile F;
140 MappedBlockStream S(0, F);
141 StreamReader R(S);
142 StringRef Str;
143
144 R.setOffset(6);
145 EXPECT_ERROR(R.readFixedString(Str, 5));
146 EXPECT_EQ(0, S.getNumBytesCopied());
147}
148
149// Test that an out of bounds read which crosses a discontiguous block
150// boundary fails and allocates no memory.
151TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
152 DiscontiguousFile F;
153 MappedBlockStream S(0, F);
154 StreamReader R(S);
155 StringRef Str;
156
157 EXPECT_ERROR(R.readFixedString(Str, 11));
158 EXPECT_EQ(0, S.getNumBytesCopied());
159}
160
161} // end anonymous namespace