/*
 * Copyright (C) 2017 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 <gtest/gtest.h>

#include <string>

#include "arch/instruction_set.h"
#include "base/compiler_filter.h"
#include "dexopt_test.h"
#include "dexoptanalyzer.h"

namespace art {
namespace dexoptanalyzer {

class DexoptAnalyzerTest : public DexoptTest {
 protected:
  std::string GetDexoptAnalyzerCmd() {
    std::string file_path = GetArtBinDir() + "/dexoptanalyzer";
    if (kIsDebugBuild) {
      file_path += 'd';
    }
    EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
    return file_path;
  }

  int Analyze(const std::string& dex_file,
              CompilerFilter::Filter compiler_filter,
              ProfileAnalysisResult profile_analysis_result,
              const char* class_loader_context,
              bool downgrade = false) {
    std::string dexoptanalyzer_cmd = GetDexoptAnalyzerCmd();
    std::vector<std::string> argv_str;
    argv_str.push_back(dexoptanalyzer_cmd);
    argv_str.push_back("--dex-file=" + dex_file);
    argv_str.push_back("--isa=" + std::string(GetInstructionSetString(kRuntimeISA)));
    argv_str.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(compiler_filter));
    argv_str.push_back("--profile-analysis-result=" +
        std::to_string(static_cast<int>(profile_analysis_result)));
    if (downgrade) {
      argv_str.push_back("--downgrade");
    }

    argv_str.push_back("--runtime-arg");
    argv_str.push_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()));
    argv_str.push_back("--runtime-arg");
    argv_str.push_back(GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
    argv_str.push_back("--image=" + GetImageLocation());
    argv_str.push_back("--android-data=" + android_data_);
    if (class_loader_context != nullptr) {
      argv_str.push_back("--class-loader-context=" + std::string(class_loader_context));
    }

    std::string error;
    return ExecAndReturnCode(argv_str, &error);
  }

  int DexoptanalyzerToOatFileAssistant(int dexoptanalyzerResult) {
    switch (dexoptanalyzerResult) {
      case 0: return OatFileAssistant::kNoDexOptNeeded;
      case 1: return OatFileAssistant::kDex2OatFromScratch;
      case 2: return OatFileAssistant::kDex2OatForBootImage;
      case 3: return OatFileAssistant::kDex2OatForFilter;
      case 4: return -OatFileAssistant::kDex2OatForBootImage;
      case 5: return -OatFileAssistant::kDex2OatForFilter;
      default: return dexoptanalyzerResult;
    }
  }

  // Verify that the output of dexoptanalyzer for the given arguments is the same
  // as the output of OatFileAssistant::GetDexOptNeeded.
  void Verify(const std::string& dex_file,
              CompilerFilter::Filter compiler_filter,
              ProfileAnalysisResult profile_analysis_result =
                  ProfileAnalysisResult::kDontOptimizeSmallDelta,
              bool downgrade = false,
              const char* class_loader_context = "PCL[]") {
    std::unique_ptr<ClassLoaderContext> context = class_loader_context == nullptr
        ? nullptr
        : ClassLoaderContext::Create(class_loader_context);
    if (context != nullptr) {
      std::vector<int> context_fds;
      ASSERT_TRUE(context->OpenDexFiles("", context_fds, /*only_read_checksums*/ true));
    }

    int dexoptanalyzerResult = Analyze(
        dex_file, compiler_filter, profile_analysis_result, class_loader_context, downgrade);
    dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
    OatFileAssistant oat_file_assistant(dex_file.c_str(),
                                        kRuntimeISA,
                                        context.get(),
                                        /*load_executable=*/ false);
    bool assume_profile_changed = profile_analysis_result == ProfileAnalysisResult::kOptimize;
    int assistantResult = oat_file_assistant.GetDexOptNeeded(
        compiler_filter, assume_profile_changed, downgrade);
    EXPECT_EQ(assistantResult, dexoptanalyzerResult);
  }
};

// The tests below exercise the same test case from oat_file_assistant_test.cc.

// Case: We have a DEX file, but no ODEX file for it.
TEST_F(DexoptAnalyzerTest, DexNoOat) {
  std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
  Copy(GetDexSrc1(), dex_location);

  Verify(dex_location, CompilerFilter::kSpeed);
  Verify(dex_location, CompilerFilter::kVerify);
  Verify(dex_location, CompilerFilter::kSpeedProfile);
  Verify(dex_location, CompilerFilter::kSpeed,
      ProfileAnalysisResult::kDontOptimizeSmallDelta, false, nullptr);
}

