blob: 34980a9a7e625935cf601b513b43310fb481071c [file] [log] [blame]
Alex Deymo2e71f902015-09-30 01:25:48 -07001//
2// Copyright (C) 2015 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
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/payload_consumer/xz_extent_writer.h"
Alex Deymo2e71f902015-09-30 01:25:48 -070018
19#include <fcntl.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <unistd.h>
23
24#include <algorithm>
Alex Deymo2e71f902015-09-30 01:25:48 -070025
Ben Chan5c02c132017-06-27 07:10:36 -070026#include <base/memory/ptr_util.h>
Alex Deymo2e71f902015-09-30 01:25:48 -070027#include <gtest/gtest.h>
28
Alex Deymo39910dc2015-11-09 17:04:30 -080029#include "update_engine/common/test_utils.h"
30#include "update_engine/common/utils.h"
31#include "update_engine/payload_consumer/fake_extent_writer.h"
Alex Deymo2e71f902015-09-30 01:25:48 -070032
Alex Deymo2e71f902015-09-30 01:25:48 -070033namespace chromeos_update_engine {
34
35namespace {
36
37const char kSampleData[] = "Redundaaaaaaaaaaaaaant\n";
38
39// Compressed data with CRC-32 check, generated with:
40// echo "Redundaaaaaaaaaaaaaant" | xz -9 --check=crc32 |
41// hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
42const uint8_t kCompressedDataCRC32[] = {
43 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x01, 0x69, 0x22, 0xde, 0x36,
44 0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
45 0xe0, 0x00, 0x16, 0x00, 0x10, 0x5d, 0x00, 0x29, 0x19, 0x48, 0x87, 0x88,
46 0xec, 0x49, 0x88, 0x73, 0x8b, 0x5d, 0xa6, 0x46, 0xb4, 0x00, 0x00, 0x00,
47 0x68, 0xfc, 0x7b, 0x25, 0x00, 0x01, 0x28, 0x17, 0x46, 0x9e, 0x08, 0xfe,
48 0x90, 0x42, 0x99, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x59, 0x5a,
49};
50
51// Compressed data without checksum, generated with:
52// echo "Redundaaaaaaaaaaaaaant" | xz -9 --check=none |
53// hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
54const uint8_t kCompressedDataNoCheck[] = {
55 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, 0xff, 0x12, 0xd9, 0x41,
56 0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
57 0xe0, 0x00, 0x16, 0x00, 0x10, 0x5d, 0x00, 0x29, 0x19, 0x48, 0x87, 0x88,
58 0xec, 0x49, 0x88, 0x73, 0x8b, 0x5d, 0xa6, 0x46, 0xb4, 0x00, 0x00, 0x00,
59 0x00, 0x01, 0x24, 0x17, 0x4a, 0xd1, 0xbd, 0x52, 0x06, 0x72, 0x9e, 0x7a,
60 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x5a,
61};
62
63// Highly redundant data bigger than the internal buffer, generated with:
64// dd if=/dev/zero bs=30K count=1 | tr '\0' 'a' | xz -9 --check=crc32 |
65// hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
66const uint8_t kCompressed30KiBofA[] = {
67 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x01, 0x69, 0x22, 0xde, 0x36,
68 0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
69 0xe0, 0x77, 0xff, 0x00, 0x41, 0x5d, 0x00, 0x30, 0xef, 0xfb, 0xbf, 0xfe,
70 0xa3, 0xb1, 0x5e, 0xe5, 0xf8, 0x3f, 0xb2, 0xaa, 0x26, 0x55, 0xf8, 0x68,
71 0x70, 0x41, 0x70, 0x15, 0x0f, 0x8d, 0xfd, 0x1e, 0x4c, 0x1b, 0x8a, 0x42,
72 0xb7, 0x19, 0xf4, 0x69, 0x18, 0x71, 0xae, 0x66, 0x23, 0x8a, 0x8a, 0x4d,
73 0x2f, 0xa3, 0x0d, 0xd9, 0x7f, 0xa6, 0xe3, 0x8c, 0x23, 0x11, 0x53, 0xe0,
74 0x59, 0x18, 0xc5, 0x75, 0x8a, 0xe2, 0x76, 0x4c, 0xee, 0x30, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0xf9, 0x47, 0xb5, 0xee, 0x00, 0x01, 0x59, 0x80,
76 0xf0, 0x01, 0x00, 0x00, 0xe0, 0x41, 0x96, 0xde, 0x3e, 0x30, 0x0d, 0x8b,
77 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x59, 0x5a,
78};
79
80} // namespace
81
82class XzExtentWriterTest : public ::testing::Test {
83 protected:
84 void SetUp() override {
85 fake_extent_writer_ = new FakeExtentWriter();
Ben Chan5c02c132017-06-27 07:10:36 -070086 xz_writer_.reset(new XzExtentWriter(base::WrapUnique(fake_extent_writer_)));
Alex Deymo2e71f902015-09-30 01:25:48 -070087 }
88
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070089 void WriteAll(const brillo::Blob& compressed) {
Alex Deymo2e71f902015-09-30 01:25:48 -070090 EXPECT_TRUE(xz_writer_->Init(fd_, {}, 1024));
91 EXPECT_TRUE(xz_writer_->Write(compressed.data(), compressed.size()));
Alex Deymo2e71f902015-09-30 01:25:48 -070092
93 EXPECT_TRUE(fake_extent_writer_->InitCalled());
Alex Deymo2e71f902015-09-30 01:25:48 -070094 }
95
96 // Owned by |xz_writer_|. This object is invalidated after |xz_writer_| is
97 // deleted.
98 FakeExtentWriter* fake_extent_writer_{nullptr};
99 std::unique_ptr<XzExtentWriter> xz_writer_;
100
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700101 const brillo::Blob sample_data_{
Amin Hassani008c4582019-01-13 16:22:47 -0800102 std::begin(kSampleData), std::begin(kSampleData) + strlen(kSampleData)};
Alex Deymo2e71f902015-09-30 01:25:48 -0700103 FileDescriptorPtr fd_;
104};
105
106TEST_F(XzExtentWriterTest, CreateAndDestroy) {
107 // Test that no Init() or End() called doesn't crash the program.
108 EXPECT_FALSE(fake_extent_writer_->InitCalled());
Alex Deymo2e71f902015-09-30 01:25:48 -0700109}
110
111TEST_F(XzExtentWriterTest, CompressedSampleData) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700112 WriteAll(brillo::Blob(std::begin(kCompressedDataNoCheck),
Amin Hassani008c4582019-01-13 16:22:47 -0800113 std::end(kCompressedDataNoCheck)));
Alex Deymo2e71f902015-09-30 01:25:48 -0700114 EXPECT_EQ(sample_data_, fake_extent_writer_->WrittenData());
115}
116
117TEST_F(XzExtentWriterTest, CompressedSampleDataWithCrc) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700118 WriteAll(brillo::Blob(std::begin(kCompressedDataCRC32),
Amin Hassani008c4582019-01-13 16:22:47 -0800119 std::end(kCompressedDataCRC32)));
Alex Deymo2e71f902015-09-30 01:25:48 -0700120 EXPECT_EQ(sample_data_, fake_extent_writer_->WrittenData());
121}
122
123TEST_F(XzExtentWriterTest, CompressedDataBiggerThanTheBuffer) {
124 // Test that even if the output data is bigger than the internal buffer, all
125 // the data is written.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700126 WriteAll(brillo::Blob(std::begin(kCompressed30KiBofA),
Amin Hassani008c4582019-01-13 16:22:47 -0800127 std::end(kCompressed30KiBofA)));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700128 brillo::Blob expected_data(30 * 1024, 'a');
Alex Deymo2e71f902015-09-30 01:25:48 -0700129 EXPECT_EQ(expected_data, fake_extent_writer_->WrittenData());
130}
131
132TEST_F(XzExtentWriterTest, GarbageDataRejected) {
133 EXPECT_TRUE(xz_writer_->Init(fd_, {}, 1024));
134 // The sample_data_ is an uncompressed string.
135 EXPECT_FALSE(xz_writer_->Write(sample_data_.data(), sample_data_.size()));
Alex Deymo2e71f902015-09-30 01:25:48 -0700136}
137
138TEST_F(XzExtentWriterTest, PartialDataIsKept) {
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700139 brillo::Blob compressed(std::begin(kCompressed30KiBofA),
Amin Hassani008c4582019-01-13 16:22:47 -0800140 std::end(kCompressed30KiBofA));
Alex Deymo2e71f902015-09-30 01:25:48 -0700141 EXPECT_TRUE(xz_writer_->Init(fd_, {}, 1024));
142 for (uint8_t byte : compressed) {
143 EXPECT_TRUE(xz_writer_->Write(&byte, 1));
144 }
Alex Deymo2e71f902015-09-30 01:25:48 -0700145
146 // The sample_data_ is an uncompressed string.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700147 brillo::Blob expected_data(30 * 1024, 'a');
Alex Deymo2e71f902015-09-30 01:25:48 -0700148 EXPECT_EQ(expected_data, fake_extent_writer_->WrittenData());
149}
150
151} // namespace chromeos_update_engine