ab_generator_unittest.cc revision 80f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63e
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(), data_file_size); 317 brillo::Blob new_op_blob(new_op.data_length()); 318 ssize_t bytes_read; 319 ASSERT_TRUE(utils::PReadAll(data_fd, 320 new_op_blob.data(), 321 new_op.data_length(), 322 new_op.data_offset(), 323 &bytes_read)); 324 ASSERT_EQ(static_cast<ssize_t>(new_op.data_length()), bytes_read); 325 EXPECT_EQ(expected_blob, new_op_blob); 326} 327 328} // namespace 329 330class ABGeneratorTest : public ::testing::Test {}; 331 332TEST_F(ABGeneratorTest, SplitSourceCopyTest) { 333 InstallOperation op; 334 op.set_type(InstallOperation::SOURCE_COPY); 335 *(op.add_src_extents()) = ExtentForRange(2, 3); 336 *(op.add_src_extents()) = ExtentForRange(6, 1); 337 *(op.add_src_extents()) = ExtentForRange(8, 4); 338 *(op.add_dst_extents()) = ExtentForRange(10, 2); 339 *(op.add_dst_extents()) = ExtentForRange(14, 3); 340 *(op.add_dst_extents()) = ExtentForRange(18, 3); 341 342 AnnotatedOperation aop; 343 aop.op = op; 344 aop.name = "SplitSourceCopyTestOp"; 345 vector<AnnotatedOperation> result_ops; 346 EXPECT_TRUE(ABGenerator::SplitSourceCopy(aop, &result_ops)); 347 EXPECT_EQ(3U, result_ops.size()); 348 349 EXPECT_EQ("SplitSourceCopyTestOp:0", result_ops[0].name); 350 InstallOperation first_op = result_ops[0].op; 351 EXPECT_EQ(InstallOperation::SOURCE_COPY, first_op.type()); 352 EXPECT_EQ(kBlockSize * 2, first_op.src_length()); 353 EXPECT_EQ(1, first_op.src_extents().size()); 354 EXPECT_EQ(2U, first_op.src_extents(0).start_block()); 355 EXPECT_EQ(2U, first_op.src_extents(0).num_blocks()); 356 EXPECT_EQ(kBlockSize * 2, first_op.dst_length()); 357 EXPECT_EQ(1, first_op.dst_extents().size()); 358 EXPECT_EQ(10U, first_op.dst_extents(0).start_block()); 359 EXPECT_EQ(2U, first_op.dst_extents(0).num_blocks()); 360 361 EXPECT_EQ("SplitSourceCopyTestOp:1", result_ops[1].name); 362 InstallOperation second_op = result_ops[1].op; 363 EXPECT_EQ(InstallOperation::SOURCE_COPY, second_op.type()); 364 EXPECT_EQ(kBlockSize * 3, second_op.src_length()); 365 EXPECT_EQ(3, second_op.src_extents().size()); 366 EXPECT_EQ(4U, second_op.src_extents(0).start_block()); 367 EXPECT_EQ(1U, second_op.src_extents(0).num_blocks()); 368 EXPECT_EQ(6U, second_op.src_extents(1).start_block()); 369 EXPECT_EQ(1U, second_op.src_extents(1).num_blocks()); 370 EXPECT_EQ(8U, second_op.src_extents(2).start_block()); 371 EXPECT_EQ(1U, second_op.src_extents(2).num_blocks()); 372 EXPECT_EQ(kBlockSize * 3, second_op.dst_length()); 373 EXPECT_EQ(1, second_op.dst_extents().size()); 374 EXPECT_EQ(14U, second_op.dst_extents(0).start_block()); 375 EXPECT_EQ(3U, second_op.dst_extents(0).num_blocks()); 376 377 EXPECT_EQ("SplitSourceCopyTestOp:2", result_ops[2].name); 378 InstallOperation third_op = result_ops[2].op; 379 EXPECT_EQ(InstallOperation::SOURCE_COPY, third_op.type()); 380 EXPECT_EQ(kBlockSize * 3, third_op.src_length()); 381 EXPECT_EQ(1, third_op.src_extents().size()); 382 EXPECT_EQ(9U, third_op.src_extents(0).start_block()); 383 EXPECT_EQ(3U, third_op.src_extents(0).num_blocks()); 384 EXPECT_EQ(kBlockSize * 3, third_op.dst_length()); 385 EXPECT_EQ(1, third_op.dst_extents().size()); 386 EXPECT_EQ(18U, third_op.dst_extents(0).start_block()); 387 EXPECT_EQ(3U, third_op.dst_extents(0).num_blocks()); 388} 389 390TEST_F(ABGeneratorTest, SplitReplaceTest) { 391 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE, false); 392} 393 394TEST_F(ABGeneratorTest, SplitReplaceIntoReplaceBzTest) { 395 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE, true); 396} 397 398TEST_F(ABGeneratorTest, SplitReplaceBzTest) { 399 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE_BZ, true); 400} 401 402TEST_F(ABGeneratorTest, SplitReplaceBzIntoReplaceTest) { 403 TestSplitReplaceOrReplaceBzOperation(InstallOperation::REPLACE_BZ, false); 404} 405 406TEST_F(ABGeneratorTest, SortOperationsByDestinationTest) { 407 vector<AnnotatedOperation> aops; 408 // One operation with multiple destination extents. 409 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 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 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(3U, aops.size()); 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 InstallOperation first_op; 442 first_op.set_type(InstallOperation::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 InstallOperation second_op; 453 second_op.set_type(InstallOperation::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 InstallOperation third_op; 466 third_op.set_type(InstallOperation::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(1U, aops.size()); 480 InstallOperation first_result_op = aops[0].op; 481 EXPECT_EQ(InstallOperation::SOURCE_COPY, first_result_op.type()); 482 EXPECT_EQ(kBlockSize * 5, first_result_op.src_length()); 483 EXPECT_EQ(3, first_result_op.src_extents().size()); 484 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(0), 1, 3)); 485 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(1), 8, 2)); 486 EXPECT_TRUE(ExtentEquals(first_result_op.src_extents(2), 11, 1)); 487 EXPECT_EQ(kBlockSize * 5, first_result_op.dst_length()); 488 EXPECT_EQ(2, first_result_op.dst_extents().size()); 489 EXPECT_TRUE(ExtentEquals(first_result_op.dst_extents(0), 6, 4)); 490 EXPECT_TRUE(ExtentEquals(first_result_op.dst_extents(1), 11, 2)); 491 EXPECT_EQ(aops[0].name, "1,2,3"); 492} 493 494TEST_F(ABGeneratorTest, MergeReplaceOperationsTest) { 495 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE, false); 496} 497 498TEST_F(ABGeneratorTest, MergeReplaceOperationsToReplaceBzTest) { 499 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE, true); 500} 501 502TEST_F(ABGeneratorTest, MergeReplaceBzOperationsTest) { 503 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE_BZ, true); 504} 505 506TEST_F(ABGeneratorTest, MergeReplaceBzOperationsToReplaceTest) { 507 TestMergeReplaceOrReplaceBzOperations(InstallOperation::REPLACE_BZ, false); 508} 509 510TEST_F(ABGeneratorTest, NoMergeOperationsTest) { 511 // Test to make sure we don't merge operations that shouldn't be merged. 512 vector<AnnotatedOperation> aops; 513 InstallOperation first_op; 514 first_op.set_type(InstallOperation::REPLACE_BZ); 515 *(first_op.add_dst_extents()) = ExtentForRange(0, 1); 516 first_op.set_data_length(kBlockSize); 517 AnnotatedOperation first_aop; 518 first_aop.op = first_op; 519 aops.push_back(first_aop); 520 521 // Should merge with first, except op types don't match... 522 InstallOperation second_op; 523 second_op.set_type(InstallOperation::REPLACE); 524 *(second_op.add_dst_extents()) = ExtentForRange(1, 2); 525 second_op.set_data_length(2 * kBlockSize); 526 AnnotatedOperation second_aop; 527 second_aop.op = second_op; 528 aops.push_back(second_aop); 529 530 // Should merge with second, except it would exceed chunk size... 531 InstallOperation third_op; 532 third_op.set_type(InstallOperation::REPLACE); 533 *(third_op.add_dst_extents()) = ExtentForRange(3, 3); 534 third_op.set_data_length(3 * kBlockSize); 535 AnnotatedOperation third_aop; 536 third_aop.op = third_op; 537 aops.push_back(third_aop); 538 539 // Should merge with third, except they aren't contiguous... 540 InstallOperation fourth_op; 541 fourth_op.set_type(InstallOperation::REPLACE); 542 *(fourth_op.add_dst_extents()) = ExtentForRange(7, 2); 543 fourth_op.set_data_length(2 * kBlockSize); 544 AnnotatedOperation fourth_aop; 545 fourth_aop.op = fourth_op; 546 aops.push_back(fourth_aop); 547 548 BlobFileWriter blob_file(0, nullptr); 549 EXPECT_TRUE(ABGenerator::MergeOperations(&aops, 4, "", &blob_file)); 550 551 // No operations were merged, the number of ops is the same. 552 EXPECT_EQ(4U, aops.size()); 553} 554 555TEST_F(ABGeneratorTest, AddSourceHashTest) { 556 vector<AnnotatedOperation> aops; 557 InstallOperation first_op; 558 first_op.set_type(InstallOperation::SOURCE_COPY); 559 first_op.set_src_length(kBlockSize); 560 *(first_op.add_src_extents()) = ExtentForRange(0, 1); 561 AnnotatedOperation first_aop; 562 first_aop.op = first_op; 563 aops.push_back(first_aop); 564 565 InstallOperation second_op; 566 second_op.set_type(InstallOperation::REPLACE); 567 AnnotatedOperation second_aop; 568 second_aop.op = second_op; 569 aops.push_back(second_aop); 570 571 string src_part_path; 572 EXPECT_TRUE(utils::MakeTempFile("AddSourceHashTest_src_part.XXXXXX", 573 &src_part_path, nullptr)); 574 ScopedPathUnlinker src_part_path_unlinker(src_part_path); 575 brillo::Blob src_data(kBlockSize); 576 test_utils::FillWithData(&src_data); 577 ASSERT_TRUE(utils::WriteFile(src_part_path.c_str(), src_data.data(), 578 src_data.size())); 579 580 EXPECT_TRUE(ABGenerator::AddSourceHash(&aops, src_part_path)); 581 582 EXPECT_TRUE(aops[0].op.has_src_sha256_hash()); 583 EXPECT_FALSE(aops[1].op.has_src_sha256_hash()); 584 brillo::Blob expected_hash; 585 EXPECT_TRUE(HashCalculator::RawHashOfData(src_data, &expected_hash)); 586 brillo::Blob result_hash(aops[0].op.src_sha256_hash().begin(), 587 aops[0].op.src_sha256_hash().end()); 588 EXPECT_EQ(expected_hash, result_hash); 589} 590 591} // namespace chromeos_update_engine 592