/*
 * 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 <stdio.h>

#include <functional>
#include <string>
#include <vector>

#include <android-base/file.h>
#include <gtest/gtest.h>
#include <openssl/sha.h>
#include <ziparchive/zip_writer.h>

#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<std::unique_ptr<Package>> packages_;

  TemporaryFile temp_file_;   // test package file.
  std::string file_content_;  // actual bytes of the package file.
};

void PackageTest::SetUp() {
  std::vector<std::string> 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<uint8_t> 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<uint8_t> 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<uint8_t> expected_sha(SHA_DIGEST_LENGTH);
  SHA1(reinterpret_cast<uint8_t*>(file_content_.data()), hash_size, expected_sha.data());

  for (const auto& package : packages_) {
    SHA_CTX ctx;
    SHA1_Init(&ctx);
    std::vector<HasherUpdateCallback> hashers{ std::bind(&SHA1_Update, &ctx, std::placeholders::_1,
                                                         std::placeholders::_2) };
    package->UpdateHashAtOffset(hashers, 0, hash_size);

    std::vector<uint8_t> 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<uint8_t> extracted(entry_name.size());
    ASSERT_EQ(0, ExtractToMemory(zip, &entry, extracted.data(), extracted.size()));
    ASSERT_EQ(entry_name, std::string(extracted.begin(), extracted.end()));
  }
}
