blob: cccf23209bf98cf2ca280cedfc3ab9573aa6783c [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 Deymo161c4a12014-05-16 15:56:21 -070017#include "update_engine/extent_writer.h"
18
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
32#include "update_engine/payload_constants.h"
Andrew de los Reyes80061062010-02-04 14:25:00 -080033#include "update_engine/test_utils.h"
34#include "update_engine/utils.h"
35
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
43COMPILE_ASSERT(sizeof(off_t) == 8, off_t_not_64_bit);
44
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
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080089 EXPECT_EQ(kBlockSize + bytes.size(), utils::FileSize(path_));
Alex Deymo161c4a12014-05-16 15:56:21 -070090
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070091 brillo::Blob result_file;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080092 EXPECT_TRUE(utils::ReadFile(path_, &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -070093
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070094 brillo::Blob expected_file(kBlockSize);
Andrew de los Reyes80061062010-02-04 14:25:00 -080095 expected_file.insert(expected_file.end(),
96 bytes.data(), bytes.data() + bytes.size());
97 ExpectVectorsEq(expected_file, result_file);
98}
99
100TEST_F(ExtentWriterTest, ZeroLengthTest) {
101 vector<Extent> extents;
102 Extent extent;
103 extent.set_start_block(1);
104 extent.set_num_blocks(1);
105 extents.push_back(extent);
106
107 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800108 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700109 EXPECT_TRUE(direct_writer.Write(nullptr, 0));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800110 EXPECT_TRUE(direct_writer.End());
111}
112
113TEST_F(ExtentWriterTest, OverflowExtentTest) {
114 WriteAlignedExtents(kBlockSize * 3, kBlockSize * 3);
115}
116
117TEST_F(ExtentWriterTest, UnalignedWriteTest) {
118 WriteAlignedExtents(7, 7);
119}
120
121TEST_F(ExtentWriterTest, LargeUnalignedWriteTest) {
122 WriteAlignedExtents(kBlockSize * 2, kBlockSize / 2);
123}
124
125void ExtentWriterTest::WriteAlignedExtents(size_t chunk_size,
126 size_t first_chunk_size) {
127 vector<Extent> extents;
128 Extent extent;
129 extent.set_start_block(1);
130 extent.set_num_blocks(1);
131 extents.push_back(extent);
132 extent.set_start_block(0);
133 extent.set_num_blocks(1);
134 extents.push_back(extent);
135 extent.set_start_block(2);
136 extent.set_num_blocks(1);
137 extents.push_back(extent);
Alex Deymo161c4a12014-05-16 15:56:21 -0700138
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700139 brillo::Blob data(kBlockSize * 3);
Alex Deymo10875d92014-11-10 21:52:57 -0800140 test_utils::FillWithData(&data);
Alex Deymo161c4a12014-05-16 15:56:21 -0700141
Andrew de los Reyes80061062010-02-04 14:25:00 -0800142 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800143 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Deymo161c4a12014-05-16 15:56:21 -0700144
Andrew de los Reyes80061062010-02-04 14:25:00 -0800145 size_t bytes_written = 0;
146 while (bytes_written < data.size()) {
147 size_t bytes_to_write = min(data.size() - bytes_written, chunk_size);
148 if (bytes_written == 0) {
149 bytes_to_write = min(data.size() - bytes_written, first_chunk_size);
150 }
151 EXPECT_TRUE(direct_writer.Write(&data[bytes_written], bytes_to_write));
152 bytes_written += bytes_to_write;
153 }
154 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700155
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800156 EXPECT_EQ(data.size(), utils::FileSize(path_));
Alex Deymo161c4a12014-05-16 15:56:21 -0700157
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700158 brillo::Blob result_file;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800159 EXPECT_TRUE(utils::ReadFile(path_, &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -0700160
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700161 brillo::Blob expected_file;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800162 expected_file.insert(expected_file.end(),
163 data.begin() + kBlockSize,
164 data.begin() + kBlockSize * 2);
165 expected_file.insert(expected_file.end(),
166 data.begin(), data.begin() + kBlockSize);
167 expected_file.insert(expected_file.end(),
168 data.begin() + kBlockSize * 2, data.end());
169 ExpectVectorsEq(expected_file, result_file);
170}
171
172TEST_F(ExtentWriterTest, ZeroPadNullTest) {
173 TestZeroPad(true);
174}
175
176TEST_F(ExtentWriterTest, ZeroPadFillTest) {
177 TestZeroPad(false);
178}
179
180void ExtentWriterTest::TestZeroPad(bool aligned_size) {
181 vector<Extent> extents;
182 Extent extent;
183 extent.set_start_block(1);
184 extent.set_num_blocks(1);
185 extents.push_back(extent);
186 extent.set_start_block(0);
187 extent.set_num_blocks(1);
188 extents.push_back(extent);
Alex Deymo161c4a12014-05-16 15:56:21 -0700189
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700190 brillo::Blob data(kBlockSize * 2);
Alex Deymo10875d92014-11-10 21:52:57 -0800191 test_utils::FillWithData(&data);
Alex Deymo161c4a12014-05-16 15:56:21 -0700192
Alex Deymo05322872015-09-30 09:50:24 -0700193 ZeroPadExtentWriter zero_pad_writer(
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700194 brillo::make_unique_ptr(new DirectExtentWriter()));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800195
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800196 EXPECT_TRUE(zero_pad_writer.Init(fd_, extents, kBlockSize));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800197 size_t bytes_to_write = data.size();
198 const size_t missing_bytes = (aligned_size ? 0 : 9);
199 bytes_to_write -= missing_bytes;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800200 fd_->Seek(kBlockSize - missing_bytes, SEEK_SET);
201 EXPECT_EQ(3, fd_->Write("xxx", 3));
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800202 ASSERT_TRUE(zero_pad_writer.Write(data.data(), bytes_to_write));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800203 EXPECT_TRUE(zero_pad_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700204
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800205 EXPECT_EQ(data.size(), utils::FileSize(path_));
Alex Deymo161c4a12014-05-16 15:56:21 -0700206
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700207 brillo::Blob result_file;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800208 EXPECT_TRUE(utils::ReadFile(path_, &result_file));
Alex Deymo161c4a12014-05-16 15:56:21 -0700209
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700210 brillo::Blob expected_file;
Andrew de los Reyes80061062010-02-04 14:25:00 -0800211 expected_file.insert(expected_file.end(),
212 data.begin() + kBlockSize,
213 data.begin() + kBlockSize * 2);
214 expected_file.insert(expected_file.end(),
215 data.begin(), data.begin() + kBlockSize);
216 if (missing_bytes) {
217 memset(&expected_file[kBlockSize - missing_bytes], 0, missing_bytes);
218 }
219
220 ExpectVectorsEq(expected_file, result_file);
221}
222
223TEST_F(ExtentWriterTest, SparseFileTest) {
224 vector<Extent> extents;
225 Extent extent;
226 extent.set_start_block(1);
227 extent.set_num_blocks(1);
228 extents.push_back(extent);
229 extent.set_start_block(kSparseHole);
230 extent.set_num_blocks(2);
231 extents.push_back(extent);
232 extent.set_start_block(0);
233 extent.set_num_blocks(1);
234 extents.push_back(extent);
235 const int block_count = 4;
236 const int on_disk_count = 2;
237
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700238 brillo::Blob data(17);
Alex Deymo10875d92014-11-10 21:52:57 -0800239 test_utils::FillWithData(&data);
Andrew de los Reyes80061062010-02-04 14:25:00 -0800240
241 DirectExtentWriter direct_writer;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800242 EXPECT_TRUE(direct_writer.Init(fd_, extents, kBlockSize));
Alex Deymo161c4a12014-05-16 15:56:21 -0700243
Andrew de los Reyes80061062010-02-04 14:25:00 -0800244 size_t bytes_written = 0;
245 while (bytes_written < (block_count * kBlockSize)) {
246 size_t bytes_to_write = min(block_count * kBlockSize - bytes_written,
247 data.size());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800248 EXPECT_TRUE(direct_writer.Write(data.data(), bytes_to_write));
Andrew de los Reyes80061062010-02-04 14:25:00 -0800249 bytes_written += bytes_to_write;
250 }
251 EXPECT_TRUE(direct_writer.End());
Alex Deymo161c4a12014-05-16 15:56:21 -0700252
Andrew de los Reyes80061062010-02-04 14:25:00 -0800253 // check file size, then data inside
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800254 ASSERT_EQ(2 * kBlockSize, utils::FileSize(path_));
Alex Deymo161c4a12014-05-16 15:56:21 -0700255
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700256 brillo::Blob resultant_data;
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -0800257 EXPECT_TRUE(utils::ReadFile(path_, &resultant_data));
Alex Deymo161c4a12014-05-16 15:56:21 -0700258
Andrew de los Reyes80061062010-02-04 14:25:00 -0800259 // Create expected data
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700260 brillo::Blob expected_data(on_disk_count * kBlockSize);
261 brillo::Blob big(block_count * kBlockSize);
262 for (brillo::Blob::size_type i = 0; i < big.size(); i++) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800263 big[i] = data[i % data.size()];
264 }
265 memcpy(&expected_data[kBlockSize], &big[0], kBlockSize);
266 memcpy(&expected_data[0], &big[3 * kBlockSize], kBlockSize);
267 ExpectVectorsEq(expected_data, resultant_data);
268}
269
270} // namespace chromeos_update_engine