1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2011 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
16d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
17d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes#include <string.h>
18d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes#include <unistd.h>
197ed561bfe6019ed4b988142e97505d7c643e119cDarin Petkov
20d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes#include <string>
21d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes#include <vector>
227ed561bfe6019ed4b988142e97505d7c643e119cDarin Petkov
235ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo#include <brillo/make_unique_ptr.h>
24d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes#include <gtest/gtest.h>
257ed561bfe6019ed4b988142e97505d7c643e119cDarin Petkov
2639910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/test_utils.h"
275ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo#include "update_engine/payload_consumer/bzip_extent_writer.h"
285ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo#include "update_engine/payload_consumer/extent_writer.h"
295ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo#include "update_engine/payload_consumer/xz_extent_writer.h"
300bc2611b49aba30202fdb9c23871430eb67e4738Alex Deymo#include "update_engine/payload_generator/bzip.h"
315ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo#include "update_engine/payload_generator/xz.h"
32d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
3310875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymousing chromeos_update_engine::test_utils::kRandomString;
34d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyesusing std::string;
35d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyesusing std::vector;
36d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
37d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyesnamespace chromeos_update_engine {
38d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
395ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymonamespace {
405ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo
415ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo// ExtentWriter class that writes to memory, used to test the decompression
425ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo// step with the corresponding extent writer.
435ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymoclass MemoryExtentWriter : public ExtentWriter {
445ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo public:
455ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  // Creates the ExtentWriter that will write all the bytes to the passed |data|
465ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  // blob.
475ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  explicit MemoryExtentWriter(brillo::Blob* data) : data_(data) {
485ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo    data_->clear();
495ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  }
505ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  ~MemoryExtentWriter() override = default;
515ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo
525ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  bool Init(FileDescriptorPtr fd,
535ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo            const vector<Extent>& extents,
545ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo            uint32_t block_size) override {
555ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo    return true;
565ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  }
575ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  bool Write(const void* bytes, size_t count) override {
585ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo    data_->reserve(data_->size() + count);
595ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo    data_->insert(data_->end(),
605ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo                  static_cast<const uint8_t*>(bytes),
615ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo                  static_cast<const uint8_t*>(bytes) + count);
625ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo    return true;
635ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  }
645ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  bool EndImpl() override { return true; }
655ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo
665ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo private:
675ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  brillo::Blob* data_;
685ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo};
695ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo
705ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymotemplate <typename W>
715ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymobool DecompressWithWriter(const brillo::Blob& in, brillo::Blob* out) {
725ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  std::unique_ptr<ExtentWriter> writer(
735ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo      new W(brillo::make_unique_ptr(new MemoryExtentWriter(out))));
745ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  // Init() parameters are ignored by the testing MemoryExtentWriter.
755ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  TEST_AND_RETURN_FALSE(writer->Init(nullptr, {}, 1));
765ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  TEST_AND_RETURN_FALSE(writer->Write(in.data(), in.size()));
775ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  TEST_AND_RETURN_FALSE(writer->End());
785ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  return true;
795ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo}
805ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo
815ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo}  // namespace
825ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo
83d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyestemplate <typename T>
84d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyesclass ZipTest : public ::testing::Test {
85d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes public:
860bc2611b49aba30202fdb9c23871430eb67e4738Alex Deymo  bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const = 0;
875ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const = 0;
88d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes};
89d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
90d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyesclass BzipTest {};
91d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
92d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyestemplate <>
93d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyesclass ZipTest<BzipTest> : public ::testing::Test {
94d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes public:
950bc2611b49aba30202fdb9c23871430eb67e4738Alex Deymo  bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const {
96d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes    return BzipCompress(in, out);
97d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes  }
985ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const {
995ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo    return DecompressWithWriter<BzipExtentWriter>(in, out);
100d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes  }
1015ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo};
1025ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo
1035ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymoclass XzTest {};
1045ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo
1055ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymotemplate <>
1065ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymoclass ZipTest<XzTest> : public ::testing::Test {
1075ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo public:
1085ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  bool ZipCompress(const brillo::Blob& in, brillo::Blob* out) const {
1095ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo    return XzCompress(in, out);
1105ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  }
1115ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  bool ZipDecompress(const brillo::Blob& in, brillo::Blob* out) const {
1125ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo    return DecompressWithWriter<XzExtentWriter>(in, out);
113d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes  }
114d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes};
115d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
1165ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo#ifdef __ANDROID__
1175ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymotypedef ::testing::Types<BzipTest, XzTest> ZipTestTypes;
1185ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo#else
1195ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo// Chrome OS implementation of Xz compressor just returns false.
1207ed561bfe6019ed4b988142e97505d7c643e119cDarin Petkovtypedef ::testing::Types<BzipTest> ZipTestTypes;
1215ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo#endif  // __ANDROID__
122d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
1235ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex DeymoTYPED_TEST_CASE(ZipTest, ZipTestTypes);
124d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
125d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los ReyesTYPED_TEST(ZipTest, SimpleTest) {
1265ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  string in_str(
1275ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo      "this should compress well xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1285ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1295ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1305ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1315ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1325ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo      "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
1335ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  brillo::Blob in(in_str.begin(), in_str.end());
1343f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob out;
1355ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  EXPECT_TRUE(this->ZipCompress(in, &out));
136d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes  EXPECT_LT(out.size(), in.size());
13780f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_GT(out.size(), 0U);
1383f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob decompressed;
139d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes  EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
140d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes  EXPECT_EQ(in.size(), decompressed.size());
141f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  EXPECT_TRUE(!memcmp(in.data(), decompressed.data(), in.size()));
142d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes}
143d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
144d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los ReyesTYPED_TEST(ZipTest, PoorCompressionTest) {
1455ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
1463f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob out;
1475ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  EXPECT_TRUE(this->ZipCompress(in, &out));
148d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes  EXPECT_GT(out.size(), in.size());
1493f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob decompressed;
1505ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  EXPECT_TRUE(this->ZipDecompress(out, &decompressed));
151d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes  EXPECT_EQ(in.size(), decompressed.size());
1525ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  EXPECT_EQ(in, decompressed);
153d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes}
154d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
155d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los ReyesTYPED_TEST(ZipTest, MalformedZipTest) {
1565ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  brillo::Blob in(std::begin(kRandomString), std::end(kRandomString));
1573f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob out;
1585ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  EXPECT_FALSE(this->ZipDecompress(in, &out));
159d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes}
160d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
161d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los ReyesTYPED_TEST(ZipTest, EmptyInputsTest) {
1625ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  brillo::Blob in;
1633f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob out;
1645ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  EXPECT_TRUE(this->ZipDecompress(in, &out));
16580f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_EQ(0U, out.size());
166d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
1675ee71ba372ddef9bc2b5e12f55f0b449d320282cAlex Deymo  EXPECT_TRUE(this->ZipCompress(in, &out));
16880f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo  EXPECT_EQ(0U, out.size());
169d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes}
170d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes
171d2135f3946c7c551f152c0a595c5528cd186afefAndrew de los Reyes}  // namespace chromeos_update_engine
172