blob: 6884c0bb124ea425fc48bc53f6783a06ff34a874 [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
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080019#include <fcntl.h>
Andrew de los Reyes80061062010-02-04 14:25:00 -080020#include <sys/stat.h>
21#include <sys/types.h>
22#include <unistd.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070023
Andrew de los Reyes80061062010-02-04 14:25:00 -080024#include <algorithm>
25#include <string>
26#include <vector>
Alex Deymo161c4a12014-05-16 15:56:21 -070027
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070028#include <brillo/make_unique_ptr.h>
29#include <brillo/secure_blob.h>
Andrew de los Reyes80061062010-02-04 14:25:00 -080030#include <gtest/gtest.h>
Alex Deymo161c4a12014-05-16 15:56:21 -070031
Alex Deymo39910dc2015-11-09 17:04:30 -080032#include "update_engine/common/test_utils.h"
33#include "update_engine/common/utils.h"
34#include "update_engine/payload_consumer/payload_constants.h"
Andrew de los Reyes80061062010-02-04 14:25:00 -080035
Alex Deymo10875d92014-11-10 21:52:57 -080036using chromeos_update_engine::test_utils::ExpectVectorsEq;
Andrew de los Reyes80061062010-02-04 14:25:00 -080037using std::min;
38using std::string;
39using std::vector;
40
41namespace chromeos_update_engine {
42
Alex Vakulenko0103c362016-01-20 07:56:15 -080043static_assert(sizeof(off_t) == 8, "off_t not 64 bit");
Andrew de los Reyes80061062010-02-04 14:25:00 -080044
45namespace {
46const char kPathTemplate[] = "./ExtentWriterTest-file.XXXXXX";
47const size_t kBlockSize = 4096;
48}
49
50class ExtentWriterTest : public ::testing::Test {
51 protected:
Alex Deymo610277e2014-11-11 21:18:11 -080052 void SetUp() override {
Andrew de los Reyes80061062010-02-04 14:25:00 -080053 memcpy(path_, kPathTemplate, sizeof(kPathTemplate));
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080054 fd_.reset(new EintrSafeFileDescriptor);
55 int fd = mkstemp(path_);
56 ASSERT_TRUE(fd_->Open(path_, O_RDWR, 0600));
57 close(fd);
Andrew de los Reyes80061062010-02-04 14:25:00 -080058 }
Alex Deymo610277e2014-11-11 21:18:11 -080059 void TearDown() override {
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080060 fd_->Close();
Andrew de los Reyes80061062010-02-04 14:25:00 -080061 unlink(path_);
62 }
Chris Masonef8d037f2014-02-19 01:53:00 +000063
Andrew de los Reyes80061062010-02-04 14:25:00 -080064 // Writes data to an extent writer in 'chunk_size' chunks with
65 // the first chunk of size first_chunk_size. It calculates what the
66 // resultant file should look like and ensure that the extent writer
67 // wrote the file correctly.
68 void WriteAlignedExtents(size_t chunk_size, size_t first_chunk_size);
69 void TestZeroPad(bool aligned_size);
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080070
71 FileDescriptorPtr fd_;
Andrew de los Reyes80061062010-02-04 14:25:00 -080072 char path_[sizeof(kPathTemplate)];
73};
74
75TEST_F(ExtentWriterTest, SimpleTest) {
76 vector<Extent> extents;
77 Extent extent;
78 extent.set_start_block(1);
79 extent.set_num_blocks(1);
80 extents.push_back(extent);
Alex Deymo161c4a12014-05-16 15:56:21 -070081
Andrew de los Reyes80061062010-02-04 14:25:00 -080082 const string bytes = "1234";
83
84 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080085 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Andrew de los Reyes80061062010-02-04 14:25:00 -080086 EXPECT_TRUE(direct_writer.Write(bytes.data(), bytes.size()));
87 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -070088
Alex Deymo5fe0c4e2016-02-16 18:46:24 -080089 EXPECT_EQ(static_cast<off_t>(kBlockSize + bytes.size()),
90 utils::FileSize(path_));
Alex Deymo161c4a12014-05-16 15:56:21 -070091
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070092 brillo::Blob result_file;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080093 EXPECT_TRUE(utils::ReadFile(path_, &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -070094
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070095 brillo::Blob expected_file(kBlockSize);
Andrew de los Reyes80061062010-02-04 14:25:00 -080096 expected_file.insert(expected_file.end(),
97 bytes.data(), bytes.data() + bytes.size());
98 ExpectVectorsEq(expected_file, result_file);
99}
100
101TEST_F(ExtentWriterTest, ZeroLengthTest) {
102 vector<Extent> extents;
103 Extent extent;
104 extent.set_start_block(1);
105 extent.set_num_blocks(1);
106 extents.push_back(extent);
107
108 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800109 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700110 EXPECT_TRUE(direct_writer.Write(nullptr, 0));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800111 EXPECT_TRUE(direct_writer.End());
112}
113
114TEST_F(ExtentWriterTest, OverflowExtentTest) {
115 WriteAlignedExtents(kBlockSize * 3, kBlockSize * 3);
116}
117
118TEST_F(ExtentWriterTest, UnalignedWriteTest) {
119 WriteAlignedExtents(7, 7);
120}
121
122TEST_F(ExtentWriterTest, LargeUnalignedWriteTest) {
123 WriteAlignedExtents(kBlockSize * 2, kBlockSize / 2);
124}
125
126void ExtentWriterTest::WriteAlignedExtents(size_t chunk_size,
127 size_t first_chunk_size) {
128 vector<Extent> extents;
129 Extent extent;
130 extent.set_start_block(1);
131 extent.set_num_blocks(1);
132 extents.push_back(extent);
133 extent.set_start_block(0);
134 extent.set_num_blocks(1);
135 extents.push_back(extent);
136 extent.set_start_block(2);
137 extent.set_num_blocks(1);
138 extents.push_back(extent);
Alex Deymo161c4a12014-05-16 15:56:21 -0700139
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700140 brillo::Blob data(kBlockSize * 3);
Alex Deymo10875d92014-11-10 21:52:57 -0800141 test_utils::FillWithData(&data);
Alex Deymo161c4a12014-05-16 15:56:21 -0700142
Andrew de los Reyes80061062010-02-04 14:25:00 -0800143 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800144 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Deymo161c4a12014-05-16 15:56:21 -0700145
Andrew de los Reyes80061062010-02-04 14:25:00 -0800146 size_t bytes_written = 0;
147 while (bytes_written < data.size()) {
148 size_t bytes_to_write = min(data.size() - bytes_written, chunk_size);
149 if (bytes_written == 0) {
150 bytes_to_write = min(data.size() - bytes_written, first_chunk_size);
151 }
152 EXPECT_TRUE(direct_writer.Write(&data[bytes_written], bytes_to_write));
153 bytes_written += bytes_to_write;
154 }
155 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700156
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800157 EXPECT_EQ(static_cast<off_t>(data.size()), utils::FileSize(path_));
Alex Deymo161c4a12014-05-16 15:56:21 -0700158
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700159 brillo::Blob result_file;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800160 EXPECT_TRUE(utils::ReadFile(path_, &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -0700161
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700162 brillo::Blob expected_file;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800163 expected_file.insert(expected_file.end(),
164 data.begin() + kBlockSize,
165 data.begin() + kBlockSize * 2);
166 expected_file.insert(expected_file.end(),
167 data.begin(), data.begin() + kBlockSize);
168 expected_file.insert(expected_file.end(),
169 data.begin() + kBlockSize * 2, data.end());
170 ExpectVectorsEq(expected_file, result_file);
171}
172
173TEST_F(ExtentWriterTest, ZeroPadNullTest) {
174 TestZeroPad(true);
175}
176
177TEST_F(ExtentWriterTest, ZeroPadFillTest) {
178 TestZeroPad(false);
179}
180
181void ExtentWriterTest::TestZeroPad(bool aligned_size) {
182 vector<Extent> extents;
183 Extent extent;
184 extent.set_start_block(1);
185 extent.set_num_blocks(1);
186 extents.push_back(extent);
187 extent.set_start_block(0);
188 extent.set_num_blocks(1);
189 extents.push_back(extent);
Alex Deymo161c4a12014-05-16 15:56:21 -0700190
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700191 brillo::Blob data(kBlockSize * 2);
Alex Deymo10875d92014-11-10 21:52:57 -0800192 test_utils::FillWithData(&data);
Alex Deymo161c4a12014-05-16 15:56:21 -0700193
Alex Deymo05322872015-09-30 09:50:24 -0700194 ZeroPadExtentWriter zero_pad_writer(
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700195 brillo::make_unique_ptr(new DirectExtentWriter()));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800196
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800197 EXPECT_TRUE(zero_pad_writer.Init(fd_, extents, kBlockSize));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800198 size_t bytes_to_write = data.size();
199 const size_t missing_bytes = (aligned_size ? 0 : 9);
200 bytes_to_write -= missing_bytes;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800201 fd_->Seek(kBlockSize - missing_bytes, SEEK_SET);
202 EXPECT_EQ(3, fd_->Write("xxx", 3));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800203 ASSERT_TRUE(zero_pad_writer.Write(data.data(), bytes_to_write));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800204 EXPECT_TRUE(zero_pad_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700205
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800206 EXPECT_EQ(static_cast<off_t>(data.size()), utils::FileSize(path_));
Alex Deymo161c4a12014-05-16 15:56:21 -0700207
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700208 brillo::Blob result_file;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800209 EXPECT_TRUE(utils::ReadFile(path_, &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -0700210
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700211 brillo::Blob expected_file;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800212 expected_file.insert(expected_file.end(),
213 data.begin() + kBlockSize,
214 data.begin() + kBlockSize * 2);
215 expected_file.insert(expected_file.end(),
216 data.begin(), data.begin() + kBlockSize);
217 if (missing_bytes) {
218 memset(&expected_file[kBlockSize - missing_bytes], 0, missing_bytes);
219 }
220
221 ExpectVectorsEq(expected_file, result_file);
222}
223
224TEST_F(ExtentWriterTest, SparseFileTest) {
225 vector<Extent> extents;
226 Extent extent;
227 extent.set_start_block(1);
228 extent.set_num_blocks(1);
229 extents.push_back(extent);
230 extent.set_start_block(kSparseHole);
231 extent.set_num_blocks(2);
232 extents.push_back(extent);
233 extent.set_start_block(0);
234 extent.set_num_blocks(1);
235 extents.push_back(extent);
236 const int block_count = 4;
237 const int on_disk_count = 2;
238
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700239 brillo::Blob data(17);
Alex Deymo10875d92014-11-10 21:52:57 -0800240 test_utils::FillWithData(&data);
Andrew de los Reyes80061062010-02-04 14:25:00 -0800241
242 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800243 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Deymo161c4a12014-05-16 15:56:21 -0700244
Andrew de los Reyes80061062010-02-04 14:25:00 -0800245 size_t bytes_written = 0;
246 while (bytes_written < (block_count * kBlockSize)) {
247 size_t bytes_to_write = min(block_count * kBlockSize - bytes_written,
248 data.size());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800249 EXPECT_TRUE(direct_writer.Write(data.data(), bytes_to_write));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800250 bytes_written += bytes_to_write;
251 }
252 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700253
Andrew de los Reyes80061062010-02-04 14:25:00 -0800254 // check file size, then data inside
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800255 ASSERT_EQ(static_cast<off_t>(2 * kBlockSize), utils::FileSize(path_));
Alex Deymo161c4a12014-05-16 15:56:21 -0700256
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700257 brillo::Blob resultant_data;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800258 EXPECT_TRUE(utils::ReadFile(path_, &resultant_data));
Alex Deymo161c4a12014-05-16 15:56:21 -0700259
Andrew de los Reyes80061062010-02-04 14:25:00 -0800260 // Create expected data
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700261 brillo::Blob expected_data(on_disk_count * kBlockSize);
262 brillo::Blob big(block_count * kBlockSize);
263 for (brillo::Blob::size_type i = 0; i < big.size(); i++) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800264 big[i] = data[i % data.size()];
265 }
266 memcpy(&expected_data[kBlockSize], &big[0], kBlockSize);
267 memcpy(&expected_data[0], &big[3 * kBlockSize], kBlockSize);
268 ExpectVectorsEq(expected_data, resultant_data);
269}
270
271} // namespace chromeos_update_engine