ab_generator_unittest.cc revision 5fe0c4ede81b82ae3425ddbbb698eceef14cbc78
1// 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// 16 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> 24#include <random> 25#include <vector> 26 27#include <gtest/gtest.h> 28 29#include "update_engine/common/hash_calculator.h" 30#include "update_engine/common/test_utils.h" 31#include "update_engine/common/utils.h" 32#include "update_engine/payload_generator/annotated_operation.h" 33#include "update_engine/payload_generator/bzip.h" 34#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" 37 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. 50void TestSplitReplaceOrReplaceBzOperation(InstallOperation_Type orig_type, 51 bool compressible) { 52 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; 64 brillo::Blob part_data; 65 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; 82 InstallOperation op; 83 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 90 brillo::Blob op_data; 91 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); 97 brillo::Blob op_blob; 98 if (orig_type == InstallOperation::REPLACE) { 99 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(); 121 BlobFileWriter blob_file(data_fd, &data_file_size); 122 123 // Split the operation. 124 vector<AnnotatedOperation> result_ops; 125 ASSERT_TRUE(ABGenerator::SplitReplaceOrReplaceBz( 126 aop, &result_ops, part_path, &blob_file)); 127 128 // Check the result. 129 InstallOperation_Type expected_type = 130 compressible ? InstallOperation::REPLACE_BZ : InstallOperation::REPLACE; 131 132 ASSERT_EQ(2U, result_ops.size()); 133 134 EXPECT_EQ("SplitTestOp:0", result_ops[0].name); 135 InstallOperation first_op = result_ops[0].op; 136 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. 142 brillo::Blob first_expected_data( 143 part_data.begin() + op_ex1_offset, 144 part_data.begin() + op_ex1_offset + op_ex1_size); 145 brillo::Blob first_expected_blob; 146 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. 153 brillo::Blob first_data_blob(first_op.data_length()); 154 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)); 160 ASSERT_EQ(bytes_read, static_cast<ssize_t>(first_op.data_length())); 161 EXPECT_EQ(first_expected_blob, first_data_blob); 162 163 EXPECT_EQ("SplitTestOp:1", result_ops[1].name); 164 InstallOperation second_op = result_ops[1].op; 165 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. 171 brillo::Blob second_expected_data( 172 part_data.begin() + op_ex2_offset, 173 part_data.begin() + op_ex2_offset + op_ex2_size); 174 brillo::Blob second_expected_blob; 175 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. 182 brillo::Blob second_data_blob(second_op.data_length()); 183 ASSERT_TRUE(utils::PReadAll(data_fd, 184 second_data_blob.data(), 185 second_op.data_length(), 186 second_op.data_offset(), 187 &bytes_read)); 188 ASSERT_EQ(bytes_read, static_cast<ssize_t>(second_op.data_length())); 189 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. 196 if (!compressible && orig_type == InstallOperation::REPLACE) { 197 EXPECT_EQ(0U, first_op.data_offset()); 198 } 199} 200 201// Tests merging of REPLACE/REPLACE_BZ operations. 202void TestMergeReplaceOrReplaceBzOperations(InstallOperation_Type orig_type, 203 bool compressible) { 204 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; 215 brillo::Blob part_data; 216 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; 230 brillo::Blob blob_data; 231 const size_t total_op_size = total_op_num_blocks * kBlockSize; 232 233 InstallOperation first_op; 234 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); 238 brillo::Blob first_op_data(part_data.begin(), 239 part_data.begin() + first_op_size); 240 brillo::Blob first_op_blob; 241 if (orig_type == InstallOperation::REPLACE) { 242 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 254 InstallOperation second_op; 255 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); 260 brillo::Blob second_op_data(part_data.begin() + first_op_size, 261 part_data.begin() + total_op_size); 262 brillo::Blob second_op_blob; 263 if (orig_type == InstallOperation::REPLACE) { 264 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(); 288 BlobFileWriter blob_file(data_fd, &data_file_size); 289 290 // Merge the operations. 291 EXPECT_TRUE(ABGenerator::MergeOperations( 292 &aops, 5, part_path, &blob_file)); 293 294 // Check the result. 295 InstallOperation_Type expected_op_type = 296 compressible ? InstallOperation::REPLACE_BZ : InstallOperation::REPLACE; 297 EXPECT_EQ(1U, aops.size()); 298 InstallOperation new_op = aops[0].op; 299 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. 307 brillo::Blob expected_data(part_data.begin(), 308 part_data.begin() + total_op_size); 309 brillo::Blob expected_blob; 310 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()); 316 ASSERT_EQ(blob_data.size() + expected_blob.size(), 317 static_cast<size_t>(data_file_size)); 318 brillo::Blob new_op_blob(new_op.data_length()); 319 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)); 325 ASSERT_EQ(static_cast<ssize_t>(new_op.data_length()), bytes_read); 326 EXPECT_EQ(expected_blob, new_op_blob); 327} 328 329} // namespace 330 331class ABGeneratorTest : public ::testing::Test {}; 332 333TEST_F(ABGeneratorTest, SplitSourceCopyTest) { 334 InstallOperation op; 335 op.set_type(InstallOperation::SOURCE_COPY); 336 *(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)); 348 EXPECT_EQ(3U, result_ops.size()); 349 350 EXPECT_EQ("SplitSourceCopyTestOp:0", result_ops[0].name); 351 InstallOperation first_op = result_ops[0].op; 352 EXPECT_EQ(InstallOperation::SOURCE_COPY, first_op.type()); 353 EXPECT_EQ(kBlockSize * 2, first_op.src_length()); 354 EXPECT_EQ(1, first_op.src_extents().size()); 355 EXPECT_EQ(2U, first_op.src_extents(0).start_block()); 356 EXPECT_EQ(2U, first_op.src_extents(0).num_blocks()); 357 EXPECT_EQ(kBlockSize * 2, first_op.dst_length()); 358 EXPECT_EQ(1, first_op.dst_extents().size()); 359 EXPECT_EQ(10U, first_op.dst_extents(0).start_block()); 360 EXPECT_EQ(2U, first_op.dst_extents(0).num_blocks()); 361 362 EXPECT_EQ("SplitSourceCopyTestOp:1", result_ops[1].name); 363 InstallOperation second_op = result_ops[1].op; 364 EXPECT_EQ(InstallOperation::SOURCE_COPY, second_op.type()); 365 EXPECT_EQ(kBlockSize * 3, second_op.src_length()); 366 EXPECT_EQ(3, second_op.src_extents().size()); 367 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()); 373 EXPECT_EQ(kBlockSize * 3, second_op.dst_length()); 374 EXPECT_EQ(1, second_op.dst_extents().size()); 375 EXPECT_EQ(14U, second_op.dst_extents(0).start_block()); 376 EXPECT_EQ(3U, second_op.dst_extents(0).num_blocks()); 377 378 EXPECT_EQ("SplitSourceCopyTestOp:2", result_ops[2].name); 379 InstallOperation third_op = result_ops[2].op; 380 EXPECT_EQ(InstallOperation::SOURCE_COPY, third_op.type()); 381 EXPECT_EQ(kBlockSize * 3, third_op.src_length()); 382 EXPECT_EQ(1, third_op.src_extents().size()); 383 EXPECT_EQ(9U, third_op.src_extents(0).start_block()); 384 EXPECT_EQ(3U, third_op.src_extents(0).num_blocks()); 385 EXPECT_EQ(kBlockSize * 3, third_op.dst_length()); 386 EXPECT_EQ(1, third_op.dst_extents().size()); 387 EXPECT_EQ(18U, third_op.dst_extents(0).start_block()); 388 EXPECT_EQ(3U, third_op.dst_extents(0).num_blocks()); 389} 390 391TEST_F(ABGeneratorTest, SplitReplaceTest) { 392 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE, false); 393} 394 395TEST_F(ABGeneratorTest, SplitReplaceIntoReplaceBzTest) { 396 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE, true); 397} 398 399TEST_F(ABGeneratorTest, SplitReplaceBzTest) { 400 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE_BZ, true); 401} 402 403TEST_F(ABGeneratorTest, SplitReplaceBzIntoReplaceTest) { 404 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE_BZ, false); 405} 406 407TEST_F(ABGeneratorTest, SortOperationsByDestinationTest) { 408 vector<AnnotatedOperation> aops; 409 // One operation with multiple destination extents. 410 InstallOperation first_op; 411 *(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. 419 InstallOperation second_op; 420 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. 426 InstallOperation third_op; 427 *(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); 434 EXPECT_EQ(3U, aops.size()); 435 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; 442 InstallOperation first_op; 443 first_op.set_type(InstallOperation::SOURCE_COPY); 444 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 453 InstallOperation second_op; 454 second_op.set_type(InstallOperation::SOURCE_COPY); 455 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 466 InstallOperation third_op; 467 third_op.set_type(InstallOperation::SOURCE_COPY); 468 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 477 BlobFileWriter blob_file(0, nullptr); 478 EXPECT_TRUE(ABGenerator::MergeOperations(&aops, 5, "", &blob_file)); 479 480 EXPECT_EQ(1U, aops.size()); 481 InstallOperation first_result_op = aops[0].op; 482 EXPECT_EQ(InstallOperation::SOURCE_COPY, 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(InstallOperation::REPLACE, false); 497} 498 499TEST_F(ABGeneratorTest, MergeReplaceOperationsToReplaceBzTest) { 500 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE, true); 501} 502 503TEST_F(ABGeneratorTest, MergeReplaceBzOperationsTest) { 504 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE_BZ, true); 505} 506 507TEST_F(ABGeneratorTest, MergeReplaceBzOperationsToReplaceTest) { 508 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE_BZ, false); 509} 510 511TEST_F(ABGeneratorTest, NoMergeOperationsTest) { 512 // Test to make sure we don't merge operations that shouldn't be merged. 513 vector<AnnotatedOperation> aops; 514 InstallOperation first_op; 515 first_op.set_type(InstallOperation::REPLACE_BZ); 516 *(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... 523 InstallOperation second_op; 524 second_op.set_type(InstallOperation::REPLACE); 525 *(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... 532 InstallOperation third_op; 533 third_op.set_type(InstallOperation::REPLACE); 534 *(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... 541 InstallOperation fourth_op; 542 fourth_op.set_type(InstallOperation::REPLACE); 543 *(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 549 BlobFileWriter blob_file(0, nullptr); 550 EXPECT_TRUE(ABGenerator::MergeOperations(&aops, 4, "", &blob_file)); 551 552 // No operations were merged, the number of ops is the same. 553 EXPECT_EQ(4U, aops.size()); 554} 555 556TEST_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; 586 EXPECT_TRUE(HashCalculator::RawHashOfData(src_data, &expected_hash)); 587 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 592} // namespace chromeos_update_engine 593