/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/

#include "cmCTestBuildAndTestHandler.h"

#include "cmSystemTools.h"
#include "cmCTest.h"
#include "cmake.h"
#include "cmGlobalGenerator.h"
#include <cmsys/Process.h>
#include "cmCTestTestHandler.h"
#include "cmCacheManager.h"

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

//----------------------------------------------------------------------
void cmCTestBuildAndTestHandler::Initialize()
{
  this->BuildTargets.erase(
    this->BuildTargets.begin(), this->BuildTargets.end());
  this->Superclass::Initialize();
}

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

//----------------------------------------------------------------------
int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
  cmOStringStream &out, std::string &cmakeOutString, std::string &cwd,
  cmake *cm)
{
  unsigned int k;
  std::vector<std::string> args;
  args.push_back(cmSystemTools::GetCMakeCommand());
  args.push_back(this->SourceDir);
  if(this->BuildGenerator.size())
    {
    std::string generator = "-G";
    generator += this->BuildGenerator;
    args.push_back(generator);
    }
  if(!this->BuildGeneratorPlatform.empty())
    {
    std::string platform = "-A";
    platform += this->BuildGeneratorPlatform;
    args.push_back(platform);
    }
  if(this->BuildGeneratorToolset.size())
    {
    std::string toolset = "-T";
    toolset += this->BuildGeneratorToolset;
    args.push_back(toolset);
    }

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

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

  for(k=0; k < this->BuildOptions.size(); ++k)
    {
    args.push_back(this->BuildOptions[k]);
    }
  if (cm->Run(args) != 0)
    {
    out << "Error: cmake execution failed\n";
    out << cmakeOutString << "\n";
    // return to the original directory
    cmSystemTools::ChangeDirectory(cwd.c_str());
    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";
      // return to the original directory
      cmSystemTools::ChangeDirectory(cwd.c_str());
      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;
}

//----------------------------------------------------------------------
void CMakeMessageCallback(const char* m, const char*, bool&, void* s)
{
  std::string* out = (std::string*)s;
  *out += m;
  *out += "\n";
}

void CMakeProgressCallback(const char*msg, float , void * s)
{
  std::string* out = (std::string*)s;
  *out += msg;
  *out += "\n";
}

//----------------------------------------------------------------------
void CMakeOutputCallback(const char* m, size_t len, void* s)
{
  std::string* out = (std::string*)s;
  out->append(m, len);
}

//----------------------------------------------------------------------
class cmCTestBuildAndTestCaptureRAII
{
  cmake& CM;
public:
  cmCTestBuildAndTestCaptureRAII(cmake& cm, std::string& s): CM(cm)
    {
    cmSystemTools::SetMessageCallback(CMakeMessageCallback, &s);
    cmSystemTools::SetStdoutCallback(CMakeOutputCallback, &s);
    cmSystemTools::SetStderrCallback(CMakeOutputCallback, &s);
    this->CM.SetProgressCallback(CMakeProgressCallback, &s);
    }
  ~cmCTestBuildAndTestCaptureRAII()
    {
    this->CM.SetProgressCallback(0, 0);
    cmSystemTools::SetStderrCallback(0, 0);
    cmSystemTools::SetStdoutCallback(0, 0);
    cmSystemTools::SetMessageCallback(0, 0);
    }
};

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

  cmake cm;
  std::string cmakeOutString;
  cmCTestBuildAndTestCaptureRAII captureRAII(cm, cmakeOutString);
  static_cast<void>(captureRAII);
  cmOStringStream out;

  if ( this->CTest->GetConfigType().size() == 0 &&
       this->ConfigSample.size())
    {
    // 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.size() && resultingConfig.size())
      {
      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
  double clock_start = cmSystemTools::GetTime();

  // make sure the binary dir is there
  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
  out << "Internal cmake changing into directory: "
    << this->BinaryDir << std::endl;
  if (!cmSystemTools::FileIsDirectory(this->BinaryDir.c_str()))
    {
    cmSystemTools::MakeDirectory(this->BinaryDir.c_str());
    }
  cmSystemTools::ChangeDirectory(this->BinaryDir.c_str());

  if(this->BuildNoCMake)
    {
    // Make the generator available for the Build call below.
    cm.SetGlobalGenerator(cm.CreateGlobalGenerator(
                            this->BuildGenerator));
    cm.SetGeneratorPlatform(this->BuildGeneratorPlatform);
    cm.SetGeneratorToolset(this->BuildGeneratorToolset);

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

  // do the build
  std::vector<std::string>::iterator tarIt;
  if ( this->BuildTargets.size() == 0 )
    {
    this->BuildTargets.push_back("");
    }
  for ( tarIt = this->BuildTargets.begin();
        tarIt != this->BuildTargets.end(); ++ tarIt )
    {
    double remainingTime = 0;
    if (this->Timeout > 0)
      {
      remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
      if (remainingTime <= 0)
        {
        if(outstring)
          {
          *outstring = "--build-and-test timeout exceeded. ";
          }
        return 1;
        }
      }
    std::string output;
    const char* config = 0;
    if ( this->CTest->GetConfigType().size() > 0 )
      {
      config = this->CTest->GetConfigType().c_str();
      }
#ifdef CMAKE_INTDIR
    if(!config)
      {
      config = CMAKE_INTDIR;
      }
#endif
    if(!config)
      {
      config = "Debug";
      }
    int retVal = cm.GetGlobalGenerator()->Build(
      this->SourceDir, this->BinaryDir,
      this->BuildProject, *tarIt,
      output, this->BuildMakeProgram,
      config,
      !this->BuildNoClean,
      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.size())
    {
    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.size())
    {
    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.c_str()))
    {
    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.c_str() << "\n";
    for(unsigned int i=0; i < failed.size(); ++i)
      {
      out << failed[i] << "\n";
      }
    if(outstring)
      {
      *outstring =  out.str();
      }
    else
      {
      cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
      }
    // return to the original directory
    cmSystemTools::ChangeDirectory(cwd.c_str());
    return 1;
    }

  std::vector<const char*> testCommand;
  testCommand.push_back(fullPath.c_str());
  for(size_t k=0; k < this->TestCommandArgs.size(); ++k)
    {
    testCommand.push_back(this->TestCommandArgs[k].c_str());
    }
  testCommand.push_back(0);
  std::string outs;
  int retval = 0;
  // run the test from the this->BuildRunDir if set
  if(this->BuildRunDir.size())
    {
    out << "Run test in directory: " << this->BuildRunDir << "\n";
    cmSystemTools::ChangeDirectory(this->BuildRunDir.c_str());
    }
  out << "Running test command: \"" << fullPath << "\"";
  for(size_t k=0; k < this->TestCommandArgs.size(); ++k)
    {
    out << " \"" << this->TestCommandArgs[k] << "\"";
    }
  out << "\n";

  // how much time is remaining
  double remainingTime = 0;
  if (this->Timeout > 0)
    {
    remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
    if (remainingTime <= 0)
      {
      if(outstring)
        {
        *outstring = "--build-and-test timeout exceeded. ";
        }
      return 1;
      }
    }

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

  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.c_str());
      this->BinaryDir
        = cmSystemTools::CollapseFullPath(this->BinaryDir.c_str());
      this->SourceDir
        = cmSystemTools::CollapseFullPath(this->SourceDir.c_str());
      }
    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 = 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;
}

