1 //
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 //
16
17 #include "update_engine/payload_consumer/delta_performer.h"
18
19 #include <endian.h>
20 #include <inttypes.h>
21
22 #include <string>
23 #include <vector>
24
25 #include <base/files/file_path.h>
26 #include <base/files/file_util.h>
27 #include <base/files/scoped_temp_dir.h>
28 #include <base/strings/string_number_conversions.h>
29 #include <base/strings/string_util.h>
30 #include <base/strings/stringprintf.h>
31 #include <gmock/gmock.h>
32 #include <google/protobuf/repeated_field.h>
33 #include <gtest/gtest.h>
34
35 #include "update_engine/common/constants.h"
36 #include "update_engine/common/fake_boot_control.h"
37 #include "update_engine/common/fake_hardware.h"
38 #include "update_engine/common/fake_prefs.h"
39 #include "update_engine/common/test_utils.h"
40 #include "update_engine/common/utils.h"
41 #include "update_engine/payload_consumer/mock_download_action.h"
42 #include "update_engine/payload_consumer/payload_constants.h"
43 #include "update_engine/payload_generator/bzip.h"
44 #include "update_engine/payload_generator/extent_ranges.h"
45 #include "update_engine/payload_generator/payload_file.h"
46 #include "update_engine/payload_generator/payload_signer.h"
47 #include "update_engine/update_metadata.pb.h"
48
49 namespace chromeos_update_engine {
50
51 using std::string;
52 using std::vector;
53 using test_utils::GetBuildArtifactsPath;
54 using test_utils::System;
55 using test_utils::kRandomString;
56 using testing::_;
57
58 extern const char* kUnittestPrivateKeyPath;
59 extern const char* kUnittestPublicKeyPath;
60
61 namespace {
62
63 const char kBogusMetadataSignature1[] =
64 "awSFIUdUZz2VWFiR+ku0Pj00V7bPQPQFYQSXjEXr3vaw3TE4xHV5CraY3/YrZpBv"
65 "J5z4dSBskoeuaO1TNC/S6E05t+yt36tE4Fh79tMnJ/z9fogBDXWgXLEUyG78IEQr"
66 "YH6/eBsQGT2RJtBgXIXbZ9W+5G9KmGDoPOoiaeNsDuqHiBc/58OFsrxskH8E6vMS"
67 "BmMGGk82mvgzic7ApcoURbCGey1b3Mwne/hPZ/bb9CIyky8Og9IfFMdL2uAweOIR"
68 "fjoTeLYZpt+WN65Vu7jJ0cQN8e1y+2yka5112wpRf/LLtPgiAjEZnsoYpLUd7CoV"
69 "pLRtClp97kN2+tXGNBQqkA==";
70
71 // Different options that determine what we should fill into the
72 // install_plan.metadata_signature to simulate the contents received in the
73 // Omaha response.
74 enum MetadataSignatureTest {
75 kEmptyMetadataSignature,
76 kInvalidMetadataSignature,
77 kValidMetadataSignature,
78 };
79
80 // Compressed data without checksum, generated with:
81 // echo -n a | xz -9 --check=none | hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
82 const uint8_t kXzCompressedData[] = {
83 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00, 0x00, 0xff, 0x12, 0xd9, 0x41,
84 0x02, 0x00, 0x21, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x10, 0xcf, 0x58, 0xcc,
85 0x01, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x01,
86 0xad, 0xa6, 0x58, 0x04, 0x06, 0x72, 0x9e, 0x7a, 0x01, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x59, 0x5a,
88 };
89
90 // Gzipped 'abc', generated with:
91 // echo -n abc | minigzip | hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
92 const uint8_t kSourceGzippedData[] = {
93 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4b, 0x4c,
94 0x4a, 0x06, 0x00, 0xc2, 0x41, 0x24, 0x35, 0x03, 0x00, 0x00, 0x00,
95 };
96
97 // Gzipped 'def', generated with:
98 // echo -n def | minigzip | hexdump -v -e '" " 12/1 "0x%02x, " "\n"'
99 const uint8_t kTargetGzippedData[] = {
100 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4b, 0x49,
101 0x4d, 0x03, 0x00, 0x61, 0xe1, 0xc4, 0x0c, 0x03, 0x00, 0x00, 0x00,
102 };
103
104 // Imgdiff data, generated with:
105 // echo -n abc | minigzip > abc && truncate -s 4096 abc
106 // echo -n def | minigzip > def && truncate -s 4096 def
107 // imgdiff abc def patch && hexdump -v -e '" " 12/1 "0x%02x, " "\n"' patch
108 const uint8_t kImgdiffData[] = {
109 0x49, 0x4d, 0x47, 0x44, 0x49, 0x46, 0x46, 0x32, 0x03, 0x00, 0x00, 0x00,
110 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1f, 0x8b, 0x08, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xf1, 0xff,
116 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x0f,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x42, 0x53, 0x44, 0x49, 0x46, 0x46, 0x34, 0x30, 0x2a, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5a,
122 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xc3, 0xc8, 0xfb, 0x1f,
123 0x00, 0x00, 0x01, 0x40, 0x00, 0x5c, 0x00, 0x20, 0x00, 0x30, 0xcd, 0x34,
124 0x12, 0x34, 0x54, 0x60, 0x5c, 0xce, 0x2e, 0xe4, 0x8a, 0x70, 0xa1, 0x21,
125 0x87, 0x91, 0xf6, 0x3e, 0x42, 0x5a, 0x68, 0x39, 0x17, 0x72, 0x45, 0x38,
126 0x50, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41,
127 0x59, 0x26, 0x53, 0x59, 0x42, 0x3c, 0xb0, 0xf9, 0x00, 0x00, 0x00, 0x01,
128 0x00, 0x07, 0x00, 0x20, 0x00, 0x21, 0x98, 0x19, 0x84, 0x61, 0x77, 0x24,
129 0x53, 0x85, 0x09, 0x04, 0x23, 0xcb, 0x0f, 0x90, 0x42, 0x53, 0x44, 0x49,
130 0x46, 0x46, 0x34, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x0f, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26,
133 0x53, 0x59, 0x6f, 0x02, 0x77, 0xf3, 0x00, 0x00, 0x07, 0x40, 0x41, 0xe0,
134 0x10, 0xc0, 0x00, 0x00, 0x02, 0x20, 0x00, 0x20, 0x00, 0x21, 0x29, 0xa3,
135 0x10, 0x86, 0x03, 0x84, 0x04, 0xae, 0x5f, 0x17, 0x72, 0x45, 0x38, 0x50,
136 0x90, 0x6f, 0x02, 0x77, 0xf3, 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59,
137 0x26, 0x53, 0x59, 0x71, 0x62, 0xbd, 0xa7, 0x00, 0x00, 0x20, 0x40, 0x32,
138 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x00, 0x48, 0x20, 0x00,
139 0x30, 0xc0, 0x02, 0xa5, 0x19, 0xa5, 0x92, 0x6f, 0xc2, 0x5d, 0xac, 0x0e,
140 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x71, 0x62, 0xbd, 0xa7, 0x42, 0x5a,
141 0x68, 0x39, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x00, 0x00, 0x00, 0x00,
142 };
143
144 } // namespace
145
146 class DeltaPerformerTest : public ::testing::Test {
147 protected:
SetUp()148 void SetUp() override {
149 install_plan_.source_slot = 0;
150 install_plan_.target_slot = 1;
151 EXPECT_CALL(mock_delegate_, ShouldCancel(_))
152 .WillRepeatedly(testing::Return(false));
153 }
154
155 // Test helper placed where it can easily be friended from DeltaPerformer.
RunManifestValidation(const DeltaArchiveManifest & manifest,uint64_t major_version,InstallPayloadType payload_type,ErrorCode expected)156 void RunManifestValidation(const DeltaArchiveManifest& manifest,
157 uint64_t major_version,
158 InstallPayloadType payload_type,
159 ErrorCode expected) {
160 install_plan_.payload_type = payload_type;
161
162 // The Manifest we are validating.
163 performer_.manifest_.CopyFrom(manifest);
164 performer_.major_payload_version_ = major_version;
165
166 EXPECT_EQ(expected, performer_.ValidateManifest());
167 }
168
GeneratePayload(const brillo::Blob & blob_data,const vector<AnnotatedOperation> & aops,bool sign_payload)169 brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
170 const vector<AnnotatedOperation>& aops,
171 bool sign_payload) {
172 return GeneratePayload(blob_data, aops, sign_payload,
173 DeltaPerformer::kSupportedMajorPayloadVersion,
174 DeltaPerformer::kSupportedMinorPayloadVersion);
175 }
176
GeneratePayload(const brillo::Blob & blob_data,const vector<AnnotatedOperation> & aops,bool sign_payload,uint64_t major_version,uint32_t minor_version)177 brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
178 const vector<AnnotatedOperation>& aops,
179 bool sign_payload,
180 uint64_t major_version,
181 uint32_t minor_version) {
182 string blob_path;
183 EXPECT_TRUE(utils::MakeTempFile("Blob-XXXXXX", &blob_path, nullptr));
184 ScopedPathUnlinker blob_unlinker(blob_path);
185 EXPECT_TRUE(utils::WriteFile(blob_path.c_str(),
186 blob_data.data(),
187 blob_data.size()));
188
189 PayloadGenerationConfig config;
190 config.version.major = major_version;
191 config.version.minor = minor_version;
192
193 PayloadFile payload;
194 EXPECT_TRUE(payload.Init(config));
195
196 PartitionConfig old_part(kLegacyPartitionNameRoot);
197 if (minor_version != kFullPayloadMinorVersion) {
198 // When generating a delta payload we need to include the old partition
199 // information to mark it as a delta payload.
200 old_part.path = "/dev/null";
201 old_part.size = 0;
202 }
203 PartitionConfig new_part(kLegacyPartitionNameRoot);
204 new_part.path = "/dev/zero";
205 new_part.size = 1234;
206
207 payload.AddPartition(old_part, new_part, aops);
208
209 // We include a kernel partition without operations.
210 old_part.name = kLegacyPartitionNameKernel;
211 new_part.name = kLegacyPartitionNameKernel;
212 new_part.size = 0;
213 payload.AddPartition(old_part, new_part, {});
214
215 string payload_path;
216 EXPECT_TRUE(utils::MakeTempFile("Payload-XXXXXX", &payload_path, nullptr));
217 ScopedPathUnlinker payload_unlinker(payload_path);
218 string private_key =
219 sign_payload ? GetBuildArtifactsPath(kUnittestPrivateKeyPath) : "";
220 EXPECT_TRUE(payload.WritePayload(
221 payload_path, blob_path, private_key, &install_plan_.metadata_size));
222
223 brillo::Blob payload_data;
224 EXPECT_TRUE(utils::ReadFile(payload_path, &payload_data));
225 return payload_data;
226 }
227
228 // Apply |payload_data| on partition specified in |source_path|.
229 // Expect result of performer_.Write() to be |expect_success|.
230 // Returns the result of the payload application.
ApplyPayload(const brillo::Blob & payload_data,const string & source_path,bool expect_success)231 brillo::Blob ApplyPayload(const brillo::Blob& payload_data,
232 const string& source_path,
233 bool expect_success) {
234 return ApplyPayloadToData(payload_data, source_path, brillo::Blob(),
235 expect_success);
236 }
237
238 // Apply the payload provided in |payload_data| reading from the |source_path|
239 // file and writing the contents to a new partition. The existing data in the
240 // new target file are set to |target_data| before applying the payload.
241 // Expect result of performer_.Write() to be |expect_success|.
242 // Returns the result of the payload application.
ApplyPayloadToData(const brillo::Blob & payload_data,const string & source_path,const brillo::Blob & target_data,bool expect_success)243 brillo::Blob ApplyPayloadToData(const brillo::Blob& payload_data,
244 const string& source_path,
245 const brillo::Blob& target_data,
246 bool expect_success) {
247 string new_part;
248 EXPECT_TRUE(utils::MakeTempFile("Partition-XXXXXX", &new_part, nullptr));
249 ScopedPathUnlinker partition_unlinker(new_part);
250 EXPECT_TRUE(utils::WriteFile(new_part.c_str(), target_data.data(),
251 target_data.size()));
252
253 // We installed the operations only in the rootfs partition, but the
254 // delta performer needs to access all the partitions.
255 fake_boot_control_.SetPartitionDevice(
256 kLegacyPartitionNameRoot, install_plan_.target_slot, new_part);
257 fake_boot_control_.SetPartitionDevice(
258 kLegacyPartitionNameRoot, install_plan_.source_slot, source_path);
259 fake_boot_control_.SetPartitionDevice(
260 kLegacyPartitionNameKernel, install_plan_.target_slot, "/dev/null");
261 fake_boot_control_.SetPartitionDevice(
262 kLegacyPartitionNameKernel, install_plan_.source_slot, "/dev/null");
263
264 EXPECT_EQ(expect_success,
265 performer_.Write(payload_data.data(), payload_data.size()));
266 EXPECT_EQ(0, performer_.Close());
267
268 brillo::Blob partition_data;
269 EXPECT_TRUE(utils::ReadFile(new_part, &partition_data));
270 return partition_data;
271 }
272
273 // Calls delta performer's Write method by pretending to pass in bytes from a
274 // delta file whose metadata size is actual_metadata_size and tests if all
275 // checks are correctly performed if the install plan contains
276 // expected_metadata_size and that the result of the parsing are as per
277 // hash_checks_mandatory flag.
DoMetadataSizeTest(uint64_t expected_metadata_size,uint64_t actual_metadata_size,bool hash_checks_mandatory)278 void DoMetadataSizeTest(uint64_t expected_metadata_size,
279 uint64_t actual_metadata_size,
280 bool hash_checks_mandatory) {
281 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
282
283 // Set a valid magic string and version number 1.
284 EXPECT_TRUE(performer_.Write("CrAU", 4));
285 uint64_t version = htobe64(kChromeOSMajorPayloadVersion);
286 EXPECT_TRUE(performer_.Write(&version, 8));
287
288 install_plan_.metadata_size = expected_metadata_size;
289 ErrorCode error_code;
290 // When filling in size in manifest, exclude the size of the 20-byte header.
291 uint64_t size_in_manifest = htobe64(actual_metadata_size - 20);
292 bool result = performer_.Write(&size_in_manifest, 8, &error_code);
293 if (expected_metadata_size == actual_metadata_size ||
294 !hash_checks_mandatory) {
295 EXPECT_TRUE(result);
296 } else {
297 EXPECT_FALSE(result);
298 EXPECT_EQ(ErrorCode::kDownloadInvalidMetadataSize, error_code);
299 }
300
301 EXPECT_LT(performer_.Close(), 0);
302 }
303
304 // Generates a valid delta file but tests the delta performer by suppling
305 // different metadata signatures as per metadata_signature_test flag and
306 // sees if the result of the parsing are as per hash_checks_mandatory flag.
DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,bool sign_payload,bool hash_checks_mandatory)307 void DoMetadataSignatureTest(MetadataSignatureTest metadata_signature_test,
308 bool sign_payload,
309 bool hash_checks_mandatory) {
310 // Loads the payload and parses the manifest.
311 brillo::Blob payload = GeneratePayload(brillo::Blob(),
312 vector<AnnotatedOperation>(), sign_payload,
313 kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
314
315 LOG(INFO) << "Payload size: " << payload.size();
316
317 install_plan_.hash_checks_mandatory = hash_checks_mandatory;
318
319 DeltaPerformer::MetadataParseResult expected_result, actual_result;
320 ErrorCode expected_error, actual_error;
321
322 // Fill up the metadata signature in install plan according to the test.
323 switch (metadata_signature_test) {
324 case kEmptyMetadataSignature:
325 install_plan_.metadata_signature.clear();
326 expected_result = DeltaPerformer::kMetadataParseError;
327 expected_error = ErrorCode::kDownloadMetadataSignatureMissingError;
328 break;
329
330 case kInvalidMetadataSignature:
331 install_plan_.metadata_signature = kBogusMetadataSignature1;
332 expected_result = DeltaPerformer::kMetadataParseError;
333 expected_error = ErrorCode::kDownloadMetadataSignatureMismatch;
334 break;
335
336 case kValidMetadataSignature:
337 default:
338 // Set the install plan's metadata size to be the same as the one
339 // in the manifest so that we pass the metadata size checks. Only
340 // then we can get to manifest signature checks.
341 ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
342 payload.data(),
343 install_plan_.metadata_size,
344 GetBuildArtifactsPath(kUnittestPrivateKeyPath),
345 &install_plan_.metadata_signature));
346 EXPECT_FALSE(install_plan_.metadata_signature.empty());
347 expected_result = DeltaPerformer::kMetadataParseSuccess;
348 expected_error = ErrorCode::kSuccess;
349 break;
350 }
351
352 // Ignore the expected result/error if hash checks are not mandatory.
353 if (!hash_checks_mandatory) {
354 expected_result = DeltaPerformer::kMetadataParseSuccess;
355 expected_error = ErrorCode::kSuccess;
356 }
357
358 // Use the public key corresponding to the private key used above to
359 // sign the metadata.
360 string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
361 EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
362 performer_.set_public_key_path(public_key_path);
363
364 // Init actual_error with an invalid value so that we make sure
365 // ParsePayloadMetadata properly populates it in all cases.
366 actual_error = ErrorCode::kUmaReportedMax;
367 actual_result = performer_.ParsePayloadMetadata(payload, &actual_error);
368
369 EXPECT_EQ(expected_result, actual_result);
370 EXPECT_EQ(expected_error, actual_error);
371
372 // Check that the parsed metadata size is what's expected. This test
373 // implicitly confirms that the metadata signature is valid, if required.
374 EXPECT_EQ(install_plan_.metadata_size, performer_.GetMetadataSize());
375 }
376
SetSupportedMajorVersion(uint64_t major_version)377 void SetSupportedMajorVersion(uint64_t major_version) {
378 performer_.supported_major_version_ = major_version;
379 }
380 FakePrefs prefs_;
381 InstallPlan install_plan_;
382 FakeBootControl fake_boot_control_;
383 FakeHardware fake_hardware_;
384 MockDownloadActionDelegate mock_delegate_;
385 DeltaPerformer performer_{
386 &prefs_, &fake_boot_control_, &fake_hardware_, &mock_delegate_, &install_plan_};
387 };
388
TEST_F(DeltaPerformerTest,FullPayloadWriteTest)389 TEST_F(DeltaPerformerTest, FullPayloadWriteTest) {
390 install_plan_.payload_type = InstallPayloadType::kFull;
391 brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
392 std::end(kRandomString));
393 expected_data.resize(4096); // block size
394 vector<AnnotatedOperation> aops;
395 AnnotatedOperation aop;
396 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
397 aop.op.set_data_offset(0);
398 aop.op.set_data_length(expected_data.size());
399 aop.op.set_type(InstallOperation::REPLACE);
400 aops.push_back(aop);
401
402 brillo::Blob payload_data = GeneratePayload(expected_data, aops, false,
403 kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
404
405 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
406 }
407
TEST_F(DeltaPerformerTest,ShouldCancelTest)408 TEST_F(DeltaPerformerTest, ShouldCancelTest) {
409 install_plan_.payload_type = InstallPayloadType::kFull;
410 brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
411 std::end(kRandomString));
412 expected_data.resize(4096); // block size
413 vector<AnnotatedOperation> aops;
414 AnnotatedOperation aop;
415 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
416 aop.op.set_data_offset(0);
417 aop.op.set_data_length(expected_data.size());
418 aop.op.set_type(InstallOperation::REPLACE);
419 aops.push_back(aop);
420
421 brillo::Blob payload_data = GeneratePayload(expected_data, aops, false,
422 kChromeOSMajorPayloadVersion, kFullPayloadMinorVersion);
423
424 testing::Mock::VerifyAndClearExpectations(&mock_delegate_);
425 EXPECT_CALL(mock_delegate_, ShouldCancel(_))
426 .WillOnce(
427 testing::DoAll(testing::SetArgumentPointee<0>(ErrorCode::kError),
428 testing::Return(true)));
429
430 ApplyPayload(payload_data, "/dev/null", false);
431 }
432
TEST_F(DeltaPerformerTest,ReplaceOperationTest)433 TEST_F(DeltaPerformerTest, ReplaceOperationTest) {
434 brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
435 std::end(kRandomString));
436 expected_data.resize(4096); // block size
437 vector<AnnotatedOperation> aops;
438 AnnotatedOperation aop;
439 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
440 aop.op.set_data_offset(0);
441 aop.op.set_data_length(expected_data.size());
442 aop.op.set_type(InstallOperation::REPLACE);
443 aops.push_back(aop);
444
445 brillo::Blob payload_data = GeneratePayload(expected_data, aops, false);
446
447 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
448 }
449
TEST_F(DeltaPerformerTest,ReplaceBzOperationTest)450 TEST_F(DeltaPerformerTest, ReplaceBzOperationTest) {
451 brillo::Blob expected_data = brillo::Blob(std::begin(kRandomString),
452 std::end(kRandomString));
453 expected_data.resize(4096); // block size
454 brillo::Blob bz_data;
455 EXPECT_TRUE(BzipCompress(expected_data, &bz_data));
456
457 vector<AnnotatedOperation> aops;
458 AnnotatedOperation aop;
459 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
460 aop.op.set_data_offset(0);
461 aop.op.set_data_length(bz_data.size());
462 aop.op.set_type(InstallOperation::REPLACE_BZ);
463 aops.push_back(aop);
464
465 brillo::Blob payload_data = GeneratePayload(bz_data, aops, false);
466
467 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
468 }
469
TEST_F(DeltaPerformerTest,ReplaceXzOperationTest)470 TEST_F(DeltaPerformerTest, ReplaceXzOperationTest) {
471 brillo::Blob xz_data(std::begin(kXzCompressedData),
472 std::end(kXzCompressedData));
473 // The compressed xz data contains only a single "a", but the operation should
474 // pad the rest of the two blocks with zeros.
475 brillo::Blob expected_data = brillo::Blob(4096, 0);
476 expected_data[0] = 'a';
477
478 AnnotatedOperation aop;
479 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
480 aop.op.set_data_offset(0);
481 aop.op.set_data_length(xz_data.size());
482 aop.op.set_type(InstallOperation::REPLACE_XZ);
483 vector<AnnotatedOperation> aops = {aop};
484
485 brillo::Blob payload_data = GeneratePayload(xz_data, aops, false);
486
487 EXPECT_EQ(expected_data, ApplyPayload(payload_data, "/dev/null", true));
488 }
489
TEST_F(DeltaPerformerTest,ZeroOperationTest)490 TEST_F(DeltaPerformerTest, ZeroOperationTest) {
491 brillo::Blob existing_data = brillo::Blob(4096 * 10, 'a');
492 brillo::Blob expected_data = existing_data;
493 // Blocks 4, 5 and 7 should have zeros instead of 'a' after the operation is
494 // applied.
495 std::fill(expected_data.data() + 4096 * 4, expected_data.data() + 4096 * 6,
496 0);
497 std::fill(expected_data.data() + 4096 * 7, expected_data.data() + 4096 * 8,
498 0);
499
500 AnnotatedOperation aop;
501 *(aop.op.add_dst_extents()) = ExtentForRange(4, 2);
502 *(aop.op.add_dst_extents()) = ExtentForRange(7, 1);
503 aop.op.set_type(InstallOperation::ZERO);
504 vector<AnnotatedOperation> aops = {aop};
505
506 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), aops, false);
507
508 EXPECT_EQ(expected_data,
509 ApplyPayloadToData(payload_data, "/dev/null", existing_data, true));
510 }
511
TEST_F(DeltaPerformerTest,SourceCopyOperationTest)512 TEST_F(DeltaPerformerTest, SourceCopyOperationTest) {
513 brillo::Blob expected_data(std::begin(kRandomString),
514 std::end(kRandomString));
515 expected_data.resize(4096); // block size
516 AnnotatedOperation aop;
517 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
518 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
519 aop.op.set_type(InstallOperation::SOURCE_COPY);
520 brillo::Blob src_hash;
521 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
522 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
523
524 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
525
526 string source_path;
527 EXPECT_TRUE(utils::MakeTempFile("Source-XXXXXX",
528 &source_path, nullptr));
529 ScopedPathUnlinker path_unlinker(source_path);
530 EXPECT_TRUE(utils::WriteFile(source_path.c_str(),
531 expected_data.data(),
532 expected_data.size()));
533
534 EXPECT_EQ(expected_data, ApplyPayload(payload_data, source_path, true));
535 }
536
TEST_F(DeltaPerformerTest,ImgdiffOperationTest)537 TEST_F(DeltaPerformerTest, ImgdiffOperationTest) {
538 brillo::Blob imgdiff_data(std::begin(kImgdiffData), std::end(kImgdiffData));
539
540 AnnotatedOperation aop;
541 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
542 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
543 aop.op.set_data_offset(0);
544 aop.op.set_data_length(imgdiff_data.size());
545 aop.op.set_type(InstallOperation::IMGDIFF);
546
547 brillo::Blob payload_data = GeneratePayload(imgdiff_data, {aop}, false);
548
549 string source_path;
550 EXPECT_TRUE(utils::MakeTempFile("Source-XXXXXX", &source_path, nullptr));
551 ScopedPathUnlinker path_unlinker(source_path);
552 brillo::Blob source_data(std::begin(kSourceGzippedData),
553 std::end(kSourceGzippedData));
554 source_data.resize(4096); // block size
555 EXPECT_TRUE(utils::WriteFile(
556 source_path.c_str(), source_data.data(), source_data.size()));
557
558 brillo::Blob target_data(std::begin(kTargetGzippedData),
559 std::end(kTargetGzippedData));
560 target_data.resize(4096); // block size
561 EXPECT_EQ(target_data, ApplyPayload(payload_data, source_path, true));
562 }
563
TEST_F(DeltaPerformerTest,SourceHashMismatchTest)564 TEST_F(DeltaPerformerTest, SourceHashMismatchTest) {
565 brillo::Blob expected_data = {'f', 'o', 'o'};
566 brillo::Blob actual_data = {'b', 'a', 'r'};
567 expected_data.resize(4096); // block size
568 actual_data.resize(4096); // block size
569
570 AnnotatedOperation aop;
571 *(aop.op.add_src_extents()) = ExtentForRange(0, 1);
572 *(aop.op.add_dst_extents()) = ExtentForRange(0, 1);
573 aop.op.set_type(InstallOperation::SOURCE_COPY);
574 brillo::Blob src_hash;
575 EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
576 aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
577
578 brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
579
580 string source_path;
581 EXPECT_TRUE(utils::MakeTempFile("Source-XXXXXX", &source_path, nullptr));
582 ScopedPathUnlinker path_unlinker(source_path);
583 EXPECT_TRUE(utils::WriteFile(source_path.c_str(), actual_data.data(),
584 actual_data.size()));
585
586 EXPECT_EQ(actual_data, ApplyPayload(payload_data, source_path, false));
587 }
588
TEST_F(DeltaPerformerTest,ExtentsToByteStringTest)589 TEST_F(DeltaPerformerTest, ExtentsToByteStringTest) {
590 uint64_t test[] = {1, 1, 4, 2, 0, 1};
591 static_assert(arraysize(test) % 2 == 0, "Array size uneven");
592 const uint64_t block_size = 4096;
593 const uint64_t file_length = 4 * block_size - 13;
594
595 google::protobuf::RepeatedPtrField<Extent> extents;
596 for (size_t i = 0; i < arraysize(test); i += 2) {
597 *(extents.Add()) = ExtentForRange(test[i], test[i + 1]);
598 }
599
600 string expected_output = "4096:4096,16384:8192,0:4083";
601 string actual_output;
602 EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents,
603 block_size,
604 file_length,
605 &actual_output));
606 EXPECT_EQ(expected_output, actual_output);
607 }
608
TEST_F(DeltaPerformerTest,ValidateManifestFullGoodTest)609 TEST_F(DeltaPerformerTest, ValidateManifestFullGoodTest) {
610 // The Manifest we are validating.
611 DeltaArchiveManifest manifest;
612 manifest.mutable_new_kernel_info();
613 manifest.mutable_new_rootfs_info();
614 manifest.set_minor_version(kFullPayloadMinorVersion);
615
616 RunManifestValidation(manifest,
617 kChromeOSMajorPayloadVersion,
618 InstallPayloadType::kFull,
619 ErrorCode::kSuccess);
620 }
621
TEST_F(DeltaPerformerTest,ValidateManifestDeltaGoodTest)622 TEST_F(DeltaPerformerTest, ValidateManifestDeltaGoodTest) {
623 // The Manifest we are validating.
624 DeltaArchiveManifest manifest;
625 manifest.mutable_old_kernel_info();
626 manifest.mutable_old_rootfs_info();
627 manifest.mutable_new_kernel_info();
628 manifest.mutable_new_rootfs_info();
629 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
630
631 RunManifestValidation(manifest,
632 kChromeOSMajorPayloadVersion,
633 InstallPayloadType::kDelta,
634 ErrorCode::kSuccess);
635 }
636
TEST_F(DeltaPerformerTest,ValidateManifestFullUnsetMinorVersion)637 TEST_F(DeltaPerformerTest, ValidateManifestFullUnsetMinorVersion) {
638 // The Manifest we are validating.
639 DeltaArchiveManifest manifest;
640
641 RunManifestValidation(manifest,
642 DeltaPerformer::kSupportedMajorPayloadVersion,
643 InstallPayloadType::kFull,
644 ErrorCode::kSuccess);
645 }
646
TEST_F(DeltaPerformerTest,ValidateManifestDeltaUnsetMinorVersion)647 TEST_F(DeltaPerformerTest, ValidateManifestDeltaUnsetMinorVersion) {
648 // The Manifest we are validating.
649 DeltaArchiveManifest manifest;
650 // Add an empty old_rootfs_info() to trick the DeltaPerformer into think that
651 // this is a delta payload manifest with a missing minor version.
652 manifest.mutable_old_rootfs_info();
653
654 RunManifestValidation(manifest,
655 DeltaPerformer::kSupportedMajorPayloadVersion,
656 InstallPayloadType::kDelta,
657 ErrorCode::kUnsupportedMinorPayloadVersion);
658 }
659
TEST_F(DeltaPerformerTest,ValidateManifestFullOldKernelTest)660 TEST_F(DeltaPerformerTest, ValidateManifestFullOldKernelTest) {
661 // The Manifest we are validating.
662 DeltaArchiveManifest manifest;
663 manifest.mutable_old_kernel_info();
664 manifest.mutable_new_kernel_info();
665 manifest.mutable_new_rootfs_info();
666 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
667
668 RunManifestValidation(manifest,
669 kChromeOSMajorPayloadVersion,
670 InstallPayloadType::kFull,
671 ErrorCode::kPayloadMismatchedType);
672 }
673
TEST_F(DeltaPerformerTest,ValidateManifestFullOldRootfsTest)674 TEST_F(DeltaPerformerTest, ValidateManifestFullOldRootfsTest) {
675 // The Manifest we are validating.
676 DeltaArchiveManifest manifest;
677 manifest.mutable_old_rootfs_info();
678 manifest.mutable_new_kernel_info();
679 manifest.mutable_new_rootfs_info();
680 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
681
682 RunManifestValidation(manifest,
683 kChromeOSMajorPayloadVersion,
684 InstallPayloadType::kFull,
685 ErrorCode::kPayloadMismatchedType);
686 }
687
TEST_F(DeltaPerformerTest,ValidateManifestFullPartitionUpdateTest)688 TEST_F(DeltaPerformerTest, ValidateManifestFullPartitionUpdateTest) {
689 // The Manifest we are validating.
690 DeltaArchiveManifest manifest;
691 PartitionUpdate* partition = manifest.add_partitions();
692 partition->mutable_old_partition_info();
693 partition->mutable_new_partition_info();
694 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion);
695
696 RunManifestValidation(manifest,
697 kBrilloMajorPayloadVersion,
698 InstallPayloadType::kFull,
699 ErrorCode::kPayloadMismatchedType);
700 }
701
TEST_F(DeltaPerformerTest,ValidateManifestBadMinorVersion)702 TEST_F(DeltaPerformerTest, ValidateManifestBadMinorVersion) {
703 // The Manifest we are validating.
704 DeltaArchiveManifest manifest;
705
706 // Generate a bad version number.
707 manifest.set_minor_version(DeltaPerformer::kSupportedMinorPayloadVersion +
708 10000);
709 // Mark the manifest as a delta payload by setting old_rootfs_info.
710 manifest.mutable_old_rootfs_info();
711
712 RunManifestValidation(manifest,
713 DeltaPerformer::kSupportedMajorPayloadVersion,
714 InstallPayloadType::kDelta,
715 ErrorCode::kUnsupportedMinorPayloadVersion);
716 }
717
TEST_F(DeltaPerformerTest,BrilloMetadataSignatureSizeTest)718 TEST_F(DeltaPerformerTest, BrilloMetadataSignatureSizeTest) {
719 EXPECT_TRUE(performer_.Write(kDeltaMagic, sizeof(kDeltaMagic)));
720
721 uint64_t major_version = htobe64(kBrilloMajorPayloadVersion);
722 EXPECT_TRUE(performer_.Write(&major_version, 8));
723
724 uint64_t manifest_size = rand() % 256;
725 uint64_t manifest_size_be = htobe64(manifest_size);
726 EXPECT_TRUE(performer_.Write(&manifest_size_be, 8));
727
728 uint32_t metadata_signature_size = rand() % 256;
729 uint32_t metadata_signature_size_be = htobe32(metadata_signature_size);
730 EXPECT_TRUE(performer_.Write(&metadata_signature_size_be, 4));
731
732 EXPECT_LT(performer_.Close(), 0);
733
734 EXPECT_TRUE(performer_.IsHeaderParsed());
735 EXPECT_EQ(kBrilloMajorPayloadVersion, performer_.GetMajorVersion());
736 uint64_t manifest_offset;
737 EXPECT_TRUE(performer_.GetManifestOffset(&manifest_offset));
738 EXPECT_EQ(24U, manifest_offset); // 4 + 8 + 8 + 4
739 EXPECT_EQ(manifest_offset + manifest_size, performer_.GetMetadataSize());
740 EXPECT_EQ(metadata_signature_size, performer_.metadata_signature_size_);
741 }
742
TEST_F(DeltaPerformerTest,BrilloVerifyMetadataSignatureTest)743 TEST_F(DeltaPerformerTest, BrilloVerifyMetadataSignatureTest) {
744 brillo::Blob payload_data = GeneratePayload({}, {}, true,
745 kBrilloMajorPayloadVersion,
746 kSourceMinorPayloadVersion);
747 install_plan_.hash_checks_mandatory = true;
748 // Just set these value so that we can use ValidateMetadataSignature directly.
749 performer_.major_payload_version_ = kBrilloMajorPayloadVersion;
750 performer_.metadata_size_ = install_plan_.metadata_size;
751 uint64_t signature_length;
752 EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
753 {GetBuildArtifactsPath(kUnittestPrivateKeyPath)}, &signature_length));
754 performer_.metadata_signature_size_ = signature_length;
755 performer_.set_public_key_path(GetBuildArtifactsPath(kUnittestPublicKeyPath));
756 EXPECT_EQ(ErrorCode::kSuccess,
757 performer_.ValidateMetadataSignature(payload_data));
758 }
759
TEST_F(DeltaPerformerTest,BadDeltaMagicTest)760 TEST_F(DeltaPerformerTest, BadDeltaMagicTest) {
761 EXPECT_TRUE(performer_.Write("junk", 4));
762 EXPECT_FALSE(performer_.Write("morejunk", 8));
763 EXPECT_LT(performer_.Close(), 0);
764 }
765
TEST_F(DeltaPerformerTest,MissingMandatoryMetadataSizeTest)766 TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
767 DoMetadataSizeTest(0, 75456, true);
768 }
769
TEST_F(DeltaPerformerTest,MissingNonMandatoryMetadataSizeTest)770 TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
771 DoMetadataSizeTest(0, 123456, false);
772 }
773
TEST_F(DeltaPerformerTest,InvalidMandatoryMetadataSizeTest)774 TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
775 DoMetadataSizeTest(13000, 140000, true);
776 }
777
TEST_F(DeltaPerformerTest,InvalidNonMandatoryMetadataSizeTest)778 TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
779 DoMetadataSizeTest(40000, 50000, false);
780 }
781
TEST_F(DeltaPerformerTest,ValidMandatoryMetadataSizeTest)782 TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
783 DoMetadataSizeTest(85376, 85376, true);
784 }
785
TEST_F(DeltaPerformerTest,MandatoryEmptyMetadataSignatureTest)786 TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
787 DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
788 }
789
TEST_F(DeltaPerformerTest,NonMandatoryEmptyMetadataSignatureTest)790 TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
791 DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
792 }
793
TEST_F(DeltaPerformerTest,MandatoryInvalidMetadataSignatureTest)794 TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
795 DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
796 }
797
TEST_F(DeltaPerformerTest,NonMandatoryInvalidMetadataSignatureTest)798 TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
799 DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
800 }
801
TEST_F(DeltaPerformerTest,MandatoryValidMetadataSignature1Test)802 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
803 DoMetadataSignatureTest(kValidMetadataSignature, false, true);
804 }
805
TEST_F(DeltaPerformerTest,MandatoryValidMetadataSignature2Test)806 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
807 DoMetadataSignatureTest(kValidMetadataSignature, true, true);
808 }
809
TEST_F(DeltaPerformerTest,NonMandatoryValidMetadataSignatureTest)810 TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
811 DoMetadataSignatureTest(kValidMetadataSignature, true, false);
812 }
813
TEST_F(DeltaPerformerTest,UsePublicKeyFromResponse)814 TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) {
815 base::FilePath key_path;
816
817 // The result of the GetPublicKeyResponse() method is based on three things
818 //
819 // 1. Whether it's an official build; and
820 // 2. Whether the Public RSA key to be used is in the root filesystem; and
821 // 3. Whether the response has a public key
822 //
823 // We test all eight combinations to ensure that we only use the
824 // public key in the response if
825 //
826 // a. it's not an official build; and
827 // b. there is no key in the root filesystem.
828
829 base::ScopedTempDir temp_dir;
830 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
831 string non_existing_file = temp_dir.path().Append("non-existing").value();
832 string existing_file = temp_dir.path().Append("existing").value();
833 EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
834
835 // Non-official build, non-existing public-key, key in response -> true
836 fake_hardware_.SetIsOfficialBuild(false);
837 performer_.public_key_path_ = non_existing_file;
838 install_plan_.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
839 EXPECT_TRUE(performer_.GetPublicKeyFromResponse(&key_path));
840 EXPECT_FALSE(key_path.empty());
841 EXPECT_EQ(unlink(key_path.value().c_str()), 0);
842 // Same with official build -> false
843 fake_hardware_.SetIsOfficialBuild(true);
844 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
845
846 // Non-official build, existing public-key, key in response -> false
847 fake_hardware_.SetIsOfficialBuild(false);
848 performer_.public_key_path_ = existing_file;
849 install_plan_.public_key_rsa = "VGVzdAo="; // result of 'echo "Test" | base64'
850 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
851 // Same with official build -> false
852 fake_hardware_.SetIsOfficialBuild(true);
853 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
854
855 // Non-official build, non-existing public-key, no key in response -> false
856 fake_hardware_.SetIsOfficialBuild(false);
857 performer_.public_key_path_ = non_existing_file;
858 install_plan_.public_key_rsa = "";
859 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
860 // Same with official build -> false
861 fake_hardware_.SetIsOfficialBuild(true);
862 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
863
864 // Non-official build, existing public-key, no key in response -> false
865 fake_hardware_.SetIsOfficialBuild(false);
866 performer_.public_key_path_ = existing_file;
867 install_plan_.public_key_rsa = "";
868 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
869 // Same with official build -> false
870 fake_hardware_.SetIsOfficialBuild(true);
871 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
872
873 // Non-official build, non-existing public-key, key in response
874 // but invalid base64 -> false
875 fake_hardware_.SetIsOfficialBuild(false);
876 performer_.public_key_path_ = non_existing_file;
877 install_plan_.public_key_rsa = "not-valid-base64";
878 EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
879 }
880
TEST_F(DeltaPerformerTest,ConfVersionsMatch)881 TEST_F(DeltaPerformerTest, ConfVersionsMatch) {
882 // Test that the versions in update_engine.conf that is installed to the
883 // image match the supported delta versions in the update engine.
884 uint32_t minor_version;
885 brillo::KeyValueStore store;
886 EXPECT_TRUE(store.Load(GetBuildArtifactsPath().Append("update_engine.conf")));
887 EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
888 EXPECT_EQ(DeltaPerformer::kSupportedMinorPayloadVersion, minor_version);
889
890 string major_version_str;
891 uint64_t major_version;
892 EXPECT_TRUE(store.GetString("PAYLOAD_MAJOR_VERSION", &major_version_str));
893 EXPECT_TRUE(base::StringToUint64(major_version_str, &major_version));
894 EXPECT_EQ(DeltaPerformer::kSupportedMajorPayloadVersion, major_version);
895 }
896
897 // Test that we recognize our own zlib compressor implementation as supported.
898 // All other equivalent implementations should be added to
899 // kCompatibleZlibFingerprint.
TEST_F(DeltaPerformerTest,ZlibFingerprintMatch)900 TEST_F(DeltaPerformerTest, ZlibFingerprintMatch) {
901 string fingerprint;
902 #ifdef __ANDROID__
903 const std::string kZlibFingerprintPath =
904 test_utils::GetBuildArtifactsPath("zlib_fingerprint");
905 #else
906 const std::string kZlibFingerprintPath = "/etc/zlib_fingerprint";
907 #endif // __ANDROID__
908 EXPECT_TRUE(base::ReadFileToString(base::FilePath(kZlibFingerprintPath),
909 &fingerprint));
910 EXPECT_TRUE(utils::IsZlibCompatible(fingerprint));
911 }
912
913 } // namespace chromeos_update_engine
914