full_update_generator_unittest.cc revision a12ee11c78ac6d7c2605921a4006b6a7416e0c35
1// Copyright (c) 2010 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/full_update_generator.h" 6 7#include <string> 8#include <vector> 9 10#include <gtest/gtest.h> 11 12#include "update_engine/delta_performer.h" 13#include "update_engine/payload_generator/extent_utils.h" 14#include "update_engine/test_utils.h" 15 16using chromeos_update_engine::test_utils::FillWithData; 17using std::string; 18using std::vector; 19 20namespace chromeos_update_engine { 21 22class FullUpdateGeneratorTest : public ::testing::Test { 23 protected: 24 void SetUp() override { 25 config_.is_delta = false; 26 config_.minor_version = DeltaPerformer::kFullPayloadMinorVersion; 27 config_.hard_chunk_size = 128 * 1024; 28 config_.block_size = 4096; 29 30 EXPECT_TRUE(utils::MakeTempFile("FullUpdateTest_rootfs.XXXXXX", 31 &config_.target.rootfs.path, 32 nullptr)); 33 EXPECT_TRUE(utils::MakeTempFile("FullUpdateTest_kernel.XXXXXX", 34 &config_.target.kernel.path, 35 nullptr)); 36 EXPECT_TRUE(utils::MakeTempFile("FullUpdateTest_blobs.XXXXXX", 37 &out_blobs_path_, 38 &out_blobs_fd_)); 39 40 blob_file_.reset(new BlobFileWriter(out_blobs_fd_, &out_blobs_length_)); 41 rootfs_part_unlinker_.reset( 42 new ScopedPathUnlinker(config_.target.rootfs.path)); 43 kernel_part_unlinker_.reset( 44 new ScopedPathUnlinker(config_.target.kernel.path)); 45 out_blobs_unlinker_.reset(new ScopedPathUnlinker(out_blobs_path_)); 46 } 47 48 PayloadGenerationConfig config_; 49 50 // Output file holding the payload blobs. 51 string out_blobs_path_; 52 int out_blobs_fd_{-1}; 53 off_t out_blobs_length_{0}; 54 ScopedFdCloser out_blobs_fd_closer_{&out_blobs_fd_}; 55 56 std::unique_ptr<BlobFileWriter> blob_file_; 57 std::unique_ptr<ScopedPathUnlinker> rootfs_part_unlinker_; 58 std::unique_ptr<ScopedPathUnlinker> kernel_part_unlinker_; 59 std::unique_ptr<ScopedPathUnlinker> out_blobs_unlinker_; 60 61 // FullUpdateGenerator under test. 62 FullUpdateGenerator generator_; 63}; 64 65TEST_F(FullUpdateGeneratorTest, RunTest) { 66 chromeos::Blob new_root(9 * 1024 * 1024); 67 chromeos::Blob new_kern(3 * 1024 * 1024); 68 FillWithData(&new_root); 69 FillWithData(&new_kern); 70 71 // Assume hashes take 2 MiB beyond the rootfs. 72 config_.rootfs_partition_size = new_root.size(); 73 config_.target.rootfs.size = new_root.size() - 2 * 1024 * 1024; 74 config_.target.kernel.size = new_kern.size(); 75 76 EXPECT_TRUE(test_utils::WriteFileVector(config_.target.rootfs.path, 77 new_root)); 78 EXPECT_TRUE(test_utils::WriteFileVector(config_.target.kernel.path, 79 new_kern)); 80 81 vector<AnnotatedOperation> rootfs_ops; 82 vector<AnnotatedOperation> kernel_ops; 83 84 EXPECT_TRUE(generator_.GenerateOperations(config_, 85 blob_file_.get(), 86 &rootfs_ops, 87 &kernel_ops)); 88 int64_t target_rootfs_chunks = 89 config_.target.rootfs.size / config_.hard_chunk_size; 90 EXPECT_EQ(target_rootfs_chunks, rootfs_ops.size()); 91 EXPECT_EQ(new_kern.size() / config_.hard_chunk_size, kernel_ops.size()); 92 for (off_t i = 0; i < target_rootfs_chunks; ++i) { 93 EXPECT_EQ(1, rootfs_ops[i].op.dst_extents_size()); 94 EXPECT_EQ(i * config_.hard_chunk_size / config_.block_size, 95 rootfs_ops[i].op.dst_extents(0).start_block()) << "i = " << i; 96 EXPECT_EQ(config_.hard_chunk_size / config_.block_size, 97 rootfs_ops[i].op.dst_extents(0).num_blocks()); 98 if (rootfs_ops[i].op.type() != InstallOperation::REPLACE) { 99 EXPECT_EQ(InstallOperation::REPLACE_BZ, rootfs_ops[i].op.type()); 100 } 101 } 102} 103 104// Test that if the chunk size is not a divisor of the image size, it handles 105// correctly the last chunk of each partition. 106TEST_F(FullUpdateGeneratorTest, ChunkSizeTooBig) { 107 config_.hard_chunk_size = 1024 * 1024; 108 config_.soft_chunk_size = config_.hard_chunk_size; 109 chromeos::Blob new_root(1536 * 1024); // 1.5 MiB 110 chromeos::Blob new_kern(128 * 1024); 111 config_.rootfs_partition_size = new_root.size(); 112 config_.target.rootfs.size = new_root.size(); 113 config_.target.kernel.size = new_kern.size(); 114 115 EXPECT_TRUE(test_utils::WriteFileVector(config_.target.rootfs.path, 116 new_root)); 117 EXPECT_TRUE(test_utils::WriteFileVector(config_.target.kernel.path, 118 new_kern)); 119 120 vector<AnnotatedOperation> rootfs_ops; 121 vector<AnnotatedOperation> kernel_ops; 122 123 EXPECT_TRUE(generator_.GenerateOperations(config_, 124 blob_file_.get(), 125 &rootfs_ops, 126 &kernel_ops)); 127 // rootfs has one chunk and a half. 128 EXPECT_EQ(2, rootfs_ops.size()); 129 EXPECT_EQ(config_.hard_chunk_size / config_.block_size, 130 BlocksInExtents(rootfs_ops[0].op.dst_extents())); 131 EXPECT_EQ((new_root.size() - config_.hard_chunk_size) / config_.block_size, 132 BlocksInExtents(rootfs_ops[1].op.dst_extents())); 133 134 // kernel has less than one chunk. 135 EXPECT_EQ(1, kernel_ops.size()); 136 EXPECT_EQ(new_kern.size() / config_.block_size, 137 BlocksInExtents(kernel_ops[0].op.dst_extents())); 138} 139 140} // namespace chromeos_update_engine 141