| // |
| // Copyright (C) 2019 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "update_engine/payload_generator/payload_properties.h" |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include <base/files/file_util.h> |
| #include <base/files/scoped_file.h> |
| #include <base/files/scoped_temp_dir.h> |
| #include <base/rand_util.h> |
| #include <base/strings/stringprintf.h> |
| #include <brillo/data_encoding.h> |
| |
| #include <gtest/gtest.h> |
| |
| #include "update_engine/common/hash_calculator.h" |
| #include "update_engine/common/test_utils.h" |
| #include "update_engine/common/utils.h" |
| #include "update_engine/payload_consumer/install_plan.h" |
| #include "update_engine/payload_generator/delta_diff_generator.h" |
| #include "update_engine/payload_generator/delta_diff_utils.h" |
| #include "update_engine/payload_generator/full_update_generator.h" |
| #include "update_engine/payload_generator/operations_generator.h" |
| #include "update_engine/payload_generator/payload_file.h" |
| #include "update_engine/payload_generator/payload_generation_config.h" |
| |
| using std::string; |
| using std::unique_ptr; |
| using std::vector; |
| |
| namespace chromeos_update_engine { |
| |
| // TODO(kimjae): current implementation is very specific to a static way of |
| // producing a deterministic test. It would definitely be beneficial to |
| // extend the |PayloadPropertiesTest::SetUp()| into a generic helper or |
| // seperate class that can handle creation of different |PayloadFile|s. |
| class PayloadPropertiesTest : public ::testing::Test { |
| protected: |
| void SetUp() override { |
| PayloadGenerationConfig config; |
| config.version.major = kBrilloMajorPayloadVersion; |
| config.version.minor = kSourceMinorPayloadVersion; |
| PayloadFile payload; |
| EXPECT_TRUE(payload.Init(config)); |
| |
| const auto SetupPartitionConfig = |
| [](PartitionConfig* config, const string& path, size_t size) { |
| config->path = path; |
| config->size = size; |
| }; |
| const auto WriteZerosToFile = [](const char path[], size_t size) { |
| string zeros(size, '\0'); |
| EXPECT_TRUE(utils::WriteFile(path, zeros.c_str(), zeros.size())); |
| }; |
| ScopedTempFile old_part_file("old_part.XXXXXX"); |
| ScopedTempFile new_part_file("new_part.XXXXXX"); |
| PartitionConfig old_part(kPartitionNameRoot); |
| PartitionConfig new_part(kPartitionNameRoot); |
| SetupPartitionConfig(&old_part, old_part_file.path(), 0); |
| SetupPartitionConfig(&new_part, new_part_file.path(), 10000); |
| WriteZerosToFile(old_part_file.path().c_str(), old_part.size); |
| WriteZerosToFile(new_part_file.path().c_str(), new_part.size); |
| |
| // Select payload generation strategy based on the config. |
| unique_ptr<OperationsGenerator> strategy(new FullUpdateGenerator()); |
| |
| vector<AnnotatedOperation> aops; |
| off_t data_file_size = 0; |
| ScopedTempFile data_file("temp_data.XXXXXX", true); |
| BlobFileWriter blob_file_writer(data_file.fd(), &data_file_size); |
| // Generate the operations using the strategy we selected above. |
| EXPECT_TRUE(strategy->GenerateOperations( |
| config, old_part, new_part, &blob_file_writer, &aops)); |
| |
| payload.AddPartition(old_part, new_part, aops, {}, 0); |
| |
| uint64_t metadata_size; |
| EXPECT_TRUE(payload.WritePayload( |
| payload_file_.path(), data_file.path(), "", &metadata_size)); |
| } |
| |
| ScopedTempFile payload_file_{"payload_file.XXXXXX"}; |
| }; |
| |
| // Validate the hash of file exists within the output. |
| TEST_F(PayloadPropertiesTest, GetPropertiesAsJsonTestHash) { |
| constexpr char kJsonProperties[] = |
| "{" |
| R"("is_delta":true,)" |
| R"("metadata_signature":"",)" |
| R"("metadata_size":165,)" |
| R"("sha256_hex":"cV7kfZBH3K0B6QJHxxykDh6b6x0WgVOmc63whPLOy7U=",)" |
| R"("size":211,)" |
| R"("version":2)" |
| "}"; |
| string json; |
| EXPECT_TRUE( |
| PayloadProperties(payload_file_.path()).GetPropertiesAsJson(&json)); |
| EXPECT_EQ(kJsonProperties, json) << "JSON contents:\n" << json; |
| } |
| |
| // Validate the hash of file and metadata are within the output. |
| TEST_F(PayloadPropertiesTest, GetPropertiesAsKeyValueTestHash) { |
| constexpr char kKeyValueProperties[] = |
| "FILE_HASH=cV7kfZBH3K0B6QJHxxykDh6b6x0WgVOmc63whPLOy7U=\n" |
| "FILE_SIZE=211\n" |
| "METADATA_HASH=aEKYyzJt2E8Gz8fzB+gmekN5mriotZCSq6R+kDfdeV4=\n" |
| "METADATA_SIZE=165\n"; |
| string key_value; |
| EXPECT_TRUE(PayloadProperties{payload_file_.path()}.GetPropertiesAsKeyValue( |
| &key_value)); |
| EXPECT_EQ(kKeyValueProperties, key_value) << "Key Value contents:\n" |
| << key_value; |
| } |
| |
| } // namespace chromeos_update_engine |