Home | History | Annotate | Download | only in payload_consumer
      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:
    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.
    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 
    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 
    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.
    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.
    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.
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    766 TEST_F(DeltaPerformerTest, MissingMandatoryMetadataSizeTest) {
    767   DoMetadataSizeTest(0, 75456, true);
    768 }
    769 
    770 TEST_F(DeltaPerformerTest, MissingNonMandatoryMetadataSizeTest) {
    771   DoMetadataSizeTest(0, 123456, false);
    772 }
    773 
    774 TEST_F(DeltaPerformerTest, InvalidMandatoryMetadataSizeTest) {
    775   DoMetadataSizeTest(13000, 140000, true);
    776 }
    777 
    778 TEST_F(DeltaPerformerTest, InvalidNonMandatoryMetadataSizeTest) {
    779   DoMetadataSizeTest(40000, 50000, false);
    780 }
    781 
    782 TEST_F(DeltaPerformerTest, ValidMandatoryMetadataSizeTest) {
    783   DoMetadataSizeTest(85376, 85376, true);
    784 }
    785 
    786 TEST_F(DeltaPerformerTest, MandatoryEmptyMetadataSignatureTest) {
    787   DoMetadataSignatureTest(kEmptyMetadataSignature, true, true);
    788 }
    789 
    790 TEST_F(DeltaPerformerTest, NonMandatoryEmptyMetadataSignatureTest) {
    791   DoMetadataSignatureTest(kEmptyMetadataSignature, true, false);
    792 }
    793 
    794 TEST_F(DeltaPerformerTest, MandatoryInvalidMetadataSignatureTest) {
    795   DoMetadataSignatureTest(kInvalidMetadataSignature, true, true);
    796 }
    797 
    798 TEST_F(DeltaPerformerTest, NonMandatoryInvalidMetadataSignatureTest) {
    799   DoMetadataSignatureTest(kInvalidMetadataSignature, true, false);
    800 }
    801 
    802 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature1Test) {
    803   DoMetadataSignatureTest(kValidMetadataSignature, false, true);
    804 }
    805 
    806 TEST_F(DeltaPerformerTest, MandatoryValidMetadataSignature2Test) {
    807   DoMetadataSignatureTest(kValidMetadataSignature, true, true);
    808 }
    809 
    810 TEST_F(DeltaPerformerTest, NonMandatoryValidMetadataSignatureTest) {
    811   DoMetadataSignatureTest(kValidMetadataSignature, true, false);
    812 }
    813 
    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 
    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.
    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