zip_unittest.cc revision 717c324c334cc3bac954101f7a127fe8ef56e4e6
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
118typedef ::testing::Types<BzipTest, XzTest> ZipTestTypes;
119
120TYPED_TEST_CASE(ZipTest, ZipTestTypes);
121
122TYPED_TEST(ZipTest, SimpleTest) {
123  string in_str(
124      "this should compress well xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
125      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
126      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
127      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
128      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
129      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
130  brillo::Blob in(in_str.begin(), in_str.end());
131  brillo::Blob out;
132  EXPECT_TRUE(this->ZipCompress(in, &out));
133  EXPECT_LT(out.size(), in.size());
134  EXPECT_GT(out.size(), 0U);
135  brillo::Blob decompressed;
136  EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
137  EXPECT_EQ(in.size(), decompressed.size());
138  EXPECT_TRUE(!memcmp(in.data(), decompressed.data(), in.size()));
139}
140
141TYPED_TEST(ZipTest, PoorCompressionTest) {
142  brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
143  brillo::Blob out;
144  EXPECT_TRUE(this->ZipCompress(in, &out));
145  EXPECT_GT(out.size(), in.size());
146  brillo::Blob decompressed;
147  EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
148  EXPECT_EQ(in.size(), decompressed.size());
149  EXPECT_EQ(in, decompressed);
150}
151
152TYPED_TEST(ZipTest, MalformedZipTest) {
153  brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
154  brillo::Blob out;
155  EXPECT_FALSE(this->ZipDecompress(in, &out));
156}
157
158TYPED_TEST(ZipTest, EmptyInputsTest) {
159  brillo::Blob in;
160  brillo::Blob out;
161  EXPECT_TRUE(this->ZipDecompress(in, &out));
162  EXPECT_EQ(0U, out.size());
163
164  EXPECT_TRUE(this->ZipCompress(in, &out));
165  EXPECT_EQ(0U, out.size());
166}
167
168}  // namespace chromeos_update_engine
169