/*
 * Copyright (C) 2021 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 <string>
#include <vector>

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "apex_file_repository.h"
#include "apexd.h"
#include "apexd_test_utils.h"
#include "apexd_utils.h"

namespace android {
namespace apex {

namespace fs = std::filesystem;

using android::apex::testing::ApexFileEq;
using android::apex::testing::IsOk;
using android::base::GetExecutableDirectory;
using android::base::StringPrintf;
using ::testing::ByRef;
using ::testing::UnorderedElementsAre;

static std::string GetTestDataDir() { return GetExecutableDirectory(); }
static std::string GetTestFile(const std::string& name) {
  return GetTestDataDir() + "/" + name;
}

// Apex that does not have pre-installed version, does not get selected
TEST(ApexdUnitTest, ApexMustHavePreInstalledVersionForSelection) {
  TemporaryDir built_in_dir;
  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
  fs::copy(GetTestFile("com.android.apex.cts.shim.apex"), built_in_dir.path);
  fs::copy(
      GetTestFile("com.android.apex.test.sharedlibs_generated.v1.libvX.apex"),
      built_in_dir.path);
  ApexFileRepository instance;
  // Pre-installed data needs to be present so that we can add data apex
  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));

  TemporaryDir data_dir;
  fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
  fs::copy(GetTestFile("com.android.apex.cts.shim.apex"), data_dir.path);
  fs::copy(
      GetTestFile("com.android.apex.test.sharedlibs_generated.v1.libvX.apex"),
      data_dir.path);
  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));

  const auto all_apex = instance.AllApexFilesByName();
  // Pass a blank instance so that the data apex files are not considered
  // pre-installed
  const ApexFileRepository instance_blank;
  auto result = SelectApexForActivation(all_apex, instance_blank);
  ASSERT_EQ(result.size(), 0u);
  // When passed proper instance they should get selected
  result = SelectApexForActivation(all_apex, instance);
  ASSERT_EQ(result.size(), 4u);
  auto apexd_test_file =
      ApexFile::Open(StringPrintf("%s/apex.apexd_test.apex", data_dir.path));
  auto shim_v1 = ApexFile::Open(
      StringPrintf("%s/com.android.apex.cts.shim.apex", data_dir.path));
  auto shared_lib_1 = ApexFile::Open(StringPrintf(
      "%s/com.android.apex.test.sharedlibs_generated.v1.libvX.apex",
      built_in_dir.path));
  auto shared_lib_2 = ApexFile::Open(StringPrintf(
      "%s/com.android.apex.test.sharedlibs_generated.v1.libvX.apex",
      data_dir.path));
  ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file)),
                                           ApexFileEq(ByRef(*shim_v1)),
                                           ApexFileEq(ByRef(*shared_lib_1)),
                                           ApexFileEq(ByRef(*shared_lib_2))));
}

// Higher version gets priority when selecting for activation
TEST(ApexdUnitTest, HigherVersionOfApexIsSelected) {
  TemporaryDir built_in_dir;
  fs::copy(GetTestFile("apex.apexd_test_v2.apex"), built_in_dir.path);
  fs::copy(GetTestFile("com.android.apex.cts.shim.apex"), built_in_dir.path);
  ApexFileRepository instance;
  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));

  TemporaryDir data_dir;
  fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
  fs::copy(GetTestFile("com.android.apex.cts.shim.v2.apex"), data_dir.path);
  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));

  auto all_apex = instance.AllApexFilesByName();
  auto result = SelectApexForActivation(all_apex, instance);
  ASSERT_EQ(result.size(), 2u);

  auto apexd_test_file_v2 = ApexFile::Open(
      StringPrintf("%s/apex.apexd_test_v2.apex", built_in_dir.path));
  auto shim_v2 = ApexFile::Open(
      StringPrintf("%s/com.android.apex.cts.shim.v2.apex", data_dir.path));
  ASSERT_THAT(result,
              UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file_v2)),
                                   ApexFileEq(ByRef(*shim_v2))));
}

// When versions are equal, non-pre-installed version gets priority
TEST(ApexdUnitTest, DataApexGetsPriorityForSameVersions) {
  TemporaryDir built_in_dir;
  fs::copy(GetTestFile("apex.apexd_test.apex"), built_in_dir.path);
  fs::copy(GetTestFile("com.android.apex.cts.shim.apex"), built_in_dir.path);
  // Initialize pre-installed APEX information
  ApexFileRepository instance;
  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));

  TemporaryDir data_dir;
  fs::copy(GetTestFile("apex.apexd_test.apex"), data_dir.path);
  fs::copy(GetTestFile("com.android.apex.cts.shim.apex"), data_dir.path);
  // Initialize ApexFile repo
  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));

  auto all_apex = instance.AllApexFilesByName();
  auto result = SelectApexForActivation(all_apex, instance);
  ASSERT_EQ(result.size(), 2u);

  auto apexd_test_file =
      ApexFile::Open(StringPrintf("%s/apex.apexd_test.apex", data_dir.path));
  auto shim_v1 = ApexFile::Open(
      StringPrintf("%s/com.android.apex.cts.shim.apex", data_dir.path));
  ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*apexd_test_file)),
                                           ApexFileEq(ByRef(*shim_v1))));
}

// Both versions of shared libs can be selected
TEST(ApexdUnitTest, SharedLibsCanHaveBothVersionSelected) {
  TemporaryDir built_in_dir;
  fs::copy(
      GetTestFile("com.android.apex.test.sharedlibs_generated.v1.libvX.apex"),
      built_in_dir.path);
  // Initialize pre-installed APEX information
  ApexFileRepository instance;
  ASSERT_TRUE(IsOk(instance.AddPreInstalledApex({built_in_dir.path})));

  TemporaryDir data_dir;
  fs::copy(
      GetTestFile("com.android.apex.test.sharedlibs_generated.v2.libvY.apex"),
      data_dir.path);
  // Initialize data APEX information
  ASSERT_TRUE(IsOk(instance.AddDataApex(data_dir.path)));

  auto all_apex = instance.AllApexFilesByName();
  auto result = SelectApexForActivation(all_apex, instance);
  ASSERT_EQ(result.size(), 2u);

  auto shared_lib_v1 = ApexFile::Open(StringPrintf(
      "%s/com.android.apex.test.sharedlibs_generated.v1.libvX.apex",
      built_in_dir.path));
  auto shared_lib_v2 = ApexFile::Open(StringPrintf(
      "%s/com.android.apex.test.sharedlibs_generated.v2.libvY.apex",
      data_dir.path));
  ASSERT_THAT(result, UnorderedElementsAre(ApexFileEq(ByRef(*shared_lib_v1)),
                                           ApexFileEq(ByRef(*shared_lib_v2))));
}

TEST(ApexdUnitTest, ProcessCompressedApex) {
  TemporaryDir built_in_dir;
  fs::copy(GetTestFile("com.android.apex.compressed.v1.capex"),
           built_in_dir.path);
  auto compressed_apex = ApexFile::Open(StringPrintf(
      "%s/com.android.apex.compressed.v1.capex", built_in_dir.path));

  TemporaryDir decompression_dir, active_apex_dir;
  std::vector<std::reference_wrapper<const ApexFile>> compressed_apex_list;
  compressed_apex_list.emplace_back(std::cref(*compressed_apex));
  auto return_value = ProcessCompressedApex(
      compressed_apex_list, decompression_dir.path, active_apex_dir.path);

  std::string decompressed_file_path = StringPrintf(
      "%s/com.android.apex.compressed@1.apex", decompression_dir.path);
  // Assert output path is not empty
  auto exists = PathExists(decompressed_file_path);
  ASSERT_TRUE(IsOk(exists));
  ASSERT_TRUE(*exists) << decompressed_file_path << " does not exist";

  // Assert that decompressed apex is same as original apex
  const std::string original_apex_file_path =
      GetTestFile("com.android.apex.compressed.v1_original.apex");
  auto comparison_result =
      CompareFiles(original_apex_file_path, decompressed_file_path);
  ASSERT_TRUE(IsOk(comparison_result));
  ASSERT_TRUE(*comparison_result);

  // Assert that the file is hard linked to active_apex_dir
  std::string hardlink_file_path = StringPrintf(
      "%s/com.android.apex.compressed@1.apex", active_apex_dir.path);
  std::error_code ec;
  bool is_hardlink =
      fs::equivalent(decompressed_file_path, hardlink_file_path, ec);
  ASSERT_FALSE(ec) << "Some error occurred while checking for hardlink";
  ASSERT_TRUE(is_hardlink);

  // Assert that return value contains active APEX, not decompressed APEX
  auto active_apex = ApexFile::Open(hardlink_file_path);
  ASSERT_THAT(return_value,
              UnorderedElementsAre(ApexFileEq(ByRef(*active_apex))));
}

TEST(ApexdUnitTest, ProcessCompressedApexRunsVerification) {
  TemporaryDir built_in_dir;
  fs::copy(GetTestFile(
               "com.android.apex.compressed_key_mismatch_with_original.capex"),
           built_in_dir.path);

  auto compressed_apex_mismatch_key = ApexFile::Open(StringPrintf(
      "%s/com.android.apex.compressed_key_mismatch_with_original.capex",
      built_in_dir.path));

  TemporaryDir decompression_dir, active_apex_dir;
  std::vector<std::reference_wrapper<const ApexFile>> compressed_apex_list;
  compressed_apex_list.emplace_back(std::cref(*compressed_apex_mismatch_key));
  auto return_value = ProcessCompressedApex(
      compressed_apex_list, decompression_dir.path, active_apex_dir.path);
  ASSERT_EQ(return_value.size(), 0u);
}

TEST(ApexdUnitTest, DecompressedApexCleanupDeleteIfActiveFileMissing) {
  // Create decompressed apex in decompression_dir
  TemporaryDir decompression_dir;
  fs::copy(GetTestFile("com.android.apex.compressed.v1_original.apex"),
           decompression_dir.path);

  TemporaryDir active_apex_dir;
  RemoveUnlinkedDecompressedApex(decompression_dir.path, active_apex_dir.path);

  // Assert that decompressed apex was deleted
  auto decompressed_file_path =
      StringPrintf("%s/com.android.apex.compressed.v1_original.apex",
                   decompression_dir.path);
  auto file_exists = PathExists(decompressed_file_path);
  ASSERT_TRUE(IsOk(file_exists));
  ASSERT_FALSE(*file_exists)
      << "Unlinked decompressed file did not get deleted";
}

TEST(ApexdUnitTest, DecompressedApexCleanupSameFilenameButNotLinked) {
  // Create decompressed apex in decompression_dir
  TemporaryDir decompression_dir;
  const std::string filename = "com.android.apex.compressed.v1_original.apex";
  fs::copy(GetTestFile(filename), decompression_dir.path);
  auto decompressed_file_path =
      StringPrintf("%s/%s", decompression_dir.path, filename.c_str());

  // Copy the same file to active_apex_dir, instead of hard-linking
  TemporaryDir active_apex_dir;
  fs::copy(GetTestFile(filename), active_apex_dir.path);

  RemoveUnlinkedDecompressedApex(decompression_dir.path, active_apex_dir.path);

  // Assert that decompressed apex was deleted
  auto file_exists = PathExists(decompressed_file_path);
  ASSERT_TRUE(IsOk(file_exists));
  ASSERT_FALSE(*file_exists)
      << "Unlinked decompressed file did not get deleted";
}

TEST(ApexdUnitTest, DecompressedApexCleanupLinkedSurvives) {
  // Create decompressed apex in decompression_dir
  TemporaryDir decompression_dir;
  const std::string filename = "com.android.apex.compressed.v1_original.apex";
  fs::copy(GetTestFile(filename), decompression_dir.path);
  auto decompressed_file_path =
      StringPrintf("%s/%s", decompression_dir.path, filename.c_str());

  // Now hardlink it to active_apex_dir
  TemporaryDir active_apex_dir;
  auto active_file_path =
      StringPrintf("%s/%s", active_apex_dir.path, filename.c_str());
  std::error_code ec;
  fs::create_hard_link(decompressed_file_path, active_file_path, ec);
  ASSERT_FALSE(ec) << "Failed to create hardlink";

  RemoveUnlinkedDecompressedApex(decompression_dir.path, active_apex_dir.path);

  // Assert that decompressed apex was not deleted
  auto file_exists = PathExists(decompressed_file_path);
  ASSERT_TRUE(IsOk(file_exists));
  ASSERT_TRUE(*file_exists) << "Linked decompressed file got deleted";
}

TEST(ApexdUnitTest, DecompressedApexCleanupDeleteIfLinkedToDifferentFilename) {
  // Create decompressed apex in decompression_dir
  TemporaryDir decompression_dir;
  const std::string filename = "com.android.apex.compressed.v1_original.apex";
  fs::copy(GetTestFile(filename), decompression_dir.path);
  auto decompressed_file_path =
      StringPrintf("%s/%s", decompression_dir.path, filename.c_str());

  // Now hardlink it to active_apex_dir but with different filename
  TemporaryDir active_apex_dir;
  auto active_file_path =
      StringPrintf("%s/different.name.apex", active_apex_dir.path);
  std::error_code ec;
  fs::create_hard_link(decompressed_file_path, active_file_path, ec);
  ASSERT_FALSE(ec) << "Failed to create hardlink";

  RemoveUnlinkedDecompressedApex(decompression_dir.path, active_apex_dir.path);

  // Assert that decompressed apex was deleted
  auto file_exists = PathExists(decompressed_file_path);
  ASSERT_TRUE(IsOk(file_exists));
  ASSERT_FALSE(*file_exists)
      << "Unlinked decompressed file did not get deleted";
}

}  // namespace apex
}  // namespace android
