full_update_generator_unittest.cc revision 8cc502dacbccdab96824d42287f230ce04004784
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() != 99 DeltaArchiveManifest_InstallOperation_Type_REPLACE) { 100 EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ, 101 rootfs_ops[i].op.type()); 102 } 103 } 104} 105 106// Test that if the chunk size is not a divisor of the image size, it handles 107// correctly the last chunk of each partition. 108TEST_F(FullUpdateGeneratorTest, ChunkSizeTooBig) { 109 config_.hard_chunk_size = 1024 * 1024; 110 config_.soft_chunk_size = config_.hard_chunk_size; 111 chromeos::Blob new_root(1536 * 1024); // 1.5 MiB 112 chromeos::Blob new_kern(128 * 1024); 113 config_.rootfs_partition_size = new_root.size(); 114 config_.target.rootfs.size = new_root.size(); 115 config_.target.kernel.size = new_kern.size(); 116 117 EXPECT_TRUE(test_utils::WriteFileVector(config_.target.rootfs.path, 118 new_root)); 119 EXPECT_TRUE(test_utils::WriteFileVector(config_.target.kernel.path, 120 new_kern)); 121 122 vector<AnnotatedOperation> rootfs_ops; 123 vector<AnnotatedOperation> kernel_ops; 124 125 EXPECT_TRUE(generator_.GenerateOperations(config_, 126 blob_file_.get(), 127 &rootfs_ops, 128 &kernel_ops)); 129 // rootfs has one chunk and a half. 130 EXPECT_EQ(2, rootfs_ops.size()); 131 EXPECT_EQ(config_.hard_chunk_size / config_.block_size, 132 BlocksInExtents(rootfs_ops[0].op.dst_extents())); 133 EXPECT_EQ((new_root.size() - config_.hard_chunk_size) / config_.block_size, 134 BlocksInExtents(rootfs_ops[1].op.dst_extents())); 135 136 // kernel has less than one chunk. 137 EXPECT_EQ(1, kernel_ops.size()); 138 EXPECT_EQ(new_kern.size() / config_.block_size, 139 BlocksInExtents(kernel_ops[0].op.dst_extents())); 140} 141 142} // namespace chromeos_update_engine 143