ab_generator_unittest.cc revision 2d3b2d635e50c6886e285afb86c3187d9e0bd360
1// Copyright 2015 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "update_engine/payload_generator/ab_generator.h" 6 7#include <fcntl.h> 8#include <sys/stat.h> 9#include <sys/types.h> 10 11#include <string> 12#include <vector> 13 14#include <gtest/gtest.h> 15 16#include "update_engine/bzip.h" 17#include "update_engine/payload_generator/annotated_operation.h" 18#include "update_engine/payload_generator/delta_diff_generator.h" 19#include "update_engine/payload_generator/extent_ranges.h" 20#include "update_engine/payload_generator/extent_utils.h" 21#include "update_engine/test_utils.h" 22#include "update_engine/utils.h" 23 24using std::string; 25using std::vector; 26 27namespace chromeos_update_engine { 28 29namespace { 30 31bool ExtentEquals(Extent ext, uint64_t start_block, uint64_t num_blocks) { 32 return ext.start_block() == start_block && ext.num_blocks() == num_blocks; 33} 34 35// Tests splitting of a REPLACE/REPLACE_BZ operation. 36void TestSplitReplaceOrReplaceBzOperation( 37 DeltaArchiveManifest_InstallOperation_Type orig_type, 38 bool compressible) { 39 const size_t op_ex1_start_block = 2; 40 const size_t op_ex1_num_blocks = 2; 41 const size_t op_ex2_start_block = 6; 42 const size_t op_ex2_num_blocks = 1; 43 const size_t part_num_blocks = 7; 44 45 // Create the target partition data. 46 string part_path; 47 EXPECT_TRUE(utils::MakeTempFile( 48 "SplitReplaceOrReplaceBzTest_part.XXXXXX", &part_path, nullptr)); 49 ScopedPathUnlinker part_path_unlinker(part_path); 50 const size_t part_size = part_num_blocks * kBlockSize; 51 chromeos::Blob part_data; 52 if (compressible) { 53 part_data.resize(part_size); 54 test_utils::FillWithData(&part_data); 55 } else { 56 std::mt19937 gen(12345); 57 std::uniform_int_distribution<uint8_t> dis(0, 255); 58 for (uint32_t i = 0; i < part_size; i++) 59 part_data.push_back(dis(gen)); 60 } 61 ASSERT_EQ(part_size, part_data.size()); 62 ASSERT_TRUE(utils::WriteFile(part_path.c_str(), part_data.data(), part_size)); 63 64 // Create original operation and blob data. 65 const size_t op_ex1_offset = op_ex1_start_block * kBlockSize; 66 const size_t op_ex1_size = op_ex1_num_blocks * kBlockSize; 67 const size_t op_ex2_offset = op_ex2_start_block * kBlockSize; 68 const size_t op_ex2_size = op_ex2_num_blocks * kBlockSize; 69 DeltaArchiveManifest_InstallOperation op; 70 op.set_type(orig_type); 71 *(op.add_dst_extents()) = ExtentForRange(op_ex1_start_block, 72 op_ex1_num_blocks); 73 *(op.add_dst_extents()) = ExtentForRange(op_ex2_start_block, 74 op_ex2_num_blocks); 75 op.set_dst_length(op_ex1_num_blocks + op_ex2_num_blocks); 76 77 chromeos::Blob op_data; 78 op_data.insert(op_data.end(), 79 part_data.begin() + op_ex1_offset, 80 part_data.begin() + op_ex1_offset + op_ex1_size); 81 op_data.insert(op_data.end(), 82 part_data.begin() + op_ex2_offset, 83 part_data.begin() + op_ex2_offset + op_ex2_size); 84 chromeos::Blob op_blob; 85 if (orig_type == DeltaArchiveManifest_InstallOperation_Type_REPLACE) { 86 op_blob = op_data; 87 } else { 88 ASSERT_TRUE(BzipCompress(op_data, &op_blob)); 89 } 90 op.set_data_offset(0); 91 op.set_data_length(op_blob.size()); 92 93 AnnotatedOperation aop; 94 aop.op = op; 95 aop.name = "SplitTestOp"; 96 97 // Create the data file. 98 string data_path; 99 EXPECT_TRUE(utils::MakeTempFile( 100 "SplitReplaceOrReplaceBzTest_data.XXXXXX", &data_path, nullptr)); 101 ScopedPathUnlinker data_path_unlinker(data_path); 102 int data_fd = open(data_path.c_str(), O_RDWR, 000); 103 EXPECT_GE(data_fd, 0); 104 ScopedFdCloser data_fd_closer(&data_fd); 105 EXPECT_TRUE(utils::WriteFile(data_path.c_str(), op_blob.data(), 106 op_blob.size())); 107 off_t data_file_size = op_blob.size(); 108 109 // Split the operation. 110 vector<AnnotatedOperation> result_ops; 111 ASSERT_TRUE(ABGenerator::SplitReplaceOrReplaceBz( 112 aop, &result_ops, part_path, data_fd, &data_file_size)); 113 114 // Check the result. 115 DeltaArchiveManifest_InstallOperation_Type expected_type = 116 compressible ? 117 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ : 118 DeltaArchiveManifest_InstallOperation_Type_REPLACE; 119 120 ASSERT_EQ(2, result_ops.size()); 121 122 EXPECT_EQ("SplitTestOp:0", result_ops[0].name); 123 DeltaArchiveManifest_InstallOperation first_op = result_ops[0].op; 124 EXPECT_EQ(expected_type, first_op.type()); 125 EXPECT_EQ(op_ex1_size, first_op.dst_length()); 126 EXPECT_EQ(1, first_op.dst_extents().size()); 127 EXPECT_TRUE(ExtentEquals(first_op.dst_extents(0), op_ex1_start_block, 128 op_ex1_num_blocks)); 129 // Obtain the expected blob. 130 chromeos::Blob first_expected_data( 131 part_data.begin() + op_ex1_offset, 132 part_data.begin() + op_ex1_offset + op_ex1_size); 133 chromeos::Blob first_expected_blob; 134 if (compressible) { 135 ASSERT_TRUE(BzipCompress(first_expected_data, &first_expected_blob)); 136 } else { 137 first_expected_blob = first_expected_data; 138 } 139 EXPECT_EQ(first_expected_blob.size(), first_op.data_length()); 140 // Check that the actual blob matches what's expected. 141 chromeos::Blob first_data_blob(first_op.data_length()); 142 ssize_t bytes_read; 143 ASSERT_TRUE(utils::PReadAll(data_fd, 144 first_data_blob.data(), 145 first_op.data_length(), 146 first_op.data_offset(), 147 &bytes_read)); 148 ASSERT_EQ(bytes_read, first_op.data_length()); 149 EXPECT_EQ(first_expected_blob, first_data_blob); 150 151 EXPECT_EQ("SplitTestOp:1", result_ops[1].name); 152 DeltaArchiveManifest_InstallOperation second_op = result_ops[1].op; 153 EXPECT_EQ(expected_type, second_op.type()); 154 EXPECT_EQ(op_ex2_size, second_op.dst_length()); 155 EXPECT_EQ(1, second_op.dst_extents().size()); 156 EXPECT_TRUE(ExtentEquals(second_op.dst_extents(0), op_ex2_start_block, 157 op_ex2_num_blocks)); 158 // Obtain the expected blob. 159 chromeos::Blob second_expected_data( 160 part_data.begin() + op_ex2_offset, 161 part_data.begin() + op_ex2_offset + op_ex2_size); 162 chromeos::Blob second_expected_blob; 163 if (compressible) { 164 ASSERT_TRUE(BzipCompress(second_expected_data, &second_expected_blob)); 165 } else { 166 second_expected_blob = second_expected_data; 167 } 168 EXPECT_EQ(second_expected_blob.size(), second_op.data_length()); 169 // Check that the actual blob matches what's expected. 170 chromeos::Blob second_data_blob(second_op.data_length()); 171 ASSERT_TRUE(utils::PReadAll(data_fd, 172 second_data_blob.data(), 173 second_op.data_length(), 174 second_op.data_offset(), 175 &bytes_read)); 176 ASSERT_EQ(bytes_read, second_op.data_length()); 177 EXPECT_EQ(second_expected_blob, second_data_blob); 178 179 // Check relative layout of data blobs. 180 EXPECT_EQ(first_op.data_offset() + first_op.data_length(), 181 second_op.data_offset()); 182 EXPECT_EQ(second_op.data_offset() + second_op.data_length(), data_file_size); 183 // If we split a REPLACE into multiple ones, ensure reuse of preexisting blob. 184 if (!compressible && 185 orig_type == DeltaArchiveManifest_InstallOperation_Type_REPLACE) { 186 EXPECT_EQ(0, first_op.data_offset()); 187 } 188} 189 190// Tests merging of REPLACE/REPLACE_BZ operations. 191void TestMergeReplaceOrReplaceBzOperations( 192 DeltaArchiveManifest_InstallOperation_Type orig_type, 193 bool compressible) { 194 const size_t first_op_num_blocks = 1; 195 const size_t second_op_num_blocks = 2; 196 const size_t total_op_num_blocks = first_op_num_blocks + second_op_num_blocks; 197 const size_t part_num_blocks = total_op_num_blocks + 2; 198 199 // Create the target partition data. 200 string part_path; 201 EXPECT_TRUE(utils::MakeTempFile( 202 "MergeReplaceOrReplaceBzTest_part.XXXXXX", &part_path, nullptr)); 203 ScopedPathUnlinker part_path_unlinker(part_path); 204 const size_t part_size = part_num_blocks * kBlockSize; 205 chromeos::Blob part_data; 206 if (compressible) { 207 part_data.resize(part_size); 208 test_utils::FillWithData(&part_data); 209 } else { 210 std::mt19937 gen(12345); 211 std::uniform_int_distribution<uint8_t> dis(0, 255); 212 for (uint32_t i = 0; i < part_size; i++) 213 part_data.push_back(dis(gen)); 214 } 215 ASSERT_EQ(part_size, part_data.size()); 216 ASSERT_TRUE(utils::WriteFile(part_path.c_str(), part_data.data(), part_size)); 217 218 // Create original operations and blob data. 219 vector<AnnotatedOperation> aops; 220 chromeos::Blob blob_data; 221 const size_t total_op_size = total_op_num_blocks * kBlockSize; 222 223 DeltaArchiveManifest_InstallOperation first_op; 224 first_op.set_type(orig_type); 225 const size_t first_op_size = first_op_num_blocks * kBlockSize; 226 first_op.set_dst_length(first_op_size); 227 *(first_op.add_dst_extents()) = ExtentForRange(0, first_op_num_blocks); 228 chromeos::Blob first_op_data(part_data.begin(), 229 part_data.begin() + first_op_size); 230 chromeos::Blob first_op_blob; 231 if (orig_type == DeltaArchiveManifest_InstallOperation_Type_REPLACE) { 232 first_op_blob = first_op_data; 233 } else { 234 ASSERT_TRUE(BzipCompress(first_op_data, &first_op_blob)); 235 } 236 first_op.set_data_offset(0); 237 first_op.set_data_length(first_op_blob.size()); 238 blob_data.insert(blob_data.end(), first_op_blob.begin(), first_op_blob.end()); 239 AnnotatedOperation first_aop; 240 first_aop.op = first_op; 241 first_aop.name = "first"; 242 aops.push_back(first_aop); 243 244 DeltaArchiveManifest_InstallOperation second_op; 245 second_op.set_type(orig_type); 246 const size_t second_op_size = second_op_num_blocks * kBlockSize; 247 second_op.set_dst_length(second_op_size); 248 *(second_op.add_dst_extents()) = ExtentForRange(first_op_num_blocks, 249 second_op_num_blocks); 250 chromeos::Blob second_op_data(part_data.begin() + first_op_size, 251 part_data.begin() + total_op_size); 252 chromeos::Blob second_op_blob; 253 if (orig_type == DeltaArchiveManifest_InstallOperation_Type_REPLACE) { 254 second_op_blob = second_op_data; 255 } else { 256 ASSERT_TRUE(BzipCompress(second_op_data, &second_op_blob)); 257 } 258 second_op.set_data_offset(first_op_blob.size()); 259 second_op.set_data_length(second_op_blob.size()); 260 blob_data.insert(blob_data.end(), second_op_blob.begin(), 261 second_op_blob.end()); 262 AnnotatedOperation second_aop; 263 second_aop.op = second_op; 264 second_aop.name = "second"; 265 aops.push_back(second_aop); 266 267 // Create the data file. 268 string data_path; 269 EXPECT_TRUE(utils::MakeTempFile( 270 "MergeReplaceOrReplaceBzTest_data.XXXXXX", &data_path, nullptr)); 271 ScopedPathUnlinker data_path_unlinker(data_path); 272 int data_fd = open(data_path.c_str(), O_RDWR, 000); 273 EXPECT_GE(data_fd, 0); 274 ScopedFdCloser data_fd_closer(&data_fd); 275 EXPECT_TRUE(utils::WriteFile(data_path.c_str(), blob_data.data(), 276 blob_data.size())); 277 off_t data_file_size = blob_data.size(); 278 279 // Merge the operations. 280 EXPECT_TRUE(ABGenerator::MergeOperations( 281 &aops, 5, part_path, data_fd, &data_file_size)); 282 283 // Check the result. 284 DeltaArchiveManifest_InstallOperation_Type expected_op_type = 285 compressible ? 286 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ : 287 DeltaArchiveManifest_InstallOperation_Type_REPLACE; 288 EXPECT_EQ(1, aops.size()); 289 DeltaArchiveManifest_InstallOperation new_op = aops[0].op; 290 EXPECT_EQ(expected_op_type, new_op.type()); 291 EXPECT_FALSE(new_op.has_src_length()); 292 EXPECT_EQ(total_op_num_blocks * kBlockSize, new_op.dst_length()); 293 EXPECT_EQ(1, new_op.dst_extents().size()); 294 EXPECT_TRUE(ExtentEquals(new_op.dst_extents(0), 0, total_op_num_blocks)); 295 EXPECT_EQ("first,second", aops[0].name); 296 297 // Check to see if the blob pointed to in the new extent has what we expect. 298 chromeos::Blob expected_data(part_data.begin(), 299 part_data.begin() + total_op_size); 300 chromeos::Blob expected_blob; 301 if (compressible) { 302 ASSERT_TRUE(BzipCompress(expected_data, &expected_blob)); 303 } else { 304 expected_blob = expected_data; 305 } 306 ASSERT_EQ(expected_blob.size(), new_op.data_length()); 307 ASSERT_EQ(blob_data.size() + expected_blob.size(), data_file_size); 308 chromeos::Blob new_op_blob(new_op.data_length()); 309 ssize_t bytes_read; 310 ASSERT_TRUE(utils::PReadAll(data_fd, 311 new_op_blob.data(), 312 new_op.data_length(), 313 new_op.data_offset(), 314 &bytes_read)); 315 ASSERT_EQ(new_op.data_length(), bytes_read); 316 EXPECT_EQ(expected_blob, new_op_blob); 317} 318 319} // namespace 320 321class ABGeneratorTest : public ::testing::Test {}; 322 323TEST_F(ABGeneratorTest, SplitSourceCopyTest) { 324 DeltaArchiveManifest_InstallOperation op; 325 op.set_type(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY); 326 *(op.add_src_extents()) = ExtentForRange(2, 3); 327 *(op.add_src_extents()) = ExtentForRange(6, 1); 328 *(op.add_src_extents()) = ExtentForRange(8, 4); 329 *(op.add_dst_extents()) = ExtentForRange(10, 2); 330 *(op.add_dst_extents()) = ExtentForRange(14, 3); 331 *(op.add_dst_extents()) = ExtentForRange(18, 3); 332 333 AnnotatedOperation aop; 334 aop.op = op; 335 aop.name = "SplitSourceCopyTestOp"; 336 vector<AnnotatedOperation> result_ops; 337 EXPECT_TRUE(ABGenerator::SplitSourceCopy(aop, &result_ops)); 338 EXPECT_EQ(result_ops.size(), 3); 339 340 EXPECT_EQ("SplitSourceCopyTestOp:0", result_ops[0].name); 341 DeltaArchiveManifest_InstallOperation first_op = result_ops[0].op; 342 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY, 343 first_op.type()); 344 EXPECT_EQ(kBlockSize * 2, first_op.src_length()); 345 EXPECT_EQ(1, first_op.src_extents().size()); 346 EXPECT_EQ(2, first_op.src_extents(0).start_block()); 347 EXPECT_EQ(2, first_op.src_extents(0).num_blocks()); 348 EXPECT_EQ(kBlockSize * 2, first_op.dst_length()); 349 EXPECT_EQ(1, first_op.dst_extents().size()); 350 EXPECT_EQ(10, first_op.dst_extents(0).start_block()); 351 EXPECT_EQ(2, first_op.dst_extents(0).num_blocks()); 352 353 EXPECT_EQ("SplitSourceCopyTestOp:1", result_ops[1].name); 354 DeltaArchiveManifest_InstallOperation second_op = result_ops[1].op; 355 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY, 356 second_op.type()); 357 EXPECT_EQ(kBlockSize * 3, second_op.src_length()); 358 EXPECT_EQ(3, second_op.src_extents().size()); 359 EXPECT_EQ(4, second_op.src_extents(0).start_block()); 360 EXPECT_EQ(1, second_op.src_extents(0).num_blocks()); 361 EXPECT_EQ(6, second_op.src_extents(1).start_block()); 362 EXPECT_EQ(1, second_op.src_extents(1).num_blocks()); 363 EXPECT_EQ(8, second_op.src_extents(2).start_block()); 364 EXPECT_EQ(1, second_op.src_extents(2).num_blocks()); 365 EXPECT_EQ(kBlockSize * 3, second_op.dst_length()); 366 EXPECT_EQ(1, second_op.dst_extents().size()); 367 EXPECT_EQ(14, second_op.dst_extents(0).start_block()); 368 EXPECT_EQ(3, second_op.dst_extents(0).num_blocks()); 369 370 EXPECT_EQ("SplitSourceCopyTestOp:2", result_ops[2].name); 371 DeltaArchiveManifest_InstallOperation third_op = result_ops[2].op; 372 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY, 373 third_op.type()); 374 EXPECT_EQ(kBlockSize * 3, third_op.src_length()); 375 EXPECT_EQ(1, third_op.src_extents().size()); 376 EXPECT_EQ(9, third_op.src_extents(0).start_block()); 377 EXPECT_EQ(3, third_op.src_extents(0).num_blocks()); 378 EXPECT_EQ(kBlockSize * 3, third_op.dst_length()); 379 EXPECT_EQ(1, third_op.dst_extents().size()); 380 EXPECT_EQ(18, third_op.dst_extents(0).start_block()); 381 EXPECT_EQ(3, third_op.dst_extents(0).num_blocks()); 382} 383 384TEST_F(ABGeneratorTest, SplitReplaceTest) { 385 TestSplitReplaceOrReplaceBzOperation( 386 DeltaArchiveManifest_InstallOperation_Type_REPLACE, false); 387} 388 389TEST_F(ABGeneratorTest, SplitReplaceIntoReplaceBzTest) { 390 TestSplitReplaceOrReplaceBzOperation( 391 DeltaArchiveManifest_InstallOperation_Type_REPLACE, true); 392} 393 394TEST_F(ABGeneratorTest, SplitReplaceBzTest) { 395 TestSplitReplaceOrReplaceBzOperation( 396 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ, true); 397} 398 399TEST_F(ABGeneratorTest, SplitReplaceBzIntoReplaceTest) { 400 TestSplitReplaceOrReplaceBzOperation( 401 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ, false); 402} 403 404TEST_F(ABGeneratorTest, SortOperationsByDestinationTest) { 405 vector<AnnotatedOperation> aops; 406 // One operation with multiple destination extents. 407 DeltaArchiveManifest_InstallOperation first_op; 408 *(first_op.add_dst_extents()) = ExtentForRange(6, 1); 409 *(first_op.add_dst_extents()) = ExtentForRange(10, 2); 410 AnnotatedOperation first_aop; 411 first_aop.op = first_op; 412 first_aop.name = "first"; 413 aops.push_back(first_aop); 414 415 // One with no destination extent. Should end up at the end of the vector. 416 DeltaArchiveManifest_InstallOperation second_op; 417 AnnotatedOperation second_aop; 418 second_aop.op = second_op; 419 second_aop.name = "second"; 420 aops.push_back(second_aop); 421 422 // One with one destination extent. 423 DeltaArchiveManifest_InstallOperation third_op; 424 *(third_op.add_dst_extents()) = ExtentForRange(3, 2); 425 AnnotatedOperation third_aop; 426 third_aop.op = third_op; 427 third_aop.name = "third"; 428 aops.push_back(third_aop); 429 430 ABGenerator::SortOperationsByDestination(&aops); 431 EXPECT_EQ(aops.size(), 3); 432 EXPECT_EQ(third_aop.name, aops[0].name); 433 EXPECT_EQ(first_aop.name, aops[1].name); 434 EXPECT_EQ(second_aop.name, aops[2].name); 435} 436 437TEST_F(ABGeneratorTest, MergeSourceCopyOperationsTest) { 438 vector<AnnotatedOperation> aops; 439 DeltaArchiveManifest_InstallOperation first_op; 440 first_op.set_type(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY); 441 first_op.set_src_length(kBlockSize); 442 first_op.set_dst_length(kBlockSize); 443 *(first_op.add_src_extents()) = ExtentForRange(1, 1); 444 *(first_op.add_dst_extents()) = ExtentForRange(6, 1); 445 AnnotatedOperation first_aop; 446 first_aop.op = first_op; 447 first_aop.name = "1"; 448 aops.push_back(first_aop); 449 450 DeltaArchiveManifest_InstallOperation second_op; 451 second_op.set_type(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY); 452 second_op.set_src_length(3 * kBlockSize); 453 second_op.set_dst_length(3 * kBlockSize); 454 *(second_op.add_src_extents()) = ExtentForRange(2, 2); 455 *(second_op.add_src_extents()) = ExtentForRange(8, 2); 456 *(second_op.add_dst_extents()) = ExtentForRange(7, 3); 457 *(second_op.add_dst_extents()) = ExtentForRange(11, 1); 458 AnnotatedOperation second_aop; 459 second_aop.op = second_op; 460 second_aop.name = "2"; 461 aops.push_back(second_aop); 462 463 DeltaArchiveManifest_InstallOperation third_op; 464 third_op.set_type(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY); 465 third_op.set_src_length(kBlockSize); 466 third_op.set_dst_length(kBlockSize); 467 *(third_op.add_src_extents()) = ExtentForRange(11, 1); 468 *(third_op.add_dst_extents()) = ExtentForRange(12, 1); 469 AnnotatedOperation third_aop; 470 third_aop.op = third_op; 471 third_aop.name = "3"; 472 aops.push_back(third_aop); 473 474 EXPECT_TRUE(ABGenerator::MergeOperations(&aops, 5, "", 0, nullptr)); 475 476 EXPECT_EQ(aops.size(), 1); 477 DeltaArchiveManifest_InstallOperation first_result_op = aops[0].op; 478 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_SOURCE_COPY, 479 first_result_op.type()); 480 EXPECT_EQ(kBlockSize * 5, first_result_op.src_length()); 481 EXPECT_EQ(3, first_result_op.src_extents().size()); 482 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(0), 1, 3)); 483 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(1), 8, 2)); 484 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(2), 11, 1)); 485 EXPECT_EQ(kBlockSize * 5, first_result_op.dst_length()); 486 EXPECT_EQ(2, first_result_op.dst_extents().size()); 487 EXPECT_TRUE(ExtentEquals(first_result_op.dst_extents(0), 6, 4)); 488 EXPECT_TRUE(ExtentEquals(first_result_op.dst_extents(1), 11, 2)); 489 EXPECT_EQ(aops[0].name, "1,2,3"); 490} 491 492TEST_F(ABGeneratorTest, MergeReplaceOperationsTest) { 493 TestMergeReplaceOrReplaceBzOperations( 494 DeltaArchiveManifest_InstallOperation_Type_REPLACE, false); 495} 496 497TEST_F(ABGeneratorTest, MergeReplaceOperationsToReplaceBzTest) { 498 TestMergeReplaceOrReplaceBzOperations( 499 DeltaArchiveManifest_InstallOperation_Type_REPLACE, true); 500} 501 502TEST_F(ABGeneratorTest, MergeReplaceBzOperationsTest) { 503 TestMergeReplaceOrReplaceBzOperations( 504 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ, true); 505} 506 507TEST_F(ABGeneratorTest, MergeReplaceBzOperationsToReplaceTest) { 508 TestMergeReplaceOrReplaceBzOperations( 509 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ, false); 510} 511 512TEST_F(ABGeneratorTest, NoMergeOperationsTest) { 513 // Test to make sure we don't merge operations that shouldn't be merged. 514 vector<AnnotatedOperation> aops; 515 DeltaArchiveManifest_InstallOperation first_op; 516 first_op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ); 517 *(first_op.add_dst_extents()) = ExtentForRange(0, 1); 518 first_op.set_data_length(kBlockSize); 519 AnnotatedOperation first_aop; 520 first_aop.op = first_op; 521 aops.push_back(first_aop); 522 523 // Should merge with first, except op types don't match... 524 DeltaArchiveManifest_InstallOperation second_op; 525 second_op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE); 526 *(second_op.add_dst_extents()) = ExtentForRange(1, 2); 527 second_op.set_data_length(2 * kBlockSize); 528 AnnotatedOperation second_aop; 529 second_aop.op = second_op; 530 aops.push_back(second_aop); 531 532 // Should merge with second, except it would exceed chunk size... 533 DeltaArchiveManifest_InstallOperation third_op; 534 third_op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE); 535 *(third_op.add_dst_extents()) = ExtentForRange(3, 3); 536 third_op.set_data_length(3 * kBlockSize); 537 AnnotatedOperation third_aop; 538 third_aop.op = third_op; 539 aops.push_back(third_aop); 540 541 // Should merge with third, except they aren't contiguous... 542 DeltaArchiveManifest_InstallOperation fourth_op; 543 fourth_op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE); 544 *(fourth_op.add_dst_extents()) = ExtentForRange(7, 2); 545 fourth_op.set_data_length(2 * kBlockSize); 546 AnnotatedOperation fourth_aop; 547 fourth_aop.op = fourth_op; 548 aops.push_back(fourth_aop); 549 550 EXPECT_TRUE(ABGenerator::MergeOperations(&aops, 4, "", 0, nullptr)); 551 552 // No operations were merged, the number of ops is the same. 553 EXPECT_EQ(aops.size(), 4); 554} 555 556} // namespace chromeos_update_engine 557