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