// Case: We have a DEX file and up-to-date ODEX file for it.
TEST_F(DexoptAnalyzerTest, OatUpToDate) {
  std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
  std::string odex_location = GetOdexDir() + "/OatUpToDate.odex";
  Copy(GetDexSrc1(), dex_location);
  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);

  Verify(dex_location, CompilerFilter::kSpeed);
  Verify(dex_location, CompilerFilter::kVerify);
  Verify(dex_location, CompilerFilter::kEverything);
  Verify(dex_location, CompilerFilter::kSpeed,
      ProfileAnalysisResult::kDontOptimizeSmallDelta, false, nullptr);
}

// Case: We have a DEX file and speed-profile ODEX file for it.
TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) {
  std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
  std::string odex_location = GetOdexDir() + "/ProfileOatUpToDate.odex";
  Copy(GetDexSrc1(), dex_location);
  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeedProfile);

  Verify(dex_location, CompilerFilter::kSpeedProfile,
      ProfileAnalysisResult::kDontOptimizeSmallDelta);
  Verify(dex_location, CompilerFilter::kVerify, ProfileAnalysisResult::kDontOptimizeSmallDelta);
  Verify(dex_location, CompilerFilter::kSpeedProfile, ProfileAnalysisResult::kOptimize);
  Verify(dex_location, CompilerFilter::kVerify, ProfileAnalysisResult::kOptimize);
}

// Case: We have a DEX file, verify odex file for it, and we ask if it's up to date
// when the profiles are empty or full.
TEST_F(DexoptAnalyzerTest, VerifyAndEmptyProfiles) {
  std::string dex_location = GetScratchDir() + "/VerifyAndEmptyProfiles.jar";
  std::string odex_location = GetOdexDir() + "/VerifyAndEmptyProfiles.odex";
  Copy(GetDexSrc1(), dex_location);

  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerify);

  // If we want to speed-profile something that was verified, do it even if
  // the profile analysis returns kDontOptimizeSmallDelta (it means that we do have profile data,
  // so a transition verify -> speed-profile is still worth).
  ASSERT_EQ(
      static_cast<int>(ReturnCode::kDex2OatForFilterOdex),
      Analyze(dex_location, CompilerFilter::kSpeedProfile,
          ProfileAnalysisResult::kDontOptimizeSmallDelta, "PCL[]"));
  // If we want to speed-profile something that was verified but the profiles are empty,
  // don't do it - there will be no gain.
  ASSERT_EQ(
      static_cast<int>(ReturnCode::kNoDexOptNeeded),
      Analyze(dex_location, CompilerFilter::kSpeedProfile,
          ProfileAnalysisResult::kDontOptimizeEmptyProfiles, "PCL[]"));
  // Standard case where we need to re-compile a speed-profile because of sufficient new
  // information in the profile.
  ASSERT_EQ(
      static_cast<int>(ReturnCode::kDex2OatForFilterOdex),
      Analyze(dex_location, CompilerFilter::kSpeedProfile,
          ProfileAnalysisResult::kOptimize, "PCL[]"));
}

TEST_F(DexoptAnalyzerTest, Downgrade) {
  std::string dex_location = GetScratchDir() + "/Downgrade.jar";
  std::string odex_location = GetOdexDir() + "/Downgrade.odex";
  Copy(GetDexSrc1(), dex_location);
  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerify);

  Verify(dex_location, CompilerFilter::kSpeedProfile,
      ProfileAnalysisResult::kDontOptimizeSmallDelta, true);
  Verify(dex_location, CompilerFilter::kVerify,
      ProfileAnalysisResult::kDontOptimizeSmallDelta, true);
}

// Case: We have a MultiDEX file and up-to-date ODEX file for it.
TEST_F(DexoptAnalyzerTest, MultiDexOatUpToDate) {
  std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
  std::string odex_location = GetOdexDir() + "/MultiDexOatUpToDate.odex";

  Copy(GetMultiDexSrc1(), dex_location);
  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);

  Verify(dex_location, CompilerFilter::kSpeed, ProfileAnalysisResult::kDontOptimizeSmallDelta);
}

