zip_unittest.cc revision 246bf21fd0074a1897c28a7c4703c2223e6224b6
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
33using chromeos_update_engine::test_utils::kRandomString;
34using std::string;
35using std::vector;
36
37namespace chromeos_update_engine {
38
39namespace {
40
41// ExtentWriter class that writes to memory, used to test the decompression
42// step with the corresponding extent writer.
43class 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
70template <typename W>
71bool 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
83template <typename T>
84class 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
90class BzipTest {};
91
92template <>
93class 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
103class XzTest {};
104
105template <>
106class 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__
117typedef ::testing::Types<BzipTest, XzTest> ZipTestTypes;
118#else
119// Chrome OS implementation of Xz compressor just returns false.
120typedef ::testing::Types<BzipTest> ZipTestTypes;
121#endif  // __ANDROID__
122
123TYPED_TEST_CASE(ZipTest, ZipTestTypes);
124
125TYPED_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
144TYPED_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
155TYPED_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
161TYPED_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