blob: 12dd1d358ef42c1f51c1c5ecf50a62c7478948c1 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070016
Alex Deymo8427b4a2014-11-05 14:00:32 -080017#include "update_engine/delta_performer.h"
18
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070019#include <inttypes.h>
20
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070021#include <string>
22#include <vector>
23
Allie Wood78750a42015-02-11 15:42:11 -080024#include <base/files/file_path.h>
Ben Chan06c76a42014-09-05 08:21:06 -070025#include <base/files/file_util.h>
Alex Deymocbf09892015-09-11 16:13:16 -070026#include <base/strings/string_number_conversions.h>
Alex Deymof1cbe172015-03-05 15:58:37 -080027#include <base/strings/string_util.h>
Alex Deymo2d621a32015-10-01 11:09:01 -070028#include <base/strings/stringprintf.h>
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070029#include <google/protobuf/repeated_field.h>
30#include <gtest/gtest.h>
31
Sen Jiang2d528b42015-09-25 11:18:12 -070032#include "update_engine/bzip.h"
Jay Srinivasand29695d2013-04-08 15:08:05 -070033#include "update_engine/constants.h"
David Zeuthene7f89172013-10-31 10:21:04 -070034#include "update_engine/fake_hardware.h"
Sen Jiang2d528b42015-09-25 11:18:12 -070035#include "update_engine/fake_prefs.h"
Gilad Arnold5bb4c902014-04-10 12:32:13 -070036#include "update_engine/fake_system_state.h"
Alex Deymo161c4a12014-05-16 15:56:21 -070037#include "update_engine/payload_constants.h"
Sen Jiang2d528b42015-09-25 11:18:12 -070038#include "update_engine/payload_generator/extent_ranges.h"
Sen Jiangd78b3892015-09-25 15:19:31 -070039#include "update_engine/payload_generator/payload_file.h"
Alex Deymo923d8fa2014-07-15 17:58:51 -070040#include "update_engine/payload_generator/payload_signer.h"
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070041#include "update_engine/test_utils.h"
42#include "update_engine/update_metadata.pb.h"
43#include "update_engine/utils.h"
44
45namespace chromeos_update_engine {
46
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070047using std::string;
48using std::vector;
Alex Deymo10875d92014-11-10 21:52:57 -080049using test_utils::System;
Alex Deymo2d621a32015-10-01 11:09:01 -070050using test_utils::kRandomString;
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070051
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070052extern const char* kUnittestPrivateKeyPath;
Darin Petkovd7061ab2010-10-06 14:37:09 -070053extern const char* kUnittestPublicKeyPath;
Andrew de los Reyes932bc4c2010-08-23 18:14:09 -070054
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -070055static const char* kBogusMetadataSignature1 =
56 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
57 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
58 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
59 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
60 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
61 "pLRtClp97kN2+tXGNBQqkA==";
Jay Srinivasan738fdf32012-12-07 17:40:54 -080062
Andrew de los Reyes27f7d372010-10-07 11:26:07 -070063namespace {
Jay Srinivasan738fdf32012-12-07 17:40:54 -080064// Different options that determine what we should fill into the
65// install_plan.metadata_signature to simulate the contents received in the
66// Omaha response.
67enum MetadataSignatureTest {
68 kEmptyMetadataSignature,
69 kInvalidMetadataSignature,
70 kValidMetadataSignature,
71};
72
Alex Deymo2d621a32015-10-01 11:09:01 -070073// Compressed data without checksum, generated with:
74// echo -n a | xz -9 --check=none | hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
75const uint8_t kXzCompressedData[] = {
76 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, 0xff, 0x12, 0xd9, 0x41,
77 0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
78 0x01, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x01,
79 0xad, 0xa6, 0x58, 0x04, 0x06, 0x72, 0x9e, 0x7a, 0x01, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x59, 0x5a,
81};
82
Alex Vakulenkod2779df2014-06-16 13:19:00 -070083} // namespace
Jay Srinivasan738fdf32012-12-07 17:40:54 -080084
Allie Woodfdf00512015-03-02 13:34:55 -080085class DeltaPerformerTest : public ::testing::Test {
Sen Jiang2d528b42015-09-25 11:18:12 -070086 protected:
Allie Woodfdf00512015-03-02 13:34:55 -080087
Sen Jiang2d528b42015-09-25 11:18:12 -070088 // Test helper placed where it can easily be friended from DeltaPerformer.
89 void RunManifestValidation(const DeltaArchiveManifest& manifest,
90 bool full_payload,
91 ErrorCode expected) {
Allie Woodfdf00512015-03-02 13:34:55 -080092 // The install plan is for Full or Delta.
Sen Jiang2d528b42015-09-25 11:18:12 -070093 install_plan_.is_full_update = full_payload;
Allie Woodfdf00512015-03-02 13:34:55 -080094
95 // The Manifest we are validating.
Sen Jiang2d528b42015-09-25 11:18:12 -070096 performer_.manifest_.CopyFrom(manifest);
Allie Woodfdf00512015-03-02 13:34:55 -080097
Sen Jiang2d528b42015-09-25 11:18:12 -070098 EXPECT_EQ(expected, performer_.ValidateManifest());
Allie Woodfdf00512015-03-02 13:34:55 -080099 }
100
Sen Jiang2d528b42015-09-25 11:18:12 -0700101 chromeos::Blob GeneratePayload(const chromeos::Blob& blob_data,
102 const vector<AnnotatedOperation>& aops,
103 bool sign_payload,
104 int32_t minor_version) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700105 string blob_path;
106 EXPECT_TRUE(utils::MakeTempFile("Blob-XXXXXX", &blob_path, nullptr));
107 ScopedPathUnlinker blob_unlinker(blob_path);
108 EXPECT_TRUE(utils::WriteFile(blob_path.c_str(),
109 blob_data.data(),
110 blob_data.size()));
111
112 PayloadGenerationConfig config;
113 config.major_version = kChromeOSMajorPayloadVersion;
114 config.minor_version = minor_version;
Sen Jiangd78b3892015-09-25 15:19:31 -0700115
116 PayloadFile payload;
117 EXPECT_TRUE(payload.Init(config));
118
Sen Jiang981eb112015-08-25 17:03:18 -0700119 PartitionConfig old_part(kLegacyPartitionNameRoot);
120 PartitionConfig new_part(kLegacyPartitionNameRoot);
121 new_part.path = blob_path;
122 new_part.size = blob_data.size();
123
124 payload.AddPartition(old_part, new_part, aops);
Sen Jiangd78b3892015-09-25 15:19:31 -0700125
126 string payload_path;
127 EXPECT_TRUE(utils::MakeTempFile("Payload-XXXXXX", &payload_path, nullptr));
128 ScopedPathUnlinker payload_unlinker(payload_path);
129 EXPECT_TRUE(payload.WritePayload(payload_path, blob_path,
130 sign_payload ? kUnittestPrivateKeyPath : "",
Sen Jiang2d528b42015-09-25 11:18:12 -0700131 &install_plan_.metadata_size));
Sen Jiangd78b3892015-09-25 15:19:31 -0700132
133 chromeos::Blob payload_data;
134 EXPECT_TRUE(utils::ReadFile(payload_path, &payload_data));
135 return payload_data;
136 }
Allie Woodfdf00512015-03-02 13:34:55 -0800137
Sen Jiang2d528b42015-09-25 11:18:12 -0700138 // Apply |payload_data| on partition specified in |source_path|.
139 chromeos::Blob ApplyPayload(const chromeos::Blob& payload_data,
140 const string& source_path) {
Alex Deymo79715ad2015-10-02 14:27:53 -0700141 return ApplyPayloadToData(payload_data, source_path, chromeos::Blob());
142 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800143
Alex Deymo79715ad2015-10-02 14:27:53 -0700144 // Apply the payload provided in |payload_data| reading from the |source_path|
145 // file and writing the contents to a new partition. The existing data in the
146 // new target file are set to |target_data| before applying the payload.
147 // Returns the result of the payload application.
148 chromeos::Blob ApplyPayloadToData(const chromeos::Blob& payload_data,
149 const string& source_path,
150 const chromeos::Blob& target_data) {
Sen Jiang2d528b42015-09-25 11:18:12 -0700151 string new_part;
152 EXPECT_TRUE(utils::MakeTempFile("Partition-XXXXXX", &new_part, nullptr));
153 ScopedPathUnlinker partition_unlinker(new_part);
Alex Deymo79715ad2015-10-02 14:27:53 -0700154 EXPECT_TRUE(utils::WriteFile(new_part.c_str(), target_data.data(),
155 target_data.size()));
156
157 install_plan_.source_path = source_path;
158 install_plan_.kernel_source_path = "/dev/null";
159 install_plan_.install_path = new_part;
160 install_plan_.kernel_install_path = "/dev/null";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800161
Sen Jiang2d528b42015-09-25 11:18:12 -0700162 EXPECT_EQ(0, performer_.Open(new_part.c_str(), 0, 0));
Alex Deymo79715ad2015-10-02 14:27:53 -0700163 EXPECT_TRUE(performer_.OpenSourceRootfs(source_path.c_str()));
Sen Jiang2d528b42015-09-25 11:18:12 -0700164 EXPECT_TRUE(performer_.Write(payload_data.data(), payload_data.size()));
165 EXPECT_EQ(0, performer_.Close());
166
167 chromeos::Blob partition_data;
168 EXPECT_TRUE(utils::ReadFile(new_part, &partition_data));
169 return partition_data;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800170 }
171
Sen Jiang2d528b42015-09-25 11:18:12 -0700172 // Calls delta performer's Write method by pretending to pass in bytes from a
173 // delta file whose metadata size is actual_metadata_size and tests if all
174 // checks are correctly performed if the install plan contains
175 // expected_metadata_size and that the result of the parsing are as per
176 // hash_checks_mandatory flag.
177 void DoMetadataSizeTest(uint64_t expected_metadata_size,
178 uint64_t actual_metadata_size,
179 bool hash_checks_mandatory) {
180 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
181 EXPECT_EQ(0, performer_.Open("/dev/null", 0, 0));
182 EXPECT_TRUE(performer_.OpenKernel("/dev/null"));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800183
Sen Jiang2d528b42015-09-25 11:18:12 -0700184 // Set a valid magic string and version number 1.
185 EXPECT_TRUE(performer_.Write("CrAU", 4));
186 uint64_t version = htobe64(kChromeOSMajorPayloadVersion);
187 EXPECT_TRUE(performer_.Write(&version, 8));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800188
Sen Jiang2d528b42015-09-25 11:18:12 -0700189 install_plan_.metadata_size = expected_metadata_size;
190 ErrorCode error_code;
191 // When filling in size in manifest, exclude the size of the 20-byte header.
192 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
193 bool result = performer_.Write(&size_in_manifest, 8, &error_code);
194 if (expected_metadata_size == actual_metadata_size ||
195 !hash_checks_mandatory) {
196 EXPECT_TRUE(result);
197 } else {
198 EXPECT_FALSE(result);
199 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
200 }
Sen Jiangd78b3892015-09-25 15:19:31 -0700201
Sen Jiang2d528b42015-09-25 11:18:12 -0700202 EXPECT_LT(performer_.Close(), 0);
203 }
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800204
Sen Jiang2d528b42015-09-25 11:18:12 -0700205 // Generates a valid delta file but tests the delta performer by suppling
206 // different metadata signatures as per metadata_signature_test flag and
207 // sees if the result of the parsing are as per hash_checks_mandatory flag.
208 void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
209 bool sign_payload,
210 bool hash_checks_mandatory) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800211
Sen Jiang2d528b42015-09-25 11:18:12 -0700212 // Loads the payload and parses the manifest.
213 chromeos::Blob payload = GeneratePayload(chromeos::Blob(),
214 vector<AnnotatedOperation>(), sign_payload,
Alex Deymocbf09892015-09-11 16:13:16 -0700215 kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800216
Sen Jiang2d528b42015-09-25 11:18:12 -0700217 LOG(INFO) << "Payload size: " << payload.size();
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800218
Sen Jiang2d528b42015-09-25 11:18:12 -0700219 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800220
Sen Jiang2d528b42015-09-25 11:18:12 -0700221 DeltaPerformer::MetadataParseResult expected_result, actual_result;
222 ErrorCode expected_error, actual_error;
223
224 // Fill up the metadata signature in install plan according to the test.
225 switch (metadata_signature_test) {
226 case kEmptyMetadataSignature:
227 install_plan_.metadata_signature.clear();
228 expected_result = DeltaPerformer::kMetadataParseError;
229 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
230 break;
231
232 case kInvalidMetadataSignature:
233 install_plan_.metadata_signature = kBogusMetadataSignature1;
234 expected_result = DeltaPerformer::kMetadataParseError;
235 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
236 break;
237
238 case kValidMetadataSignature:
239 default:
240 // Set the install plan's metadata size to be the same as the one
241 // in the manifest so that we pass the metadata size checks. Only
242 // then we can get to manifest signature checks.
243 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
244 payload.data(),
245 install_plan_.metadata_size,
246 kUnittestPrivateKeyPath,
247 &install_plan_.metadata_signature));
248 EXPECT_FALSE(install_plan_.metadata_signature.empty());
249 expected_result = DeltaPerformer::kMetadataParseSuccess;
250 expected_error = ErrorCode::kSuccess;
251 break;
252 }
253
254 // Ignore the expected result/error if hash checks are not mandatory.
255 if (!hash_checks_mandatory) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800256 expected_result = DeltaPerformer::kMetadataParseSuccess;
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700257 expected_error = ErrorCode::kSuccess;
Sen Jiang2d528b42015-09-25 11:18:12 -0700258 }
259
260 // Use the public key corresponding to the private key used above to
261 // sign the metadata.
262 EXPECT_TRUE(utils::FileExists(kUnittestPublicKeyPath));
263 performer_.set_public_key_path(kUnittestPublicKeyPath);
264
265 // Init actual_error with an invalid value so that we make sure
266 // ParsePayloadMetadata properly populates it in all cases.
267 actual_error = ErrorCode::kUmaReportedMax;
268 actual_result = performer_.ParsePayloadMetadata(payload, &actual_error);
269
270 EXPECT_EQ(expected_result, actual_result);
271 EXPECT_EQ(expected_error, actual_error);
272
273 // Check that the parsed metadata size is what's expected. This test
274 // implicitly confirms that the metadata signature is valid, if required.
275 EXPECT_EQ(install_plan_.metadata_size, performer_.GetMetadataSize());
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800276 }
277
Sen Jiangb8060e42015-09-24 17:30:50 -0700278 void SetSupportedMajorVersion(uint64_t major_version) {
279 performer_.supported_major_version_ = major_version;
280 }
Sen Jiang2d528b42015-09-25 11:18:12 -0700281 FakePrefs prefs_;
282 InstallPlan install_plan_;
283 FakeSystemState fake_system_state_;
284 DeltaPerformer performer_{&prefs_, &fake_system_state_, &install_plan_};
285};
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800286
Sen Jiang2d528b42015-09-25 11:18:12 -0700287TEST_F(DeltaPerformerTest, FullPayloadWriteTest) {
288 install_plan_.is_full_update = true;
289 chromeos::Blob expected_data = chromeos::Blob(std::begin(kRandomString),
290 std::end(kRandomString));
291 expected_data.resize(4096); // block size
292 vector<AnnotatedOperation> aops;
293 AnnotatedOperation aop;
294 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
295 aop.op.set_data_offset(0);
296 aop.op.set_data_length(expected_data.size());
297 aop.op.set_type(InstallOperation::REPLACE);
298 aops.push_back(aop);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800299
Sen Jiang2d528b42015-09-25 11:18:12 -0700300 chromeos::Blob payload_data = GeneratePayload(expected_data, aops, false,
Alex Deymocbf09892015-09-11 16:13:16 -0700301 kFullPayloadMinorVersion);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800302
Alex Deymo79715ad2015-10-02 14:27:53 -0700303 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null"));
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800304}
305
Sen Jiang2d528b42015-09-25 11:18:12 -0700306TEST_F(DeltaPerformerTest, ReplaceOperationTest) {
307 chromeos::Blob expected_data = chromeos::Blob(std::begin(kRandomString),
308 std::end(kRandomString));
309 expected_data.resize(4096); // block size
310 vector<AnnotatedOperation> aops;
311 AnnotatedOperation aop;
312 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
313 aop.op.set_data_offset(0);
314 aop.op.set_data_length(expected_data.size());
315 aop.op.set_type(InstallOperation::REPLACE);
316 aops.push_back(aop);
317
318 chromeos::Blob payload_data = GeneratePayload(expected_data, aops, false,
319 kSourceMinorPayloadVersion);
320
321 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null"));
322}
323
324TEST_F(DeltaPerformerTest, ReplaceBzOperationTest) {
325 chromeos::Blob expected_data = chromeos::Blob(std::begin(kRandomString),
326 std::end(kRandomString));
327 expected_data.resize(4096); // block size
328 chromeos::Blob bz_data;
329 EXPECT_TRUE(BzipCompress(expected_data, &bz_data));
330
331 vector<AnnotatedOperation> aops;
332 AnnotatedOperation aop;
333 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
334 aop.op.set_data_offset(0);
335 aop.op.set_data_length(bz_data.size());
336 aop.op.set_type(InstallOperation::REPLACE_BZ);
337 aops.push_back(aop);
338
339 chromeos::Blob payload_data = GeneratePayload(bz_data, aops, false,
340 kSourceMinorPayloadVersion);
341
342 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null"));
343}
344
Alex Deymo2d621a32015-10-01 11:09:01 -0700345TEST_F(DeltaPerformerTest, ReplaceXzOperationTest) {
346 chromeos::Blob xz_data(std::begin(kXzCompressedData),
347 std::end(kXzCompressedData));
348 // The compressed xz data contains only a single "a", but the operation should
349 // pad the rest of the two blocks with zeros.
350 chromeos::Blob expected_data = chromeos::Blob(4096, 0);
351 expected_data[0] = 'a';
352
353 AnnotatedOperation aop;
354 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
355 aop.op.set_data_offset(0);
356 aop.op.set_data_length(xz_data.size());
357 aop.op.set_type(InstallOperation::REPLACE_XZ);
358 vector<AnnotatedOperation> aops = {aop};
359
360 chromeos::Blob payload_data = GeneratePayload(xz_data, aops, false,
361 kSourceMinorPayloadVersion);
362
363 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null"));
364}
365
Alex Deymo79715ad2015-10-02 14:27:53 -0700366TEST_F(DeltaPerformerTest, ZeroOperationTest) {
367 chromeos::Blob existing_data = chromeos::Blob(4096 * 10, 'a');
368 chromeos::Blob expected_data = existing_data;
369 // Blocks 4, 5 and 7 should have zeros instead of 'a' after the operation is
370 // applied.
371 std::fill(expected_data.data() + 4096 * 4, expected_data.data() + 4096 * 6,
372 0);
373 std::fill(expected_data.data() + 4096 * 7, expected_data.data() + 4096 * 8,
374 0);
375
376 AnnotatedOperation aop;
377 *(aop.op.add_dst_extents()) = ExtentForRange(4, 2);
378 *(aop.op.add_dst_extents()) = ExtentForRange(7, 1);
379 aop.op.set_type(InstallOperation::ZERO);
380 vector<AnnotatedOperation> aops = {aop};
381
382 chromeos::Blob payload_data = GeneratePayload(chromeos::Blob(), aops, false,
383 kSourceMinorPayloadVersion);
384
385 EXPECT_EQ(expected_data,
386 ApplyPayloadToData(payload_data, "/dev/null", existing_data));
387}
388
Sen Jiang2d528b42015-09-25 11:18:12 -0700389TEST_F(DeltaPerformerTest, SourceCopyOperationTest) {
390 chromeos::Blob expected_data = chromeos::Blob(std::begin(kRandomString),
391 std::end(kRandomString));
392 expected_data.resize(4096); // block size
393 vector<AnnotatedOperation> aops;
394 AnnotatedOperation aop;
395 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
396 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
397 aop.op.set_type(InstallOperation::SOURCE_COPY);
398 aops.push_back(aop);
399
400 chromeos::Blob payload_data = GeneratePayload(chromeos::Blob(), aops, false,
401 kSourceMinorPayloadVersion);
402 string source_path;
403 EXPECT_TRUE(utils::MakeTempFile("Source-XXXXXX",
404 &source_path, nullptr));
405 ScopedPathUnlinker path_unlinker(source_path);
406 EXPECT_TRUE(utils::WriteFile(source_path.c_str(),
407 expected_data.data(),
408 expected_data.size()));
409
410 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source_path));
411}
412
413TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) {
Allie Wood56873452015-03-27 17:48:40 -0700414 uint64_t test[] = {1, 1, 4, 2, 0, 1};
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800415 COMPILE_ASSERT(arraysize(test) % 2 == 0, array_size_uneven);
416 const uint64_t block_size = 4096;
Allie Wood56873452015-03-27 17:48:40 -0700417 const uint64_t file_length = 4 * block_size - 13;
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800418
419 google::protobuf::RepeatedPtrField<Extent> extents;
420 for (size_t i = 0; i < arraysize(test); i += 2) {
Sen Jiang2d528b42015-09-25 11:18:12 -0700421 *(extents.Add()) = ExtentForRange(test[i], test[i + 1]);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800422 }
423
Allie Wood56873452015-03-27 17:48:40 -0700424 string expected_output = "4096:4096,16384:8192,0:4083";
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800425 string actual_output;
426 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
427 block_size,
428 file_length,
429 &actual_output));
430 EXPECT_EQ(expected_output, actual_output);
431}
Darin Petkov68c10d12010-10-14 09:24:37 -0700432
Sen Jiang2d528b42015-09-25 11:18:12 -0700433TEST_F(DeltaPerformerTest, ValidateManifestFullGoodTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800434 // The Manifest we are validating.
435 DeltaArchiveManifest manifest;
436 manifest.mutable_new_kernel_info();
437 manifest.mutable_new_rootfs_info();
Alex Deymocbf09892015-09-11 16:13:16 -0700438 manifest.set_minor_version(kFullPayloadMinorVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800439
Sen Jiang2d528b42015-09-25 11:18:12 -0700440 RunManifestValidation(manifest, true, ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800441}
442
Sen Jiang2d528b42015-09-25 11:18:12 -0700443TEST_F(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800444 // The Manifest we are validating.
445 DeltaArchiveManifest manifest;
446 manifest.mutable_old_kernel_info();
447 manifest.mutable_old_rootfs_info();
448 manifest.mutable_new_kernel_info();
449 manifest.mutable_new_rootfs_info();
450 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
451
Sen Jiang2d528b42015-09-25 11:18:12 -0700452 RunManifestValidation(manifest, false, ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800453}
454
Sen Jiang2d528b42015-09-25 11:18:12 -0700455TEST_F(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800456 // The Manifest we are validating.
457 DeltaArchiveManifest manifest;
458
Sen Jiang2d528b42015-09-25 11:18:12 -0700459 RunManifestValidation(manifest, true, ErrorCode::kSuccess);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800460}
461
Sen Jiang2d528b42015-09-25 11:18:12 -0700462TEST_F(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800463 // The Manifest we are validating.
464 DeltaArchiveManifest manifest;
465
Sen Jiang2d528b42015-09-25 11:18:12 -0700466 RunManifestValidation(manifest, false,
467 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800468}
469
Sen Jiang2d528b42015-09-25 11:18:12 -0700470TEST_F(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800471 // The Manifest we are validating.
472 DeltaArchiveManifest manifest;
473 manifest.mutable_old_kernel_info();
474 manifest.mutable_new_kernel_info();
475 manifest.mutable_new_rootfs_info();
476 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
477
Sen Jiang2d528b42015-09-25 11:18:12 -0700478 RunManifestValidation(manifest, true, ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800479}
480
Sen Jiang2d528b42015-09-25 11:18:12 -0700481TEST_F(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800482 // The Manifest we are validating.
483 DeltaArchiveManifest manifest;
484 manifest.mutable_old_rootfs_info();
485 manifest.mutable_new_kernel_info();
486 manifest.mutable_new_rootfs_info();
487 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
488
Sen Jiang2d528b42015-09-25 11:18:12 -0700489 RunManifestValidation(manifest, true, ErrorCode::kPayloadMismatchedType);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800490}
491
Sen Jiang2d528b42015-09-25 11:18:12 -0700492TEST_F(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
Don Garrettb8dd1d92013-11-22 17:40:02 -0800493 // The Manifest we are validating.
494 DeltaArchiveManifest manifest;
495
496 // Generate a bad version number.
497 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
498 10000);
499
Sen Jiang2d528b42015-09-25 11:18:12 -0700500 RunManifestValidation(manifest, false,
501 ErrorCode::kUnsupportedMinorPayloadVersion);
Don Garrettb8dd1d92013-11-22 17:40:02 -0800502}
503
Sen Jiangb8060e42015-09-24 17:30:50 -0700504TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeTest) {
505 SetSupportedMajorVersion(kBrilloMajorPayloadVersion);
506 EXPECT_EQ(0, performer_.Open("/dev/null", 0, 0));
507 EXPECT_TRUE(performer_.OpenKernel("/dev/null"));
508 EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
509
510 uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
511 EXPECT_TRUE(performer_.Write(&major_version, 8));
512
513 uint64_t manifest_size = rand() % 256;
514 uint64_t manifest_size_be = htobe64(manifest_size);
515 EXPECT_TRUE(performer_.Write(&manifest_size_be, 8));
516
517 uint32_t metadata_signature_size = rand() % 256;
518 uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
519 EXPECT_TRUE(performer_.Write(&metadata_signature_size_be, 4));
520
521 EXPECT_LT(performer_.Close(), 0);
522
523 EXPECT_TRUE(performer_.IsHeaderParsed());
524 EXPECT_EQ(kBrilloMajorPayloadVersion, performer_.GetMajorVersion());
525 uint64_t manifest_offset;
526 EXPECT_TRUE(performer_.GetManifestOffset(&manifest_offset));
527 EXPECT_EQ(24, manifest_offset); // 4 + 8 + 8 + 4
528 EXPECT_EQ(24 + manifest_size + metadata_signature_size,
529 performer_.GetMetadataSize());
530}
531
Sen Jiang2d528b42015-09-25 11:18:12 -0700532TEST_F(DeltaPerformerTest, BadDeltaMagicTest) {
533 EXPECT_EQ(0, performer_.Open("/dev/null", 0, 0));
534 EXPECT_TRUE(performer_.OpenKernel("/dev/null"));
535 EXPECT_TRUE(performer_.Write("junk", 4));
Sen Jiang2d528b42015-09-25 11:18:12 -0700536 EXPECT_FALSE(performer_.Write("morejunk", 8));
537 EXPECT_LT(performer_.Close(), 0);
Darin Petkov934bb412010-11-18 11:21:35 -0800538}
539
Sen Jiang2d528b42015-09-25 11:18:12 -0700540TEST_F(DeltaPerformerTest, WriteUpdatesPayloadState) {
541 EXPECT_EQ(0, performer_.Open("/dev/null", 0, 0));
542 EXPECT_TRUE(performer_.OpenKernel("/dev/null"));
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800543
Sen Jiang2d528b42015-09-25 11:18:12 -0700544 EXPECT_CALL(*(fake_system_state_.mock_payload_state()),
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800545 DownloadProgress(4)).Times(1);
Sen Jiang2d528b42015-09-25 11:18:12 -0700546 EXPECT_CALL(*(fake_system_state_.mock_payload_state()),
Sen Jiangb8060e42015-09-24 17:30:50 -0700547 DownloadProgress(8)).Times(1);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800548
Sen Jiang2d528b42015-09-25 11:18:12 -0700549 EXPECT_TRUE(performer_.Write("junk", 4));
Sen Jiang2d528b42015-09-25 11:18:12 -0700550 EXPECT_FALSE(performer_.Write("morejunk", 8));
551 EXPECT_LT(performer_.Close(), 0);
Jay Srinivasan2b5a0f02012-12-19 17:25:56 -0800552}
553
Sen Jiang2d528b42015-09-25 11:18:12 -0700554TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800555 DoMetadataSizeTest(0, 75456, true);
Jay Srinivasan51dcf262012-09-13 17:24:32 -0700556}
557
Sen Jiang2d528b42015-09-25 11:18:12 -0700558TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800559 DoMetadataSizeTest(0, 123456, false);
560}
561
Sen Jiang2d528b42015-09-25 11:18:12 -0700562TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800563 DoMetadataSizeTest(13000, 140000, true);
564}
565
Sen Jiang2d528b42015-09-25 11:18:12 -0700566TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800567 DoMetadataSizeTest(40000, 50000, false);
568}
569
Sen Jiang2d528b42015-09-25 11:18:12 -0700570TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800571 DoMetadataSizeTest(85376, 85376, true);
572}
573
Sen Jiang2d528b42015-09-25 11:18:12 -0700574TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700575 DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800576}
577
Sen Jiang2d528b42015-09-25 11:18:12 -0700578TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700579 DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800580}
581
Sen Jiang2d528b42015-09-25 11:18:12 -0700582TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700583 DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800584}
585
Sen Jiang2d528b42015-09-25 11:18:12 -0700586TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700587 DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800588}
589
Sen Jiang2d528b42015-09-25 11:18:12 -0700590TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700591 DoMetadataSignatureTest(kValidMetadataSignature, false, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800592}
593
Sen Jiang2d528b42015-09-25 11:18:12 -0700594TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700595 DoMetadataSignatureTest(kValidMetadataSignature, true, true);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800596}
597
Sen Jiang2d528b42015-09-25 11:18:12 -0700598TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
Sen Jiangd78b3892015-09-25 15:19:31 -0700599 DoMetadataSignatureTest(kValidMetadataSignature, true, false);
Jay Srinivasan738fdf32012-12-07 17:40:54 -0800600}
601
Sen Jiang2d528b42015-09-25 11:18:12 -0700602TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) {
David Zeuthene7f89172013-10-31 10:21:04 -0700603 base::FilePath key_path;
604
605 // The result of the GetPublicKeyResponse() method is based on three things
606 //
607 // 1. Whether it's an official build; and
608 // 2. Whether the Public RSA key to be used is in the root filesystem; and
Alex Vakulenko072359c2014-07-18 11:41:07 -0700609 // 3. Whether the response has a public key
David Zeuthene7f89172013-10-31 10:21:04 -0700610 //
611 // We test all eight combinations to ensure that we only use the
612 // public key in the response if
613 //
614 // a. it's not an official build; and
615 // b. there is no key in the root filesystem.
616
Sen Jiang2d528b42015-09-25 11:18:12 -0700617 FakeHardware* fake_hardware = fake_system_state_.fake_hardware();
David Zeuthene7f89172013-10-31 10:21:04 -0700618
619 string temp_dir;
Gilad Arnolda6742b32014-01-11 00:18:34 -0800620 EXPECT_TRUE(utils::MakeTempDirectory("PublicKeyFromResponseTests.XXXXXX",
David Zeuthene7f89172013-10-31 10:21:04 -0700621 &temp_dir));
622 string non_existing_file = temp_dir + "/non-existing";
623 string existing_file = temp_dir + "/existing";
Alex Vakulenko75039d72014-03-25 12:36:28 -0700624 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
David Zeuthene7f89172013-10-31 10:21:04 -0700625
626 // Non-official build, non-existing public-key, key in response -> true
Don Garrett6646b442013-11-13 15:29:11 -0800627 fake_hardware->SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700628 performer_.public_key_path_ = non_existing_file;
629 install_plan_.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
630 EXPECT_TRUE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700631 EXPECT_FALSE(key_path.empty());
632 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
633 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -0800634 fake_hardware->SetIsOfficialBuild(true);
Sen Jiang2d528b42015-09-25 11:18:12 -0700635 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700636
637 // Non-official build, existing public-key, key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -0800638 fake_hardware->SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700639 performer_.public_key_path_ = existing_file;
640 install_plan_.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
641 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700642 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -0800643 fake_hardware->SetIsOfficialBuild(true);
Sen Jiang2d528b42015-09-25 11:18:12 -0700644 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700645
646 // Non-official build, non-existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -0800647 fake_hardware->SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700648 performer_.public_key_path_ = non_existing_file;
649 install_plan_.public_key_rsa = "";
650 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700651 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -0800652 fake_hardware->SetIsOfficialBuild(true);
Sen Jiang2d528b42015-09-25 11:18:12 -0700653 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700654
655 // Non-official build, existing public-key, no key in response -> false
Don Garrett6646b442013-11-13 15:29:11 -0800656 fake_hardware->SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700657 performer_.public_key_path_ = existing_file;
658 install_plan_.public_key_rsa = "";
659 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700660 // Same with official build -> false
Don Garrett6646b442013-11-13 15:29:11 -0800661 fake_hardware->SetIsOfficialBuild(true);
Sen Jiang2d528b42015-09-25 11:18:12 -0700662 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700663
664 // Non-official build, non-existing public-key, key in response
665 // but invalid base64 -> false
Don Garrett6646b442013-11-13 15:29:11 -0800666 fake_hardware->SetIsOfficialBuild(false);
Sen Jiang2d528b42015-09-25 11:18:12 -0700667 performer_.public_key_path_ = non_existing_file;
668 install_plan_.public_key_rsa = "not-valid-base64";
669 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
David Zeuthene7f89172013-10-31 10:21:04 -0700670
Alex Deymo10875d92014-11-10 21:52:57 -0800671 EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
David Zeuthene7f89172013-10-31 10:21:04 -0700672}
673
Alex Deymocbf09892015-09-11 16:13:16 -0700674TEST_F(DeltaPerformerTest, ConfVersionsMatch) {
675 // Test that the versions in update_engine.conf that is installed to the
676 // image match the supported delta versions in the update engine.
Allie Wood78750a42015-02-11 15:42:11 -0800677 uint32_t minor_version;
Alex Deymob42b98d2015-07-06 17:42:38 -0700678 chromeos::KeyValueStore store;
679 EXPECT_TRUE(store.Load(base::FilePath("update_engine.conf")));
680 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
681 EXPECT_EQ(DeltaPerformer::kSupportedMinorPayloadVersion, minor_version);
Alex Deymocbf09892015-09-11 16:13:16 -0700682
683 string major_version_str;
684 uint64_t major_version;
685 EXPECT_TRUE(store.GetString("PAYLOAD_MAJOR_VERSION", &major_version_str));
686 EXPECT_TRUE(base::StringToUint64(major_version_str, &major_version));
687 EXPECT_EQ(DeltaPerformer::kSupportedMajorPayloadVersion, major_version);
Allie Wood78750a42015-02-11 15:42:11 -0800688}
689
Andrew de los Reyes09e56d62010-04-23 13:45:53 -0700690} // namespace chromeos_update_engine