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

#include <cstdlib>
#include <cstring>
#include <iostream>

#include "cmsys/FStream.hxx"
#include "cmsys/Process.h"
#include "cmsys/RegularExpression.hxx"

#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
#include "cmake.h"

#ifdef _WIN32
#  include <fcntl.h> // for _O_BINARY
#  include <io.h>    // for _setmode
#  include <stdio.h> // for std{out,err} and fileno
#endif

cmCTestLaunch::cmCTestLaunch(int argc, const char* const* argv)
{
  this->Passthru = true;
  this->Process = nullptr;
  this->ExitCode = 1;
  this->CWD = cmSystemTools::GetCurrentWorkingDirectory();

  if (!this->ParseArguments(argc, argv)) {
    return;
  }

  this->ComputeFileNames();

  this->ScrapeRulesLoaded = false;
  this->HaveOut = false;
  this->HaveErr = false;
  this->Process = cmsysProcess_New();
}

cmCTestLaunch::~cmCTestLaunch()
{
  cmsysProcess_Delete(this->Process);
  if (!this->Passthru) {
    cmSystemTools::RemoveFile(this->LogOut);
    cmSystemTools::RemoveFile(this->LogErr);
  }
}

bool cmCTestLaunch::ParseArguments(int argc, const char* const* argv)
{
  // Launcher options occur first and are separated from the real
  // command line by a '--' option.
  enum Doing
  {
    DoingNone,
    DoingOutput,
    DoingSource,
    DoingLanguage,
    DoingTargetName,
    DoingTargetType,
    DoingBuildDir,
    DoingCount,
    DoingFilterPrefix
  };
  Doing doing = DoingNone;
  int arg0 = 0;
  for (int i = 1; !arg0 && i < argc; ++i) {
    const char* arg = argv[i];
    if (strcmp(arg, "--") == 0) {
      arg0 = i + 1;
    } else if (strcmp(arg, "--output") == 0) {
      doing = DoingOutput;
    } else if (strcmp(arg, "--source") == 0) {
      doing = DoingSource;
    } else if (strcmp(arg, "--language") == 0) {
      doing = DoingLanguage;
    } else if (strcmp(arg, "--target-name") == 0) {
      doing = DoingTargetName;
    } else if (strcmp(arg, "--target-type") == 0) {
      doing = DoingTargetType;
    } else if (strcmp(arg, "--build-dir") == 0) {
      doing = DoingBuildDir;
    } else if (strcmp(arg, "--filter-prefix") == 0) {
      doing = DoingFilterPrefix;
    } else if (doing == DoingOutput) {
      this->OptionOutput = arg;
      doing = DoingNone;
    } else if (doing == DoingSource) {
      this->OptionSource = arg;
      doing = DoingNone;
    } else if (doing == DoingLanguage) {
      this->OptionLanguage = arg;
      if (this->OptionLanguage == "CXX") {
        this->OptionLanguage = "C++";
      }
      doing = DoingNone;
    } else if (doing == DoingTargetName) {
      this->OptionTargetName = arg;
      doing = DoingNone;
    } else if (doing == DoingTargetType) {
      this->OptionTargetType = arg;
      doing = DoingNone;
    } else if (doing == DoingBuildDir) {
      this->OptionBuildDir = arg;
      doing = DoingNone;
    } else if (doing == DoingFilterPrefix) {
      this->OptionFilterPrefix = arg;
      doing = DoingNone;
    }
  }

  // Extract the real command line.
  if (arg0) {
    this->RealArgC = argc - arg0;
    this->RealArgV = argv + arg0;
    for (int i = 0; i < this->RealArgC; ++i) {
      this->HandleRealArg(this->RealArgV[i]);
    }
    return true;
  }
  this->RealArgC = 0;
  this->RealArgV = nullptr;
  std::cerr << "No launch/command separator ('--') found!\n";
  return false;
}

void cmCTestLaunch::HandleRealArg(const char* arg)
{
#ifdef _WIN32
  // Expand response file arguments.
  if (arg[0] == '@' && cmSystemTools::FileExists(arg + 1)) {
    cmsys::ifstream fin(arg + 1);
    std::string line;
    while (cmSystemTools::GetLineFromStream(fin, line)) {
      cmSystemTools::ParseWindowsCommandLine(line.c_str(), this->RealArgs);
    }
    return;
  }
#endif
  this->RealArgs.emplace_back(arg);
}

