From 37304f3cc920804c97d52df929b9871c057c55e0 Mon Sep 17 00:00:00 2001 From: xunchang Date: Tue, 12 Mar 2019 12:40:14 -0700 Subject: Implement FilePackage class This is another implementation of the Package class. And we will later need it when reading the package from FUSE. Bug: 127071893 Test: unit tests pass, sideload a file package on sailfish Change-Id: I3de5d5ef60b29c8b73517d6de3498459d7d95975 --- tests/Android.bp | 2 + tests/component/verifier_test.cpp | 15 +++-- tests/unit/package_test.cpp | 117 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 tests/unit/package_test.cpp (limited to 'tests') diff --git a/tests/Android.bp b/tests/Android.bp index 898ed7d60..ef5919eb5 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -77,6 +77,7 @@ librecovery_static_libs = [ "librecovery", "librecovery_fastboot", "libminui", + "libpackage", "libverifier", "libotautil", @@ -117,6 +118,7 @@ cc_test { static_libs: libapplypatch_static_libs + [ "librecovery_ui", "libminui", + "libpackage", "libverifier", "libotautil", "libupdater", diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp index c26d76d73..c904cd038 100644 --- a/tests/component/verifier_test.cpp +++ b/tests/component/verifier_test.cpp @@ -240,8 +240,10 @@ class VerifierTest : public testing::TestWithParam> { void SetUp() override { std::vector args = GetParam(); std::string path = from_testdata_base(args[0]); - package_ = Package::CreateMemoryPackage(path, nullptr); - ASSERT_NE(nullptr, package_); + memory_package_ = Package::CreateMemoryPackage(path, nullptr); + ASSERT_NE(nullptr, memory_package_); + file_package_ = Package::CreateFilePackage(path, nullptr); + ASSERT_NE(nullptr, file_package_); for (auto it = ++args.cbegin(); it != args.cend(); ++it) { std::string public_key_file = from_testdata_base("testkey_" + *it + ".x509.pem"); @@ -250,7 +252,8 @@ class VerifierTest : public testing::TestWithParam> { } } - std::unique_ptr package_; + std::unique_ptr memory_package_; + std::unique_ptr file_package_; std::vector certs_; }; @@ -304,11 +307,13 @@ TEST(VerifierTest, BadPackage_SignatureStartOutOfBounds) { } TEST_P(VerifierSuccessTest, VerifySucceed) { - ASSERT_EQ(VERIFY_SUCCESS, verify_file(package_.get(), certs_)); + ASSERT_EQ(VERIFY_SUCCESS, verify_file(memory_package_.get(), certs_)); + ASSERT_EQ(VERIFY_SUCCESS, verify_file(file_package_.get(), certs_)); } TEST_P(VerifierFailureTest, VerifyFailure) { - ASSERT_EQ(VERIFY_FAILURE, verify_file(package_.get(), certs_)); + ASSERT_EQ(VERIFY_FAILURE, verify_file(memory_package_.get(), certs_)); + ASSERT_EQ(VERIFY_FAILURE, verify_file(file_package_.get(), certs_)); } INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest, diff --git a/tests/unit/package_test.cpp b/tests/unit/package_test.cpp new file mode 100644 index 000000000..fa492d38b --- /dev/null +++ b/tests/unit/package_test.cpp @@ -0,0 +1,117 @@ +/* + * 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 agree 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 + +#include +#include +#include + +#include +#include +#include +#include + +#include "common/test_constants.h" +#include "package.h" + +class PackageTest : public ::testing::Test { + protected: + void SetUp() override; + + // A list of package classes for test, including MemoryPackage and FilePackage. + std::vector> packages_; + + TemporaryFile temp_file_; // test package file. + std::string file_content_; // actual bytes of the package file. +}; + +void PackageTest::SetUp() { + std::vector entries = { "file1.txt", "file2.txt", "dir1/file3.txt" }; + FILE* file_ptr = fdopen(temp_file_.release(), "wb"); + ZipWriter writer(file_ptr); + for (const auto& entry : entries) { + ASSERT_EQ(0, writer.StartEntry(entry.c_str(), ZipWriter::kCompress)); + ASSERT_EQ(0, writer.WriteBytes(entry.c_str(), entry.size())); + ASSERT_EQ(0, writer.FinishEntry()); + } + writer.Finish(); + ASSERT_EQ(0, fclose(file_ptr)); + + ASSERT_TRUE(android::base::ReadFileToString(temp_file_.path, &file_content_)); + auto memory_package = Package::CreateMemoryPackage(temp_file_.path, nullptr); + ASSERT_TRUE(memory_package); + packages_.emplace_back(std::move(memory_package)); + + auto file_package = Package::CreateFilePackage(temp_file_.path, nullptr); + ASSERT_TRUE(file_package); + packages_.emplace_back(std::move(file_package)); +} + +TEST_F(PackageTest, ReadFullyAtOffset_success) { + for (const auto& package : packages_) { + std::vector buffer(file_content_.size()); + ASSERT_TRUE(package->ReadFullyAtOffset(buffer.data(), file_content_.size(), 0)); + ASSERT_EQ(file_content_, std::string(buffer.begin(), buffer.end())); + + ASSERT_TRUE(package->ReadFullyAtOffset(buffer.data(), file_content_.size() - 10, 10)); + ASSERT_EQ(file_content_.substr(10), std::string(buffer.begin(), buffer.end() - 10)); + } +} + +TEST_F(PackageTest, ReadFullyAtOffset_failure) { + for (const auto& package : packages_) { + std::vector buffer(file_content_.size()); + // Out of bound read. + ASSERT_FALSE(package->ReadFullyAtOffset(buffer.data(), file_content_.size(), 10)); + } +} + +TEST_F(PackageTest, UpdateHashAtOffset_sha1_hash) { + // Check that the hash matches for first half of the file. + uint64_t hash_size = file_content_.size() / 2; + std::vector expected_sha(SHA_DIGEST_LENGTH); + SHA1(reinterpret_cast(file_content_.data()), hash_size, expected_sha.data()); + + for (const auto& package : packages_) { + SHA_CTX ctx; + SHA1_Init(&ctx); + std::vector hashers{ std::bind(&SHA1_Update, &ctx, std::placeholders::_1, + std::placeholders::_2) }; + package->UpdateHashAtOffset(hashers, 0, hash_size); + + std::vector calculated_sha(SHA_DIGEST_LENGTH); + SHA1_Final(calculated_sha.data(), &ctx); + ASSERT_EQ(expected_sha, calculated_sha); + } +} + +TEST_F(PackageTest, GetZipArchiveHandle_extract_entry) { + for (const auto& package : packages_) { + ZipArchiveHandle zip = package->GetZipArchiveHandle(); + ASSERT_TRUE(zip); + + // Check that we can extract one zip entry. + std::string entry_name = "dir1/file3.txt"; + ZipString path(entry_name.c_str()); + ZipEntry entry; + ASSERT_EQ(0, FindEntry(zip, path, &entry)); + + std::vector extracted(entry_name.size()); + ASSERT_EQ(0, ExtractToMemory(zip, &entry, extracted.data(), extracted.size())); + ASSERT_EQ(entry_name, std::string(extracted.begin(), extracted.end())); + } +} -- cgit v1.2.3