// // 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 #include #include #include #include #include #include #include #include #include #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 strategy(new FullUpdateGenerator()); vector 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