void cmCTestLaunch::ComputeFileNames()
{
  // We just passthru the behavior of the real command unless the
  // CTEST_LAUNCH_LOGS environment variable is set.
  const char* d = getenv("CTEST_LAUNCH_LOGS");
  if (!(d && *d)) {
    return;
  }
  this->Passthru = false;

  // The environment variable specifies the directory into which we
  // generate build logs.
  this->LogDir = d;
  cmSystemTools::ConvertToUnixSlashes(this->LogDir);
  this->LogDir += "/";

  // We hash the input command working dir and command line to obtain
  // a repeatable and (probably) unique name for log files.
  cmCryptoHash md5(cmCryptoHash::AlgoMD5);
  md5.Initialize();
  md5.Append(this->CWD);
  for (std::string const& realArg : this->RealArgs) {
    md5.Append(realArg);
  }
  this->LogHash = md5.FinalizeHex();

  // We store stdout and stderr in temporary log files.
  this->LogOut = cmStrCat(this->LogDir, "launch-", this->LogHash, "-out.txt");
  this->LogErr = cmStrCat(this->LogDir, "launch-", this->LogHash, "-err.txt");
}

void cmCTestLaunch::RunChild()
{
  // Ignore noopt make rules
  if (this->RealArgs.empty() || this->RealArgs[0] == ":") {
    this->ExitCode = 0;
    return;
  }

  // Prepare to run the real command.
  cmsysProcess* cp = this->Process;
  cmsysProcess_SetCommand(cp, this->RealArgV);

  cmsys::ofstream fout;
  cmsys::ofstream ferr;
  if (this->Passthru) {
    // In passthru mode we just share the output pipes.
    cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
    cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
  } else {
    // In full mode we record the child output pipes to log files.
    fout.open(this->LogOut.c_str(), std::ios::out | std::ios::binary);
    ferr.open(this->LogErr.c_str(), std::ios::out | std::ios::binary);
  }

#ifdef _WIN32
  // Do this so that newline transformation is not done when writing to cout
  // and cerr below.
  _setmode(fileno(stdout), _O_BINARY);
  _setmode(fileno(stderr), _O_BINARY);
#endif

  // Run the real command.
  cmsysProcess_Execute(cp);

  // Record child stdout and stderr if necessary.
  if (!this->Passthru) {
    char* data = nullptr;
    int length = 0;
    cmProcessOutput processOutput;
    std::string strdata;
    while (int p = cmsysProcess_WaitForData(cp, &data, &length, nullptr)) {
      if (p == cmsysProcess_Pipe_STDOUT) {
        processOutput.DecodeText(data, length, strdata, 1);
        fout.write(strdata.c_str(), strdata.size());
        std::cout.write(strdata.c_str(), strdata.size());
        this->HaveOut = true;
      } else if (p == cmsysProcess_Pipe_STDERR) {
        processOutput.DecodeText(data, length, strdata, 2);
        ferr.write(strdata.c_str(), strdata.size());
        std::cerr.write(strdata.c_str(), strdata.size());
        this->HaveErr = true;
      }
    }
    processOutput.DecodeText(std::string(), strdata, 1);
    if (!strdata.empty()) {
      fout.write(strdata.c_str(), strdata.size());
      std::cout.write(strdata.c_str(), strdata.size());
    }
    processOutput.DecodeText(std::string(), strdata, 2);
    if (!strdata.empty()) {
      ferr.write(strdata.c_str(), strdata.size());
      std::cerr.write(strdata.c_str(), strdata.size());
    }
  }

  // Wait for the real command to finish.
  cmsysProcess_WaitForExit(cp, nullptr);
  this->ExitCode = cmsysProcess_GetExitValue(cp);
}

int cmCTestLaunch::Run()
{
  if (!this->Process) {
    std::cerr << "Could not allocate cmsysProcess instance!\n";
    return -1;
  }

  this->RunChild();

  if (this->CheckResults()) {
    return this->ExitCode;
  }

  this->LoadConfig();
  this->WriteXML();

  return this->ExitCode;
}

void cmCTestLaunch::LoadLabels()
{
  if (this->OptionBuildDir.empty() || this->OptionTargetName.empty()) {
    return;
  }

  // Labels are listed in per-target files.
  std::string fname = cmStrCat(this->OptionBuildDir, "/CMakeFiles/",
                               this->OptionTargetName, ".dir/Labels.txt");

  // We are interested in per-target labels for this source file.
  std::string source = this->OptionSource;
  cmSystemTools::ConvertToUnixSlashes(source);

  // Load the labels file.
  cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
  if (!fin) {
    return;
  }
  bool inTarget = true;
  bool inSource = false;
  std::string line;
  while (cmSystemTools::GetLineFromStream(fin, line)) {
    if (line.empty() || line[0] == '#') {
      // Ignore blank and comment lines.
      continue;
    }
    if (line[0] == ' ') {
      // Label lines appear indented by one space.
      if (inTarget || inSource) {
        this->Labels.insert(line.substr(1));
      }
    } else if (!this->OptionSource.empty() && !inSource) {
      // Non-indented lines specify a source file name.  The first one
      // is the end of the target-wide labels.  Use labels following a
      // matching source.
      inTarget = false;
      inSource = this->SourceMatches(line, source);
    } else {
      return;
    }
  }
}

