/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmCTestBuildAndTestHandler.h"

#include "cmCTest.h"
#include "cmCTestTestHandler.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
#include "cmake.h"

#include "cmsys/Process.h"
#include <chrono>
#include <cstring>
#include <ratio>
#include <stdlib.h>

cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
{
  this->BuildTwoConfig = false;
  this->BuildNoClean = false;
  this->BuildNoCMake = false;
  this->Timeout = cmDuration::zero();
}

void cmCTestBuildAndTestHandler::Initialize()
{
  this->BuildTargets.clear();
  this->Superclass::Initialize();
}

const char* cmCTestBuildAndTestHandler::GetOutput()
{
  return this->Output.c_str();
}
int cmCTestBuildAndTestHandler::ProcessHandler()
{
  this->Output.clear();
  std::string output;
  cmSystemTools::ResetErrorOccuredFlag();
  int retv = this->RunCMakeAndTest(&this->Output);
  cmSystemTools::ResetErrorOccuredFlag();
  return retv;
}

int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
                                         std::ostringstream& out,
                                         std::string& cmakeOutString,
                                         cmake* cm)
{
  std::vector<std::string> args;
  args.push_back(cmSystemTools::GetCMakeCommand());
  args.push_back(this->SourceDir);
  if (!this->BuildGenerator.empty()) {
    args.push_back("-G" + this->BuildGenerator);
  }
  if (!this->BuildGeneratorPlatform.empty()) {
    args.push_back("-A" + this->BuildGeneratorPlatform);
  }
  if (!this->BuildGeneratorToolset.empty()) {
    args.push_back("-T" + this->BuildGeneratorToolset);
  }

  const char* config = nullptr;
  if (!this->CTest->GetConfigType().empty()) {
    config = this->CTest->GetConfigType().c_str();
  }
#ifdef CMAKE_INTDIR
  if (!config) {
    config = CMAKE_INTDIR;
  }
#endif

  if (config) {
    args.push_back("-DCMAKE_BUILD_TYPE:STRING=" + std::string(config));
  }

  for (std::string const& opt : this->BuildOptions) {
    args.push_back(opt);
  }
  if (cm->Run(args) != 0) {
    out << "Error: cmake execution failed\n";
    out << cmakeOutString << "\n";
    if (outstring) {
      *outstring = out.str();
    } else {
      cmCTestLog(this->CTest, ERROR_MESSAGE, out.str() << std::endl);
    }
    return 1;
  }
  // do another config?
  if (this->BuildTwoConfig) {
    if (cm->Run(args) != 0) {
      out << "Error: cmake execution failed\n";
      out << cmakeOutString << "\n";
      if (outstring) {
        *outstring = out.str();
      } else {
        cmCTestLog(this->CTest, ERROR_MESSAGE, out.str() << std::endl);
      }
      return 1;
    }
  }
  out << "======== CMake output     ======\n";
  out << cmakeOutString;
  out << "======== End CMake output ======\n";
  return 0;
}

class cmCTestBuildAndTestCaptureRAII
{
  cmake& CM;

public:
  cmCTestBuildAndTestCaptureRAII(cmake& cm, std::string& s)
    : CM(cm)
  {
    cmSystemTools::SetMessageCallback(
      [&s](const std::string& msg, const char* /*unused*/) {
        s += msg;
        s += "\n";
      });

    cmSystemTools::SetStdoutCallback([&s](std::string const& m) { s += m; });
    cmSystemTools::SetStderrCallback([&s](std::string const& m) { s += m; });

    this->CM.SetProgressCallback([&s](const char* msg, float /*unused*/) {
      s += msg;
      s += "\n";
    });
  }

  ~cmCTestBuildAndTestCaptureRAII()
  {
    this->CM.SetProgressCallback(nullptr);
    cmSystemTools::SetStderrCallback(nullptr);
    cmSystemTools::SetStdoutCallback(nullptr);
    cmSystemTools::SetMessageCallback(nullptr);
  }
};

