blob: 4d6b4d6f944275682f2f4f89234eea8c71f7a8c9 [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
Andrew de los Reyes80061062010-02-04 14:25:00 -080019#include <algorithm>
20#include <string>
21#include <vector>
Alex Deymo161c4a12014-05-16 15:56:21 -070022
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070023#include <brillo/make_unique_ptr.h>
24#include <brillo/secure_blob.h>
Andrew de los Reyes80061062010-02-04 14:25:00 -080025#include <gtest/gtest.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070026
Alex Deymo39910dc2015-11-09 17:04:30 -080027#include "update_engine/common/test_utils.h"
28#include "update_engine/common/utils.h"
29#include "update_engine/payload_consumer/payload_constants.h"
Andrew de los Reyes80061062010-02-04 14:25:00 -080030
Alex Deymo10875d92014-11-10 21:52:57 -080031using chromeos_update_engine::test_utils::ExpectVectorsEq;
Andrew de los Reyes80061062010-02-04 14:25:00 -080032using std::min;
33using std::string;
34using std::vector;
35
36namespace chromeos_update_engine {
37
Alex Vakulenko0103c362016-01-20 07:56:15 -080038static_assert(sizeof(off_t) == 8, "off_t not 64 bit");
Andrew de los Reyes80061062010-02-04 14:25:00 -080039
40namespace {
Andrew de los Reyes80061062010-02-04 14:25:00 -080041const size_t kBlockSize = 4096;
42}
43
44class ExtentWriterTest : public ::testing::Test {
45 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080046 void SetUp() override {
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080047 fd_.reset(new EintrSafeFileDescriptor);
Alex Deymobffa0602016-02-12 17:16:29 -080048 ASSERT_TRUE(fd_->Open(temp_file_.path().c_str(), O_RDWR, 0600));
Andrew de los Reyes80061062010-02-04 14:25:00 -080049 }
Alex Deymo610277e2014-11-11 21:18:11 -080050 void TearDown() override {
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080051 fd_->Close();
Andrew de los Reyes80061062010-02-04 14:25:00 -080052 }
Chris Masonef8d037f2014-02-19 01:53:00 +000053
Andrew de los Reyes80061062010-02-04 14:25:00 -080054 // Writes data to an extent writer in 'chunk_size' chunks with
55 // the first chunk of size first_chunk_size. It calculates what the
56 // resultant file should look like and ensure that the extent writer
57 // wrote the file correctly.
58 void WriteAlignedExtents(size_t chunk_size, size_t first_chunk_size);
59 void TestZeroPad(bool aligned_size);
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080060
61 FileDescriptorPtr fd_;
Alex Deymobffa0602016-02-12 17:16:29 -080062 test_utils::ScopedTempFile temp_file_{"ExtentWriterTest-file.XXXXXX"};
Andrew de los Reyes80061062010-02-04 14:25:00 -080063};
64
65TEST_F(ExtentWriterTest, SimpleTest) {
66 vector<Extent> extents;
67 Extent extent;
68 extent.set_start_block(1);
69 extent.set_num_blocks(1);
70 extents.push_back(extent);
Alex Deymo161c4a12014-05-16 15:56:21 -070071
Andrew de los Reyes80061062010-02-04 14:25:00 -080072 const string bytes = "1234";
73
74 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080075 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Andrew de los Reyes80061062010-02-04 14:25:00 -080076 EXPECT_TRUE(direct_writer.Write(bytes.data(), bytes.size()));
77 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -070078
Alex Deymo5fe0c4e2016-02-16 18:46:24 -080079 EXPECT_EQ(static_cast<off_t>(kBlockSize + bytes.size()),
Alex Deymobffa0602016-02-12 17:16:29 -080080 utils::FileSize(temp_file_.path()));
Alex Deymo161c4a12014-05-16 15:56:21 -070081
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070082 brillo::Blob result_file;
Alex Deymobffa0602016-02-12 17:16:29 -080083 EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -070084
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070085 brillo::Blob expected_file(kBlockSize);
Andrew de los Reyes80061062010-02-04 14:25:00 -080086 expected_file.insert(expected_file.end(),
87 bytes.data(), bytes.data() + bytes.size());
88 ExpectVectorsEq(expected_file, result_file);
89}
90
91TEST_F(ExtentWriterTest, ZeroLengthTest) {
92 vector<Extent> extents;
93 Extent extent;
94 extent.set_start_block(1);
95 extent.set_num_blocks(1);
96 extents.push_back(extent);
97
98 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080099 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700100 EXPECT_TRUE(direct_writer.Write(nullptr, 0));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800101 EXPECT_TRUE(direct_writer.End());
102}
103
104TEST_F(ExtentWriterTest, OverflowExtentTest) {
105 WriteAlignedExtents(kBlockSize * 3, kBlockSize * 3);
106}
107
108TEST_F(ExtentWriterTest, UnalignedWriteTest) {
109 WriteAlignedExtents(7, 7);
110}
111
112TEST_F(ExtentWriterTest, LargeUnalignedWriteTest) {
113 WriteAlignedExtents(kBlockSize * 2, kBlockSize / 2);
114}
115
116void ExtentWriterTest::WriteAlignedExtents(size_t chunk_size,
117 size_t first_chunk_size) {
118 vector<Extent> extents;
119 Extent extent;
120 extent.set_start_block(1);
121 extent.set_num_blocks(1);
122 extents.push_back(extent);
123 extent.set_start_block(0);
124 extent.set_num_blocks(1);
125 extents.push_back(extent);
126 extent.set_start_block(2);
127 extent.set_num_blocks(1);
128 extents.push_back(extent);
Alex Deymo161c4a12014-05-16 15:56:21 -0700129
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700130 brillo::Blob data(kBlockSize * 3);
Alex Deymo10875d92014-11-10 21:52:57 -0800131 test_utils::FillWithData(&data);
Alex Deymo161c4a12014-05-16 15:56:21 -0700132
Andrew de los Reyes80061062010-02-04 14:25:00 -0800133 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800134 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Deymo161c4a12014-05-16 15:56:21 -0700135
Andrew de los Reyes80061062010-02-04 14:25:00 -0800136 size_t bytes_written = 0;
137 while (bytes_written < data.size()) {
138 size_t bytes_to_write = min(data.size() - bytes_written, chunk_size);
139 if (bytes_written == 0) {
140 bytes_to_write = min(data.size() - bytes_written, first_chunk_size);
141 }
142 EXPECT_TRUE(direct_writer.Write(&data[bytes_written], bytes_to_write));
143 bytes_written += bytes_to_write;
144 }
145 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700146
Alex Deymobffa0602016-02-12 17:16:29 -0800147 EXPECT_EQ(static_cast<off_t>(data.size()),
148 utils::FileSize(temp_file_.path()));
Alex Deymo161c4a12014-05-16 15:56:21 -0700149
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700150 brillo::Blob result_file;
Alex Deymobffa0602016-02-12 17:16:29 -0800151 EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -0700152
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700153 brillo::Blob expected_file;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800154 expected_file.insert(expected_file.end(),
155 data.begin() + kBlockSize,
156 data.begin() + kBlockSize * 2);
157 expected_file.insert(expected_file.end(),
158 data.begin(), data.begin() + kBlockSize);
159 expected_file.insert(expected_file.end(),
160 data.begin() + kBlockSize * 2, data.end());
161 ExpectVectorsEq(expected_file, result_file);
162}
163
164TEST_F(ExtentWriterTest, ZeroPadNullTest) {
165 TestZeroPad(true);
166}
167
168TEST_F(ExtentWriterTest, ZeroPadFillTest) {
169 TestZeroPad(false);
170}
171
172void ExtentWriterTest::TestZeroPad(bool aligned_size) {
173 vector<Extent> extents;
174 Extent extent;
175 extent.set_start_block(1);
176 extent.set_num_blocks(1);
177 extents.push_back(extent);
178 extent.set_start_block(0);
179 extent.set_num_blocks(1);
180 extents.push_back(extent);
Alex Deymo161c4a12014-05-16 15:56:21 -0700181
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700182 brillo::Blob data(kBlockSize * 2);
Alex Deymo10875d92014-11-10 21:52:57 -0800183 test_utils::FillWithData(&data);
Alex Deymo161c4a12014-05-16 15:56:21 -0700184
Alex Deymo05322872015-09-30 09:50:24 -0700185 ZeroPadExtentWriter zero_pad_writer(
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700186 brillo::make_unique_ptr(new DirectExtentWriter()));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800187
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800188 EXPECT_TRUE(zero_pad_writer.Init(fd_, extents, kBlockSize));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800189 size_t bytes_to_write = data.size();
190 const size_t missing_bytes = (aligned_size ? 0 : 9);
191 bytes_to_write -= missing_bytes;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800192 fd_->Seek(kBlockSize - missing_bytes, SEEK_SET);
193 EXPECT_EQ(3, fd_->Write("xxx", 3));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800194 ASSERT_TRUE(zero_pad_writer.Write(data.data(), bytes_to_write));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800195 EXPECT_TRUE(zero_pad_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700196
Alex Deymobffa0602016-02-12 17:16:29 -0800197 EXPECT_EQ(static_cast<off_t>(data.size()),
198 utils::FileSize(temp_file_.path()));
Alex Deymo161c4a12014-05-16 15:56:21 -0700199
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700200 brillo::Blob result_file;
Alex Deymobffa0602016-02-12 17:16:29 -0800201 EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -0700202
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700203 brillo::Blob expected_file;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800204 expected_file.insert(expected_file.end(),
205 data.begin() + kBlockSize,
206 data.begin() + kBlockSize * 2);
207 expected_file.insert(expected_file.end(),
208 data.begin(), data.begin() + kBlockSize);
209 if (missing_bytes) {
210 memset(&expected_file[kBlockSize - missing_bytes], 0, missing_bytes);
211 }
212
213 ExpectVectorsEq(expected_file, result_file);
214}
215
216TEST_F(ExtentWriterTest, SparseFileTest) {
217 vector<Extent> extents;
218 Extent extent;
219 extent.set_start_block(1);
220 extent.set_num_blocks(1);
221 extents.push_back(extent);
222 extent.set_start_block(kSparseHole);
223 extent.set_num_blocks(2);
224 extents.push_back(extent);
225 extent.set_start_block(0);
226 extent.set_num_blocks(1);
227 extents.push_back(extent);
228 const int block_count = 4;
229 const int on_disk_count = 2;
230
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700231 brillo::Blob data(17);
Alex Deymo10875d92014-11-10 21:52:57 -0800232 test_utils::FillWithData(&data);
Andrew de los Reyes80061062010-02-04 14:25:00 -0800233
234 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800235 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Deymo161c4a12014-05-16 15:56:21 -0700236
Andrew de los Reyes80061062010-02-04 14:25:00 -0800237 size_t bytes_written = 0;
238 while (bytes_written < (block_count * kBlockSize)) {
239 size_t bytes_to_write = min(block_count * kBlockSize - bytes_written,
240 data.size());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800241 EXPECT_TRUE(direct_writer.Write(data.data(), bytes_to_write));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800242 bytes_written += bytes_to_write;
243 }
244 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700245
Andrew de los Reyes80061062010-02-04 14:25:00 -0800246 // check file size, then data inside
Alex Deymobffa0602016-02-12 17:16:29 -0800247 ASSERT_EQ(static_cast<off_t>(2 * kBlockSize),
248 utils::FileSize(temp_file_.path()));
Alex Deymo161c4a12014-05-16 15:56:21 -0700249
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700250 brillo::Blob resultant_data;
Alex Deymobffa0602016-02-12 17:16:29 -0800251 EXPECT_TRUE(utils::ReadFile(temp_file_.path(), &resultant_data));
Alex Deymo161c4a12014-05-16 15:56:21 -0700252
Andrew de los Reyes80061062010-02-04 14:25:00 -0800253 // Create expected data
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700254 brillo::Blob expected_data(on_disk_count * kBlockSize);
255 brillo::Blob big(block_count * kBlockSize);
256 for (brillo::Blob::size_type i = 0; i < big.size(); i++) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800257 big[i] = data[i % data.size()];
258 }
259 memcpy(&expected_data[kBlockSize], &big[0], kBlockSize);
260 memcpy(&expected_data[0], &big[3 * kBlockSize], kBlockSize);
261 ExpectVectorsEq(expected_data, resultant_data);
262}
263
264} // namespace chromeos_update_engine