• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "base/unix_file/mapped_file.h"
18 #include "base/logging.h"
19 #include "base/unix_file/fd_file.h"
20 #include "base/unix_file/random_access_file_test.h"
21 #include "base/unix_file/random_access_file_utils.h"
22 #include "base/unix_file/string_file.h"
23 #include "gtest/gtest.h"
24 
25 namespace unix_file {
26 
27 class MappedFileTest : public RandomAccessFileTest {
28  protected:
MappedFileTest()29   MappedFileTest() : kContent("some content") {
30   }
31 
SetUp()32   void SetUp() {
33     art::CommonTest::SetEnvironmentVariables(android_data_);
34 
35     good_path_ = GetTmpPath("some-file.txt");
36     int fd = TEMP_FAILURE_RETRY(open(good_path_.c_str(), O_CREAT|O_RDWR, 0666));
37     FdFile dst(fd);
38 
39     StringFile src;
40     src.Assign(kContent);
41 
42     ASSERT_TRUE(CopyFile(src, &dst));
43   }
44 
MakeTestFile()45   virtual RandomAccessFile* MakeTestFile() {
46     TEMP_FAILURE_RETRY(truncate(good_path_.c_str(), 0));
47     MappedFile* f = new MappedFile;
48     CHECK(f->Open(good_path_, MappedFile::kReadWriteMode));
49     return f;
50   }
51 
52   const std::string kContent;
53   std::string good_path_;
54 };
55 
TEST_F(MappedFileTest,OkayToNotUse)56 TEST_F(MappedFileTest, OkayToNotUse) {
57   MappedFile file;
58   EXPECT_EQ(-1, file.Fd());
59   EXPECT_FALSE(file.IsOpened());
60   EXPECT_FALSE(file.IsMapped());
61 }
62 
TEST_F(MappedFileTest,OpenClose)63 TEST_F(MappedFileTest, OpenClose) {
64   MappedFile file;
65   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
66   EXPECT_GE(file.Fd(), 0);
67   EXPECT_TRUE(file.IsOpened());
68   EXPECT_EQ(kContent.size(), file.size());
69   EXPECT_EQ(0, file.Close());
70   EXPECT_EQ(-1, file.Fd());
71   EXPECT_FALSE(file.IsOpened());
72 }
73 
TEST_F(MappedFileTest,OpenFdClose)74 TEST_F(MappedFileTest, OpenFdClose) {
75   FILE* f = tmpfile();
76   ASSERT_TRUE(f != NULL);
77   MappedFile file(fileno(f));
78   EXPECT_GE(file.Fd(), 0);
79   EXPECT_TRUE(file.IsOpened());
80   EXPECT_EQ(0, file.Close());
81 }
82 
TEST_F(MappedFileTest,CanUseAfterMapReadOnly)83 TEST_F(MappedFileTest, CanUseAfterMapReadOnly) {
84   MappedFile file;
85   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
86   EXPECT_FALSE(file.IsMapped());
87   EXPECT_TRUE(file.MapReadOnly());
88   EXPECT_TRUE(file.IsMapped());
89   EXPECT_EQ(kContent.size(), file.size());
90   ASSERT_TRUE(file.data());
91   EXPECT_EQ(0, memcmp(kContent.c_str(), file.data(), file.size()));
92   EXPECT_EQ(0, file.Flush());
93 }
94 
TEST_F(MappedFileTest,CanUseAfterMapReadWrite)95 TEST_F(MappedFileTest, CanUseAfterMapReadWrite) {
96   MappedFile file;
97   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode));
98   EXPECT_FALSE(file.IsMapped());
99   EXPECT_TRUE(file.MapReadWrite(1));
100   EXPECT_TRUE(file.IsMapped());
101   EXPECT_EQ(1, file.size());
102   ASSERT_TRUE(file.data());
103   EXPECT_EQ(kContent[0], *file.data());
104   EXPECT_EQ(0, file.Flush());
105 }
106 
TEST_F(MappedFileTest,CanWriteNewData)107 TEST_F(MappedFileTest, CanWriteNewData) {
108   const std::string new_path(GetTmpPath("new-file.txt"));
109   ASSERT_EQ(-1, unlink(new_path.c_str()));
110   ASSERT_EQ(ENOENT, errno);
111 
112   MappedFile file;
113   ASSERT_TRUE(file.Open(new_path, MappedFile::kReadWriteMode));
114   EXPECT_TRUE(file.MapReadWrite(kContent.size()));
115   EXPECT_TRUE(file.IsMapped());
116   EXPECT_EQ(kContent.size(), file.size());
117   ASSERT_TRUE(file.data());
118   memcpy(file.data(), kContent.c_str(), kContent.size());
119   EXPECT_EQ(0, file.Close());
120   EXPECT_FALSE(file.IsMapped());
121 
122   FdFile new_file(TEMP_FAILURE_RETRY(open(new_path.c_str(), O_RDONLY)));
123   StringFile buffer;
124   ASSERT_TRUE(CopyFile(new_file, &buffer));
125   EXPECT_EQ(kContent, buffer.ToStringPiece());
126   EXPECT_EQ(0, unlink(new_path.c_str()));
127 }
128 
TEST_F(MappedFileTest,FileMustExist)129 TEST_F(MappedFileTest, FileMustExist) {
130   const std::string bad_path(GetTmpPath("does-not-exist.txt"));
131   MappedFile file;
132   EXPECT_FALSE(file.Open(bad_path, MappedFile::kReadOnlyMode));
133   EXPECT_EQ(-1, file.Fd());
134 }
135 
TEST_F(MappedFileTest,FileMustBeWritable)136 TEST_F(MappedFileTest, FileMustBeWritable) {
137   MappedFile file;
138   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
139   EXPECT_FALSE(file.MapReadWrite(10));
140 }
141 
TEST_F(MappedFileTest,RemappingAllowedUntilSuccess)142 TEST_F(MappedFileTest, RemappingAllowedUntilSuccess) {
143   MappedFile file;
144   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
145   EXPECT_FALSE(file.MapReadWrite(10));
146   EXPECT_FALSE(file.MapReadWrite(10));
147 }
148 
TEST_F(MappedFileTest,ResizeMappedFile)149 TEST_F(MappedFileTest, ResizeMappedFile) {
150   MappedFile file;
151   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode));
152   ASSERT_TRUE(file.MapReadWrite(10));
153   EXPECT_EQ(10, file.GetLength());
154   EXPECT_TRUE(file.Unmap());
155   EXPECT_TRUE(file.MapReadWrite(20));
156   EXPECT_EQ(20, file.GetLength());
157   EXPECT_EQ(0, file.Flush());
158   EXPECT_TRUE(file.Unmap());
159   EXPECT_EQ(0, file.Flush());
160   EXPECT_EQ(0, file.SetLength(5));
161   EXPECT_TRUE(file.MapReadOnly());
162   EXPECT_EQ(5, file.GetLength());
163 }
164 
TEST_F(MappedFileTest,ReadNotMapped)165 TEST_F(MappedFileTest, ReadNotMapped) {
166   TestRead();
167 }
168 
TEST_F(MappedFileTest,SetLengthNotMapped)169 TEST_F(MappedFileTest, SetLengthNotMapped) {
170   TestSetLength();
171 }
172 
TEST_F(MappedFileTest,WriteNotMapped)173 TEST_F(MappedFileTest, WriteNotMapped) {
174   TestWrite();
175 }
176 
TEST_F(MappedFileTest,ReadMappedReadOnly)177 TEST_F(MappedFileTest, ReadMappedReadOnly) {
178   MappedFile file;
179   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
180   ASSERT_TRUE(file.MapReadOnly());
181   TestReadContent(kContent, &file);
182 }
183 
TEST_F(MappedFileTest,ReadMappedReadWrite)184 TEST_F(MappedFileTest, ReadMappedReadWrite) {
185   MappedFile file;
186   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode));
187   ASSERT_TRUE(file.MapReadWrite(kContent.size()));
188   TestReadContent(kContent, &file);
189 }
190 
TEST_F(MappedFileTest,WriteMappedReadWrite)191 TEST_F(MappedFileTest, WriteMappedReadWrite) {
192   TEMP_FAILURE_RETRY(unlink(good_path_.c_str()));
193   MappedFile file;
194   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode));
195   ASSERT_TRUE(file.MapReadWrite(kContent.size()));
196 
197   // Can't write to a negative offset.
198   EXPECT_EQ(-EINVAL, file.Write(kContent.c_str(), 0, -123));
199 
200   // A zero-length write is a no-op.
201   EXPECT_EQ(0, file.Write(kContent.c_str(), 0, 0));
202   // But the file size is as given when mapped.
203   EXPECT_EQ(kContent.size(), file.GetLength());
204 
205   // Data written past the end are discarded.
206   EXPECT_EQ(kContent.size() - 1,
207             file.Write(kContent.c_str(), kContent.size(), 1));
208   EXPECT_EQ(0, memcmp(kContent.c_str(), file.data() + 1, kContent.size() - 1));
209 
210   // Data can be overwritten.
211   EXPECT_EQ(kContent.size(), file.Write(kContent.c_str(), kContent.size(), 0));
212   EXPECT_EQ(0, memcmp(kContent.c_str(), file.data(), kContent.size()));
213 }
214 
215 #if 0  // death tests don't work on android yet
216 
217 class MappedFileDeathTest : public MappedFileTest {};
218 
219 TEST_F(MappedFileDeathTest, MustMapBeforeUse) {
220   MappedFile file;
221   EXPECT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
222   EXPECT_DEATH(file.data(), "mapped_");
223 }
224 
225 TEST_F(MappedFileDeathTest, RemappingNotAllowedReadOnly) {
226   MappedFile file;
227   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
228   ASSERT_TRUE(file.MapReadOnly());
229   EXPECT_DEATH(file.MapReadOnly(), "mapped_");
230 }
231 
232 TEST_F(MappedFileDeathTest, RemappingNotAllowedReadWrite) {
233   MappedFile file;
234   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode));
235   ASSERT_TRUE(file.MapReadWrite(10));
236   EXPECT_DEATH(file.MapReadWrite(10), "mapped_");
237 }
238 
239 TEST_F(MappedFileDeathTest, SetLengthMappedReadWrite) {
240   MappedFile file;
241   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode));
242   ASSERT_TRUE(file.MapReadWrite(10));
243   EXPECT_EQ(10, file.GetLength());
244   EXPECT_DEATH(file.SetLength(0), ".*");
245 }
246 
247 TEST_F(MappedFileDeathTest, SetLengthMappedReadOnly) {
248   MappedFile file;
249   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
250   ASSERT_TRUE(file.MapReadOnly());
251   EXPECT_EQ(kContent.size(), file.GetLength());
252   EXPECT_DEATH(file.SetLength(0), ".*");
253 }
254 
255 TEST_F(MappedFileDeathTest, WriteMappedReadOnly) {
256   MappedFile file;
257   ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
258   ASSERT_TRUE(file.MapReadOnly());
259   char buf[10];
260   EXPECT_DEATH(file.Write(buf, 0, 0), ".*");
261 }
262 
263 #endif
264 
265 }  // namespace unix_file
266