• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SetUp()25   void SetUp() override {
26     tf_ = new TemporaryFile;
27   }
28 
TearDown()29   void TearDown() override {
30     delete tf_;
31   }
32 
WriteTestData()33   void WriteTestData() {
34     ASSERT_TRUE(android::base::WriteStringToFd("0123456789abcdefghijklmnopqrstuvxyz", tf_->fd));
35   }
36 
37   MemoryFileAtOffset memory_;
38 
39   TemporaryFile* tf_ = nullptr;
40 };
41 
TEST_F(MemoryFileTest,offset_0)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 
TEST_F(MemoryFileTest,offset_non_zero)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 
TEST_F(MemoryFileTest,offset_non_zero_larger_than_pagesize)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 
TEST_F(MemoryFileTest,offset_pagesize_aligned)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 
TEST_F(MemoryFileTest,offset_pagesize_aligned_plus_extra)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 
TEST_F(MemoryFileTest,read_error)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 
TEST_F(MemoryFileTest,read_string)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 
TEST_F(MemoryFileTest,read_string_error)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 
TEST_F(MemoryFileTest,read_past_file_within_mapping)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 
TEST_F(MemoryFileTest,map_partial_offset_aligned)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 
TEST_F(MemoryFileTest,map_partial_offset_unaligned)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 
TEST_F(MemoryFileTest,map_overflow)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 
TEST_F(MemoryFileTest,init_reinit)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