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