mapped_file_test.cc revision 7940e44f4517de5e2634a7e07d58d0fb26160513
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
25namespace unix_file {
26
27class MappedFileTest : public RandomAccessFileTest {
28 protected:
29  MappedFileTest() : kContent("some content") {
30  }
31
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
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
56TEST_F(MappedFileTest, OkayToNotUse) {
57  MappedFile file;
58  EXPECT_EQ(-1, file.Fd());
59  EXPECT_FALSE(file.IsOpened());
60  EXPECT_FALSE(file.IsMapped());
61}
62
63TEST_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
74TEST_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
83TEST_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
95TEST_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
107TEST_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
129TEST_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
136TEST_F(MappedFileTest, FileMustBeWritable) {
137  MappedFile file;
138  ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
139  EXPECT_FALSE(file.MapReadWrite(10));
140}
141
142TEST_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
149TEST_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
165TEST_F(MappedFileTest, ReadNotMapped) {
166  TestRead();
167}
168
169TEST_F(MappedFileTest, SetLengthNotMapped) {
170  TestSetLength();
171}
172
173TEST_F(MappedFileTest, WriteNotMapped) {
174  TestWrite();
175}
176
177TEST_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
184TEST_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
191TEST_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
217class MappedFileDeathTest : public MappedFileTest {};
218
219TEST_F(MappedFileDeathTest, MustMapBeforeUse) {
220  MappedFile file;
221  EXPECT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode));
222  EXPECT_DEATH(file.data(), "mapped_");
223}
224
225TEST_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
232TEST_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
239TEST_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
247TEST_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
255TEST_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