xref: /aosp_15_r20/external/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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:
ExpectNoMappedData(const MemoryMappedFile & mapped_file)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 
TEST_F(MemoryMappedFileTest,DefaultConstructor)65 TEST_F(MemoryMappedFileTest, DefaultConstructor) {
66   MemoryMappedFile mapped_file;
67   ExpectNoMappedData(mapped_file);
68 }
69 
TEST_F(MemoryMappedFileTest,UnmapWithoutMap)70 TEST_F(MemoryMappedFileTest, UnmapWithoutMap) {
71   MemoryMappedFile mapped_file;
72   mapped_file.Unmap();
73 }
74 
TEST_F(MemoryMappedFileTest,MapNonexistentFile)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 
TEST_F(MemoryMappedFileTest,MapEmptyFile)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 
TEST_F(MemoryMappedFileTest,MapNonEmptyFile)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 
TEST_F(MemoryMappedFileTest,RemapAfterMap)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 
TEST_F(MemoryMappedFileTest,MapWithOffset)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 }
212