1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2010 The Android Open Source Project 3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License"); 5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License. 6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at 7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// http://www.apache.org/licenses/LICENSE-2.0 9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software 11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS, 12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and 14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License. 15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// 167a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 17aab50e31f0b80ed53a9b8d5dbabcf943974bd32cAlex Deymo#include "update_engine/payload_generator/full_update_generator.h" 18aab50e31f0b80ed53a9b8d5dbabcf943974bd32cAlex Deymo 197a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov#include <string> 207a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov#include <vector> 217a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 227a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov#include <gtest/gtest.h> 237a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 2439910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/test_utils.h" 2539910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/payload_constants.h" 266c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo#include "update_engine/payload_generator/extent_utils.h" 277a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 2810875d90cf67f883ba7c9ed13bc8d706aa8c6fbcAlex Deymousing chromeos_update_engine::test_utils::FillWithData; 297a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkovusing std::string; 307a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkovusing std::vector; 317a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 327a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkovnamespace chromeos_update_engine { 337a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 34f1cbe1783dd025bd7243a8df12f20548196cc023Alex Deymoclass FullUpdateGeneratorTest : public ::testing::Test { 35f1cbe1783dd025bd7243a8df12f20548196cc023Alex Deymo protected: 36f1cbe1783dd025bd7243a8df12f20548196cc023Alex Deymo void SetUp() override { 37f1cbe1783dd025bd7243a8df12f20548196cc023Alex Deymo config_.is_delta = false; 3838818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo config_.version.minor = kFullPayloadMinorVersion; 392d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo config_.hard_chunk_size = 128 * 1024; 40f1cbe1783dd025bd7243a8df12f20548196cc023Alex Deymo config_.block_size = 4096; 416c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo 42ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_TRUE(utils::MakeTempFile("FullUpdateTest_partition.XXXXXX", 43ebdf17d4202c67933764135bfc1cece629829201Sen Jiang &new_part_conf.path, 446c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo nullptr)); 456c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo EXPECT_TRUE(utils::MakeTempFile("FullUpdateTest_blobs.XXXXXX", 466c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo &out_blobs_path_, 476c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo &out_blobs_fd_)); 486c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo 498cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file_.reset(new BlobFileWriter(out_blobs_fd_, &out_blobs_length_)); 50ebdf17d4202c67933764135bfc1cece629829201Sen Jiang part_path_unlinker_.reset(new ScopedPathUnlinker(new_part_conf.path)); 516c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo out_blobs_unlinker_.reset(new ScopedPathUnlinker(out_blobs_path_)); 52f1cbe1783dd025bd7243a8df12f20548196cc023Alex Deymo } 537a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 54f1cbe1783dd025bd7243a8df12f20548196cc023Alex Deymo PayloadGenerationConfig config_; 55625406cee9a90ac2ed895f480286b7f0e8497f38Sen Jiang PartitionConfig new_part_conf{"part"}; 56ebdf17d4202c67933764135bfc1cece629829201Sen Jiang 57ebdf17d4202c67933764135bfc1cece629829201Sen Jiang vector<AnnotatedOperation> aops; 587a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 596c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo // Output file holding the payload blobs. 606c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo string out_blobs_path_; 616c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo int out_blobs_fd_{-1}; 628cc502dacbccdab96824d42287f230ce04004784Sen Jiang off_t out_blobs_length_{0}; 636c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo ScopedFdCloser out_blobs_fd_closer_{&out_blobs_fd_}; 646c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo 658cc502dacbccdab96824d42287f230ce04004784Sen Jiang std::unique_ptr<BlobFileWriter> blob_file_; 66ebdf17d4202c67933764135bfc1cece629829201Sen Jiang std::unique_ptr<ScopedPathUnlinker> part_path_unlinker_; 676c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo std::unique_ptr<ScopedPathUnlinker> out_blobs_unlinker_; 686c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo 696c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo // FullUpdateGenerator under test. 706c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo FullUpdateGenerator generator_; 716c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo}; 727a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 73f1cbe1783dd025bd7243a8df12f20548196cc023Alex DeymoTEST_F(FullUpdateGeneratorTest, RunTest) { 743f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob new_part(9 * 1024 * 1024); 75ebdf17d4202c67933764135bfc1cece629829201Sen Jiang FillWithData(&new_part); 76ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf.size = new_part.size(); 777a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 78ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_TRUE(test_utils::WriteFileVector(new_part_conf.path, new_part)); 79477aec2166a571cbe28081d806c3226e8b31b6e9Alex Deymo 806c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo EXPECT_TRUE(generator_.GenerateOperations(config_, 81ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf, // this is ignored 82ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf, 838cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file_.get(), 84ebdf17d4202c67933764135bfc1cece629829201Sen Jiang &aops)); 85ebdf17d4202c67933764135bfc1cece629829201Sen Jiang int64_t new_part_chunks = new_part_conf.size / config_.hard_chunk_size; 865fe0c4ede81b82ae3425ddbbb698eceef14cbc78Alex Deymo EXPECT_EQ(new_part_chunks, static_cast<int64_t>(aops.size())); 87ebdf17d4202c67933764135bfc1cece629829201Sen Jiang for (off_t i = 0; i < new_part_chunks; ++i) { 88ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_EQ(1, aops[i].op.dst_extents_size()); 8938818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo EXPECT_EQ( 9038818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo static_cast<uint64_t>(i * config_.hard_chunk_size / config_.block_size), 9138818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo aops[i].op.dst_extents(0).start_block()) 9238818fbf1f2f937051b5bcc01ff74539a3c9b27dAlex Deymo << "i = " << i; 932d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo EXPECT_EQ(config_.hard_chunk_size / config_.block_size, 94ebdf17d4202c67933764135bfc1cece629829201Sen Jiang aops[i].op.dst_extents(0).num_blocks()); 95ebdf17d4202c67933764135bfc1cece629829201Sen Jiang if (aops[i].op.type() != InstallOperation::REPLACE) { 96ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_EQ(InstallOperation::REPLACE_BZ, aops[i].op.type()); 977a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov } 987a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov } 997a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov} 1007a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov 1016c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo// Test that if the chunk size is not a divisor of the image size, it handles 102ebdf17d4202c67933764135bfc1cece629829201Sen Jiang// correctly the last chunk of the partition. 1036c396a9b3020df9b0b58886fd6f36523bec29d3aAlex DeymoTEST_F(FullUpdateGeneratorTest, ChunkSizeTooBig) { 1042d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo config_.hard_chunk_size = 1024 * 1024; 1052d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo config_.soft_chunk_size = config_.hard_chunk_size; 1063f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob new_part(1536 * 1024); // 1.5 MiB 107ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf.size = new_part.size(); 1086c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo 109ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_TRUE(test_utils::WriteFileVector(new_part_conf.path, new_part)); 1106c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo 1116c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo EXPECT_TRUE(generator_.GenerateOperations(config_, 112ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf, // this is ignored 113ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf, 1148cc502dacbccdab96824d42287f230ce04004784Sen Jiang blob_file_.get(), 115ebdf17d4202c67933764135bfc1cece629829201Sen Jiang &aops)); 116ebdf17d4202c67933764135bfc1cece629829201Sen Jiang // new_part has one chunk and a half. 11780f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo EXPECT_EQ(2U, aops.size()); 1182d3b2d635e50c6886e285afb86c3187d9e0bd360Alex Deymo EXPECT_EQ(config_.hard_chunk_size / config_.block_size, 119ebdf17d4202c67933764135bfc1cece629829201Sen Jiang BlocksInExtents(aops[0].op.dst_extents())); 120ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_EQ((new_part.size() - config_.hard_chunk_size) / config_.block_size, 121ebdf17d4202c67933764135bfc1cece629829201Sen Jiang BlocksInExtents(aops[1].op.dst_extents())); 122ebdf17d4202c67933764135bfc1cece629829201Sen Jiang} 123ebdf17d4202c67933764135bfc1cece629829201Sen Jiang 124ebdf17d4202c67933764135bfc1cece629829201Sen Jiang// Test that if the image size is much smaller than the chunk size, it handles 125ebdf17d4202c67933764135bfc1cece629829201Sen Jiang// correctly the only chunk of the partition. 126ebdf17d4202c67933764135bfc1cece629829201Sen JiangTEST_F(FullUpdateGeneratorTest, ImageSizeTooSmall) { 1273f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko brillo::Blob new_part(16 * 1024); 128ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf.size = new_part.size(); 129ebdf17d4202c67933764135bfc1cece629829201Sen Jiang 130ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_TRUE(test_utils::WriteFileVector(new_part_conf.path, new_part)); 131ebdf17d4202c67933764135bfc1cece629829201Sen Jiang 132ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_TRUE(generator_.GenerateOperations(config_, 133ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf, // this is ignored 134ebdf17d4202c67933764135bfc1cece629829201Sen Jiang new_part_conf, 135ebdf17d4202c67933764135bfc1cece629829201Sen Jiang blob_file_.get(), 136ebdf17d4202c67933764135bfc1cece629829201Sen Jiang &aops)); 137ebdf17d4202c67933764135bfc1cece629829201Sen Jiang 138ebdf17d4202c67933764135bfc1cece629829201Sen Jiang // new_part has less than one chunk. 13980f70ff45f8ea9a679c0c3ed0dc143dd2fe2b63eAlex Deymo EXPECT_EQ(1U, aops.size()); 140ebdf17d4202c67933764135bfc1cece629829201Sen Jiang EXPECT_EQ(new_part.size() / config_.block_size, 141ebdf17d4202c67933764135bfc1cece629829201Sen Jiang BlocksInExtents(aops[0].op.dst_extents())); 1426c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo} 1436c396a9b3020df9b0b58886fd6f36523bec29d3aAlex Deymo 1447a22d791f58f8de711a4d70f247c1c14833c8e4bDarin Petkov} // namespace chromeos_update_engine 145