Home | History | Annotate | Download | only in payload_consumer
      1 //
      2 // Copyright (C) 2017 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_consumer/extent_reader.h"
     18 
     19 #include <fcntl.h>
     20 
     21 #include <algorithm>
     22 #include <string>
     23 #include <vector>
     24 
     25 #include <brillo/secure_blob.h>
     26 #include <gtest/gtest.h>
     27 
     28 #include "update_engine/common/test_utils.h"
     29 #include "update_engine/common/utils.h"
     30 #include "update_engine/payload_consumer/file_descriptor.h"
     31 #include "update_engine/payload_consumer/payload_constants.h"
     32 #include "update_engine/payload_generator/extent_ranges.h"
     33 #include "update_engine/payload_generator/extent_utils.h"
     34 
     35 using chromeos_update_engine::test_utils::ExpectVectorsEq;
     36 using std::min;
     37 using std::string;
     38 using std::vector;
     39 
     40 namespace chromeos_update_engine {
     41 
     42 namespace {
     43 const size_t kBlockSize = 8;
     44 const size_t kRandomIterations = 1000;
     45 }  // namespace
     46 
     47 class ExtentReaderTest : public ::testing::Test {
     48  protected:
     49   void SetUp() override {
     50     sample_.resize(4096 * 10);
     51     srand(time(nullptr));
     52     unsigned int rand_seed;
     53     for (size_t i = 0; i < sample_.size(); i++) {
     54       sample_[i] = rand_r(&rand_seed) % 256;
     55     }
     56     ASSERT_TRUE(utils::WriteFile(
     57         temp_file_.path().c_str(), sample_.data(), sample_.size()));
     58 
     59     fd_.reset(new EintrSafeFileDescriptor());
     60     ASSERT_TRUE(fd_->Open(temp_file_.path().c_str(), O_RDONLY, 0600));
     61   }
     62   void TearDown() override { fd_->Close(); }
     63 
     64   void ReadExtents(vector<Extent> extents, brillo::Blob* blob) {
     65     blob->clear();
     66     for (const auto& extent : extents) {
     67       blob->insert(
     68           blob->end(),
     69           &sample_[extent.start_block() * kBlockSize],
     70           &sample_[(extent.start_block() + extent.num_blocks()) * kBlockSize]);
     71     }
     72   }
     73 
     74   FileDescriptorPtr fd_;
     75   test_utils::ScopedTempFile temp_file_{"ExtentReaderTest-file.XXXXXX"};
     76   brillo::Blob sample_;
     77 };
     78 
     79 TEST_F(ExtentReaderTest, SimpleTest) {
     80   vector<Extent> extents = {ExtentForRange(1, 1)};
     81   DirectExtentReader reader;
     82   EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
     83   EXPECT_TRUE(reader.Seek(0));
     84   brillo::Blob blob1(utils::BlocksInExtents(extents) * kBlockSize);
     85   EXPECT_TRUE(reader.Read(blob1.data(), blob1.size()));
     86   brillo::Blob blob2;
     87   ReadExtents(extents, &blob2);
     88   ExpectVectorsEq(blob1, blob2);
     89 }
     90 
     91 TEST_F(ExtentReaderTest, ZeroExtentLengthTest) {
     92   vector<Extent> extents = {ExtentForRange(1, 0)};
     93   DirectExtentReader reader;
     94   EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
     95   EXPECT_TRUE(reader.Seek(0));
     96   brillo::Blob blob(1);
     97   EXPECT_TRUE(reader.Read(blob.data(), 0));
     98   EXPECT_FALSE(reader.Read(blob.data(), 1));
     99 }
    100 
    101 TEST_F(ExtentReaderTest, NoExtentTest) {
    102   DirectExtentReader reader;
    103   EXPECT_TRUE(reader.Init(fd_, {}, kBlockSize));
    104   EXPECT_TRUE(reader.Seek(0));
    105   brillo::Blob blob(1);
    106   EXPECT_TRUE(reader.Read(blob.data(), 0));
    107   EXPECT_FALSE(reader.Read(blob.data(), 1));
    108 }
    109 
    110 TEST_F(ExtentReaderTest, OverflowExtentTest) {
    111   vector<Extent> extents = {ExtentForRange(1, 1)};
    112   DirectExtentReader reader;
    113   EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
    114   EXPECT_TRUE(reader.Seek(0));
    115   brillo::Blob blob(utils::BlocksInExtents(extents) * kBlockSize + 1);
    116   EXPECT_FALSE(reader.Read(blob.data(), blob.size()));
    117 }
    118 
    119 TEST_F(ExtentReaderTest, SeekOverflow1Test) {
    120   vector<Extent> extents = {ExtentForRange(1, 0)};
    121   DirectExtentReader reader;
    122   EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
    123   EXPECT_TRUE(reader.Seek(0));
    124   EXPECT_FALSE(reader.Seek(1));
    125 }
    126 
    127 TEST_F(ExtentReaderTest, SeekOverflow2Test) {
    128   DirectExtentReader reader;
    129   reader.Init(fd_, {}, kBlockSize);
    130   EXPECT_TRUE(reader.Seek(0));
    131   EXPECT_FALSE(reader.Seek(1));
    132 }
    133 
    134 TEST_F(ExtentReaderTest, SeekOverflow3Test) {
    135   vector<Extent> extents = {ExtentForRange(1, 1)};
    136   DirectExtentReader reader;
    137   EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
    138   // Seek to the end of the extents should be fine as long as nothing is read.
    139   EXPECT_TRUE(reader.Seek(kBlockSize));
    140   EXPECT_FALSE(reader.Seek(kBlockSize + 1));
    141 }
    142 
    143 TEST_F(ExtentReaderTest, RandomReadTest) {
    144   vector<Extent> extents = {ExtentForRange(0, 0),
    145                             ExtentForRange(1, 1),
    146                             ExtentForRange(3, 0),
    147                             ExtentForRange(4, 2),
    148                             ExtentForRange(7, 1)};
    149   DirectExtentReader reader;
    150   EXPECT_TRUE(reader.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
    151 
    152   brillo::Blob result;
    153   ReadExtents(extents, &result);
    154 
    155   brillo::Blob blob(utils::BlocksInExtents(extents) * kBlockSize);
    156   srand(time(nullptr));
    157   uint32_t rand_seed;
    158   for (size_t idx = 0; idx < kRandomIterations; idx++) {
    159     // zero to full size available.
    160     size_t start = rand_r(&rand_seed) % blob.size();
    161     size_t size = rand_r(&rand_seed) % (blob.size() - start);
    162     EXPECT_TRUE(reader.Seek(start));
    163     EXPECT_TRUE(reader.Read(blob.data(), size));
    164     for (size_t i = 0; i < size; i++) {
    165       ASSERT_EQ(blob[i], result[start + i]);
    166     }
    167   }
    168 }
    169 
    170 }  // namespace chromeos_update_engine
    171