blob: 48b27cba8b06e3a7ba2c1977d46c0ad6f2736ae0 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2009 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//
Andrew de los Reyes80061062010-02-04 14:25:00 -080016
Alex Deymo39910dc2015-11-09 17:04:30 -080017#include "update_engine/payload_consumer/extent_writer.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070018
Xiyuan Xia4eccae22016-02-26 14:30:02 -080019#include <fcntl.h>
20
Andrew de los Reyes80061062010-02-04 14:25:00 -080021#include <algorithm>
Ben Chanab5a0af2017-10-12 14:57:50 -070022#include <memory>
Andrew de los Reyes80061062010-02-04 14:25:00 -080023#include <string>
24#include <vector>
Alex Deymo161c4a12014-05-16 15:56:21 -070025
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070026#include <brillo/secure_blob.h>
Andrew de los Reyes80061062010-02-04 14:25:00 -080027#include <gtest/gtest.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070028
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/payload_constants.h"
Amin Hassanicd7edbe2017-09-18 17:05:02 -070032#include "update_engine/payload_generator/extent_ranges.h"
Andrew de los Reyes80061062010-02-04 14:25:00 -080033
Alex Deymo10875d92014-11-10 21:52:57 -080034using chromeos_update_engine::test_utils::ExpectVectorsEq;
Andrew de los Reyes80061062010-02-04 14:25:00 -080035using std::min;
36using std::string;
37using std::vector;
38
39namespace chromeos_update_engine {
40
Alex Vakulenko0103c362016-01-20 07:56:15 -080041static_assert(sizeof(off_t) == 8, "off_t not 64 bit");
Andrew de los Reyes80061062010-02-04 14:25:00 -080042
43namespace {
Andrew de los Reyes80061062010-02-04 14:25:00 -080044const size_t kBlockSize = 4096;
45}
46
47class ExtentWriterTest : public ::testing::Test {
48 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080049 void SetUp() override {
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080050 fd_.reset(new EintrSafeFileDescriptor);
Alex Deymobffa0602016-02-12 17:16:29 -080051 ASSERT_TRUE(fd_->Open(temp_file_.path().c_str(), O_RDWR, 0600));
Andrew de los Reyes80061062010-02-04 14:25:00 -080052 }
Alex Deymo610277e2014-11-11 21:18:11 -080053 void TearDown() override {
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080054 fd_->Close();
Andrew de los Reyes80061062010-02-04 14:25:00 -080055 }
Chris Masonef8d037f2014-02-19 01:53:00 +000056
Andrew de los Reyes80061062010-02-04 14:25:00 -080057 // Writes data to an extent writer in 'chunk_size' chunks with
58 // the first chunk of size first_chunk_size. It calculates what the
59 // resultant file should look like and ensure that the extent writer
60 // wrote the file correctly.
61 void WriteAlignedExtents(size_t chunk_size, size_t first_chunk_size);
62 void TestZeroPad(bool aligned_size);
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080063
64 FileDescriptorPtr fd_;
Alex Deymobffa0602016-02-12 17:16:29 -080065 test_utils::ScopedTempFile temp_file_{"ExtentWriterTest-file.XXXXXX"};
Andrew de los Reyes80061062010-02-04 14:25:00 -080066};
67
68TEST_F(ExtentWriterTest, SimpleTest) {
Amin Hassanicd7edbe2017-09-18 17:05:02 -070069 vector<Extent> extents = {ExtentForRange(1, 1)};
Andrew de los Reyes80061062010-02-04 14:25:00 -080070 const string bytes = "1234";
Andrew de los Reyes80061062010-02-04 14:25:00 -080071 DirectExtentWriter direct_writer;
Amin Hassanicd7edbe2017-09-18 17:05:02 -070072 EXPECT_TRUE(
73 direct_writer.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
Andrew de los Reyes80061062010-02-04 14:25:00 -080074 EXPECT_TRUE(direct_writer.Write(bytes.data(), bytes.size()));
75 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -070076
Alex Deymo5fe0c4e2016-02-16 18:46:24 -080077 EXPECT_EQ(static_cast<off_t>(kBlockSize + bytes.size()),
Alex Deymobffa0602016-02-12 17:16:29 -080078 utils::FileSize(temp_file_.path()));
Alex Deymo161c4a12014-05-16 15:56:21 -070079
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070080 brillo::Blob result_file;
Alex Deymobffa0602016-02-12 17:16:29 -080081 EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -070082
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070083 brillo::Blob expected_file(kBlockSize);
Andrew de los Reyes80061062010-02-04 14:25:00 -080084 expected_file.insert(expected_file.end(),
85 bytes.data(), bytes.data() + bytes.size());
86 ExpectVectorsEq(expected_file, result_file);
87}
88
89TEST_F(ExtentWriterTest, ZeroLengthTest) {
Amin Hassanicd7edbe2017-09-18 17:05:02 -070090 vector<Extent> extents = {ExtentForRange(1, 1)};
Andrew de los Reyes80061062010-02-04 14:25:00 -080091 DirectExtentWriter direct_writer;
Amin Hassanicd7edbe2017-09-18 17:05:02 -070092 EXPECT_TRUE(
93 direct_writer.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
Alex Vakulenko88b591f2014-08-28 16:48:57 -070094 EXPECT_TRUE(direct_writer.Write(nullptr, 0));
Andrew de los Reyes80061062010-02-04 14:25:00 -080095 EXPECT_TRUE(direct_writer.End());
96}
97
98TEST_F(ExtentWriterTest, OverflowExtentTest) {
99 WriteAlignedExtents(kBlockSize * 3, kBlockSize * 3);
100}
101
102TEST_F(ExtentWriterTest, UnalignedWriteTest) {
103 WriteAlignedExtents(7, 7);
104}
105
106TEST_F(ExtentWriterTest, LargeUnalignedWriteTest) {
107 WriteAlignedExtents(kBlockSize * 2, kBlockSize / 2);
108}
109
110void ExtentWriterTest::WriteAlignedExtents(size_t chunk_size,
111 size_t first_chunk_size) {
Amin Hassanicd7edbe2017-09-18 17:05:02 -0700112 vector<Extent> extents = {
113 ExtentForRange(1, 1), ExtentForRange(0, 1), ExtentForRange(2, 1)};
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700114 brillo::Blob data(kBlockSize * 3);
Alex Deymo10875d92014-11-10 21:52:57 -0800115 test_utils::FillWithData(&data);
Alex Deymo161c4a12014-05-16 15:56:21 -0700116
Andrew de los Reyes80061062010-02-04 14:25:00 -0800117 DirectExtentWriter direct_writer;
Amin Hassanicd7edbe2017-09-18 17:05:02 -0700118 EXPECT_TRUE(
119 direct_writer.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
Alex Deymo161c4a12014-05-16 15:56:21 -0700120
Andrew de los Reyes80061062010-02-04 14:25:00 -0800121 size_t bytes_written = 0;
122 while (bytes_written < data.size()) {
123 size_t bytes_to_write = min(data.size() - bytes_written, chunk_size);
124 if (bytes_written == 0) {
125 bytes_to_write = min(data.size() - bytes_written, first_chunk_size);
126 }
127 EXPECT_TRUE(direct_writer.Write(&data[bytes_written], bytes_to_write));
128 bytes_written += bytes_to_write;
129 }
130 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700131
Alex Deymobffa0602016-02-12 17:16:29 -0800132 EXPECT_EQ(static_cast<off_t>(data.size()),
133 utils::FileSize(temp_file_.path()));
Alex Deymo161c4a12014-05-16 15:56:21 -0700134
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700135 brillo::Blob result_file;
Alex Deymobffa0602016-02-12 17:16:29 -0800136 EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -0700137
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700138 brillo::Blob expected_file;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800139 expected_file.insert(expected_file.end(),
140 data.begin() + kBlockSize,
141 data.begin() + kBlockSize * 2);
142 expected_file.insert(expected_file.end(),
143 data.begin(), data.begin() + kBlockSize);
144 expected_file.insert(expected_file.end(),
145 data.begin() + kBlockSize * 2, data.end());
146 ExpectVectorsEq(expected_file, result_file);
147}
148
149TEST_F(ExtentWriterTest, ZeroPadNullTest) {
150 TestZeroPad(true);
151}
152
153TEST_F(ExtentWriterTest, ZeroPadFillTest) {
154 TestZeroPad(false);
155}
156
157void ExtentWriterTest::TestZeroPad(bool aligned_size) {
Amin Hassanicd7edbe2017-09-18 17:05:02 -0700158 vector<Extent> extents = {ExtentForRange(1, 1), ExtentForRange(0, 1)};
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700159 brillo::Blob data(kBlockSize * 2);
Alex Deymo10875d92014-11-10 21:52:57 -0800160 test_utils::FillWithData(&data);
Alex Deymo161c4a12014-05-16 15:56:21 -0700161
Ben Chanab5a0af2017-10-12 14:57:50 -0700162 ZeroPadExtentWriter zero_pad_writer(std::make_unique<DirectExtentWriter>());
Andrew de los Reyes80061062010-02-04 14:25:00 -0800163
Amin Hassanicd7edbe2017-09-18 17:05:02 -0700164 EXPECT_TRUE(
165 zero_pad_writer.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800166 size_t bytes_to_write = data.size();
167 const size_t missing_bytes = (aligned_size ? 0 : 9);
168 bytes_to_write -= missing_bytes;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800169 fd_->Seek(kBlockSize - missing_bytes, SEEK_SET);
170 EXPECT_EQ(3, fd_->Write("xxx", 3));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800171 ASSERT_TRUE(zero_pad_writer.Write(data.data(), bytes_to_write));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800172 EXPECT_TRUE(zero_pad_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700173
Alex Deymobffa0602016-02-12 17:16:29 -0800174 EXPECT_EQ(static_cast<off_t>(data.size()),
175 utils::FileSize(temp_file_.path()));
Alex Deymo161c4a12014-05-16 15:56:21 -0700176
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700177 brillo::Blob result_file;
Alex Deymobffa0602016-02-12 17:16:29 -0800178 EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -0700179
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700180 brillo::Blob expected_file;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800181 expected_file.insert(expected_file.end(),
182 data.begin() + kBlockSize,
183 data.begin() + kBlockSize * 2);
184 expected_file.insert(expected_file.end(),
185 data.begin(), data.begin() + kBlockSize);
186 if (missing_bytes) {
187 memset(&expected_file[kBlockSize - missing_bytes], 0, missing_bytes);
188 }
189
190 ExpectVectorsEq(expected_file, result_file);
191}
192
193TEST_F(ExtentWriterTest, SparseFileTest) {
Amin Hassanicd7edbe2017-09-18 17:05:02 -0700194 vector<Extent> extents = {ExtentForRange(1, 1),
195 ExtentForRange(kSparseHole, 2),
196 ExtentForRange(0, 1)};
Andrew de los Reyes80061062010-02-04 14:25:00 -0800197 const int block_count = 4;
198 const int on_disk_count = 2;
199
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700200 brillo::Blob data(17);
Alex Deymo10875d92014-11-10 21:52:57 -0800201 test_utils::FillWithData(&data);
Andrew de los Reyes80061062010-02-04 14:25:00 -0800202
203 DirectExtentWriter direct_writer;
Amin Hassanicd7edbe2017-09-18 17:05:02 -0700204 EXPECT_TRUE(
205 direct_writer.Init(fd_, {extents.begin(), extents.end()}, kBlockSize));
Alex Deymo161c4a12014-05-16 15:56:21 -0700206
Andrew de los Reyes80061062010-02-04 14:25:00 -0800207 size_t bytes_written = 0;
208 while (bytes_written < (block_count * kBlockSize)) {
209 size_t bytes_to_write = min(block_count * kBlockSize - bytes_written,
210 data.size());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800211 EXPECT_TRUE(direct_writer.Write(data.data(), bytes_to_write));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800212 bytes_written += bytes_to_write;
213 }
214 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700215
Andrew de los Reyes80061062010-02-04 14:25:00 -0800216 // check file size, then data inside
Alex Deymobffa0602016-02-12 17:16:29 -0800217 ASSERT_EQ(static_cast<off_t>(2 * kBlockSize),
218 utils::FileSize(temp_file_.path()));
Alex Deymo161c4a12014-05-16 15:56:21 -0700219
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700220 brillo::Blob resultant_data;
Alex Deymobffa0602016-02-12 17:16:29 -0800221 EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &resultant_data));
Alex Deymo161c4a12014-05-16 15:56:21 -0700222
Andrew de los Reyes80061062010-02-04 14:25:00 -0800223 // Create expected data
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700224 brillo::Blob expected_data(on_disk_count * kBlockSize);
225 brillo::Blob big(block_count * kBlockSize);
226 for (brillo::Blob::size_type i = 0; i < big.size(); i++) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800227 big[i] = data[i % data.size()];
228 }
229 memcpy(&expected_data[kBlockSize], &big[0], kBlockSize);
230 memcpy(&expected_data[0], &big[3 * kBlockSize], kBlockSize);
231 ExpectVectorsEq(expected_data, resultant_data);
232}
233
234} // namespace chromeos_update_engine