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

#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
#include "cmake.h"

#include <cstring>
#include <sstream>
#include <stdlib.h>

class cmExecutionStatus;

cmCTestHandlerCommand::cmCTestHandlerCommand()
{
  const size_t INIT_SIZE = 100;
  size_t cc;
  this->Arguments.reserve(INIT_SIZE);
  for (cc = 0; cc < INIT_SIZE; ++cc) {
    this->Arguments.push_back(nullptr);
  }
  this->Arguments[ct_RETURN_VALUE] = "RETURN_VALUE";
  this->Arguments[ct_CAPTURE_CMAKE_ERROR] = "CAPTURE_CMAKE_ERROR";
  this->Arguments[ct_SOURCE] = "SOURCE";
  this->Arguments[ct_BUILD] = "BUILD";
  this->Arguments[ct_SUBMIT_INDEX] = "SUBMIT_INDEX";
  this->Last = ct_LAST;
  this->AppendXML = false;
  this->Quiet = false;
}

namespace {
// class to save and restore the error state for ctest_* commands
// if a ctest_* command has a CAPTURE_CMAKE_ERROR then put the error
// state into there and restore the system wide error to what
// it was before the command ran
class SaveRestoreErrorState
{
public:
  SaveRestoreErrorState()
  {
    this->InitialErrorState = cmSystemTools::GetErrorOccuredFlag();
    cmSystemTools::ResetErrorOccuredFlag(); // rest the error state
    this->CaptureCMakeErrorValue = false;
  }
  // if the function has a CAPTURE_CMAKE_ERROR then we should restore
  // the error state to what it was before the function was run
  // if not then let the error state be what it is
  void CaptureCMakeError() { this->CaptureCMakeErrorValue = true; }
  ~SaveRestoreErrorState()
  {
    // if we are not saving the return value then make sure
    // if it was in error it goes back to being in error
    // otherwise leave it be what it is
    if (!this->CaptureCMakeErrorValue) {
      if (this->InitialErrorState) {
        cmSystemTools::SetErrorOccured();
      }
      return;
    }
    // if we have saved the error in a return variable
    // then put things back exactly like they were
    bool currentState = cmSystemTools::GetErrorOccuredFlag();
    // if the state changed during this command we need
    // to handle it, if not then nothing needs to be done
    if (currentState != this->InitialErrorState) {
      // restore the initial error state
      if (this->InitialErrorState) {
        cmSystemTools::SetErrorOccured();
      } else {
        cmSystemTools::ResetErrorOccuredFlag();
      }
    }
  }

private:
  bool InitialErrorState;
  bool CaptureCMakeErrorValue;
};
}

bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
                                        cmExecutionStatus& /*unused*/)
{
  // save error state and restore it if needed
  SaveRestoreErrorState errorState;
  // Allocate space for argument values.
  this->Values.clear();
  this->Values.resize(this->Last, nullptr);

  // Process input arguments.
  this->ArgumentDoing = ArgumentDoingNone;
  // look at all arguments and do not short circuit on the first
  // bad one so that CAPTURE_CMAKE_ERROR can override setting the
  // global error state
  bool foundBadArgument = false;
  for (std::string const& arg : args) {
    // Check this argument.
    if (!this->CheckArgumentKeyword(arg) && !this->CheckArgumentValue(arg)) {
      std::ostringstream e;
      e << "called with unknown argument \"" << arg << "\".";
      this->SetError(e.str());
      foundBadArgument = true;
    }
    // note bad argument
    if (this->ArgumentDoing == ArgumentDoingError) {
      foundBadArgument = true;
    }
  }
  bool capureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] &&
                           *this->Values[ct_CAPTURE_CMAKE_ERROR]);
  // now that arguments are parsed check to see if there is a
  // CAPTURE_CMAKE_ERROR specified let the errorState object know.
  if (capureCMakeError) {
    errorState.CaptureCMakeError();
  }
  // if we found a bad argument then exit before running command
  if (foundBadArgument) {
    // store the cmake error
    if (capureCMakeError) {
      this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                    "-1");
      std::string const err = this->GetName() + " " + this->GetError();
      if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) {
        cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
      }
      // return success because failure is recorded in CAPTURE_CMAKE_ERROR
      return true;
    }
    // return failure because of bad argument
    return false;
  }

  // Set the config type of this ctest to the current value of the
  // CTEST_CONFIGURATION_TYPE script variable if it is defined.
  // The current script value trumps the -C argument on the command
  // line.
  const char* ctestConfigType =
    this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE");
  if (ctestConfigType) {
    this->CTest->SetConfigType(ctestConfigType);
  }

  if (this->Values[ct_BUILD]) {
    this->CTest->SetCTestConfiguration(
      "BuildDirectory",
      cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(),
      this->Quiet);
  } else {
    std::string const& bdir =
      this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY");
    if (!bdir.empty()) {
      this->CTest->SetCTestConfiguration(
        "BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(),
        this->Quiet);
    } else {
      cmCTestLog(this->CTest, ERROR_MESSAGE,
                 "CTEST_BINARY_DIRECTORY not set" << std::endl;);
    }
  }
  if (this->Values[ct_SOURCE]) {
    cmCTestLog(this->CTest, DEBUG,
               "Set source directory to: " << this->Values[ct_SOURCE]
                                           << std::endl);
    this->CTest->SetCTestConfiguration(
      "SourceDirectory",
      cmSystemTools::CollapseFullPath(this->Values[ct_SOURCE]).c_str(),
      this->Quiet);
  } else {
    this->CTest->SetCTestConfiguration(
      "SourceDirectory",
      cmSystemTools::CollapseFullPath(
        this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY"))
        .c_str(),
      this->Quiet);
  }

  if (const char* changeId =
        this->Makefile->GetDefinition("CTEST_CHANGE_ID")) {
    this->CTest->SetCTestConfiguration("ChangeId", changeId, this->Quiet);
  }

  cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
  cmCTestGenericHandler* handler = this->InitializeHandler();
  if (!handler) {
    cmCTestLog(this->CTest, ERROR_MESSAGE,
               "Cannot instantiate test handler " << this->GetName()
                                                  << std::endl);
    if (capureCMakeError) {
      this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                    "-1");
      const char* err = this->GetError();
      if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
        cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n");
      }
      return true;
    }
    return false;
  }

  handler->SetAppendXML(this->AppendXML);

  handler->PopulateCustomVectors(this->Makefile);
  if (this->Values[ct_SUBMIT_INDEX]) {
    if (!this->CTest->GetDropSiteCDash() &&
        this->CTest->GetDartVersion() <= 1) {
      cmCTestLog(
        this->CTest, ERROR_MESSAGE,
        "Dart before version 2.0 does not support collecting submissions."
          << std::endl
          << "Please upgrade the server to Dart 2 or higher, or do not use "
             "SUBMIT_INDEX."
          << std::endl);
    } else {
      handler->SetSubmitIndex(atoi(this->Values[ct_SUBMIT_INDEX]));
    }
  }
  cmWorkingDirectory workdir(
    this->CTest->GetCTestConfiguration("BuildDirectory"));
  if (workdir.Failed()) {
    this->SetError("failed to change directory to " +
                   this->CTest->GetCTestConfiguration("BuildDirectory") +
                   " : " + std::strerror(workdir.GetLastResult()));
    if (capureCMakeError) {
      this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                    "-1");
      cmCTestLog(this->CTest, ERROR_MESSAGE,
                 this->GetName() << " " << this->GetError() << "\n");
      // return success because failure is recorded in CAPTURE_CMAKE_ERROR
      return true;
    }
    return false;
  }

  int res = handler->ProcessHandler();
  if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
    std::ostringstream str;
    str << res;
    this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE],
                                  str.str().c_str());
  }
  this->ProcessAdditionalValues(handler);
  // log the error message if there was an error
  if (capureCMakeError) {
    const char* returnString = "0";
    if (cmSystemTools::GetErrorOccuredFlag()) {
      returnString = "-1";
      const char* err = this->GetError();
      // print out the error if it is not "unknown error" which means
      // there was no message
      if (err && !cmSystemTools::FindLastString(err, "unknown error.")) {
        cmCTestLog(this->CTest, ERROR_MESSAGE, err);
      }
    }
    // store the captured cmake error state 0 or -1
    this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
                                  returnString);
  }
  return true;
}

void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*)
{
}

bool cmCTestHandlerCommand::CheckArgumentKeyword(std::string const& arg)
{
  // Look for non-value arguments common to all commands.
  if (arg == "APPEND") {
    this->ArgumentDoing = ArgumentDoingNone;
    this->AppendXML = true;
    return true;
  }
  if (arg == "QUIET") {
    this->ArgumentDoing = ArgumentDoingNone;
    this->Quiet = true;
    return true;
  }

  // Check for a keyword in our argument/value table.
  for (unsigned int k = 0; k < this->Arguments.size(); ++k) {
    if (this->Arguments[k] && arg == this->Arguments[k]) {
      this->ArgumentDoing = ArgumentDoingKeyword;
      this->ArgumentIndex = k;
      return true;
    }
  }
  return false;
}

bool cmCTestHandlerCommand::CheckArgumentValue(std::string const& arg)
{
  if (this->ArgumentDoing == ArgumentDoingKeyword) {
    this->ArgumentDoing = ArgumentDoingNone;
    unsigned int k = this->ArgumentIndex;
    if (this->Values[k]) {
      std::ostringstream e;
      e << "Called with more than one value for " << this->Arguments[k];
      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
      this->ArgumentDoing = ArgumentDoingError;
      return true;
    }
    this->Values[k] = arg.c_str();
    cmCTestLog(this->CTest, DEBUG,
               "Set " << this->Arguments[k] << " to " << arg << "\n");
    return true;
  }
  return false;
}
