/ src / common / linux / memory_mapped_file_unittest.cc
memory_mapped_file_unittest.cc
  1  // Copyright 2011 Google LLC
  2  //
  3  // Redistribution and use in source and binary forms, with or without
  4  // modification, are permitted provided that the following conditions are
  5  // met:
  6  //
  7  //     * Redistributions of source code must retain the above copyright
  8  // notice, this list of conditions and the following disclaimer.
  9  //     * Redistributions in binary form must reproduce the above
 10  // copyright notice, this list of conditions and the following disclaimer
 11  // in the documentation and/or other materials provided with the
 12  // distribution.
 13  //     * Neither the name of Google LLC nor the names of its
 14  // contributors may be used to endorse or promote products derived from
 15  // this software without specific prior written permission.
 16  //
 17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  
 29  // memory_mapped_file_unittest.cc:
 30  // Unit tests for google_breakpad::MemoryMappedFile.
 31  
 32  #ifdef HAVE_CONFIG_H
 33  #include <config.h>  // Must come first
 34  #endif
 35  
 36  #include <fcntl.h>
 37  #include <string.h>
 38  #include <unistd.h>
 39  
 40  #include <string>
 41  
 42  #include "breakpad_googletest_includes.h"
 43  #include "common/linux/memory_mapped_file.h"
 44  #include "common/tests/auto_tempdir.h"
 45  #include "common/tests/file_utils.h"
 46  #include "common/using_std_string.h"
 47  
 48  using google_breakpad::AutoTempDir;
 49  using google_breakpad::MemoryMappedFile;
 50  using google_breakpad::WriteFile;
 51  
 52  namespace {
 53  
 54  class MemoryMappedFileTest : public testing::Test {
 55   protected:
 56    void ExpectNoMappedData(const MemoryMappedFile& mapped_file) {
 57      EXPECT_TRUE(mapped_file.content().IsEmpty());
 58      EXPECT_TRUE(mapped_file.data() == NULL);
 59      EXPECT_EQ(0U, mapped_file.size());
 60    }
 61  };
 62  
 63  }  // namespace
 64  
 65  TEST_F(MemoryMappedFileTest, DefaultConstructor) {
 66    MemoryMappedFile mapped_file;
 67    ExpectNoMappedData(mapped_file);
 68  }
 69  
 70  TEST_F(MemoryMappedFileTest, UnmapWithoutMap) {
 71    MemoryMappedFile mapped_file;
 72    mapped_file.Unmap();
 73  }
 74  
 75  TEST_F(MemoryMappedFileTest, MapNonexistentFile) {
 76    {
 77      MemoryMappedFile mapped_file("nonexistent-file", 0);
 78      ExpectNoMappedData(mapped_file);
 79    }
 80    {
 81      MemoryMappedFile mapped_file;
 82      EXPECT_FALSE(mapped_file.Map("nonexistent-file", 0));
 83      ExpectNoMappedData(mapped_file);
 84    }
 85  }
 86  
 87  TEST_F(MemoryMappedFileTest, MapEmptyFile) {
 88    AutoTempDir temp_dir;
 89    string test_file = temp_dir.path() + "/empty_file";
 90    ASSERT_TRUE(WriteFile(test_file.c_str(), NULL, 0));
 91  
 92    {
 93      MemoryMappedFile mapped_file(test_file.c_str(), 0);
 94      ExpectNoMappedData(mapped_file);
 95    }
 96    {
 97      MemoryMappedFile mapped_file;
 98      EXPECT_TRUE(mapped_file.Map(test_file.c_str(), 0));
 99      ExpectNoMappedData(mapped_file);
100    }
101  }
102  
103  TEST_F(MemoryMappedFileTest, MapNonEmptyFile) {
104    char data[256];
105    size_t data_size = sizeof(data);
106    for (size_t i = 0; i < data_size; ++i) {
107      data[i] = i;
108    }
109  
110    AutoTempDir temp_dir;
111    string test_file = temp_dir.path() + "/test_file";
112    ASSERT_TRUE(WriteFile(test_file.c_str(), data, data_size));
113  
114    {
115      MemoryMappedFile mapped_file(test_file.c_str(), 0);
116      EXPECT_FALSE(mapped_file.content().IsEmpty());
117      EXPECT_TRUE(mapped_file.data() != NULL);
118      EXPECT_EQ(data_size, mapped_file.size());
119      EXPECT_EQ(0, memcmp(data, mapped_file.data(), data_size));
120    }
121    {
122      MemoryMappedFile mapped_file;
123      EXPECT_TRUE(mapped_file.Map(test_file.c_str(), 0));
124      EXPECT_FALSE(mapped_file.content().IsEmpty());
125      EXPECT_TRUE(mapped_file.data() != NULL);
126      EXPECT_EQ(data_size, mapped_file.size());
127      EXPECT_EQ(0, memcmp(data, mapped_file.data(), data_size));
128    }
129  }
130  
131  TEST_F(MemoryMappedFileTest, RemapAfterMap) {
132    char data1[256];
133    size_t data1_size = sizeof(data1);
134    for (size_t i = 0; i < data1_size; ++i) {
135      data1[i] = i;
136    }
137  
138    char data2[50];
139    size_t data2_size = sizeof(data2);
140    for (size_t i = 0; i < data2_size; ++i) {
141      data2[i] = 255 - i;
142    }
143  
144    AutoTempDir temp_dir;
145    string test_file1 = temp_dir.path() + "/test_file1";
146    string test_file2 = temp_dir.path() + "/test_file2";
147    ASSERT_TRUE(WriteFile(test_file1.c_str(), data1, data1_size));
148    ASSERT_TRUE(WriteFile(test_file2.c_str(), data2, data2_size));
149  
150    {
151      MemoryMappedFile mapped_file(test_file1.c_str(), 0);
152      EXPECT_FALSE(mapped_file.content().IsEmpty());
153      EXPECT_TRUE(mapped_file.data() != NULL);
154      EXPECT_EQ(data1_size, mapped_file.size());
155      EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size));
156  
157      mapped_file.Map(test_file2.c_str(), 0);
158      EXPECT_FALSE(mapped_file.content().IsEmpty());
159      EXPECT_TRUE(mapped_file.data() != NULL);
160      EXPECT_EQ(data2_size, mapped_file.size());
161      EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size));
162    }
163    {
164      MemoryMappedFile mapped_file;
165      EXPECT_TRUE(mapped_file.Map(test_file1.c_str(), 0));
166      EXPECT_FALSE(mapped_file.content().IsEmpty());
167      EXPECT_TRUE(mapped_file.data() != NULL);
168      EXPECT_EQ(data1_size, mapped_file.size());
169      EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size));
170  
171      mapped_file.Map(test_file2.c_str(), 0);
172      EXPECT_FALSE(mapped_file.content().IsEmpty());
173      EXPECT_TRUE(mapped_file.data() != NULL);
174      EXPECT_EQ(data2_size, mapped_file.size());
175      EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size));
176    }
177  }
178  
179  TEST_F(MemoryMappedFileTest, MapWithOffset) {
180    // Put more data in the test file this time. Offsets can only be
181    // done on page boundaries, so we need a two page file to test this.
182    const int page_size = 4096;
183    char data1[2 * page_size];
184    size_t data1_size = sizeof(data1);
185    for (size_t i = 0; i < data1_size; ++i) {
186      data1[i] = i & 0x7f;
187    }
188  
189    AutoTempDir temp_dir;
190    string test_file1 = temp_dir.path() + "/test_file1";
191    ASSERT_TRUE(WriteFile(test_file1.c_str(), data1, data1_size));
192    {
193      MemoryMappedFile mapped_file(test_file1.c_str(), page_size);
194      EXPECT_FALSE(mapped_file.content().IsEmpty());
195      EXPECT_TRUE(mapped_file.data() != NULL);
196      EXPECT_EQ(data1_size - page_size, mapped_file.size());
197      EXPECT_EQ(
198          0,
199          memcmp(data1 + page_size, mapped_file.data(), data1_size - page_size));
200    }
201    {
202      MemoryMappedFile mapped_file;
203      mapped_file.Map(test_file1.c_str(), page_size);
204      EXPECT_FALSE(mapped_file.content().IsEmpty());
205      EXPECT_TRUE(mapped_file.data() != NULL);
206      EXPECT_EQ(data1_size - page_size, mapped_file.size());
207      EXPECT_EQ(
208          0,
209          memcmp(data1 + page_size, mapped_file.data(), data1_size - page_size));
210    }
211  }