Home | History | Annotate | Download | only in payload_generator
      1 //
      2 // Copyright (C) 2011 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 <string.h>
     18 #include <unistd.h>
     19 
     20 #include <memory>
     21 #include <string>
     22 #include <vector>
     23 
     24 #include <gtest/gtest.h>
     25 
     26 #include "update_engine/common/test_utils.h"
     27 #include "update_engine/payload_consumer/bzip_extent_writer.h"
     28 #include "update_engine/payload_consumer/extent_writer.h"
     29 #include "update_engine/payload_consumer/xz_extent_writer.h"
     30 #include "update_engine/payload_generator/bzip.h"
     31 #include "update_engine/payload_generator/xz.h"
     32 
     33 using chromeos_update_engine::test_utils::kRandomString;
     34 using google::protobuf::RepeatedPtrField;
     35 using std::string;
     36 using std::vector;
     37 
     38 namespace chromeos_update_engine {
     39 
     40 namespace {
     41 
     42 // ExtentWriter class that writes to memory, used to test the decompression
     43 // step with the corresponding extent writer.
     44 class MemoryExtentWriter : public ExtentWriter {
     45  public:
     46   // Creates the ExtentWriter that will write all the bytes to the passed |data|
     47   // blob.
     48   explicit MemoryExtentWriter(brillo::Blob* data) : data_(data) {
     49     data_->clear();
     50   }
     51   ~MemoryExtentWriter() override = default;
     52 
     53   bool Init(FileDescriptorPtr fd,
     54             const RepeatedPtrField<Extent>& extents,
     55             uint32_t block_size) override {
     56     return true;
     57   }
     58   bool Write(const void* bytes, size_t count) override {
     59     data_->reserve(data_->size() + count);
     60     data_->insert(data_->end(),
     61                   static_cast<const uint8_t*>(bytes),
     62                   static_cast<const uint8_t*>(bytes) + count);
     63     return true;
     64   }
     65   bool EndImpl() override { return true; }
     66 
     67  private:
     68   brillo::Blob* data_;
     69 };
     70 
     71 template <typename W>
     72 bool DecompressWithWriter(const brillo::Blob& in, brillo::Blob* out) {
     73   std::unique_ptr<ExtentWriter> writer(
     74       new W(std::make_unique<MemoryExtentWriter>(out)));
     75   // Init() parameters are ignored by the testing MemoryExtentWriter.
     76   bool ok = writer->Init(nullptr, {}, 1);
     77   ok = writer->Write(in.data(), in.size()) && ok;
     78   // Call End() even if the Write failed.
     79   ok = writer->End() && ok;
     80   return ok;
     81 }
     82 
     83 }  // namespace
     84 
     85 template <typename T>
     86 class ZipTest : public ::testing::Test {
     87  public:
     88   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const = 0;
     89   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const = 0;
     90 };
     91 
     92 class BzipTest {};
     93 
     94 template <>
     95 class ZipTest<BzipTest> : public ::testing::Test {
     96  public:
     97   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const {
     98     return BzipCompress(in, out);
     99   }
    100   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const {
    101     return DecompressWithWriter<BzipExtentWriter>(in, out);
    102   }
    103 };
    104 
    105 class XzTest {};
    106 
    107 template <>
    108 class ZipTest<XzTest> : public ::testing::Test {
    109  public:
    110   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const {
    111     return XzCompress(in, out);
    112   }
    113   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const {
    114     return DecompressWithWriter<XzExtentWriter>(in, out);
    115   }
    116 };
    117 
    118 #ifdef __ANDROID__
    119 typedef ::testing::Types<BzipTest, XzTest> ZipTestTypes;
    120 #else
    121 // Chrome OS implementation of Xz compressor just returns false.
    122 typedef ::testing::Types<BzipTest> ZipTestTypes;
    123 #endif  // __ANDROID__
    124 
    125 TYPED_TEST_CASE(ZipTest, ZipTestTypes);
    126 
    127 TYPED_TEST(ZipTest, SimpleTest) {
    128   string in_str(
    129       "this should compress well xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    130       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    131       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    132       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    133       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    134       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    135   brillo::Blob in(in_str.begin(), in_str.end());
    136   brillo::Blob out;
    137   EXPECT_TRUE(this->ZipCompress(in, &out));
    138   EXPECT_LT(out.size(), in.size());
    139   EXPECT_GT(out.size(), 0U);
    140   brillo::Blob decompressed;
    141   EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
    142   EXPECT_EQ(in.size(), decompressed.size());
    143   EXPECT_TRUE(!memcmp(in.data(), decompressed.data(), in.size()));
    144 }
    145 
    146 TYPED_TEST(ZipTest, PoorCompressionTest) {
    147   brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
    148   brillo::Blob out;
    149   EXPECT_TRUE(this->ZipCompress(in, &out));
    150   EXPECT_GT(out.size(), in.size());
    151   brillo::Blob decompressed;
    152   EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
    153   EXPECT_EQ(in.size(), decompressed.size());
    154   EXPECT_EQ(in, decompressed);
    155 }
    156 
    157 TYPED_TEST(ZipTest, MalformedZipTest) {
    158   brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
    159   brillo::Blob out;
    160   EXPECT_FALSE(this->ZipDecompress(in, &out));
    161 }
    162 
    163 TYPED_TEST(ZipTest, EmptyInputsTest) {
    164   brillo::Blob in;
    165   brillo::Blob out;
    166   EXPECT_TRUE(this->ZipDecompress(in, &out));
    167   EXPECT_EQ(0U, out.size());
    168 
    169   EXPECT_TRUE(this->ZipCompress(in, &out));
    170   EXPECT_EQ(0U, out.size());
    171 }
    172 
    173 }  // namespace chromeos_update_engine
    174