Home | History | Annotate | Download | only in payload_generator
      1 //
      2 // Copyright (C) 2015 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 "update_engine/payload_generator/block_mapping.h"
     18 
     19 #include <fcntl.h>
     20 #include <sys/stat.h>
     21 #include <sys/types.h>
     22 
     23 #include <string>
     24 #include <vector>
     25 
     26 #include <gtest/gtest.h>
     27 
     28 #include "update_engine/common/test_utils.h"
     29 #include "update_engine/common/utils.h"
     30 
     31 using std::string;
     32 using std::vector;
     33 
     34 namespace chromeos_update_engine {
     35 
     36 namespace {
     37 
     38 }  // namespace
     39 
     40 class BlockMappingTest : public ::testing::Test {
     41  protected:
     42   void SetUp() override {
     43     EXPECT_TRUE(utils::MakeTempFile("BlockMappingTest_old.XXXXXX",
     44                                     &old_part_path_,
     45                                     nullptr));
     46     EXPECT_TRUE(utils::MakeTempFile("BlockMappingTest_new.XXXXXX",
     47                                     &new_part_path_,
     48                                     nullptr));
     49 
     50     old_part_unlinker_.reset(new ScopedPathUnlinker(old_part_path_));
     51     new_part_unlinker_.reset(new ScopedPathUnlinker(new_part_path_));
     52   }
     53 
     54   // Old new partition files used in testing.
     55   string old_part_path_;
     56   string new_part_path_;
     57   std::unique_ptr<ScopedPathUnlinker> old_part_unlinker_;
     58   std::unique_ptr<ScopedPathUnlinker> new_part_unlinker_;
     59 
     60   size_t block_size_{1024};
     61   BlockMapping bm_{block_size_};  // BlockMapping under test.
     62 };
     63 
     64 TEST_F(BlockMappingTest, FirstAddedBlockIsZero) {
     65   brillo::Blob blob(block_size_);
     66   // The BlockMapping just assigns the block ids in order, so it doesn't matter
     67   // what are the contents of the first block.
     68   blob[0] = 42;
     69   EXPECT_EQ(0, bm_.AddBlock(blob));
     70   blob[0] = 5;
     71   EXPECT_EQ(1, bm_.AddBlock(blob));
     72 }
     73 
     74 TEST_F(BlockMappingTest, BlocksAreNotKeptInMemory) {
     75   test_utils::WriteFileString(old_part_path_, string(block_size_, 'a'));
     76   int old_fd = HANDLE_EINTR(open(old_part_path_.c_str(), O_RDONLY));
     77   ScopedFdCloser old_fd_closer(&old_fd);
     78 
     79   EXPECT_EQ(0, bm_.AddDiskBlock(old_fd, 0));
     80 
     81   // Check that the block_data is not stored on memory if we just used the block
     82   // once.
     83   for (const auto& it : bm_.mapping_) {
     84     for (const BlockMapping::UniqueBlock& ublock : it.second) {
     85       EXPECT_TRUE(ublock.block_data.empty());
     86     }
     87   }
     88 
     89   brillo::Blob block(block_size_, 'a');
     90   for (int i = 0; i < 5; ++i) {
     91     // Re-add the same block 5 times.
     92     EXPECT_EQ(0, bm_.AddBlock(block));
     93   }
     94 
     95   for (const auto& it : bm_.mapping_) {
     96     for (const BlockMapping::UniqueBlock& ublock : it.second) {
     97       EXPECT_FALSE(ublock.block_data.empty());
     98       // The block was loaded from disk only 4 times, and after that the counter
     99       // is not updated anymore.
    100       EXPECT_EQ(4U, ublock.times_read);
    101     }
    102   }
    103 }
    104 
    105 TEST_F(BlockMappingTest, MapPartitionBlocks) {
    106   // A string with 10 blocks where all the blocks are different.
    107   string old_contents(10 * block_size_, '\0');
    108   for (size_t i = 0; i < old_contents.size(); ++i)
    109     old_contents[i] = 4 + i / block_size_;
    110   test_utils::WriteFileString(old_part_path_, old_contents);
    111 
    112   // A string including the block with all zeros and overlapping some of the
    113   // other blocks in old_contents.
    114   string new_contents(6 * block_size_, '\0');
    115   for (size_t i = 0; i < new_contents.size(); ++i)
    116     new_contents[i] = i / block_size_;
    117   test_utils::WriteFileString(new_part_path_, new_contents);
    118 
    119   vector<BlockMapping::BlockId> old_ids, new_ids;
    120   EXPECT_TRUE(MapPartitionBlocks(old_part_path_,
    121                                  new_part_path_,
    122                                  old_contents.size(),
    123                                  new_contents.size(),
    124                                  block_size_,
    125                                  &old_ids,
    126                                  &new_ids));
    127 
    128   EXPECT_EQ((vector<BlockMapping::BlockId>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
    129             old_ids);
    130   EXPECT_EQ((vector<BlockMapping::BlockId>{0, 11, 12, 13, 1, 2}),
    131             new_ids);
    132 }
    133 
    134 }  // namespace chromeos_update_engine
    135