diff options
Diffstat (limited to 'unittests/Support/MemoryBufferTest.cpp')
-rw-r--r-- | unittests/Support/MemoryBufferTest.cpp | 77 |
1 files changed, 75 insertions, 2 deletions
diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 1d9f482c519db..2b8806c394f34 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -11,12 +11,16 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/OwningPtr.h" #include "gtest/gtest.h" using namespace llvm; +namespace { + class MemoryBufferTest : public testing::Test { protected: MemoryBufferTest() @@ -25,13 +29,18 @@ protected: virtual void SetUp() { } + /// Common testing for different modes of getOpenFileSlice. + /// Creates a temporary file with known contents, and uses + /// MemoryBuffer::getOpenFileSlice to map it. + /// If \p Reopen is true, the file is closed after creating and reopened + /// anew before using MemoryBuffer. + void testGetOpenFileSlice(bool Reopen); + typedef OwningPtr<MemoryBuffer> OwningBuffer; std::string data; }; -namespace { - TEST_F(MemoryBufferTest, get) { // Default name and null-terminator flag OwningBuffer MB1(MemoryBuffer::getMemBuffer(data)); @@ -56,6 +65,28 @@ TEST_F(MemoryBufferTest, get) { EXPECT_EQ("this is some data", data); } +TEST_F(MemoryBufferTest, NullTerminator4K) { + // Test that a file with size that is a multiple of the page size can be null + // terminated correctly by MemoryBuffer. + int TestFD; + SmallString<64> TestPath; + sys::fs::createTemporaryFile("MemoryBufferTest_NullTerminator4K", "temp", + TestFD, TestPath); + raw_fd_ostream OF(TestFD, true, /*unbuffered=*/true); + for (unsigned i = 0; i < 4096 / 16; ++i) { + OF << "0123456789abcdef"; + } + OF.close(); + + OwningPtr<MemoryBuffer> MB; + error_code EC = MemoryBuffer::getFile(TestPath.c_str(), MB); + ASSERT_FALSE(EC); + + const char *BufData = MB->getBufferStart(); + EXPECT_EQ('f', BufData[4095]); + EXPECT_EQ('\0', BufData[4096]); +} + TEST_F(MemoryBufferTest, copy) { // copy with no name OwningBuffer MBC1(MemoryBuffer::getMemBufferCopy(data)); @@ -95,4 +126,46 @@ TEST_F(MemoryBufferTest, make_new) { EXPECT_EQ(0, Four->getBufferStart()[0]); } +void MemoryBufferTest::testGetOpenFileSlice(bool Reopen) { + // Test that MemoryBuffer::getOpenFile works properly when no null + // terminator is requested and the size is large enough to trigger + // the usage of memory mapping. + int TestFD; + SmallString<64> TestPath; + // Create a temporary file and write data into it. + sys::fs::createTemporaryFile("prefix", "temp", TestFD, TestPath); + // OF is responsible for closing the file; If the file is not + // reopened, it will be unbuffered so that the results are + // immediately visible through the fd. + raw_fd_ostream OF(TestFD, true, !Reopen); + for (int i = 0; i < 60000; ++i) { + OF << "0123456789"; + } + + if (Reopen) { + OF.close(); + EXPECT_FALSE(sys::fs::openFileForRead(TestPath.c_str(), TestFD)); + } + + OwningBuffer Buf; + error_code EC = MemoryBuffer::getOpenFileSlice(TestFD, TestPath.c_str(), Buf, + 40000, // Size + 80000 // Offset + ); + EXPECT_FALSE(EC); + + StringRef BufData = Buf->getBuffer(); + EXPECT_EQ(BufData.size(), 40000U); + EXPECT_EQ(BufData[0], '0'); + EXPECT_EQ(BufData[9], '9'); +} + +TEST_F(MemoryBufferTest, getOpenFileNoReopen) { + testGetOpenFileSlice(false); +} + +TEST_F(MemoryBufferTest, getOpenFileReopened) { + testGetOpenFileSlice(true); +} + } |