blob: 60bdf261fd349b35c89df0219810aed739ad1b69 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -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//
Alex Deymo14158572015-06-13 03:37:08 -070016
17#include "update_engine/payload_generator/ab_generator.h"
18
19#include <fcntl.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22
23#include <string>
Alex Deymo80f70ff2016-02-10 16:08:11 -080024#include <random>
Alex Deymo14158572015-06-13 03:37:08 -070025#include <vector>
26
27#include <gtest/gtest.h>
28
Alex Deymo39910dc2015-11-09 17:04:30 -080029#include "update_engine/common/hash_calculator.h"
30#include "update_engine/common/test_utils.h"
31#include "update_engine/common/utils.h"
Alex Deymo14158572015-06-13 03:37:08 -070032#include "update_engine/payload_generator/annotated_operation.h"
Alex Deymoabdc0112015-10-22 11:53:12 -070033#include "update_engine/payload_generator/bzip.h"
Alex Deymo14158572015-06-13 03:37:08 -070034#include "update_engine/payload_generator/delta_diff_generator.h"
35#include "update_engine/payload_generator/extent_ranges.h"
36#include "update_engine/payload_generator/extent_utils.h"
Alex Deymo14158572015-06-13 03:37:08 -070037
38using std::string;
39using std::vector;
40
41namespace chromeos_update_engine {
42
43namespace {
44
45bool ExtentEquals(Extent ext, uint64_t start_block, uint64_t num_blocks) {
46 return ext.start_block() == start_block && ext.num_blocks() == num_blocks;
47}
48
49// Tests splitting of a REPLACE/REPLACE_BZ operation.
Alex Deymoa12ee112015-08-12 22:19:32 -070050void TestSplitReplaceOrReplaceBzOperation(InstallOperation_Type orig_type,
51 bool compressible) {
Alex Deymo14158572015-06-13 03:37:08 -070052 const size_t op_ex1_start_block = 2;
53 const size_t op_ex1_num_blocks = 2;
54 const size_t op_ex2_start_block = 6;
55 const size_t op_ex2_num_blocks = 1;
56 const size_t part_num_blocks = 7;
57
58 // Create the target partition data.
59 string part_path;
60 EXPECT_TRUE(utils::MakeTempFile(
61 "SplitReplaceOrReplaceBzTest_part.XXXXXX", &part_path, nullptr));
62 ScopedPathUnlinker part_path_unlinker(part_path);
63 const size_t part_size = part_num_blocks * kBlockSize;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070064 brillo::Blob part_data;
Alex Deymo14158572015-06-13 03:37:08 -070065 if (compressible) {
66 part_data.resize(part_size);
67 test_utils::FillWithData(&part_data);
68 } else {
69 std::mt19937 gen(12345);
70 std::uniform_int_distribution<uint8_t> dis(0, 255);
71 for (uint32_t i = 0; i < part_size; i++)
72 part_data.push_back(dis(gen));
73 }
74 ASSERT_EQ(part_size, part_data.size());
75 ASSERT_TRUE(utils::WriteFile(part_path.c_str(), part_data.data(), part_size));
76
77 // Create original operation and blob data.
78 const size_t op_ex1_offset = op_ex1_start_block * kBlockSize;
79 const size_t op_ex1_size = op_ex1_num_blocks * kBlockSize;
80 const size_t op_ex2_offset = op_ex2_start_block * kBlockSize;
81 const size_t op_ex2_size = op_ex2_num_blocks * kBlockSize;
Alex Deymoa12ee112015-08-12 22:19:32 -070082 InstallOperation op;
Alex Deymo14158572015-06-13 03:37:08 -070083 op.set_type(orig_type);
84 *(op.add_dst_extents()) = ExtentForRange(op_ex1_start_block,
85 op_ex1_num_blocks);
86 *(op.add_dst_extents()) = ExtentForRange(op_ex2_start_block,
87 op_ex2_num_blocks);
88 op.set_dst_length(op_ex1_num_blocks + op_ex2_num_blocks);
89
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070090 brillo::Blob op_data;
Alex Deymo14158572015-06-13 03:37:08 -070091 op_data.insert(op_data.end(),
92 part_data.begin() + op_ex1_offset,
93 part_data.begin() + op_ex1_offset + op_ex1_size);
94 op_data.insert(op_data.end(),
95 part_data.begin() + op_ex2_offset,
96 part_data.begin() + op_ex2_offset + op_ex2_size);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -070097 brillo::Blob op_blob;
Alex Deymoa12ee112015-08-12 22:19:32 -070098 if (orig_type == InstallOperation::REPLACE) {
Alex Deymo14158572015-06-13 03:37:08 -070099 op_blob = op_data;
100 } else {
101 ASSERT_TRUE(BzipCompress(op_data, &op_blob));
102 }
103 op.set_data_offset(0);
104 op.set_data_length(op_blob.size());
105
106 AnnotatedOperation aop;
107 aop.op = op;
108 aop.name = "SplitTestOp";
109
110 // Create the data file.
111 string data_path;
112 EXPECT_TRUE(utils::MakeTempFile(
113 "SplitReplaceOrReplaceBzTest_data.XXXXXX", &data_path, nullptr));
114 ScopedPathUnlinker data_path_unlinker(data_path);
115 int data_fd = open(data_path.c_str(), O_RDWR, 000);
116 EXPECT_GE(data_fd, 0);
117 ScopedFdCloser data_fd_closer(&data_fd);
118 EXPECT_TRUE(utils::WriteFile(data_path.c_str(), op_blob.data(),
119 op_blob.size()));
120 off_t data_file_size = op_blob.size();
Sen Jiang8cc502d2015-08-10 10:04:54 -0700121 BlobFileWriter blob_file(data_fd, &data_file_size);
Alex Deymo14158572015-06-13 03:37:08 -0700122
123 // Split the operation.
124 vector<AnnotatedOperation> result_ops;
125 ASSERT_TRUE(ABGenerator::SplitReplaceOrReplaceBz(
Sen Jiang8cc502d2015-08-10 10:04:54 -0700126 aop, &result_ops, part_path, &blob_file));
Alex Deymo14158572015-06-13 03:37:08 -0700127
128 // Check the result.
Alex Deymoa12ee112015-08-12 22:19:32 -0700129 InstallOperation_Type expected_type =
130 compressible ? InstallOperation::REPLACE_BZ : InstallOperation::REPLACE;
Alex Deymo14158572015-06-13 03:37:08 -0700131
Alex Deymo80f70ff2016-02-10 16:08:11 -0800132 ASSERT_EQ(2U, result_ops.size());
Alex Deymo14158572015-06-13 03:37:08 -0700133
134 EXPECT_EQ("SplitTestOp:0", result_ops[0].name);
Alex Deymoa12ee112015-08-12 22:19:32 -0700135 InstallOperation first_op = result_ops[0].op;
Alex Deymo14158572015-06-13 03:37:08 -0700136 EXPECT_EQ(expected_type, first_op.type());
137 EXPECT_EQ(op_ex1_size, first_op.dst_length());
138 EXPECT_EQ(1, first_op.dst_extents().size());
139 EXPECT_TRUE(ExtentEquals(first_op.dst_extents(0), op_ex1_start_block,
140 op_ex1_num_blocks));
141 // Obtain the expected blob.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700142 brillo::Blob first_expected_data(
Alex Deymo14158572015-06-13 03:37:08 -0700143 part_data.begin() + op_ex1_offset,
144 part_data.begin() + op_ex1_offset + op_ex1_size);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700145 brillo::Blob first_expected_blob;
Alex Deymo14158572015-06-13 03:37:08 -0700146 if (compressible) {
147 ASSERT_TRUE(BzipCompress(first_expected_data, &first_expected_blob));
148 } else {
149 first_expected_blob = first_expected_data;
150 }
151 EXPECT_EQ(first_expected_blob.size(), first_op.data_length());
152 // Check that the actual blob matches what's expected.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700153 brillo::Blob first_data_blob(first_op.data_length());
Alex Deymo14158572015-06-13 03:37:08 -0700154 ssize_t bytes_read;
155 ASSERT_TRUE(utils::PReadAll(data_fd,
156 first_data_blob.data(),
157 first_op.data_length(),
158 first_op.data_offset(),
159 &bytes_read));
Alex Deymo80f70ff2016-02-10 16:08:11 -0800160 ASSERT_EQ(bytes_read, static_cast<ssize_t>(first_op.data_length()));
Alex Deymo14158572015-06-13 03:37:08 -0700161 EXPECT_EQ(first_expected_blob, first_data_blob);
162
163 EXPECT_EQ("SplitTestOp:1", result_ops[1].name);
Alex Deymoa12ee112015-08-12 22:19:32 -0700164 InstallOperation second_op = result_ops[1].op;
Alex Deymo14158572015-06-13 03:37:08 -0700165 EXPECT_EQ(expected_type, second_op.type());
166 EXPECT_EQ(op_ex2_size, second_op.dst_length());
167 EXPECT_EQ(1, second_op.dst_extents().size());
168 EXPECT_TRUE(ExtentEquals(second_op.dst_extents(0), op_ex2_start_block,
169 op_ex2_num_blocks));
170 // Obtain the expected blob.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700171 brillo::Blob second_expected_data(
Alex Deymo14158572015-06-13 03:37:08 -0700172 part_data.begin() + op_ex2_offset,
173 part_data.begin() + op_ex2_offset + op_ex2_size);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700174 brillo::Blob second_expected_blob;
Alex Deymo14158572015-06-13 03:37:08 -0700175 if (compressible) {
176 ASSERT_TRUE(BzipCompress(second_expected_data, &second_expected_blob));
177 } else {
178 second_expected_blob = second_expected_data;
179 }
180 EXPECT_EQ(second_expected_blob.size(), second_op.data_length());
181 // Check that the actual blob matches what's expected.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700182 brillo::Blob second_data_blob(second_op.data_length());
Alex Deymo14158572015-06-13 03:37:08 -0700183 ASSERT_TRUE(utils::PReadAll(data_fd,
184 second_data_blob.data(),
185 second_op.data_length(),
186 second_op.data_offset(),
187 &bytes_read));
Alex Deymo80f70ff2016-02-10 16:08:11 -0800188 ASSERT_EQ(bytes_read, static_cast<ssize_t>(second_op.data_length()));
Alex Deymo14158572015-06-13 03:37:08 -0700189 EXPECT_EQ(second_expected_blob, second_data_blob);
190
191 // Check relative layout of data blobs.
192 EXPECT_EQ(first_op.data_offset() + first_op.data_length(),
193 second_op.data_offset());
194 EXPECT_EQ(second_op.data_offset() + second_op.data_length(), data_file_size);
195 // If we split a REPLACE into multiple ones, ensure reuse of preexisting blob.
Alex Deymoa12ee112015-08-12 22:19:32 -0700196 if (!compressible && orig_type == InstallOperation::REPLACE) {
Alex Deymo80f70ff2016-02-10 16:08:11 -0800197 EXPECT_EQ(0U, first_op.data_offset());
Alex Deymo14158572015-06-13 03:37:08 -0700198 }
199}
200
201// Tests merging of REPLACE/REPLACE_BZ operations.
Alex Deymoa12ee112015-08-12 22:19:32 -0700202void TestMergeReplaceOrReplaceBzOperations(InstallOperation_Type orig_type,
203 bool compressible) {
Alex Deymo14158572015-06-13 03:37:08 -0700204 const size_t first_op_num_blocks = 1;
205 const size_t second_op_num_blocks = 2;
206 const size_t total_op_num_blocks = first_op_num_blocks + second_op_num_blocks;
207 const size_t part_num_blocks = total_op_num_blocks + 2;
208
209 // Create the target partition data.
210 string part_path;
211 EXPECT_TRUE(utils::MakeTempFile(
212 "MergeReplaceOrReplaceBzTest_part.XXXXXX", &part_path, nullptr));
213 ScopedPathUnlinker part_path_unlinker(part_path);
214 const size_t part_size = part_num_blocks * kBlockSize;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700215 brillo::Blob part_data;
Alex Deymo14158572015-06-13 03:37:08 -0700216 if (compressible) {
217 part_data.resize(part_size);
218 test_utils::FillWithData(&part_data);
219 } else {
220 std::mt19937 gen(12345);
221 std::uniform_int_distribution<uint8_t> dis(0, 255);
222 for (uint32_t i = 0; i < part_size; i++)
223 part_data.push_back(dis(gen));
224 }
225 ASSERT_EQ(part_size, part_data.size());
226 ASSERT_TRUE(utils::WriteFile(part_path.c_str(), part_data.data(), part_size));
227
228 // Create original operations and blob data.
229 vector<AnnotatedOperation> aops;
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700230 brillo::Blob blob_data;
Alex Deymo14158572015-06-13 03:37:08 -0700231 const size_t total_op_size = total_op_num_blocks * kBlockSize;
232
Alex Deymoa12ee112015-08-12 22:19:32 -0700233 InstallOperation first_op;
Alex Deymo14158572015-06-13 03:37:08 -0700234 first_op.set_type(orig_type);
235 const size_t first_op_size = first_op_num_blocks * kBlockSize;
236 first_op.set_dst_length(first_op_size);
237 *(first_op.add_dst_extents()) = ExtentForRange(0, first_op_num_blocks);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700238 brillo::Blob first_op_data(part_data.begin(),
Alex Deymo14158572015-06-13 03:37:08 -0700239 part_data.begin() + first_op_size);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700240 brillo::Blob first_op_blob;
Alex Deymoa12ee112015-08-12 22:19:32 -0700241 if (orig_type == InstallOperation::REPLACE) {
Alex Deymo14158572015-06-13 03:37:08 -0700242 first_op_blob = first_op_data;
243 } else {
244 ASSERT_TRUE(BzipCompress(first_op_data, &first_op_blob));
245 }
246 first_op.set_data_offset(0);
247 first_op.set_data_length(first_op_blob.size());
248 blob_data.insert(blob_data.end(), first_op_blob.begin(), first_op_blob.end());
249 AnnotatedOperation first_aop;
250 first_aop.op = first_op;
251 first_aop.name = "first";
252 aops.push_back(first_aop);
253
Alex Deymoa12ee112015-08-12 22:19:32 -0700254 InstallOperation second_op;
Alex Deymo14158572015-06-13 03:37:08 -0700255 second_op.set_type(orig_type);
256 const size_t second_op_size = second_op_num_blocks * kBlockSize;
257 second_op.set_dst_length(second_op_size);
258 *(second_op.add_dst_extents()) = ExtentForRange(first_op_num_blocks,
259 second_op_num_blocks);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700260 brillo::Blob second_op_data(part_data.begin() + first_op_size,
Alex Deymo14158572015-06-13 03:37:08 -0700261 part_data.begin() + total_op_size);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700262 brillo::Blob second_op_blob;
Alex Deymoa12ee112015-08-12 22:19:32 -0700263 if (orig_type == InstallOperation::REPLACE) {
Alex Deymo14158572015-06-13 03:37:08 -0700264 second_op_blob = second_op_data;
265 } else {
266 ASSERT_TRUE(BzipCompress(second_op_data, &second_op_blob));
267 }
268 second_op.set_data_offset(first_op_blob.size());
269 second_op.set_data_length(second_op_blob.size());
270 blob_data.insert(blob_data.end(), second_op_blob.begin(),
271 second_op_blob.end());
272 AnnotatedOperation second_aop;
273 second_aop.op = second_op;
274 second_aop.name = "second";
275 aops.push_back(second_aop);
276
277 // Create the data file.
278 string data_path;
279 EXPECT_TRUE(utils::MakeTempFile(
280 "MergeReplaceOrReplaceBzTest_data.XXXXXX", &data_path, nullptr));
281 ScopedPathUnlinker data_path_unlinker(data_path);
282 int data_fd = open(data_path.c_str(), O_RDWR, 000);
283 EXPECT_GE(data_fd, 0);
284 ScopedFdCloser data_fd_closer(&data_fd);
285 EXPECT_TRUE(utils::WriteFile(data_path.c_str(), blob_data.data(),
286 blob_data.size()));
287 off_t data_file_size = blob_data.size();
Sen Jiang8cc502d2015-08-10 10:04:54 -0700288 BlobFileWriter blob_file(data_fd, &data_file_size);
Alex Deymo14158572015-06-13 03:37:08 -0700289
290 // Merge the operations.
291 EXPECT_TRUE(ABGenerator::MergeOperations(
Sen Jiang8cc502d2015-08-10 10:04:54 -0700292 &aops, 5, part_path, &blob_file));
Alex Deymo14158572015-06-13 03:37:08 -0700293
294 // Check the result.
Alex Deymoa12ee112015-08-12 22:19:32 -0700295 InstallOperation_Type expected_op_type =
296 compressible ? InstallOperation::REPLACE_BZ : InstallOperation::REPLACE;
Alex Deymo80f70ff2016-02-10 16:08:11 -0800297 EXPECT_EQ(1U, aops.size());
Alex Deymoa12ee112015-08-12 22:19:32 -0700298 InstallOperation new_op = aops[0].op;
Alex Deymo14158572015-06-13 03:37:08 -0700299 EXPECT_EQ(expected_op_type, new_op.type());
300 EXPECT_FALSE(new_op.has_src_length());
301 EXPECT_EQ(total_op_num_blocks * kBlockSize, new_op.dst_length());
302 EXPECT_EQ(1, new_op.dst_extents().size());
303 EXPECT_TRUE(ExtentEquals(new_op.dst_extents(0), 0, total_op_num_blocks));
304 EXPECT_EQ("first,second", aops[0].name);
305
306 // Check to see if the blob pointed to in the new extent has what we expect.
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700307 brillo::Blob expected_data(part_data.begin(),
Alex Deymo14158572015-06-13 03:37:08 -0700308 part_data.begin() + total_op_size);
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700309 brillo::Blob expected_blob;
Alex Deymo14158572015-06-13 03:37:08 -0700310 if (compressible) {
311 ASSERT_TRUE(BzipCompress(expected_data, &expected_blob));
312 } else {
313 expected_blob = expected_data;
314 }
315 ASSERT_EQ(expected_blob.size(), new_op.data_length());
Alex Deymo5fe0c4e2016-02-16 18:46:24 -0800316 ASSERT_EQ(blob_data.size() + expected_blob.size(),
317 static_cast<size_t>(data_file_size));
Alex Vakulenko3f39d5c2015-10-13 09:27:13 -0700318 brillo::Blob new_op_blob(new_op.data_length());
Alex Deymo14158572015-06-13 03:37:08 -0700319 ssize_t bytes_read;
320 ASSERT_TRUE(utils::PReadAll(data_fd,
321 new_op_blob.data(),
322 new_op.data_length(),
323 new_op.data_offset(),
324 &bytes_read));
Alex Deymo80f70ff2016-02-10 16:08:11 -0800325 ASSERT_EQ(static_cast<ssize_t>(new_op.data_length()), bytes_read);
Alex Deymo14158572015-06-13 03:37:08 -0700326 EXPECT_EQ(expected_blob, new_op_blob);
327}
328
329} // namespace
330
331class ABGeneratorTest : public ::testing::Test {};
332
333TEST_F(ABGeneratorTest, SplitSourceCopyTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700334 InstallOperation op;
335 op.set_type(InstallOperation::SOURCE_COPY);
Alex Deymo14158572015-06-13 03:37:08 -0700336 *(op.add_src_extents()) = ExtentForRange(2, 3);
337 *(op.add_src_extents()) = ExtentForRange(6, 1);
338 *(op.add_src_extents()) = ExtentForRange(8, 4);
339 *(op.add_dst_extents()) = ExtentForRange(10, 2);
340 *(op.add_dst_extents()) = ExtentForRange(14, 3);
341 *(op.add_dst_extents()) = ExtentForRange(18, 3);
342
343 AnnotatedOperation aop;
344 aop.op = op;
345 aop.name = "SplitSourceCopyTestOp";
346 vector<AnnotatedOperation> result_ops;
347 EXPECT_TRUE(ABGenerator::SplitSourceCopy(aop, &result_ops));
Alex Deymo80f70ff2016-02-10 16:08:11 -0800348 EXPECT_EQ(3U, result_ops.size());
Alex Deymo14158572015-06-13 03:37:08 -0700349
350 EXPECT_EQ("SplitSourceCopyTestOp:0", result_ops[0].name);
Alex Deymoa12ee112015-08-12 22:19:32 -0700351 InstallOperation first_op = result_ops[0].op;
352 EXPECT_EQ(InstallOperation::SOURCE_COPY, first_op.type());
Alex Deymo14158572015-06-13 03:37:08 -0700353 EXPECT_EQ(kBlockSize * 2, first_op.src_length());
354 EXPECT_EQ(1, first_op.src_extents().size());
Alex Deymo80f70ff2016-02-10 16:08:11 -0800355 EXPECT_EQ(2U, first_op.src_extents(0).start_block());
356 EXPECT_EQ(2U, first_op.src_extents(0).num_blocks());
Alex Deymo14158572015-06-13 03:37:08 -0700357 EXPECT_EQ(kBlockSize * 2, first_op.dst_length());
358 EXPECT_EQ(1, first_op.dst_extents().size());
Alex Deymo80f70ff2016-02-10 16:08:11 -0800359 EXPECT_EQ(10U, first_op.dst_extents(0).start_block());
360 EXPECT_EQ(2U, first_op.dst_extents(0).num_blocks());
Alex Deymo14158572015-06-13 03:37:08 -0700361
362 EXPECT_EQ("SplitSourceCopyTestOp:1", result_ops[1].name);
Alex Deymoa12ee112015-08-12 22:19:32 -0700363 InstallOperation second_op = result_ops[1].op;
364 EXPECT_EQ(InstallOperation::SOURCE_COPY, second_op.type());
Alex Deymo14158572015-06-13 03:37:08 -0700365 EXPECT_EQ(kBlockSize * 3, second_op.src_length());
366 EXPECT_EQ(3, second_op.src_extents().size());
Alex Deymo80f70ff2016-02-10 16:08:11 -0800367 EXPECT_EQ(4U, second_op.src_extents(0).start_block());
368 EXPECT_EQ(1U, second_op.src_extents(0).num_blocks());
369 EXPECT_EQ(6U, second_op.src_extents(1).start_block());
370 EXPECT_EQ(1U, second_op.src_extents(1).num_blocks());
371 EXPECT_EQ(8U, second_op.src_extents(2).start_block());
372 EXPECT_EQ(1U, second_op.src_extents(2).num_blocks());
Alex Deymo14158572015-06-13 03:37:08 -0700373 EXPECT_EQ(kBlockSize * 3, second_op.dst_length());
374 EXPECT_EQ(1, second_op.dst_extents().size());
Alex Deymo80f70ff2016-02-10 16:08:11 -0800375 EXPECT_EQ(14U, second_op.dst_extents(0).start_block());
376 EXPECT_EQ(3U, second_op.dst_extents(0).num_blocks());
Alex Deymo14158572015-06-13 03:37:08 -0700377
378 EXPECT_EQ("SplitSourceCopyTestOp:2", result_ops[2].name);
Alex Deymoa12ee112015-08-12 22:19:32 -0700379 InstallOperation third_op = result_ops[2].op;
380 EXPECT_EQ(InstallOperation::SOURCE_COPY, third_op.type());
Alex Deymo14158572015-06-13 03:37:08 -0700381 EXPECT_EQ(kBlockSize * 3, third_op.src_length());
382 EXPECT_EQ(1, third_op.src_extents().size());
Alex Deymo80f70ff2016-02-10 16:08:11 -0800383 EXPECT_EQ(9U, third_op.src_extents(0).start_block());
384 EXPECT_EQ(3U, third_op.src_extents(0).num_blocks());
Alex Deymo14158572015-06-13 03:37:08 -0700385 EXPECT_EQ(kBlockSize * 3, third_op.dst_length());
386 EXPECT_EQ(1, third_op.dst_extents().size());
Alex Deymo80f70ff2016-02-10 16:08:11 -0800387 EXPECT_EQ(18U, third_op.dst_extents(0).start_block());
388 EXPECT_EQ(3U, third_op.dst_extents(0).num_blocks());
Alex Deymo14158572015-06-13 03:37:08 -0700389}
390
391TEST_F(ABGeneratorTest, SplitReplaceTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700392 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE, false);
Alex Deymo14158572015-06-13 03:37:08 -0700393}
394
395TEST_F(ABGeneratorTest, SplitReplaceIntoReplaceBzTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700396 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE, true);
Alex Deymo14158572015-06-13 03:37:08 -0700397}
398
399TEST_F(ABGeneratorTest, SplitReplaceBzTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700400 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE_BZ, true);
Alex Deymo14158572015-06-13 03:37:08 -0700401}
402
403TEST_F(ABGeneratorTest, SplitReplaceBzIntoReplaceTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700404 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE_BZ, false);
Alex Deymo14158572015-06-13 03:37:08 -0700405}
406
407TEST_F(ABGeneratorTest, SortOperationsByDestinationTest) {
408 vector<AnnotatedOperation> aops;
409 // One operation with multiple destination extents.
Alex Deymoa12ee112015-08-12 22:19:32 -0700410 InstallOperation first_op;
Alex Deymo14158572015-06-13 03:37:08 -0700411 *(first_op.add_dst_extents()) = ExtentForRange(6, 1);
412 *(first_op.add_dst_extents()) = ExtentForRange(10, 2);
413 AnnotatedOperation first_aop;
414 first_aop.op = first_op;
415 first_aop.name = "first";
416 aops.push_back(first_aop);
417
418 // One with no destination extent. Should end up at the end of the vector.
Alex Deymoa12ee112015-08-12 22:19:32 -0700419 InstallOperation second_op;
Alex Deymo14158572015-06-13 03:37:08 -0700420 AnnotatedOperation second_aop;
421 second_aop.op = second_op;
422 second_aop.name = "second";
423 aops.push_back(second_aop);
424
425 // One with one destination extent.
Alex Deymoa12ee112015-08-12 22:19:32 -0700426 InstallOperation third_op;
Alex Deymo14158572015-06-13 03:37:08 -0700427 *(third_op.add_dst_extents()) = ExtentForRange(3, 2);
428 AnnotatedOperation third_aop;
429 third_aop.op = third_op;
430 third_aop.name = "third";
431 aops.push_back(third_aop);
432
433 ABGenerator::SortOperationsByDestination(&aops);
Alex Deymo80f70ff2016-02-10 16:08:11 -0800434 EXPECT_EQ(3U, aops.size());
Alex Deymo14158572015-06-13 03:37:08 -0700435 EXPECT_EQ(third_aop.name, aops[0].name);
436 EXPECT_EQ(first_aop.name, aops[1].name);
437 EXPECT_EQ(second_aop.name, aops[2].name);
438}
439
440TEST_F(ABGeneratorTest, MergeSourceCopyOperationsTest) {
441 vector<AnnotatedOperation> aops;
Alex Deymoa12ee112015-08-12 22:19:32 -0700442 InstallOperation first_op;
443 first_op.set_type(InstallOperation::SOURCE_COPY);
Alex Deymo14158572015-06-13 03:37:08 -0700444 first_op.set_src_length(kBlockSize);
445 first_op.set_dst_length(kBlockSize);
446 *(first_op.add_src_extents()) = ExtentForRange(1, 1);
447 *(first_op.add_dst_extents()) = ExtentForRange(6, 1);
448 AnnotatedOperation first_aop;
449 first_aop.op = first_op;
450 first_aop.name = "1";
451 aops.push_back(first_aop);
452
Alex Deymoa12ee112015-08-12 22:19:32 -0700453 InstallOperation second_op;
454 second_op.set_type(InstallOperation::SOURCE_COPY);
Alex Deymo14158572015-06-13 03:37:08 -0700455 second_op.set_src_length(3 * kBlockSize);
456 second_op.set_dst_length(3 * kBlockSize);
457 *(second_op.add_src_extents()) = ExtentForRange(2, 2);
458 *(second_op.add_src_extents()) = ExtentForRange(8, 2);
459 *(second_op.add_dst_extents()) = ExtentForRange(7, 3);
460 *(second_op.add_dst_extents()) = ExtentForRange(11, 1);
461 AnnotatedOperation second_aop;
462 second_aop.op = second_op;
463 second_aop.name = "2";
464 aops.push_back(second_aop);
465
Alex Deymoa12ee112015-08-12 22:19:32 -0700466 InstallOperation third_op;
467 third_op.set_type(InstallOperation::SOURCE_COPY);
Alex Deymo14158572015-06-13 03:37:08 -0700468 third_op.set_src_length(kBlockSize);
469 third_op.set_dst_length(kBlockSize);
470 *(third_op.add_src_extents()) = ExtentForRange(11, 1);
471 *(third_op.add_dst_extents()) = ExtentForRange(12, 1);
472 AnnotatedOperation third_aop;
473 third_aop.op = third_op;
474 third_aop.name = "3";
475 aops.push_back(third_aop);
476
Sen Jiang8cc502d2015-08-10 10:04:54 -0700477 BlobFileWriter blob_file(0, nullptr);
478 EXPECT_TRUE(ABGenerator::MergeOperations(&aops, 5, "", &blob_file));
Alex Deymo14158572015-06-13 03:37:08 -0700479
Alex Deymo80f70ff2016-02-10 16:08:11 -0800480 EXPECT_EQ(1U, aops.size());
Alex Deymoa12ee112015-08-12 22:19:32 -0700481 InstallOperation first_result_op = aops[0].op;
482 EXPECT_EQ(InstallOperation::SOURCE_COPY, first_result_op.type());
Alex Deymo14158572015-06-13 03:37:08 -0700483 EXPECT_EQ(kBlockSize * 5, first_result_op.src_length());
484 EXPECT_EQ(3, first_result_op.src_extents().size());
485 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(0), 1, 3));
486 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(1), 8, 2));
487 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(2), 11, 1));
488 EXPECT_EQ(kBlockSize * 5, first_result_op.dst_length());
489 EXPECT_EQ(2, first_result_op.dst_extents().size());
490 EXPECT_TRUE(ExtentEquals(first_result_op.dst_extents(0), 6, 4));
491 EXPECT_TRUE(ExtentEquals(first_result_op.dst_extents(1), 11, 2));
492 EXPECT_EQ(aops[0].name, "1,2,3");
493}
494
495TEST_F(ABGeneratorTest, MergeReplaceOperationsTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700496 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE, false);
Alex Deymo14158572015-06-13 03:37:08 -0700497}
498
499TEST_F(ABGeneratorTest, MergeReplaceOperationsToReplaceBzTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700500 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE, true);
Alex Deymo14158572015-06-13 03:37:08 -0700501}
502
503TEST_F(ABGeneratorTest, MergeReplaceBzOperationsTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700504 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE_BZ, true);
Alex Deymo14158572015-06-13 03:37:08 -0700505}
506
507TEST_F(ABGeneratorTest, MergeReplaceBzOperationsToReplaceTest) {
Alex Deymoa12ee112015-08-12 22:19:32 -0700508 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE_BZ, false);
Alex Deymo14158572015-06-13 03:37:08 -0700509}
510
511TEST_F(ABGeneratorTest, NoMergeOperationsTest) {
512 // Test to make sure we don't merge operations that shouldn't be merged.
513 vector<AnnotatedOperation> aops;
Alex Deymoa12ee112015-08-12 22:19:32 -0700514 InstallOperation first_op;
515 first_op.set_type(InstallOperation::REPLACE_BZ);
Alex Deymo14158572015-06-13 03:37:08 -0700516 *(first_op.add_dst_extents()) = ExtentForRange(0, 1);
517 first_op.set_data_length(kBlockSize);
518 AnnotatedOperation first_aop;
519 first_aop.op = first_op;
520 aops.push_back(first_aop);
521
522 // Should merge with first, except op types don't match...
Alex Deymoa12ee112015-08-12 22:19:32 -0700523 InstallOperation second_op;
524 second_op.set_type(InstallOperation::REPLACE);
Alex Deymo14158572015-06-13 03:37:08 -0700525 *(second_op.add_dst_extents()) = ExtentForRange(1, 2);
526 second_op.set_data_length(2 * kBlockSize);
527 AnnotatedOperation second_aop;
528 second_aop.op = second_op;
529 aops.push_back(second_aop);
530
531 // Should merge with second, except it would exceed chunk size...
Alex Deymoa12ee112015-08-12 22:19:32 -0700532 InstallOperation third_op;
533 third_op.set_type(InstallOperation::REPLACE);
Alex Deymo14158572015-06-13 03:37:08 -0700534 *(third_op.add_dst_extents()) = ExtentForRange(3, 3);
535 third_op.set_data_length(3 * kBlockSize);
536 AnnotatedOperation third_aop;
537 third_aop.op = third_op;
538 aops.push_back(third_aop);
539
540 // Should merge with third, except they aren't contiguous...
Alex Deymoa12ee112015-08-12 22:19:32 -0700541 InstallOperation fourth_op;
542 fourth_op.set_type(InstallOperation::REPLACE);
Alex Deymo14158572015-06-13 03:37:08 -0700543 *(fourth_op.add_dst_extents()) = ExtentForRange(7, 2);
544 fourth_op.set_data_length(2 * kBlockSize);
545 AnnotatedOperation fourth_aop;
546 fourth_aop.op = fourth_op;
547 aops.push_back(fourth_aop);
548
Sen Jiang8cc502d2015-08-10 10:04:54 -0700549 BlobFileWriter blob_file(0, nullptr);
550 EXPECT_TRUE(ABGenerator::MergeOperations(&aops, 4, "", &blob_file));
Alex Deymo14158572015-06-13 03:37:08 -0700551
552 // No operations were merged, the number of ops is the same.
Alex Deymo80f70ff2016-02-10 16:08:11 -0800553 EXPECT_EQ(4U, aops.size());
Alex Deymo14158572015-06-13 03:37:08 -0700554}
555
Sen Jiang82352f92015-11-09 16:36:53 -0800556TEST_F(ABGeneratorTest, AddSourceHashTest) {
557 vector<AnnotatedOperation> aops;
558 InstallOperation first_op;
559 first_op.set_type(InstallOperation::SOURCE_COPY);
560 first_op.set_src_length(kBlockSize);
561 *(first_op.add_src_extents()) = ExtentForRange(0, 1);
562 AnnotatedOperation first_aop;
563 first_aop.op = first_op;
564 aops.push_back(first_aop);
565
566 InstallOperation second_op;
567 second_op.set_type(InstallOperation::REPLACE);
568 AnnotatedOperation second_aop;
569 second_aop.op = second_op;
570 aops.push_back(second_aop);
571
572 string src_part_path;
573 EXPECT_TRUE(utils::MakeTempFile("AddSourceHashTest_src_part.XXXXXX",
574 &src_part_path, nullptr));
575 ScopedPathUnlinker src_part_path_unlinker(src_part_path);
576 brillo::Blob src_data(kBlockSize);
577 test_utils::FillWithData(&src_data);
578 ASSERT_TRUE(utils::WriteFile(src_part_path.c_str(), src_data.data(),
579 src_data.size()));
580
581 EXPECT_TRUE(ABGenerator::AddSourceHash(&aops, src_part_path));
582
583 EXPECT_TRUE(aops[0].op.has_src_sha256_hash());
584 EXPECT_FALSE(aops[1].op.has_src_sha256_hash());
585 brillo::Blob expected_hash;
Alex Deymo39910dc2015-11-09 17:04:30 -0800586 EXPECT_TRUE(HashCalculator::RawHashOfData(src_data, &expected_hash));
Sen Jiang82352f92015-11-09 16:36:53 -0800587 brillo::Blob result_hash(aops[0].op.src_sha256_hash().begin(),
588 aops[0].op.src_sha256_hash().end());
589 EXPECT_EQ(expected_hash, result_hash);
590}
591
Alex Deymo14158572015-06-13 03:37:08 -0700592} // namespace chromeos_update_engine