/*
 * Copyright (C) 2020 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 <errno.h>
#include <sys/stat.h>

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

#include "apex_file.h"
#include "apexd_test_utils.h"
#include "apexd_verity.h"

namespace android {
namespace apex {

using namespace std::literals;

using android::apex::testing::IsOk;
using android::base::GetExecutableDirectory;
using android::base::ReadFileToString;
using android::base::StringPrintf;

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

TEST(ApexdVerityTest, ReusesHashtree) {
  TemporaryDir td;

  auto apex = ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree.apex"));
  ASSERT_TRUE(IsOk(apex));
  auto verity_data = apex->VerifyApexVerity(apex->GetBundledPublicKey());
  ASSERT_TRUE(IsOk(verity_data));

  auto hashtree_file = StringPrintf("%s/hashtree", td.path);
  auto status = PrepareHashTree(*apex, *verity_data, hashtree_file);
  ASSERT_TRUE(IsOk(status));
  ASSERT_EQ(KRegenerate, *status);

  std::string first_hashtree;
  ASSERT_TRUE(ReadFileToString(hashtree_file, &first_hashtree))
      << "Failed to read " << hashtree_file;

  // Now call PrepareHashTree again. Since digest matches, hashtree should be
  // reused.
  status = PrepareHashTree(*apex, *verity_data, hashtree_file);
  ASSERT_TRUE(IsOk(status));
  ASSERT_EQ(kReuse, *status);

  std::string second_hashtree;
  ASSERT_TRUE(ReadFileToString(hashtree_file, &second_hashtree))
      << "Failed to read " << hashtree_file;

  // Hashtree file shouldn't be modified.
  ASSERT_EQ(first_hashtree, second_hashtree)
      << hashtree_file << " was regenerated";
}

TEST(ApexdVerityTest, RegenerateHashree) {
  TemporaryDir td;

  auto apex = ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree.apex"));
  ASSERT_TRUE(IsOk(apex));
  auto verity_data = apex->VerifyApexVerity(apex->GetBundledPublicKey());
  ASSERT_TRUE(IsOk(verity_data));

  auto hashtree_file = StringPrintf("%s/hashtree", td.path);
  auto status = PrepareHashTree(*apex, *verity_data, hashtree_file);
  ASSERT_TRUE(IsOk(status));
  ASSERT_EQ(KRegenerate, *status);

  std::string first_hashtree;
  ASSERT_TRUE(ReadFileToString(hashtree_file, &first_hashtree))
      << "Failed to read " << hashtree_file;

  auto apex2 =
      ApexFile::Open(GetTestFile("apex.apexd_test_no_hashtree_2.apex"));
  ASSERT_TRUE(IsOk(apex2));
  auto verity_data2 = apex2->VerifyApexVerity(apex2->GetBundledPublicKey());
  ASSERT_TRUE(IsOk(verity_data2));

  // Now call PrepareHashTree again. Since digest doesn't match, hashtree
  // should be regenerated.
  status = PrepareHashTree(*apex2, *verity_data2, hashtree_file);
  ASSERT_TRUE(IsOk(status));
  ASSERT_EQ(KRegenerate, *status);

  std::string second_hashtree;
  ASSERT_TRUE(ReadFileToString(hashtree_file, &second_hashtree))
      << "Failed to read " << hashtree_file;

  // Hashtree file should be regenerated.
  ASSERT_NE(first_hashtree, second_hashtree) << hashtree_file << " was reused";
}

TEST(ApexdVerityTest, CannotPrepareHashTreeForCompressedApex) {
  TemporaryDir td;

  auto apex =
      ApexFile::Open(GetTestFile("com.android.apex.compressed.v1.capex"));
  ASSERT_TRUE(IsOk(apex));
  std::string hash_tree;
  ApexVerityData verity_data;
  auto result = PrepareHashTree(*apex, verity_data, hash_tree);
  ASSERT_FALSE(IsOk(result));
  ASSERT_THAT(
      result.error().message(),
      ::testing::HasSubstr("Cannot prepare HashTree of compressed APEX"));
}

}  // namespace apex
}  // namespace android
