/*
 * 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 <string>
#include <vector>

#include "base/common_art_test.h"
#include "base/file_utils.h"
#include "base/os.h"
#include "exec_utils.h"
#include "oat_file.h"

namespace art {

static const char* kDexDiagContains = "--contains=boot.vdex";
static const char* kDexDiagContainsFails = "--contains=anything_other_than_core.vdex";
static const char* kDexDiagHelp = "--help";
static const char* kDexDiagVerbose = "--verbose";
static const char* kDexDiagBinaryName = "dexdiag";

class DexDiagTest : public CommonArtTest {
 protected:
  void SetUp() override { CommonArtTest::SetUp(); }

  // Path to the dexdiag(d?)[32|64] binary.
  std::string GetDexDiagFilePath() {
    std::string path = GetArtBinDir() + '/' + kDexDiagBinaryName;
    std::string path32 = path + "32";
    // If we have both a 32-bit and a 64-bit build, the 32-bit file will have a 32 suffix.
    if (OS::FileExists(path32.c_str()) && !Is64BitInstructionSet(kRuntimeISA)) {
      return path32;
    } else {
      // This is a 64-bit build or only a single build exists.
      return path;
    }
  }

  std::unique_ptr<OatFile> OpenOatAndVdexFiles() {
    // Open the core.oat file.
    // This is a little convoluted because we have to
    // get the location of the default core image (.../framework/core.oat),
    // find it in the right architecture subdirectory (.../framework/arm/core.oat),
    // Then, opening the oat file has the side-effect of opening the corresponding
    // vdex file (.../framework/arm/core.vdex).
    const std::string default_location = GetCoreOatLocation();
    EXPECT_TRUE(!default_location.empty());
    std::string oat_location = GetSystemImageFilename(default_location.c_str(), kRuntimeISA);
    EXPECT_TRUE(!oat_location.empty());
    std::cout << "==" << oat_location << std::endl;
    std::string error_msg;
    std::unique_ptr<OatFile> oat(OatFile::Open(/*zip_fd=*/-1,
                                               oat_location,
                                               oat_location,
                                               /*executable=*/false,
                                               /*low_4gb=*/false,
                                               &error_msg));
    EXPECT_TRUE(oat != nullptr) << error_msg;
    return oat;
  }

  // Run dexdiag with a custom boot image location.
  bool Exec(pid_t this_pid, const std::vector<std::string>& args, std::string* error_msg) {
    // Invoke 'dexdiag' against the current process.
    // This should succeed because we have a runtime and so it should
    // be able to map in the boot.art and do a diff for it.
    std::vector<std::string> exec_argv;

    // Build the command line "dexdiag <args> this_pid".
    std::string executable_path = GetDexDiagFilePath();
    EXPECT_TRUE(OS::FileExists(executable_path.c_str()))
        << executable_path << " should be a valid file path";
    exec_argv.push_back(executable_path);
    for (const auto& arg : args) {
      exec_argv.push_back(arg);
    }
    exec_argv.push_back(std::to_string(this_pid));

    return ::art::Exec(exec_argv, error_msg);
  }
};

// We can't run these tests on the host, as they will fail when trying to open
// /proc/pid/pagemap.
// On the target, we invoke 'dexdiag' against the current process.
// This should succeed because we have a runtime and so dexdiag should
// be able to find the map for, e.g., boot.vdex and friends.
TEST_F(DexDiagTest, DexDiagHelpTest) {
  // TODO: test the resulting output.
  std::string error_msg;
  ASSERT_TRUE(Exec(getpid(), {kDexDiagHelp}, &error_msg))
      << "Failed to execute -- because: " << error_msg;
}

#if defined(ART_TARGET)
TEST_F(DexDiagTest, DexDiagContainsTest) {
#else
TEST_F(DexDiagTest, DISABLED_DexDiagContainsTest) {
#endif
  std::unique_ptr<OatFile> oat = OpenOatAndVdexFiles();
  // TODO: test the resulting output.
  std::string error_msg;
  ASSERT_TRUE(Exec(getpid(), {kDexDiagContains}, &error_msg))
      << "Failed to execute -- because: " << error_msg;
}

#if defined(ART_TARGET)
TEST_F(DexDiagTest, DexDiagContainsFailsTest) {
#else
TEST_F(DexDiagTest, DISABLED_DexDiagContainsFailsTest) {
#endif
  std::unique_ptr<OatFile> oat = OpenOatAndVdexFiles();
  // TODO: test the resulting output.
  std::string error_msg;
  ASSERT_FALSE(Exec(getpid(), {kDexDiagContainsFails}, &error_msg))
      << "Failed to execute -- because: " << error_msg;
}

#if defined(ART_TARGET)
TEST_F(DexDiagTest, DexDiagVerboseTest) {
#else
TEST_F(DexDiagTest, DISABLED_DexDiagVerboseTest) {
#endif
  // TODO: test the resulting output.
  std::unique_ptr<OatFile> oat = OpenOatAndVdexFiles();
  std::string error_msg;
  ASSERT_TRUE(Exec(getpid(), {kDexDiagVerbose}, &error_msg))
      << "Failed to execute -- because: " << error_msg;
}

}  // namespace art