int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
{
  // if the generator and make program are not specified then it is an error
  if (this->BuildGenerator.empty()) {
    if (outstring) {
      *outstring = "--build-and-test requires that the generator "
                   "be provided using the --build-generator "
                   "command line option. ";
    }
    return 1;
  }

  cmake cm(cmake::RoleProject, cmState::Project);
  cm.SetHomeDirectory("");
  cm.SetHomeOutputDirectory("");
  std::string cmakeOutString;
  cmCTestBuildAndTestCaptureRAII captureRAII(cm, cmakeOutString);
  static_cast<void>(captureRAII);
  std::ostringstream out;

  if (this->CTest->GetConfigType().empty() && !this->ConfigSample.empty()) {
    // use the config sample to set the ConfigType
    std::string fullPath;
    std::string resultingConfig;
    std::vector<std::string> extraPaths;
    std::vector<std::string> failed;
    fullPath = cmCTestTestHandler::FindExecutable(
      this->CTest, this->ConfigSample.c_str(), resultingConfig, extraPaths,
      failed);
    if (!fullPath.empty() && !resultingConfig.empty()) {
      this->CTest->SetConfigType(resultingConfig.c_str());
    }
    out << "Using config sample with results: " << fullPath << " and "
        << resultingConfig << std::endl;
  }

  // we need to honor the timeout specified, the timeout include cmake, build
  // and test time
  auto clock_start = std::chrono::steady_clock::now();

  // make sure the binary dir is there
  out << "Internal cmake changing into directory: " << this->BinaryDir
      << std::endl;
  if (!cmSystemTools::FileIsDirectory(this->BinaryDir)) {
    cmSystemTools::MakeDirectory(this->BinaryDir);
  }
  cmWorkingDirectory workdir(this->BinaryDir);
  if (workdir.Failed()) {
    auto msg = "Failed to change working directory to " + this->BinaryDir +
      " : " + std::strerror(workdir.GetLastResult()) + "\n";
    if (outstring) {
      *outstring = msg;
    } else {
      cmCTestLog(this->CTest, ERROR_MESSAGE, msg);
    }
    return 1;
  }

  if (this->BuildNoCMake) {
    // Make the generator available for the Build call below.
    cmGlobalGenerator* gen = cm.CreateGlobalGenerator(this->BuildGenerator);
    cm.SetGlobalGenerator(gen);
    if (!this->BuildGeneratorPlatform.empty()) {
      cmMakefile mf(gen, cm.GetCurrentSnapshot());
      if (!gen->SetGeneratorPlatform(this->BuildGeneratorPlatform, &mf)) {
        return 1;
      }
    }

    // Load the cache to make CMAKE_MAKE_PROGRAM available.
    cm.LoadCache(this->BinaryDir);
  } else {
    // do the cmake step, no timeout here since it is not a sub process
    if (this->RunCMake(outstring, out, cmakeOutString, &cm)) {
      return 1;
    }
  }

  // do the build
  if (this->BuildTargets.empty()) {
    this->BuildTargets.emplace_back();
  }
  for (std::string const& tar : this->BuildTargets) {
    cmDuration remainingTime = std::chrono::seconds(0);
    if (this->Timeout > cmDuration::zero()) {
      remainingTime =
        this->Timeout - (std::chrono::steady_clock::now() - clock_start);
      if (remainingTime <= std::chrono::seconds(0)) {
        if (outstring) {
          *outstring = "--build-and-test timeout exceeded. ";
        }
        return 1;
      }
    }
    std::string output;
    const char* config = nullptr;
    if (!this->CTest->GetConfigType().empty()) {
      config = this->CTest->GetConfigType().c_str();
    }
#ifdef CMAKE_INTDIR
    if (!config) {
      config = CMAKE_INTDIR;
    }
#endif
    if (!config) {
      config = "Debug";
    }
    int retVal = cm.GetGlobalGenerator()->Build(
      cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir,
      this->BuildProject, tar, output, this->BuildMakeProgram, config,
      !this->BuildNoClean, false, false, remainingTime);
    out << output;
    // if the build failed then return
    if (retVal) {
      if (outstring) {
        *outstring = out.str();
      }
      return 1;
    }
  }
  if (outstring) {
    *outstring = out.str();
  }

  // if no test was specified then we are done
  if (this->TestCommand.empty()) {
    return 0;
  }

  // now run the compiled test if we can find it
  // store the final location in fullPath
  std::string fullPath;
  std::string resultingConfig;
  std::vector<std::string> extraPaths;
  // if this->ExecutableDirectory is set try that as well
  if (!this->ExecutableDirectory.empty()) {
    std::string tempPath = this->ExecutableDirectory;
    tempPath += "/";
    tempPath += this->TestCommand;
    extraPaths.push_back(tempPath);
  }
  std::vector<std::string> failed;
  fullPath =
    cmCTestTestHandler::FindExecutable(this->CTest, this->TestCommand.c_str(),
                                       resultingConfig, extraPaths, failed);

  if (!cmSystemTools::FileExists(fullPath)) {
    out << "Could not find path to executable, perhaps it was not built: "
        << this->TestCommand << "\n";
    out << "tried to find it in these places:\n";
    out << fullPath << "\n";
    for (std::string const& fail : failed) {
      out << fail << "\n";
    }
    if (outstring) {
      *outstring = out.str();
    } else {
      cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
    }
    return 1;
  }

  std::vector<const char*> testCommand;
  testCommand.push_back(fullPath.c_str());
  for (std::string const& testCommandArg : this->TestCommandArgs) {
    testCommand.push_back(testCommandArg.c_str());
  }
  testCommand.push_back(nullptr);
  std::string outs;
  int retval = 0;
  // run the test from the this->BuildRunDir if set
  if (!this->BuildRunDir.empty()) {
    out << "Run test in directory: " << this->BuildRunDir << "\n";
    if (!workdir.SetDirectory(this->BuildRunDir)) {
      out << "Failed to change working directory : "
          << std::strerror(workdir.GetLastResult()) << "\n";
      if (outstring) {
        *outstring = out.str();
      } else {
        cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
      }
      return 1;
    }
  }
  out << "Running test command: \"" << fullPath << "\"";
  for (std::string const& testCommandArg : this->TestCommandArgs) {
    out << " \"" << testCommandArg << "\"";
  }
  out << "\n";

  // how much time is remaining
  cmDuration remainingTime = std::chrono::seconds(0);
  if (this->Timeout > cmDuration::zero()) {
    remainingTime =
      this->Timeout - (std::chrono::steady_clock::now() - clock_start);
    if (remainingTime <= std::chrono::seconds(0)) {
      if (outstring) {
        *outstring = "--build-and-test timeout exceeded. ";
      }
      return 1;
    }
  }

  int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr,
                                        remainingTime, nullptr);

  if (runTestRes != cmsysProcess_State_Exited || retval != 0) {
    out << "Test command failed: " << testCommand[0] << "\n";
    retval = 1;
  }

  out << outs << "\n";
  if (outstring) {
    *outstring = out.str();
  } else {
    cmCTestLog(this->CTest, OUTPUT, out.str() << std::endl);
  }
  return retval;
}

