mapped_file_test.cc revision f896965072343a2d6ad64d46a61112b10b3645dd
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 RandomAccessFileTest::SetUp(); 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 void TearDown() { 46 ASSERT_EQ(unlink(good_path_.c_str()), 0); 47 48 RandomAccessFileTest::TearDown(); 49 } 50 51 virtual RandomAccessFile* MakeTestFile() { 52 TEMP_FAILURE_RETRY(truncate(good_path_.c_str(), 0)); 53 MappedFile* f = new MappedFile; 54 CHECK(f->Open(good_path_, MappedFile::kReadWriteMode)); 55 return f; 56 } 57 58 const std::string kContent; 59 std::string good_path_; 60}; 61 62TEST_F(MappedFileTest, OkayToNotUse) { 63 MappedFile file; 64 EXPECT_EQ(-1, file.Fd()); 65 EXPECT_FALSE(file.IsOpened()); 66 EXPECT_FALSE(file.IsMapped()); 67} 68 69TEST_F(MappedFileTest, OpenClose) { 70 MappedFile file; 71 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 72 EXPECT_GE(file.Fd(), 0); 73 EXPECT_TRUE(file.IsOpened()); 74 EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size())); 75 EXPECT_EQ(0, file.Close()); 76 EXPECT_EQ(-1, file.Fd()); 77 EXPECT_FALSE(file.IsOpened()); 78} 79 80TEST_F(MappedFileTest, OpenFdClose) { 81 FILE* f = tmpfile(); 82 ASSERT_TRUE(f != NULL); 83 MappedFile file(fileno(f)); 84 EXPECT_GE(file.Fd(), 0); 85 EXPECT_TRUE(file.IsOpened()); 86 EXPECT_EQ(0, file.Close()); 87} 88 89TEST_F(MappedFileTest, CanUseAfterMapReadOnly) { 90 MappedFile file; 91 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 92 EXPECT_FALSE(file.IsMapped()); 93 EXPECT_TRUE(file.MapReadOnly()); 94 EXPECT_TRUE(file.IsMapped()); 95 EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size())); 96 ASSERT_TRUE(file.data()); 97 EXPECT_EQ(0, memcmp(kContent.c_str(), file.data(), file.size())); 98 EXPECT_EQ(0, file.Flush()); 99} 100 101TEST_F(MappedFileTest, CanUseAfterMapReadWrite) { 102 MappedFile file; 103 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode)); 104 EXPECT_FALSE(file.IsMapped()); 105 EXPECT_TRUE(file.MapReadWrite(1)); 106 EXPECT_TRUE(file.IsMapped()); 107 EXPECT_EQ(1, file.size()); 108 ASSERT_TRUE(file.data()); 109 EXPECT_EQ(kContent[0], *file.data()); 110 EXPECT_EQ(0, file.Flush()); 111} 112 113TEST_F(MappedFileTest, CanWriteNewData) { 114 const std::string new_path(GetTmpPath("new-file.txt")); 115 ASSERT_EQ(-1, unlink(new_path.c_str())); 116 ASSERT_EQ(ENOENT, errno); 117 118 MappedFile file; 119 ASSERT_TRUE(file.Open(new_path, MappedFile::kReadWriteMode)); 120 EXPECT_TRUE(file.MapReadWrite(kContent.size())); 121 EXPECT_TRUE(file.IsMapped()); 122 EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.size())); 123 ASSERT_TRUE(file.data()); 124 memcpy(file.data(), kContent.c_str(), kContent.size()); 125 EXPECT_EQ(0, file.Close()); 126 EXPECT_FALSE(file.IsMapped()); 127 128 FdFile new_file(TEMP_FAILURE_RETRY(open(new_path.c_str(), O_RDONLY))); 129 StringFile buffer; 130 ASSERT_TRUE(CopyFile(new_file, &buffer)); 131 EXPECT_EQ(kContent, buffer.ToStringPiece()); 132 EXPECT_EQ(0, unlink(new_path.c_str())); 133} 134 135TEST_F(MappedFileTest, FileMustExist) { 136 const std::string bad_path(GetTmpPath("does-not-exist.txt")); 137 MappedFile file; 138 EXPECT_FALSE(file.Open(bad_path, MappedFile::kReadOnlyMode)); 139 EXPECT_EQ(-1, file.Fd()); 140} 141 142TEST_F(MappedFileTest, FileMustBeWritable) { 143 MappedFile file; 144 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 145 EXPECT_FALSE(file.MapReadWrite(10)); 146} 147 148TEST_F(MappedFileTest, RemappingAllowedUntilSuccess) { 149 MappedFile file; 150 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 151 EXPECT_FALSE(file.MapReadWrite(10)); 152 EXPECT_FALSE(file.MapReadWrite(10)); 153} 154 155TEST_F(MappedFileTest, ResizeMappedFile) { 156 MappedFile file; 157 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode)); 158 ASSERT_TRUE(file.MapReadWrite(10)); 159 EXPECT_EQ(10, file.GetLength()); 160 EXPECT_TRUE(file.Unmap()); 161 EXPECT_TRUE(file.MapReadWrite(20)); 162 EXPECT_EQ(20, file.GetLength()); 163 EXPECT_EQ(0, file.Flush()); 164 EXPECT_TRUE(file.Unmap()); 165 EXPECT_EQ(0, file.Flush()); 166 EXPECT_EQ(0, file.SetLength(5)); 167 EXPECT_TRUE(file.MapReadOnly()); 168 EXPECT_EQ(5, file.GetLength()); 169} 170 171TEST_F(MappedFileTest, ReadNotMapped) { 172 TestRead(); 173} 174 175TEST_F(MappedFileTest, SetLengthNotMapped) { 176 TestSetLength(); 177} 178 179TEST_F(MappedFileTest, WriteNotMapped) { 180 TestWrite(); 181} 182 183TEST_F(MappedFileTest, ReadMappedReadOnly) { 184 MappedFile file; 185 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 186 ASSERT_TRUE(file.MapReadOnly()); 187 TestReadContent(kContent, &file); 188} 189 190TEST_F(MappedFileTest, ReadMappedReadWrite) { 191 MappedFile file; 192 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode)); 193 ASSERT_TRUE(file.MapReadWrite(kContent.size())); 194 TestReadContent(kContent, &file); 195} 196 197TEST_F(MappedFileTest, WriteMappedReadWrite) { 198 TEMP_FAILURE_RETRY(unlink(good_path_.c_str())); 199 MappedFile file; 200 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode)); 201 ASSERT_TRUE(file.MapReadWrite(kContent.size())); 202 203 // Can't write to a negative offset. 204 EXPECT_EQ(-EINVAL, file.Write(kContent.c_str(), 0, -123)); 205 206 // A zero-length write is a no-op. 207 EXPECT_EQ(0, file.Write(kContent.c_str(), 0, 0)); 208 // But the file size is as given when mapped. 209 EXPECT_EQ(kContent.size(), static_cast<uint64_t>(file.GetLength())); 210 211 // Data written past the end are discarded. 212 EXPECT_EQ(kContent.size() - 1, 213 static_cast<uint64_t>(file.Write(kContent.c_str(), kContent.size(), 1))); 214 EXPECT_EQ(0, memcmp(kContent.c_str(), file.data() + 1, kContent.size() - 1)); 215 216 // Data can be overwritten. 217 EXPECT_EQ(kContent.size(), 218 static_cast<uint64_t>(file.Write(kContent.c_str(), kContent.size(), 0))); 219 EXPECT_EQ(0, memcmp(kContent.c_str(), file.data(), kContent.size())); 220} 221 222#if 0 // death tests don't work on android yet 223 224class MappedFileDeathTest : public MappedFileTest {}; 225 226TEST_F(MappedFileDeathTest, MustMapBeforeUse) { 227 MappedFile file; 228 EXPECT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 229 EXPECT_DEATH(file.data(), "mapped_"); 230} 231 232TEST_F(MappedFileDeathTest, RemappingNotAllowedReadOnly) { 233 MappedFile file; 234 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 235 ASSERT_TRUE(file.MapReadOnly()); 236 EXPECT_DEATH(file.MapReadOnly(), "mapped_"); 237} 238 239TEST_F(MappedFileDeathTest, RemappingNotAllowedReadWrite) { 240 MappedFile file; 241 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode)); 242 ASSERT_TRUE(file.MapReadWrite(10)); 243 EXPECT_DEATH(file.MapReadWrite(10), "mapped_"); 244} 245 246TEST_F(MappedFileDeathTest, SetLengthMappedReadWrite) { 247 MappedFile file; 248 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadWriteMode)); 249 ASSERT_TRUE(file.MapReadWrite(10)); 250 EXPECT_EQ(10, file.GetLength()); 251 EXPECT_DEATH(file.SetLength(0), ".*"); 252} 253 254TEST_F(MappedFileDeathTest, SetLengthMappedReadOnly) { 255 MappedFile file; 256 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 257 ASSERT_TRUE(file.MapReadOnly()); 258 EXPECT_EQ(kContent.size(), file.GetLength()); 259 EXPECT_DEATH(file.SetLength(0), ".*"); 260} 261 262TEST_F(MappedFileDeathTest, WriteMappedReadOnly) { 263 MappedFile file; 264 ASSERT_TRUE(file.Open(good_path_, MappedFile::kReadOnlyMode)); 265 ASSERT_TRUE(file.MapReadOnly()); 266 char buf[10]; 267 EXPECT_DEATH(file.Write(buf, 0, 0), ".*"); 268} 269 270#endif 271 272} // namespace unix_file 273