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