// Case: We have a MultiDEX file where the secondary dex file is out of date.
TEST_F(DexoptAnalyzerTest, MultiDexSecondaryOutOfDate) {
  std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
  std::string odex_location = GetOdexDir() + "/MultiDexSecondaryOutOfDate.odex";

  // Compile code for GetMultiDexSrc1.
  Copy(GetMultiDexSrc1(), dex_location);
  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);

  // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
  // is out of date.
  Copy(GetMultiDexSrc2(), dex_location);

  Verify(dex_location, CompilerFilter::kSpeed, ProfileAnalysisResult::kDontOptimizeSmallDelta);
}

// Case: We have a DEX file and an ODEX file out of date with respect to the
// dex checksum.
TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) {
  std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
  std::string odex_location = GetOdexDir() + "/OatDexOutOfDate.odex";

  // We create a dex, generate an oat for it, then overwrite the dex with a
  // different dex to make the oat out of date.
  Copy(GetDexSrc1(), dex_location);
  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
  Copy(GetDexSrc2(), dex_location);

  Verify(dex_location, CompilerFilter::kSpeed);
}

// Case: We have a DEX file and an ODEX file out of date with respect to the
// boot image.
TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) {
  std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
  std::string odex_location = GetOdexDir() + "/OatImageOutOfDate.odex";

  Copy(GetDexSrc1(), dex_location);
  GenerateOatForTest(dex_location,
                     odex_location,
                     CompilerFilter::kSpeed,
                     /*with_alternate_image=*/true);

  Verify(dex_location, CompilerFilter::kVerify);
  Verify(dex_location, CompilerFilter::kSpeed);
}

// Case: We have a DEX file and an ODEX file, but no OAT file.
TEST_F(DexoptAnalyzerTest, DexOdexNoOat) {
  std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
  std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";

  Copy(GetDexSrc1(), dex_location);
  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);

  Verify(dex_location, CompilerFilter::kSpeed);
  Verify(dex_location, CompilerFilter::kEverything);
}

// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
// OAT file. Expect: The status is kNoDexOptNeeded.
TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) {
  std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";

  Copy(GetResourceOnlySrc1(), dex_location);

  Verify(dex_location, CompilerFilter::kSpeed);
  Verify(dex_location, CompilerFilter::kVerify);
}

// Case: We have a DEX file, an ODEX file and an OAT file.
TEST_F(DexoptAnalyzerTest, OdexOatOverlap) {
  std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
  std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
  std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";

  Copy(GetDexSrc1(), dex_location);
  GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);

  // Create the oat file by copying the odex so they are located in the same
  // place in memory.
  Copy(odex_location, oat_location);

  Verify(dex_location, CompilerFilter::kSpeed);
}

// Case: Non-standard extension for dex file.
TEST_F(DexoptAnalyzerTest, LongDexExtension) {
  std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
  Copy(GetDexSrc1(), dex_location);

  Verify(dex_location, CompilerFilter::kSpeed);
}

// Case: Very short, non-existent Dex location.
TEST_F(DexoptAnalyzerTest, ShortDexLocation) {
  std::string dex_location = "/xx";

  Verify(dex_location, CompilerFilter::kSpeed);
}

// Case: We have a DEX file and up-to-date OAT file for it, and we check with
// a class loader context.
TEST_F(DexoptAnalyzerTest, ClassLoaderContext) {
  std::string dex_location1 = GetScratchDir() + "/DexToAnalyze.jar";
  std::string odex_location1 = GetOdexDir() + "/DexToAnalyze.odex";
  std::string dex_location2 = GetScratchDir() + "/DexInContext.jar";
  Copy(GetDexSrc1(), dex_location1);
  Copy(GetDexSrc2(), dex_location2);

  std::string class_loader_context = "PCL[" + dex_location2 + "]";
  std::string class_loader_context_option = "--class-loader-context=PCL[" + dex_location2 + "]";

  // Generate the odex to get the class loader context also open the dex files.
  GenerateOdexForTest(dex_location1, odex_location1, CompilerFilter::kSpeed, /* compilation_reason= */ nullptr, /* extra_args= */ { class_loader_context_option });

  Verify(dex_location1, CompilerFilter::kSpeed, ProfileAnalysisResult::kDontOptimizeSmallDelta,
      false, class_loader_context.c_str());
}

}  // namespace dexoptanalyzer
}  // namespace art
