full_update_generator_unittest.cc revision 6c396a9b3020df9b0b58886fd6f36523bec29d3a
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_.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    rootfs_part_unlinker_.reset(
41        new ScopedPathUnlinker(config_.target.rootfs.path));
42    kernel_part_unlinker_.reset(
43        new ScopedPathUnlinker(config_.target.kernel.path));
44    out_blobs_unlinker_.reset(new ScopedPathUnlinker(out_blobs_path_));
45  }
46
47  PayloadGenerationConfig config_;
48
49  // Output file holding the payload blobs.
50  string out_blobs_path_;
51  int out_blobs_fd_{-1};
52  ScopedFdCloser out_blobs_fd_closer_{&out_blobs_fd_};
53
54  std::unique_ptr<ScopedPathUnlinker> rootfs_part_unlinker_;
55  std::unique_ptr<ScopedPathUnlinker> kernel_part_unlinker_;
56  std::unique_ptr<ScopedPathUnlinker> out_blobs_unlinker_;
57
58  // FullUpdateGenerator under test.
59  FullUpdateGenerator generator_;
60};
61
62TEST_F(FullUpdateGeneratorTest, RunTest) {
63  chromeos::Blob new_root(9 * 1024 * 1024);
64  chromeos::Blob new_kern(3 * 1024 * 1024);
65  FillWithData(&new_root);
66  FillWithData(&new_kern);
67
68  // Assume hashes take 2 MiB beyond the rootfs.
69  config_.rootfs_partition_size = new_root.size();
70  config_.target.rootfs.size = new_root.size() - 2 * 1024 * 1024;
71  config_.target.kernel.size = new_kern.size();
72
73  EXPECT_TRUE(test_utils::WriteFileVector(config_.target.rootfs.path,
74                                          new_root));
75  EXPECT_TRUE(test_utils::WriteFileVector(config_.target.kernel.path,
76                                          new_kern));
77
78  off_t out_blobs_length = 0;
79  vector<AnnotatedOperation> rootfs_ops;
80  vector<AnnotatedOperation> kernel_ops;
81
82  EXPECT_TRUE(generator_.GenerateOperations(config_,
83                                            out_blobs_fd_,
84                                            &out_blobs_length,
85                                            &rootfs_ops,
86                                            &kernel_ops));
87  int64_t target_rootfs_chunks =
88      config_.target.rootfs.size / config_.chunk_size;
89  EXPECT_EQ(target_rootfs_chunks, rootfs_ops.size());
90  EXPECT_EQ(new_kern.size() / config_.chunk_size, kernel_ops.size());
91  for (off_t i = 0; i < target_rootfs_chunks; ++i) {
92    EXPECT_EQ(1, rootfs_ops[i].op.dst_extents_size());
93    EXPECT_EQ(i * config_.chunk_size / config_.block_size,
94              rootfs_ops[i].op.dst_extents(0).start_block()) << "i = " << i;
95    EXPECT_EQ(config_.chunk_size / config_.block_size,
96              rootfs_ops[i].op.dst_extents(0).num_blocks());
97    if (rootfs_ops[i].op.type() !=
98        DeltaArchiveManifest_InstallOperation_Type_REPLACE) {
99      EXPECT_EQ(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ,
100                rootfs_ops[i].op.type());
101    }
102  }
103}
104
105// Test that if the chunk size is not a divisor of the image size, it handles
106// correctly the last chunk of each partition.
107TEST_F(FullUpdateGeneratorTest, ChunkSizeTooBig) {
108  config_.chunk_size = 1024 * 1024;
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  off_t out_blobs_length = 0;
121  vector<AnnotatedOperation> rootfs_ops;
122  vector<AnnotatedOperation> kernel_ops;
123
124  EXPECT_TRUE(generator_.GenerateOperations(config_,
125                                            out_blobs_fd_,
126                                            &out_blobs_length,
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_.chunk_size / config_.block_size,
132            BlocksInExtents(rootfs_ops[0].op.dst_extents()));
133  EXPECT_EQ((new_root.size() - config_.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