1 /* 2 * Copyright (C) 2016 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 <android-base/test_utils.h> 18 #include <android-base/file.h> 19 #include <gtest/gtest.h> 20 21 #include "Memory.h" 22 23 class MemoryFileTest : public ::testing::Test { 24 protected: 25 void SetUp() override { 26 tf_ = new TemporaryFile; 27 } 28 29 void TearDown() override { 30 delete tf_; 31 } 32 33 void WriteTestData() { 34 ASSERT_TRUE(android::base::WriteStringToFd("0123456789abcdefghijklmnopqrstuvxyz", tf_->fd)); 35 } 36 37 MemoryFileAtOffset memory_; 38 39 TemporaryFile* tf_ = nullptr; 40 }; 41 42 TEST_F(MemoryFileTest, offset_0) { 43 WriteTestData(); 44 45 ASSERT_TRUE(memory_.Init(tf_->path, 0)); 46 std::vector<char> buffer(11); 47 ASSERT_TRUE(memory_.Read(0, buffer.data(), 10)); 48 buffer[10] = '\0'; 49 ASSERT_STREQ("0123456789", buffer.data()); 50 } 51 52 TEST_F(MemoryFileTest, offset_non_zero) { 53 WriteTestData(); 54 55 ASSERT_TRUE(memory_.Init(tf_->path, 10)); 56 std::vector<char> buffer(11); 57 ASSERT_TRUE(memory_.Read(0, buffer.data(), 10)); 58 buffer[10] = '\0'; 59 ASSERT_STREQ("abcdefghij", buffer.data()); 60 } 61 62 TEST_F(MemoryFileTest, offset_non_zero_larger_than_pagesize) { 63 size_t pagesize = getpagesize(); 64 std::string large_string; 65 for (size_t i = 0; i < pagesize; i++) { 66 large_string += '1'; 67 } 68 large_string += "012345678901234abcdefgh"; 69 ASSERT_TRUE(android::base::WriteStringToFd(large_string, tf_->fd)); 70 71 ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 15)); 72 std::vector<char> buffer(9); 73 ASSERT_TRUE(memory_.Read(0, buffer.data(), 8)); 74 buffer[8] = '\0'; 75 ASSERT_STREQ("abcdefgh", buffer.data()); 76 } 77 78 TEST_F(MemoryFileTest, offset_pagesize_aligned) { 79 size_t pagesize = getpagesize(); 80 std::string data; 81 for (size_t i = 0; i < 2 * pagesize; i++) { 82 data += static_cast<char>((i / pagesize) + '0'); 83 data += static_cast<char>((i % 10) + '0'); 84 } 85 ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd)); 86 87 ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize)); 88 std::vector<char> buffer(11); 89 ASSERT_TRUE(memory_.Read(0, buffer.data(), 10)); 90 buffer[10] = '\0'; 91 std::string expected_str; 92 for (size_t i = 0; i < 5; i++) { 93 expected_str += '1'; 94 expected_str += static_cast<char>(((i + pagesize) % 10) + '0'); 95 } 96 ASSERT_STREQ(expected_str.c_str(), buffer.data()); 97 } 98 99 TEST_F(MemoryFileTest, offset_pagesize_aligned_plus_extra) { 100 size_t pagesize = getpagesize(); 101 std::string data; 102 for (size_t i = 0; i < 2 * pagesize; i++) { 103 data += static_cast<char>((i / pagesize) + '0'); 104 data += static_cast<char>((i % 10) + '0'); 105 } 106 ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd)); 107 108 ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize + 10)); 109 std::vector<char> buffer(11); 110 ASSERT_TRUE(memory_.Read(0, buffer.data(), 10)); 111 buffer[10] = '\0'; 112 std::string expected_str; 113 for (size_t i = 0; i < 5; i++) { 114 expected_str += '1'; 115 expected_str += static_cast<char>(((i + pagesize + 5) % 10) + '0'); 116 } 117 ASSERT_STREQ(expected_str.c_str(), buffer.data()); 118 } 119 120 TEST_F(MemoryFileTest, read_error) { 121 std::string data; 122 for (size_t i = 0; i < 5000; i++) { 123 data += static_cast<char>((i % 10) + '0'); 124 } 125 ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd)); 126 127 std::vector<char> buffer(100); 128 129 // Read before init. 130 ASSERT_FALSE(memory_.Read(0, buffer.data(), 10)); 131 132 ASSERT_TRUE(memory_.Init(tf_->path, 0)); 133 134 ASSERT_FALSE(memory_.Read(10000, buffer.data(), 10)); 135 ASSERT_FALSE(memory_.Read(5000, buffer.data(), 10)); 136 ASSERT_FALSE(memory_.Read(4990, buffer.data(), 11)); 137 ASSERT_TRUE(memory_.Read(4990, buffer.data(), 10)); 138 ASSERT_FALSE(memory_.Read(4999, buffer.data(), 2)); 139 ASSERT_TRUE(memory_.Read(4999, buffer.data(), 1)); 140 } 141 142 TEST_F(MemoryFileTest, read_string) { 143 std::string value("name_in_file"); 144 ASSERT_TRUE(android::base::WriteFully(tf_->fd, value.c_str(), value.size() + 1)); 145 146 std::string name; 147 ASSERT_TRUE(memory_.Init(tf_->path, 0)); 148 ASSERT_TRUE(memory_.ReadString(0, &name)); 149 ASSERT_EQ("name_in_file", name); 150 ASSERT_TRUE(memory_.ReadString(5, &name)); 151 ASSERT_EQ("in_file", name); 152 } 153 154 TEST_F(MemoryFileTest, read_string_error) { 155 std::vector<uint8_t> buffer = { 0x23, 0x32, 0x45 }; 156 ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); 157 158 std::string name; 159 ASSERT_TRUE(memory_.Init(tf_->path, 0)); 160 161 // Read from a non-existant address. 162 ASSERT_FALSE(memory_.ReadString(100, &name)); 163 164 // This should fail because there is no terminating \0 165 ASSERT_FALSE(memory_.ReadString(0, &name)); 166 } 167 168 TEST_F(MemoryFileTest, read_past_file_within_mapping) { 169 size_t pagesize = getpagesize(); 170 171 ASSERT_TRUE(pagesize > 100); 172 std::vector<uint8_t> buffer(pagesize - 100); 173 for (size_t i = 0; i < pagesize - 100; i++) { 174 buffer[i] = static_cast<uint8_t>((i % 0x5e) + 0x20); 175 } 176 ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); 177 178 ASSERT_TRUE(memory_.Init(tf_->path, 0)); 179 180 for (size_t i = 0; i < 100; i++) { 181 uint8_t value; 182 ASSERT_FALSE(memory_.Read(buffer.size() + i, &value, 1)) << "Should have failed at value " << i; 183 } 184 } 185 186 TEST_F(MemoryFileTest, map_partial_offset_aligned) { 187 size_t pagesize = getpagesize(); 188 std::vector<uint8_t> buffer(pagesize * 10); 189 for (size_t i = 0; i < pagesize * 10; i++) { 190 buffer[i] = i / pagesize + 1; 191 } 192 ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); 193 194 // Map in only two pages of the data, and after the first page. 195 ASSERT_TRUE(memory_.Init(tf_->path, pagesize, pagesize * 2)); 196 197 std::vector<uint8_t> read_buffer(pagesize * 2); 198 // Make sure that reading after mapped data is a failure. 199 ASSERT_FALSE(memory_.Read(pagesize * 2, read_buffer.data(), 1)); 200 ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize * 2)); 201 for (size_t i = 0; i < pagesize; i++) { 202 ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i; 203 } 204 for (size_t i = pagesize; i < pagesize * 2; i++) { 205 ASSERT_EQ(3, read_buffer[i]) << "Failed at byte " << i; 206 } 207 } 208 209 TEST_F(MemoryFileTest, map_partial_offset_unaligned) { 210 size_t pagesize = getpagesize(); 211 ASSERT_TRUE(pagesize > 0x100); 212 std::vector<uint8_t> buffer(pagesize * 10); 213 for (size_t i = 0; i < buffer.size(); i++) { 214 buffer[i] = i / pagesize + 1; 215 } 216 ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); 217 218 // Map in only two pages of the data, and after the first page. 219 ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, pagesize * 2)); 220 221 std::vector<uint8_t> read_buffer(pagesize * 2); 222 // Make sure that reading after mapped data is a failure. 223 ASSERT_FALSE(memory_.Read(pagesize * 2, read_buffer.data(), 1)); 224 ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize * 2)); 225 for (size_t i = 0; i < pagesize - 0x100; i++) { 226 ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i; 227 } 228 for (size_t i = pagesize - 0x100; i < 2 * pagesize - 0x100; i++) { 229 ASSERT_EQ(3, read_buffer[i]) << "Failed at byte " << i; 230 } 231 for (size_t i = 2 * pagesize - 0x100; i < pagesize * 2; i++) { 232 ASSERT_EQ(4, read_buffer[i]) << "Failed at byte " << i; 233 } 234 } 235 236 TEST_F(MemoryFileTest, map_overflow) { 237 size_t pagesize = getpagesize(); 238 ASSERT_TRUE(pagesize > 0x100); 239 std::vector<uint8_t> buffer(pagesize * 10); 240 for (size_t i = 0; i < buffer.size(); i++) { 241 buffer[i] = i / pagesize + 1; 242 } 243 ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); 244 245 // Map in only two pages of the data, and after the first page. 246 ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, UINT64_MAX)); 247 248 std::vector<uint8_t> read_buffer(pagesize * 10); 249 ASSERT_FALSE(memory_.Read(pagesize * 9 - 0x100 + 1, read_buffer.data(), 1)); 250 ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize * 9 - 0x100)); 251 } 252 253 TEST_F(MemoryFileTest, init_reinit) { 254 size_t pagesize = getpagesize(); 255 std::vector<uint8_t> buffer(pagesize * 2); 256 for (size_t i = 0; i < buffer.size(); i++) { 257 buffer[i] = i / pagesize + 1; 258 } 259 ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); 260 261 ASSERT_TRUE(memory_.Init(tf_->path, 0)); 262 std::vector<uint8_t> read_buffer(buffer.size()); 263 ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize)); 264 for (size_t i = 0; i < pagesize; i++) { 265 ASSERT_EQ(1, read_buffer[i]) << "Failed at byte " << i; 266 } 267 268 // Now reinit. 269 ASSERT_TRUE(memory_.Init(tf_->path, pagesize)); 270 ASSERT_TRUE(memory_.Read(0, read_buffer.data(), pagesize)); 271 for (size_t i = 0; i < pagesize; i++) { 272 ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i; 273 } 274 } 275