bool cmCTestLaunch::SourceMatches(std::string const& lhs,
                                  std::string const& rhs)
{
  // TODO: Case sensitivity, UseRelativePaths, etc.  Note that both
  // paths in the comparison get generated by CMake.  This is done for
  // every source in the target, so it should be efficient (cannot use
  // cmSystemTools::IsSameFile).
  return lhs == rhs;
}

bool cmCTestLaunch::IsError() const
{
  return this->ExitCode != 0;
}

void cmCTestLaunch::WriteXML()
{
  // Name the xml file.
  std::string logXML =
    cmStrCat(this->LogDir, this->IsError() ? "error-" : "warning-",
             this->LogHash, ".xml");

  // Use cmGeneratedFileStream to atomically create the report file.
  cmGeneratedFileStream fxml(logXML);
  cmXMLWriter xml(fxml, 2);
  cmXMLElement e2(xml, "Failure");
  e2.Attribute("type", this->IsError() ? "Error" : "Warning");
  this->WriteXMLAction(e2);
  this->WriteXMLCommand(e2);
  this->WriteXMLResult(e2);
  this->WriteXMLLabels(e2);
}

void cmCTestLaunch::WriteXMLAction(cmXMLElement& e2)
{
  e2.Comment("Meta-information about the build action");
  cmXMLElement e3(e2, "Action");

  // TargetName
  if (!this->OptionTargetName.empty()) {
    e3.Element("TargetName", this->OptionTargetName);
  }

  // Language
  if (!this->OptionLanguage.empty()) {
    e3.Element("Language", this->OptionLanguage);
  }

  // SourceFile
  if (!this->OptionSource.empty()) {
    std::string source = this->OptionSource;
    cmSystemTools::ConvertToUnixSlashes(source);

    // If file is in source tree use its relative location.
    if (cmSystemTools::FileIsFullPath(this->SourceDir) &&
        cmSystemTools::FileIsFullPath(source) &&
        cmSystemTools::IsSubDirectory(source, this->SourceDir)) {
      source = cmSystemTools::RelativePath(this->SourceDir, source);
    }

    e3.Element("SourceFile", source);
  }

  // OutputFile
  if (!this->OptionOutput.empty()) {
    e3.Element("OutputFile", this->OptionOutput);
  }

  // OutputType
  const char* outputType = nullptr;
  if (!this->OptionTargetType.empty()) {
    if (this->OptionTargetType == "EXECUTABLE") {
      outputType = "executable";
    } else if (this->OptionTargetType == "SHARED_LIBRARY") {
      outputType = "shared library";
    } else if (this->OptionTargetType == "MODULE_LIBRARY") {
      outputType = "module library";
    } else if (this->OptionTargetType == "STATIC_LIBRARY") {
      outputType = "static library";
    }
  } else if (!this->OptionSource.empty()) {
    outputType = "object file";
  }
  if (outputType) {
    e3.Element("OutputType", outputType);
  }
}

void cmCTestLaunch::WriteXMLCommand(cmXMLElement& e2)
{
  e2.Comment("Details of command");
  cmXMLElement e3(e2, "Command");
  if (!this->CWD.empty()) {
    e3.Element("WorkingDirectory", this->CWD);
  }
  for (std::string const& realArg : this->RealArgs) {
    e3.Element("Argument", realArg);
  }
}

void cmCTestLaunch::WriteXMLResult(cmXMLElement& e2)
{
  e2.Comment("Result of command");
  cmXMLElement e3(e2, "Result");

  // StdOut
  this->DumpFileToXML(e3, "StdOut", this->LogOut);

  // StdErr
  this->DumpFileToXML(e3, "StdErr", this->LogErr);

  // ExitCondition
  cmXMLElement e4(e3, "ExitCondition");
  cmsysProcess* cp = this->Process;
  switch (cmsysProcess_GetState(cp)) {
    case cmsysProcess_State_Starting:
      e4.Content("No process has been executed");
      break;
    case cmsysProcess_State_Executing:
      e4.Content("The process is still executing");
      break;
    case cmsysProcess_State_Disowned:
      e4.Content("Disowned");
      break;
    case cmsysProcess_State_Killed:
      e4.Content("Killed by parent");
      break;

    case cmsysProcess_State_Expired:
      e4.Content("Killed when timeout expired");
      break;
    case cmsysProcess_State_Exited:
      e4.Content(this->ExitCode);
      break;
    case cmsysProcess_State_Exception:
      e4.Content("Terminated abnormally: ");
      e4.Content(cmsysProcess_GetExceptionString(cp));
      break;
    case cmsysProcess_State_Error:
      e4.Content("Error administrating child process: ");
      e4.Content(cmsysProcess_GetErrorString(cp));
      break;
  }
}

