Home | History | Annotate | Download | only in tests
      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