Home | History | Annotate | Download | only in Support
      1 //===- llvm/unittest/Support/MemoryBufferTest.cpp - MemoryBuffer tests ----===//
      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 // This file implements unit tests for the MemoryBuffer support class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/Support/FileSystem.h"
     15 #include "llvm/Support/MemoryBuffer.h"
     16 #include "llvm/Support/raw_ostream.h"
     17 #include "gtest/gtest.h"
     18 
     19 using namespace llvm;
     20 
     21 namespace {
     22 
     23 class MemoryBufferTest : public testing::Test {
     24 protected:
     25   MemoryBufferTest()
     26   : data("this is some data")
     27   { }
     28 
     29   virtual void SetUp() { }
     30 
     31   /// Common testing for different modes of getOpenFileSlice.
     32   /// Creates a temporary file with known contents, and uses
     33   /// MemoryBuffer::getOpenFileSlice to map it.
     34   /// If \p Reopen is true, the file is closed after creating and reopened
     35   /// anew before using MemoryBuffer.
     36   void testGetOpenFileSlice(bool Reopen);
     37 
     38   typedef std::unique_ptr<MemoryBuffer> OwningBuffer;
     39 
     40   std::string data;
     41 };
     42 
     43 TEST_F(MemoryBufferTest, get) {
     44   // Default name and null-terminator flag
     45   OwningBuffer MB1(MemoryBuffer::getMemBuffer(data));
     46   EXPECT_TRUE(nullptr != MB1.get());
     47 
     48   // RequiresNullTerminator = false
     49   OwningBuffer MB2(MemoryBuffer::getMemBuffer(data, "one", false));
     50   EXPECT_TRUE(nullptr != MB2.get());
     51 
     52   // RequiresNullTerminator = true
     53   OwningBuffer MB3(MemoryBuffer::getMemBuffer(data, "two", true));
     54   EXPECT_TRUE(nullptr != MB3.get());
     55 
     56   // verify all 3 buffers point to the same address
     57   EXPECT_EQ(MB1->getBufferStart(), MB2->getBufferStart());
     58   EXPECT_EQ(MB2->getBufferStart(), MB3->getBufferStart());
     59 
     60   // verify the original data is unmodified after deleting the buffers
     61   MB1.reset();
     62   MB2.reset();
     63   MB3.reset();
     64   EXPECT_EQ("this is some data", data);
     65 }
     66 
     67 TEST_F(MemoryBufferTest, NullTerminator4K) {
     68   // Test that a file with size that is a multiple of the page size can be null
     69   // terminated correctly by MemoryBuffer.
     70   int TestFD;
     71   SmallString<64> TestPath;
     72   sys::fs::createTemporaryFile("MemoryBufferTest_NullTerminator4K", "temp",
     73                                TestFD, TestPath);
     74   raw_fd_ostream OF(TestFD, true, /*unbuffered=*/true);
     75   for (unsigned i = 0; i < 4096 / 16; ++i) {
     76     OF << "0123456789abcdef";
     77   }
     78   OF.close();
     79 
     80   ErrorOr<OwningBuffer> MB = MemoryBuffer::getFile(TestPath.c_str());
     81   std::error_code EC = MB.getError();
     82   ASSERT_FALSE(EC);
     83 
     84   const char *BufData = MB.get()->getBufferStart();
     85   EXPECT_EQ('f', BufData[4095]);
     86   EXPECT_EQ('\0', BufData[4096]);
     87 }
     88 
     89 TEST_F(MemoryBufferTest, copy) {
     90   // copy with no name
     91   OwningBuffer MBC1(MemoryBuffer::getMemBufferCopy(data));
     92   EXPECT_TRUE(nullptr != MBC1.get());
     93 
     94   // copy with a name
     95   OwningBuffer MBC2(MemoryBuffer::getMemBufferCopy(data, "copy"));
     96   EXPECT_TRUE(nullptr != MBC2.get());
     97 
     98   // verify the two copies do not point to the same place
     99   EXPECT_NE(MBC1->getBufferStart(), MBC2->getBufferStart());
    100 }
    101 
    102 TEST_F(MemoryBufferTest, make_new) {
    103   // 0-sized buffer
    104   OwningBuffer Zero(MemoryBuffer::getNewUninitMemBuffer(0));
    105   EXPECT_TRUE(nullptr != Zero.get());
    106 
    107   // uninitialized buffer with no name
    108   OwningBuffer One(MemoryBuffer::getNewUninitMemBuffer(321));
    109   EXPECT_TRUE(nullptr != One.get());
    110 
    111   // uninitialized buffer with name
    112   OwningBuffer Two(MemoryBuffer::getNewUninitMemBuffer(123, "bla"));
    113   EXPECT_TRUE(nullptr != Two.get());
    114 
    115   // 0-initialized buffer with no name
    116   OwningBuffer Three(MemoryBuffer::getNewMemBuffer(321, data));
    117   EXPECT_TRUE(nullptr != Three.get());
    118   for (size_t i = 0; i < 321; ++i)
    119     EXPECT_EQ(0, Three->getBufferStart()[0]);
    120 
    121   // 0-initialized buffer with name
    122   OwningBuffer Four(MemoryBuffer::getNewMemBuffer(123, "zeros"));
    123   EXPECT_TRUE(nullptr != Four.get());
    124   for (size_t i = 0; i < 123; ++i)
    125     EXPECT_EQ(0, Four->getBufferStart()[0]);
    126 }
    127 
    128 void MemoryBufferTest::testGetOpenFileSlice(bool Reopen) {
    129   // Test that MemoryBuffer::getOpenFile works properly when no null
    130   // terminator is requested and the size is large enough to trigger
    131   // the usage of memory mapping.
    132   int TestFD;
    133   SmallString<64> TestPath;
    134   // Create a temporary file and write data into it.
    135   sys::fs::createTemporaryFile("prefix", "temp", TestFD, TestPath);
    136   // OF is responsible for closing the file; If the file is not
    137   // reopened, it will be unbuffered so that the results are
    138   // immediately visible through the fd.
    139   raw_fd_ostream OF(TestFD, true, !Reopen);
    140   for (int i = 0; i < 60000; ++i) {
    141     OF << "0123456789";
    142   }
    143 
    144   if (Reopen) {
    145     OF.close();
    146     EXPECT_FALSE(sys::fs::openFileForRead(TestPath.c_str(), TestFD));
    147   }
    148 
    149   ErrorOr<OwningBuffer> Buf =
    150       MemoryBuffer::getOpenFileSlice(TestFD, TestPath.c_str(),
    151                                      40000, // Size
    152                                      80000  // Offset
    153                                      );
    154 
    155   std::error_code EC = Buf.getError();
    156   EXPECT_FALSE(EC);
    157 
    158   StringRef BufData = Buf.get()->getBuffer();
    159   EXPECT_EQ(BufData.size(), 40000U);
    160   EXPECT_EQ(BufData[0], '0');
    161   EXPECT_EQ(BufData[9], '9');
    162 }
    163 
    164 TEST_F(MemoryBufferTest, getOpenFileNoReopen) {
    165   testGetOpenFileSlice(false);
    166 }
    167 
    168 TEST_F(MemoryBufferTest, getOpenFileReopened) {
    169   testGetOpenFileSlice(true);
    170 }
    171 
    172 }
    173