| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <sys/mount.h> | 5 #include <sys/mount.h> |
| 6 #include <inttypes.h> | 6 #include <inttypes.h> |
| 7 | 7 |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include <base/file_util.h> | 12 #include <base/file_util.h> |
| 13 #include <base/scoped_ptr.h> | 13 #include <base/scoped_ptr.h> |
| 14 #include <base/string_util.h> | 14 #include <base/string_util.h> |
| 15 #include <google/protobuf/repeated_field.h> | 15 #include <google/protobuf/repeated_field.h> |
| 16 #include <gtest/gtest.h> | 16 #include <gtest/gtest.h> |
| 17 | 17 |
| 18 #include "update_engine/delta_diff_generator.h" | 18 #include "update_engine/delta_diff_generator.h" |
| 19 #include "update_engine/delta_performer.h" | 19 #include "update_engine/delta_performer.h" |
| 20 #include "update_engine/extent_ranges.h" | 20 #include "update_engine/extent_ranges.h" |
| 21 #include "update_engine/full_update_generator.h" |
| 21 #include "update_engine/graph_types.h" | 22 #include "update_engine/graph_types.h" |
| 22 #include "update_engine/payload_signer.h" | 23 #include "update_engine/payload_signer.h" |
| 23 #include "update_engine/prefs_mock.h" | 24 #include "update_engine/prefs_mock.h" |
| 24 #include "update_engine/test_utils.h" | 25 #include "update_engine/test_utils.h" |
| 25 #include "update_engine/update_metadata.pb.h" | 26 #include "update_engine/update_metadata.pb.h" |
| 26 #include "update_engine/utils.h" | 27 #include "update_engine/utils.h" |
| 27 | 28 |
| 28 namespace chromeos_update_engine { | 29 namespace chromeos_update_engine { |
| 29 | 30 |
| 30 using std::min; | 31 using std::min; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644); | 107 int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644); |
| 107 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); | 108 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); |
| 108 ScopedFdCloser fd_closer(&fd); | 109 ScopedFdCloser fd_closer(&fd); |
| 109 off_t rc = lseek(fd, size + 1, SEEK_SET); | 110 off_t rc = lseek(fd, size + 1, SEEK_SET); |
| 110 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1)); | 111 TEST_AND_RETURN_FALSE_ERRNO(rc != static_cast<off_t>(-1)); |
| 111 int return_code = ftruncate(fd, size); | 112 int return_code = ftruncate(fd, size); |
| 112 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0); | 113 TEST_AND_RETURN_FALSE_ERRNO(return_code == 0); |
| 113 return true; | 114 return true; |
| 114 } | 115 } |
| 115 | 116 |
| 116 void DoSmallImageTest(bool full_kernel, bool noop) { | 117 void DoSmallImageTest(bool full_kernel, bool full_rootfs, bool noop) { |
| 117 string a_img, b_img; | 118 string a_img, b_img; |
| 118 EXPECT_TRUE(utils::MakeTempFile("/tmp/a_img.XXXXXX", &a_img, NULL)); | 119 EXPECT_TRUE(utils::MakeTempFile("/tmp/a_img.XXXXXX", &a_img, NULL)); |
| 119 ScopedPathUnlinker a_img_unlinker(a_img); | 120 ScopedPathUnlinker a_img_unlinker(a_img); |
| 120 EXPECT_TRUE(utils::MakeTempFile("/tmp/b_img.XXXXXX", &b_img, NULL)); | 121 EXPECT_TRUE(utils::MakeTempFile("/tmp/b_img.XXXXXX", &b_img, NULL)); |
| 121 ScopedPathUnlinker b_img_unlinker(b_img); | 122 ScopedPathUnlinker b_img_unlinker(b_img); |
| 122 | 123 |
| 123 CreateExtImageAtPath(a_img, NULL); | 124 CreateExtImageAtPath(a_img, NULL); |
| 124 | 125 |
| 125 int image_size = static_cast<int>(utils::FileSize(a_img)); | 126 int image_size = static_cast<int>(utils::FileSize(a_img)); |
| 126 | 127 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 EXPECT_TRUE(utils::MakeTempFile("/tmp/delta.XXXXXX", &delta_path, NULL)); | 215 EXPECT_TRUE(utils::MakeTempFile("/tmp/delta.XXXXXX", &delta_path, NULL)); |
| 215 LOG(INFO) << "delta path: " << delta_path; | 216 LOG(INFO) << "delta path: " << delta_path; |
| 216 ScopedPathUnlinker delta_path_unlinker(delta_path); | 217 ScopedPathUnlinker delta_path_unlinker(delta_path); |
| 217 { | 218 { |
| 218 string a_mnt, b_mnt; | 219 string a_mnt, b_mnt; |
| 219 ScopedLoopMounter a_mounter(a_img, &a_mnt, MS_RDONLY); | 220 ScopedLoopMounter a_mounter(a_img, &a_mnt, MS_RDONLY); |
| 220 ScopedLoopMounter b_mounter(b_img, &b_mnt, MS_RDONLY); | 221 ScopedLoopMounter b_mounter(b_img, &b_mnt, MS_RDONLY); |
| 221 | 222 |
| 222 EXPECT_TRUE( | 223 EXPECT_TRUE( |
| 223 DeltaDiffGenerator::GenerateDeltaUpdateFile( | 224 DeltaDiffGenerator::GenerateDeltaUpdateFile( |
| 224 a_mnt, | 225 full_rootfs ? "" : a_mnt, |
| 225 a_img, | 226 full_rootfs ? "" : a_img, |
| 226 b_mnt, | 227 b_mnt, |
| 227 b_img, | 228 b_img, |
| 228 full_kernel ? "" : old_kernel, | 229 full_kernel ? "" : old_kernel, |
| 229 new_kernel, | 230 new_kernel, |
| 230 delta_path, | 231 delta_path, |
| 231 kUnittestPrivateKeyPath)); | 232 kUnittestPrivateKeyPath)); |
| 232 } | 233 } |
| 233 | 234 |
| 234 // Read delta into memory. | 235 // Read delta into memory. |
| 235 vector<char> delta; | 236 vector<char> delta; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 EXPECT_EQ(1, manifest.kernel_install_operations_size()); | 272 EXPECT_EQ(1, manifest.kernel_install_operations_size()); |
| 272 } | 273 } |
| 273 | 274 |
| 274 if (full_kernel) { | 275 if (full_kernel) { |
| 275 EXPECT_FALSE(manifest.has_old_kernel_info()); | 276 EXPECT_FALSE(manifest.has_old_kernel_info()); |
| 276 } else { | 277 } else { |
| 277 EXPECT_EQ(old_kernel_data.size(), manifest.old_kernel_info().size()); | 278 EXPECT_EQ(old_kernel_data.size(), manifest.old_kernel_info().size()); |
| 278 EXPECT_FALSE(manifest.old_kernel_info().hash().empty()); | 279 EXPECT_FALSE(manifest.old_kernel_info().hash().empty()); |
| 279 } | 280 } |
| 280 | 281 |
| 282 if (full_rootfs) { |
| 283 EXPECT_FALSE(manifest.has_old_rootfs_info()); |
| 284 } else { |
| 285 EXPECT_EQ(image_size, manifest.old_rootfs_info().size()); |
| 286 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty()); |
| 287 } |
| 288 |
| 281 EXPECT_EQ(new_kernel_data.size(), manifest.new_kernel_info().size()); | 289 EXPECT_EQ(new_kernel_data.size(), manifest.new_kernel_info().size()); |
| 282 EXPECT_EQ(image_size, manifest.old_rootfs_info().size()); | |
| 283 EXPECT_EQ(image_size, manifest.new_rootfs_info().size()); | 290 EXPECT_EQ(image_size, manifest.new_rootfs_info().size()); |
| 284 | 291 |
| 285 EXPECT_FALSE(manifest.new_kernel_info().hash().empty()); | 292 EXPECT_FALSE(manifest.new_kernel_info().hash().empty()); |
| 286 EXPECT_FALSE(manifest.old_rootfs_info().hash().empty()); | |
| 287 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty()); | 293 EXPECT_FALSE(manifest.new_rootfs_info().hash().empty()); |
| 288 } | 294 } |
| 289 | 295 |
| 290 PrefsMock prefs; | 296 PrefsMock prefs; |
| 291 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize, | 297 EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize, |
| 292 manifest_metadata_size)).WillOnce(Return(true)); | 298 manifest_metadata_size)).WillOnce(Return(true)); |
| 293 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _)) | 299 EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _)) |
| 294 .WillRepeatedly(Return(true)); | 300 .WillRepeatedly(Return(true)); |
| 295 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _)) | 301 EXPECT_CALL(prefs, GetInt64(kPrefsUpdateStateNextOperation, _)) |
| 296 .WillOnce(Return(false)); | 302 .WillOnce(Return(false)); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath)); | 345 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath)); |
| 340 EXPECT_TRUE(performer.VerifyPayload( | 346 EXPECT_TRUE(performer.VerifyPayload( |
| 341 kUnittestPublicKeyPath, | 347 kUnittestPublicKeyPath, |
| 342 OmahaHashCalculator::OmahaHashOfData(delta), | 348 OmahaHashCalculator::OmahaHashOfData(delta), |
| 343 delta.size())); | 349 delta.size())); |
| 344 EXPECT_TRUE(performer.VerifyAppliedUpdate(a_img, old_kernel)); | 350 EXPECT_TRUE(performer.VerifyAppliedUpdate(a_img, old_kernel)); |
| 345 } | 351 } |
| 346 } | 352 } |
| 347 | 353 |
| 348 TEST(DeltaPerformerTest, RunAsRootSmallImageTest) { | 354 TEST(DeltaPerformerTest, RunAsRootSmallImageTest) { |
| 349 DoSmallImageTest(false, false); | 355 DoSmallImageTest(false, false, false); |
| 350 } | 356 } |
| 351 | 357 |
| 352 TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) { | 358 TEST(DeltaPerformerTest, RunAsRootFullKernelSmallImageTest) { |
| 353 DoSmallImageTest(true, false); | 359 DoSmallImageTest(true, false, false); |
| 360 } |
| 361 |
| 362 TEST(DeltaPerformerTest, RunAsRootFullSmallImageTest) { |
| 363 DoSmallImageTest(true, true, false); |
| 354 } | 364 } |
| 355 | 365 |
| 356 TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) { | 366 TEST(DeltaPerformerTest, RunAsRootNoopSmallImageTest) { |
| 357 DoSmallImageTest(false, true); | 367 DoSmallImageTest(false, false, true); |
| 358 } | |
| 359 | |
| 360 TEST(DeltaPerformerTest, NewFullUpdateTest) { | |
| 361 vector<char> new_root(20 * 1024 * 1024); | |
| 362 vector<char> new_kern(16 * 1024 * 1024); | |
| 363 const off_t kChunkSize = 128 * 1024; | |
| 364 FillWithData(&new_root); | |
| 365 FillWithData(&new_kern); | |
| 366 // Assume hashes take 2 MiB beyond the rootfs. | |
| 367 off_t new_rootfs_size = new_root.size() - 2 * 1024 * 1024; | |
| 368 | |
| 369 string new_root_path; | |
| 370 EXPECT_TRUE(utils::MakeTempFile("/tmp/NewFullUpdateTest_R.XXXXXX", | |
| 371 &new_root_path, | |
| 372 NULL)); | |
| 373 ScopedPathUnlinker new_root_path_unlinker(new_root_path); | |
| 374 EXPECT_TRUE(WriteFileVector(new_root_path, new_root)); | |
| 375 | |
| 376 string new_kern_path; | |
| 377 EXPECT_TRUE(utils::MakeTempFile("/tmp/NewFullUpdateTest_K.XXXXXX", | |
| 378 &new_kern_path, | |
| 379 NULL)); | |
| 380 ScopedPathUnlinker new_kern_path_unlinker(new_kern_path); | |
| 381 EXPECT_TRUE(WriteFileVector(new_kern_path, new_kern)); | |
| 382 | |
| 383 string out_blobs_path; | |
| 384 int out_blobs_fd; | |
| 385 EXPECT_TRUE(utils::MakeTempFile("/tmp/NewFullUpdateTest_D.XXXXXX", | |
| 386 &out_blobs_path, | |
| 387 &out_blobs_fd)); | |
| 388 ScopedPathUnlinker out_blobs_path_unlinker(out_blobs_path); | |
| 389 ScopedFdCloser out_blobs_fd_closer(&out_blobs_fd); | |
| 390 | |
| 391 off_t out_blobs_length = 0; | |
| 392 | |
| 393 Graph graph; | |
| 394 vector<DeltaArchiveManifest_InstallOperation> kernel_ops; | |
| 395 vector<Vertex::Index> final_order; | |
| 396 | |
| 397 EXPECT_TRUE(DeltaDiffGenerator::ReadFullUpdateFromDisk(&graph, | |
| 398 new_kern_path, | |
| 399 new_root_path, | |
| 400 new_rootfs_size, | |
| 401 out_blobs_fd, | |
| 402 &out_blobs_length, | |
| 403 kChunkSize, | |
| 404 &kernel_ops, | |
| 405 &final_order)); | |
| 406 EXPECT_EQ(new_rootfs_size / kChunkSize, graph.size()); | |
| 407 EXPECT_EQ(new_rootfs_size / kChunkSize, final_order.size()); | |
| 408 EXPECT_EQ(new_kern.size() / kChunkSize, kernel_ops.size()); | |
| 409 for (off_t i = 0; i < (new_rootfs_size / kChunkSize); ++i) { | |
| 410 EXPECT_EQ(i, final_order[i]); | |
| 411 EXPECT_EQ(1, graph[i].op.dst_extents_size()); | |
| 412 EXPECT_EQ(i * kChunkSize / kBlockSize, | |
| 413 graph[i].op.dst_extents(0).start_block()) << "i = " << i; | |
| 414 EXPECT_EQ(kChunkSize / kBlockSize, | |
| 415 graph[i].op.dst_extents(0).num_blocks()); | |
| 416 if (graph[i].op.type() != | |
| 417 DeltaArchiveManifest_InstallOperation_Type_REPLACE) { | |
| 418 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ, | |
| 419 graph[i].op.type()); | |
| 420 } | |
| 421 } | |
| 422 } | 368 } |
| 423 | 369 |
| 424 TEST(DeltaPerformerTest, IsIdempotentOperationTest) { | 370 TEST(DeltaPerformerTest, IsIdempotentOperationTest) { |
| 425 DeltaArchiveManifest_InstallOperation op; | 371 DeltaArchiveManifest_InstallOperation op; |
| 426 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); | 372 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); |
| 427 *(op.add_dst_extents()) = ExtentForRange(0, 5); | 373 *(op.add_dst_extents()) = ExtentForRange(0, 5); |
| 428 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); | 374 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); |
| 429 *(op.add_src_extents()) = ExtentForRange(4, 1); | 375 *(op.add_src_extents()) = ExtentForRange(4, 1); |
| 430 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op)); | 376 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op)); |
| 431 op.clear_src_extents(); | 377 op.clear_src_extents(); |
| 432 *(op.add_src_extents()) = ExtentForRange(5, 3); | 378 *(op.add_src_extents()) = ExtentForRange(5, 3); |
| 433 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); | 379 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); |
| 434 *(op.add_dst_extents()) = ExtentForRange(20, 6); | 380 *(op.add_dst_extents()) = ExtentForRange(20, 6); |
| 435 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); | 381 EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); |
| 436 *(op.add_src_extents()) = ExtentForRange(19, 2); | 382 *(op.add_src_extents()) = ExtentForRange(19, 2); |
| 437 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op)); | 383 EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op)); |
| 438 } | 384 } |
| 439 | 385 |
| 440 } // namespace chromeos_update_engine | 386 } // namespace chromeos_update_engine |
| OLD | NEW |