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