int cmCTestBuildAndTestHandler::ProcessCommandLineArguments(
  const std::string& currentArg, size_t& idx,
  const std::vector<std::string>& allArgs)
{
  // --build-and-test options
  if (currentArg.find("--build-and-test", 0) == 0 &&
      idx < allArgs.size() - 1) {
    if (idx + 2 < allArgs.size()) {
      idx++;
      this->SourceDir = allArgs[idx];
      idx++;
      this->BinaryDir = allArgs[idx];
      // dir must exist before CollapseFullPath is called
      cmSystemTools::MakeDirectory(this->BinaryDir);
      this->BinaryDir = cmSystemTools::CollapseFullPath(this->BinaryDir);
      this->SourceDir = cmSystemTools::CollapseFullPath(this->SourceDir);
    } else {
      cmCTestLog(this->CTest, ERROR_MESSAGE,
                 "--build-and-test must have source and binary dir"
                   << std::endl);
      return 0;
    }
  }
  if (currentArg.find("--build-target", 0) == 0 && idx < allArgs.size() - 1) {
    idx++;
    this->BuildTargets.push_back(allArgs[idx]);
  }
  if (currentArg.find("--build-nocmake", 0) == 0) {
    this->BuildNoCMake = true;
  }
  if (currentArg.find("--build-run-dir", 0) == 0 && idx < allArgs.size() - 1) {
    idx++;
    this->BuildRunDir = allArgs[idx];
  }
  if (currentArg.find("--build-two-config", 0) == 0) {
    this->BuildTwoConfig = true;
  }
  if (currentArg.find("--build-exe-dir", 0) == 0 && idx < allArgs.size() - 1) {
    idx++;
    this->ExecutableDirectory = allArgs[idx];
  }
  if (currentArg.find("--test-timeout", 0) == 0 && idx < allArgs.size() - 1) {
    idx++;
    this->Timeout = cmDuration(atof(allArgs[idx].c_str()));
  }
  if (currentArg == "--build-generator" && idx < allArgs.size() - 1) {
    idx++;
    this->BuildGenerator = allArgs[idx];
  }
  if (currentArg == "--build-generator-platform" && idx < allArgs.size() - 1) {
    idx++;
    this->BuildGeneratorPlatform = allArgs[idx];
  }
  if (currentArg == "--build-generator-toolset" && idx < allArgs.size() - 1) {
    idx++;
    this->BuildGeneratorToolset = allArgs[idx];
  }
  if (currentArg.find("--build-project", 0) == 0 && idx < allArgs.size() - 1) {
    idx++;
    this->BuildProject = allArgs[idx];
  }
  if (currentArg.find("--build-makeprogram", 0) == 0 &&
      idx < allArgs.size() - 1) {
    idx++;
    this->BuildMakeProgram = allArgs[idx];
  }
  if (currentArg.find("--build-config-sample", 0) == 0 &&
      idx < allArgs.size() - 1) {
    idx++;
    this->ConfigSample = allArgs[idx];
  }
  if (currentArg.find("--build-noclean", 0) == 0) {
    this->BuildNoClean = true;
  }
  if (currentArg.find("--build-options", 0) == 0) {
    while (idx + 1 < allArgs.size() && allArgs[idx + 1] != "--build-target" &&
           allArgs[idx + 1] != "--test-command") {
      ++idx;
      this->BuildOptions.push_back(allArgs[idx]);
    }
  }
  if (currentArg.find("--test-command", 0) == 0 && idx < allArgs.size() - 1) {
    ++idx;
    this->TestCommand = allArgs[idx];
    while (idx + 1 < allArgs.size()) {
      ++idx;
      this->TestCommandArgs.push_back(allArgs[idx]);
    }
  }
  return 1;
}
