1 //===- llvm/unittest/Support/MemoryBufferTest.cpp - MemoryBuffer tests ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements unit tests for the MemoryBuffer support class.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Support/MemoryBuffer.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/FileUtilities.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/Testing/Support/Error.h"
19 #include "gtest/gtest.h"
25 class MemoryBufferTest : public testing::Test {
28 : data("this is some data")
31 void SetUp() override {}
33 /// Common testing for different modes of getOpenFileSlice.
34 /// Creates a temporary file with known contents, and uses
35 /// MemoryBuffer::getOpenFileSlice to map it.
36 /// If \p Reopen is true, the file is closed after creating and reopened
37 /// anew before using MemoryBuffer.
38 void testGetOpenFileSlice(bool Reopen);
40 typedef std::unique_ptr<MemoryBuffer> OwningBuffer;
45 TEST_F(MemoryBufferTest, get) {
46 // Default name and null-terminator flag
47 OwningBuffer MB1(MemoryBuffer::getMemBuffer(data));
48 EXPECT_TRUE(nullptr != MB1.get());
50 // RequiresNullTerminator = false
51 OwningBuffer MB2(MemoryBuffer::getMemBuffer(data, "one", false));
52 EXPECT_TRUE(nullptr != MB2.get());
54 // RequiresNullTerminator = true
55 OwningBuffer MB3(MemoryBuffer::getMemBuffer(data, "two", true));
56 EXPECT_TRUE(nullptr != MB3.get());
58 // verify all 3 buffers point to the same address
59 EXPECT_EQ(MB1->getBufferStart(), MB2->getBufferStart());
60 EXPECT_EQ(MB2->getBufferStart(), MB3->getBufferStart());
62 // verify the original data is unmodified after deleting the buffers
66 EXPECT_EQ("this is some data", data);
69 TEST_F(MemoryBufferTest, NullTerminator4K) {
70 // Test that a file with size that is a multiple of the page size can be null
71 // terminated correctly by MemoryBuffer.
73 SmallString<64> TestPath;
74 sys::fs::createTemporaryFile("MemoryBufferTest_NullTerminator4K", "temp",
76 FileRemover Cleanup(TestPath);
77 raw_fd_ostream OF(TestFD, true, /*unbuffered=*/true);
78 for (unsigned i = 0; i < 4096 / 16; ++i) {
79 OF << "0123456789abcdef";
83 ErrorOr<OwningBuffer> MB = MemoryBuffer::getFile(TestPath.c_str());
84 std::error_code EC = MB.getError();
87 const char *BufData = MB.get()->getBufferStart();
88 EXPECT_EQ('f', BufData[4095]);
89 EXPECT_EQ('\0', BufData[4096]);
92 TEST_F(MemoryBufferTest, copy) {
94 OwningBuffer MBC1(MemoryBuffer::getMemBufferCopy(data));
95 EXPECT_TRUE(nullptr != MBC1.get());
98 OwningBuffer MBC2(MemoryBuffer::getMemBufferCopy(data, "copy"));
99 EXPECT_TRUE(nullptr != MBC2.get());
101 // verify the two copies do not point to the same place
102 EXPECT_NE(MBC1->getBufferStart(), MBC2->getBufferStart());
105 TEST_F(MemoryBufferTest, make_new) {
107 OwningBuffer Zero(WritableMemoryBuffer::getNewUninitMemBuffer(0));
108 EXPECT_TRUE(nullptr != Zero.get());
110 // uninitialized buffer with no name
111 OwningBuffer One(WritableMemoryBuffer::getNewUninitMemBuffer(321));
112 EXPECT_TRUE(nullptr != One.get());
114 // uninitialized buffer with name
115 OwningBuffer Two(WritableMemoryBuffer::getNewUninitMemBuffer(123, "bla"));
116 EXPECT_TRUE(nullptr != Two.get());
118 // 0-initialized buffer with no name
119 OwningBuffer Three(MemoryBuffer::getNewMemBuffer(321, data));
120 EXPECT_TRUE(nullptr != Three.get());
121 for (size_t i = 0; i < 321; ++i)
122 EXPECT_EQ(0, Three->getBufferStart()[0]);
124 // 0-initialized buffer with name
125 OwningBuffer Four(MemoryBuffer::getNewMemBuffer(123, "zeros"));
126 EXPECT_TRUE(nullptr != Four.get());
127 for (size_t i = 0; i < 123; ++i)
128 EXPECT_EQ(0, Four->getBufferStart()[0]);
131 void MemoryBufferTest::testGetOpenFileSlice(bool Reopen) {
132 // Test that MemoryBuffer::getOpenFile works properly when no null
133 // terminator is requested and the size is large enough to trigger
134 // the usage of memory mapping.
136 SmallString<64> TestPath;
137 // Create a temporary file and write data into it.
138 sys::fs::createTemporaryFile("prefix", "temp", TestFD, TestPath);
139 FileRemover Cleanup(TestPath);
140 // OF is responsible for closing the file; If the file is not
141 // reopened, it will be unbuffered so that the results are
142 // immediately visible through the fd.
143 raw_fd_ostream OF(TestFD, true, !Reopen);
144 for (int i = 0; i < 60000; ++i) {
150 EXPECT_FALSE(sys::fs::openFileForRead(TestPath.c_str(), TestFD));
153 ErrorOr<OwningBuffer> Buf =
154 MemoryBuffer::getOpenFileSlice(TestFD, TestPath.c_str(),
159 std::error_code EC = Buf.getError();
162 StringRef BufData = Buf.get()->getBuffer();
163 EXPECT_EQ(BufData.size(), 40000U);
164 EXPECT_EQ(BufData[0], '0');
165 EXPECT_EQ(BufData[9], '9');
168 TEST_F(MemoryBufferTest, getOpenFileNoReopen) {
169 testGetOpenFileSlice(false);
172 TEST_F(MemoryBufferTest, getOpenFileReopened) {
173 testGetOpenFileSlice(true);
176 TEST_F(MemoryBufferTest, reference) {
177 OwningBuffer MB(MemoryBuffer::getMemBuffer(data));
178 MemoryBufferRef MBR(*MB);
180 EXPECT_EQ(MB->getBufferStart(), MBR.getBufferStart());
181 EXPECT_EQ(MB->getBufferIdentifier(), MBR.getBufferIdentifier());
184 TEST_F(MemoryBufferTest, slice) {
185 // Create a file that is six pages long with different data on each page.
187 SmallString<64> TestPath;
188 sys::fs::createTemporaryFile("MemoryBufferTest_Slice", "temp", FD, TestPath);
189 FileRemover Cleanup(TestPath);
190 raw_fd_ostream OF(FD, true, /*unbuffered=*/true);
191 for (unsigned i = 0; i < 0x2000 / 8; ++i) {
194 for (unsigned i = 0; i < 0x2000 / 8; ++i) {
197 for (unsigned i = 0; i < 0x2000 / 8; ++i) {
202 // Try offset of one page.
203 ErrorOr<OwningBuffer> MB = MemoryBuffer::getFileSlice(TestPath.str(),
205 std::error_code EC = MB.getError();
207 EXPECT_EQ(0x4000UL, MB.get()->getBufferSize());
209 StringRef BufData = MB.get()->getBuffer();
210 EXPECT_TRUE(BufData.substr(0x0000,8).equals("12345678"));
211 EXPECT_TRUE(BufData.substr(0x0FF8,8).equals("12345678"));
212 EXPECT_TRUE(BufData.substr(0x1000,8).equals("abcdefgh"));
213 EXPECT_TRUE(BufData.substr(0x2FF8,8).equals("abcdefgh"));
214 EXPECT_TRUE(BufData.substr(0x3000,8).equals("ABCDEFGH"));
215 EXPECT_TRUE(BufData.substr(0x3FF8,8).equals("ABCDEFGH"));
217 // Try non-page aligned.
218 ErrorOr<OwningBuffer> MB2 = MemoryBuffer::getFileSlice(TestPath.str(),
222 EXPECT_EQ(0x3000UL, MB2.get()->getBufferSize());
224 StringRef BufData2 = MB2.get()->getBuffer();
225 EXPECT_TRUE(BufData2.substr(0x0000,8).equals("12345678"));
226 EXPECT_TRUE(BufData2.substr(0x17F8,8).equals("12345678"));
227 EXPECT_TRUE(BufData2.substr(0x1800,8).equals("abcdefgh"));
228 EXPECT_TRUE(BufData2.substr(0x2FF8,8).equals("abcdefgh"));
231 TEST_F(MemoryBufferTest, writableSlice) {
232 // Create a file initialized with some data
234 SmallString<64> TestPath;
235 sys::fs::createTemporaryFile("MemoryBufferTest_WritableSlice", "temp", FD,
237 FileRemover Cleanup(TestPath);
238 raw_fd_ostream OF(FD, true);
239 for (unsigned i = 0; i < 0x1000; ++i)
240 OF << "0123456789abcdef";
245 WritableMemoryBuffer::getFileSlice(TestPath.str(), 0x6000, 0x2000);
246 ASSERT_FALSE(MBOrError.getError());
247 // Write some data. It should be mapped private, so that upon completion
248 // the original file contents are not modified.
249 WritableMemoryBuffer &MB = **MBOrError;
250 ASSERT_EQ(0x6000u, MB.getBufferSize());
251 char *Start = MB.getBufferStart();
252 ASSERT_EQ(MB.getBufferEnd(), MB.getBufferStart() + MB.getBufferSize());
253 ::memset(Start, 'x', MB.getBufferSize());
256 auto MBOrError = MemoryBuffer::getFile(TestPath);
257 ASSERT_FALSE(MBOrError.getError());
258 auto &MB = **MBOrError;
259 ASSERT_EQ(0x10000u, MB.getBufferSize());
260 for (size_t i = 0; i < MB.getBufferSize(); i += 0x10)
261 EXPECT_EQ("0123456789abcdef", MB.getBuffer().substr(i, 0x10)) << "i: " << i;