void cmCTestLaunch::WriteXMLLabels(cmXMLElement& e2)
{
  this->LoadLabels();
  if (!this->Labels.empty()) {
    e2.Comment("Interested parties");
    cmXMLElement e3(e2, "Labels");
    for (std::string const& label : this->Labels) {
      e3.Element("Label", label);
    }
  }
}

void cmCTestLaunch::DumpFileToXML(cmXMLElement& e3, const char* tag,
                                  std::string const& fname)
{
  cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);

  std::string line;
  const char* sep = "";

  cmXMLElement e4(e3, tag);
  while (cmSystemTools::GetLineFromStream(fin, line)) {
    if (MatchesFilterPrefix(line)) {
      continue;
    }
    if (this->Match(line, this->RegexWarningSuppress)) {
      line = cmStrCat("[CTest: warning suppressed] ", line);
    } else if (this->Match(line, this->RegexWarning)) {
      line = cmStrCat("[CTest: warning matched] ", line);
    }
    e4.Content(sep);
    e4.Content(line);
    sep = "\n";
  }
}

bool cmCTestLaunch::CheckResults()
{
  // Skip XML in passthru mode.
  if (this->Passthru) {
    return true;
  }

  // We always report failure for error conditions.
  if (this->IsError()) {
    return false;
  }

  // Scrape the output logs to look for warnings.
  if ((this->HaveErr && this->ScrapeLog(this->LogErr)) ||
      (this->HaveOut && this->ScrapeLog(this->LogOut))) {
    return false;
  }
  return true;
}

void cmCTestLaunch::LoadScrapeRules()
{
  if (this->ScrapeRulesLoaded) {
    return;
  }
  this->ScrapeRulesLoaded = true;

  // Common compiler warning formats.  These are much simpler than the
  // full log-scraping expressions because we do not need to extract
  // file and line information.
  this->RegexWarning.emplace_back("(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]");
  this->RegexWarning.emplace_back("(^|[ :])[Rr][Ee][Mm][Aa][Rr][Kk]");
  this->RegexWarning.emplace_back("(^|[ :])[Nn][Oo][Tt][Ee]");

  // Load custom match rules given to us by CTest.
  this->LoadScrapeRules("Warning", this->RegexWarning);
  this->LoadScrapeRules("WarningSuppress", this->RegexWarningSuppress);
}

void cmCTestLaunch::LoadScrapeRules(
  const char* purpose, std::vector<cmsys::RegularExpression>& regexps)
{
  std::string fname = cmStrCat(this->LogDir, "Custom", purpose, ".txt");
  cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
  std::string line;
  cmsys::RegularExpression rex;
  while (cmSystemTools::GetLineFromStream(fin, line)) {
    if (rex.compile(line)) {
      regexps.push_back(rex);
    }
  }
}

bool cmCTestLaunch::ScrapeLog(std::string const& fname)
{
  this->LoadScrapeRules();

  // Look for log file lines matching warning expressions but not
  // suppression expressions.
  cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
  std::string line;
  while (cmSystemTools::GetLineFromStream(fin, line)) {
    if (MatchesFilterPrefix(line)) {
      continue;
    }

    if (this->Match(line, this->RegexWarning) &&
        !this->Match(line, this->RegexWarningSuppress)) {
      return true;
    }
  }
  return false;
}

bool cmCTestLaunch::Match(std::string const& line,
                          std::vector<cmsys::RegularExpression>& regexps)
{
  for (cmsys::RegularExpression& r : regexps) {
    if (r.find(line)) {
      return true;
    }
  }
  return false;
}

bool cmCTestLaunch::MatchesFilterPrefix(std::string const& line) const
{
  return !this->OptionFilterPrefix.empty() &&
    cmHasPrefix(line, this->OptionFilterPrefix);
}

int cmCTestLaunch::Main(int argc, const char* const argv[])
{
  if (argc == 2) {
    std::cerr << "ctest --launch: this mode is for internal CTest use only"
              << std::endl;
    return 1;
  }
  cmCTestLaunch self(argc, argv);
  return self.Run();
}

void cmCTestLaunch::LoadConfig()
{
  cmake cm(cmake::RoleScript, cmState::CTest);
  cm.SetHomeDirectory("");
  cm.SetHomeOutputDirectory("");
  cm.GetCurrentSnapshot().SetDefaultDefinitions();
  cmGlobalGenerator gg(&cm);
  cmMakefile mf(&gg, cm.GetCurrentSnapshot());
  std::string fname = cmStrCat(this->LogDir, "CTestLaunchConfig.cmake");
  if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname)) {
    this->SourceDir = mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
    cmSystemTools::ConvertToUnixSlashes(this->SourceDir);
  }
}
