• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
MemoryExtentWriter(brillo::Blob * data)47   explicit MemoryExtentWriter(brillo::Blob* data) : data_(data) {
48     data_->clear();
49   }
50   ~MemoryExtentWriter() override = default;
51 
Init(FileDescriptorPtr fd,const vector<Extent> & extents,uint32_t block_size)52   bool Init(FileDescriptorPtr fd,
53             const vector<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_->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   }
EndImpl()64   bool EndImpl() override { return true; }
65 
66  private:
67   brillo::Blob* data_;
68 };
69 
70 template <typename W>
DecompressWithWriter(const brillo::Blob & in,brillo::Blob * out)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   bool ok = writer->Init(nullptr, {}, 1);
76   ok = writer->Write(in.data(), in.size()) && ok;
77   // Call End() even if the Write failed.
78   ok = writer->End() && ok;
79   return ok;
80 }
81 
82 }  // namespace
83 
84 template <typename T>
85 class ZipTest : public ::testing::Test {
86  public:
87   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const = 0;
88   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const = 0;
89 };
90 
91 class BzipTest {};
92 
93 template <>
94 class ZipTest<BzipTest> : public ::testing::Test {
95  public:
ZipCompress(const brillo::Blob & in,brillo::Blob * out) const96   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const {
97     return BzipCompress(in, out);
98   }
ZipDecompress(const brillo::Blob & in,brillo::Blob * out) const99   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const {
100     return DecompressWithWriter<BzipExtentWriter>(in, out);
101   }
102 };
103 
104 class XzTest {};
105 
106 template <>
107 class ZipTest<XzTest> : public ::testing::Test {
108  public:
ZipCompress(const brillo::Blob & in,brillo::Blob * out) const109   bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const {
110     return XzCompress(in, out);
111   }
ZipDecompress(const brillo::Blob & in,brillo::Blob * out) const112   bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const {
113     return DecompressWithWriter<XzExtentWriter>(in, out);
114   }
115 };
116 
117 #ifdef __ANDROID__
118 typedef ::testing::Types<BzipTest, XzTest> ZipTestTypes;
119 #else
120 // Chrome OS implementation of Xz compressor just returns false.
121 typedef ::testing::Types<BzipTest> ZipTestTypes;
122 #endif  // __ANDROID__
123 
124 TYPED_TEST_CASE(ZipTest, ZipTestTypes);
125 
TYPED_TEST(ZipTest,SimpleTest)126 TYPED_TEST(ZipTest, SimpleTest) {
127   string in_str(
128       "this should compress well xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
129       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
130       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
131       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
132       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
133       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
134   brillo::Blob in(in_str.begin(), in_str.end());
135   brillo::Blob out;
136   EXPECT_TRUE(this->ZipCompress(in, &out));
137   EXPECT_LT(out.size(), in.size());
138   EXPECT_GT(out.size(), 0U);
139   brillo::Blob decompressed;
140   EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
141   EXPECT_EQ(in.size(), decompressed.size());
142   EXPECT_TRUE(!memcmp(in.data(), decompressed.data(), in.size()));
143 }
144 
TYPED_TEST(ZipTest,PoorCompressionTest)145 TYPED_TEST(ZipTest, PoorCompressionTest) {
146   brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
147   brillo::Blob out;
148   EXPECT_TRUE(this->ZipCompress(in, &out));
149   EXPECT_GT(out.size(), in.size());
150   brillo::Blob decompressed;
151   EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
152   EXPECT_EQ(in.size(), decompressed.size());
153   EXPECT_EQ(in, decompressed);
154 }
155 
TYPED_TEST(ZipTest,MalformedZipTest)156 TYPED_TEST(ZipTest, MalformedZipTest) {
157   brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
158   brillo::Blob out;
159   EXPECT_FALSE(this->ZipDecompress(in, &out));
160 }
161 
TYPED_TEST(ZipTest,EmptyInputsTest)162 TYPED_TEST(ZipTest, EmptyInputsTest) {
163   brillo::Blob in;
164   brillo::Blob out;
165   EXPECT_TRUE(this->ZipDecompress(in, &out));
166   EXPECT_EQ(0U, out.size());
167 
168   EXPECT_TRUE(this->ZipCompress(in, &out));
169   EXPECT_EQ(0U, out.size());
170 }
171 
172 }  // namespace chromeos_update_engine
173