xref: /aosp_15_r20/system/update_engine/payload_generator/zip_unittest.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
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 <brillo/secure_blob.h>
25 #include <gtest/gtest.h>
26 
27 #include "update_engine/common/test_utils.h"
28 #include "update_engine/payload_consumer/bzip_extent_writer.h"
29 #include "update_engine/payload_consumer/extent_writer.h"
30 #include "update_engine/payload_consumer/xz_extent_writer.h"
31 #include "update_engine/payload_generator/bzip.h"
32 #include "update_engine/payload_generator/xz.h"
33 
34 using chromeos_update_engine::test_utils::kRandomString;
35 using google::protobuf::RepeatedPtrField;
36 using std::string;
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.
MemoryExtentWriter(brillo::Blob * data)48   explicit MemoryExtentWriter(brillo::Blob* data) : data_(data) {
49     data_->clear();
50   }
51   ~MemoryExtentWriter() override = default;
52 
Init(const RepeatedPtrField<Extent> & extents,uint32_t block_size)53   bool Init(const RepeatedPtrField<Extent>& extents,
54             uint32_t block_size) override {
55     return true;
56   }
Write(const void * bytes,size_t count)57   bool Write(const void* bytes, size_t count) override {
58     data_->insert(data_->end(),
59                   static_cast<const uint8_t*>(bytes),
60                   static_cast<const uint8_t*>(bytes) + count);
61     return true;
62   }
63 
64  private:
65   brillo::Blob* data_;
66 };
67 
68 template <typename W>
DecompressWithWriter(const brillo::Blob & in,brillo::Blob * out)69 bool DecompressWithWriter(const brillo::Blob& in, brillo::Blob* out) {
70   out->reserve(in.size());
71   std::unique_ptr<ExtentWriter> writer(
72       new W(std::make_unique<MemoryExtentWriter>(out)));
73   // Init() parameters are ignored by the testing MemoryExtentWriter.
74   bool ok = writer->Init({}, 1);
75   ok = writer->Write(in.data(), in.size()) && ok;
76   return ok;
77 }
78 
79 }  // namespace
80 
81 template <typename T>
82 class ZipTest : public ::testing::Test {
83  public:
84   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const = 0;
85   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const = 0;
86 };
87 
88 class BzipTest {};
89 
90 template <>
91 class ZipTest<BzipTest> : public ::testing::Test {
92  public:
ZipCompress(const brillo::Blob & in,brillo::Blob * out) const93   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const {
94     return BzipCompress(in, out);
95   }
ZipDecompress(const brillo::Blob & in,brillo::Blob * out) const96   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const {
97     return DecompressWithWriter<BzipExtentWriter>(in, out);
98   }
99 };
100 
101 class XzTest {};
102 
103 template <>
104 class ZipTest<XzTest> : public ::testing::Test {
105  public:
ZipCompress(const brillo::Blob & in,brillo::Blob * out) const106   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const {
107     return XzCompress(in, out);
108   }
ZipDecompress(const brillo::Blob & in,brillo::Blob * out) const109   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const {
110     return DecompressWithWriter<XzExtentWriter>(in, out);
111   }
112 };
113 
114 typedef ::testing::Types<BzipTest, XzTest> ZipTestTypes;
115 
116 TYPED_TEST_CASE(ZipTest, ZipTestTypes);
117 
TYPED_TEST(ZipTest,SimpleTest)118 TYPED_TEST(ZipTest, SimpleTest) {
119   string in_str(
120       "this should compress well xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
121       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
122       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
123       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
124       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
125       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
126   brillo::Blob in(in_str.begin(), in_str.end());
127   brillo::Blob out;
128   EXPECT_TRUE(this->ZipCompress(in, &out));
129   EXPECT_LT(out.size(), in.size());
130   EXPECT_GT(out.size(), 0U);
131   brillo::Blob decompressed;
132   EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
133   EXPECT_EQ(in.size(), decompressed.size());
134   EXPECT_EQ(0, memcmp(in.data(), decompressed.data(), in.size()));
135 }
136 
TYPED_TEST(ZipTest,PoorCompressionTest)137 TYPED_TEST(ZipTest, PoorCompressionTest) {
138   brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
139   brillo::Blob out;
140   EXPECT_TRUE(this->ZipCompress(in, &out));
141   EXPECT_GT(out.size(), in.size());
142   brillo::Blob decompressed;
143   EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
144   EXPECT_EQ(in.size(), decompressed.size());
145   EXPECT_EQ(in, decompressed);
146 }
147 
TYPED_TEST(ZipTest,MalformedZipTest)148 TYPED_TEST(ZipTest, MalformedZipTest) {
149   brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
150   brillo::Blob out;
151   EXPECT_FALSE(this->ZipDecompress(in, &out));
152 }
153 
TYPED_TEST(ZipTest,EmptyInputsTest)154 TYPED_TEST(ZipTest, EmptyInputsTest) {
155   brillo::Blob in;
156   brillo::Blob out;
157   EXPECT_TRUE(this->ZipDecompress(in, &out));
158   EXPECT_EQ(0U, out.size());
159 
160   EXPECT_TRUE(this->ZipCompress(in, &out));
161   EXPECT_EQ(0U, out.size());
162 }
163 
TYPED_TEST(ZipTest,CompressELFTest)164 TYPED_TEST(ZipTest, CompressELFTest) {
165   string path = test_utils::GetBuildArtifactsPath("delta_generator");
166   brillo::Blob in;
167   ASSERT_TRUE(utils::ReadFile(path, &in));
168   brillo::Blob out;
169   EXPECT_TRUE(this->ZipCompress(in, &out));
170   EXPECT_LT(out.size(), in.size());
171   EXPECT_GT(out.size(), 0U);
172   brillo::Blob decompressed;
173   EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
174   EXPECT_EQ(in.size(), decompressed.size());
175   EXPECT_EQ(0, memcmp(in.data(), decompressed.data(), in.size()));
176 }
177 
178 }  // namespace chromeos_update_engine
179