zip_unittest.cc revision ab5a0af8e6ebac0211da5b08010e4855ce463108
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 33using chromeos_update_engine::test_utils::kRandomString; 34using google::protobuf::RepeatedPtrField; 35using std::string; 36using std::vector; 37 38namespace chromeos_update_engine { 39 40namespace { 41 42// ExtentWriter class that writes to memory, used to test the decompression 43// step with the corresponding extent writer. 44class 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 71template <typename W> 72bool 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 85template <typename T> 86class 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 92class BzipTest {}; 93 94template <> 95class 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 105class XzTest {}; 106 107template <> 108class 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__ 119typedef ::testing::Types<BzipTest, XzTest> ZipTestTypes; 120#else 121// Chrome OS implementation of Xz compressor just returns false. 122typedef ::testing::Types<BzipTest> ZipTestTypes; 123#endif // __ANDROID__ 124 125TYPED_TEST_CASE(ZipTest, ZipTestTypes); 126 127TYPED_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 146TYPED_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 157TYPED_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 163TYPED_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