Implement ctest_upload command

This commit is contained in:
Zach Mullen 2011-02-18 12:11:51 -05:00 committed by Brad King
parent 0554e5e50f
commit 350546db3a
16 changed files with 376 additions and 48 deletions

View File

@ -394,6 +394,8 @@ SET(CTEST_SRCS cmCTest.cxx
CTest/cmCTestTestHandler.cxx
CTest/cmCTestUpdateCommand.cxx
CTest/cmCTestUpdateHandler.cxx
CTest/cmCTestUploadCommand.cxx
CTest/cmCTestUploadHandler.cxx
CTest/cmCTestVC.cxx
CTest/cmCTestVC.h

View File

@ -50,6 +50,7 @@
#include "cmCTestSubmitCommand.h"
#include "cmCTestTestCommand.h"
#include "cmCTestUpdateCommand.h"
#include "cmCTestUploadCommand.h"
#define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log"
@ -357,6 +358,7 @@ void cmCTestScriptHandler::CreateCMake()
this->AddCTestCommand(new cmCTestSubmitCommand);
this->AddCTestCommand(new cmCTestTestCommand);
this->AddCTestCommand(new cmCTestUpdateCommand);
this->AddCTestCommand(new cmCTestUploadCommand);
}
void cmCTestScriptHandler::GetCommandDocumentation(

View File

@ -1204,6 +1204,7 @@ int cmCTestSubmitHandler::ProcessHandler()
this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml");
this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml");
this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml");
this->CTest->AddIfExists(cmCTest::PartUpload, "Upload.xml");
// Query parts for files to submit.
for(cmCTest::Part p = cmCTest::PartStart;

View File

@ -1282,7 +1282,7 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os,
result->Properties->AttachedFiles.begin();
file != result->Properties->AttachedFiles.end(); ++file)
{
std::string base64 = this->EncodeFile(*file);
std::string base64 = this->CTest->Base64GzipEncodeFile(*file);
std::string fname = cmSystemTools::GetFilenameName(*file);
os << "\t\t<NamedMeasurement name=\"Attached File\" encoding=\"base64\" "
"compression=\"tar/gzip\" filename=\"" << fname << "\" type=\"file\">"
@ -1292,48 +1292,6 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os,
}
}
//----------------------------------------------------------------------
std::string cmCTestTestHandler::EncodeFile(std::string file)
{
std::string tarFile = file + "_temp.tar.gz";
std::vector<cmStdString> files;
files.push_back(file);
if(!cmSystemTools::CreateTar(tarFile.c_str(), files, true, false, false))
{
cmCTestLog(this->CTest, ERROR_MESSAGE, "Error creating tar while "
"attaching file: " << file << std::endl);
return "";
}
long len = cmSystemTools::FileLength(tarFile.c_str());
std::ifstream ifs(tarFile.c_str(), std::ios::in
#ifdef _WIN32
| std::ios::binary
#endif
);
unsigned char *file_buffer = new unsigned char [ len + 1 ];
ifs.read(reinterpret_cast<char*>(file_buffer), len);
ifs.close();
cmSystemTools::RemoveFile(tarFile.c_str());
unsigned char *encoded_buffer
= new unsigned char [ static_cast<int>(
static_cast<double>(len) * 1.5 + 5.0) ];
unsigned long rlen
= cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
std::string base64 = "";
for(unsigned long i = 0; i < rlen; i++)
{
base64 += encoded_buffer[i];
}
delete [] file_buffer;
delete [] encoded_buffer;
return base64;
}
//----------------------------------------------------------------------
int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec)
{

View File

@ -151,8 +151,6 @@ protected:
void WriteTestResultFooter(std::ostream& os, cmCTestTestResult* result);
// Write attached test files into the xml
void AttachFiles(std::ostream& os, cmCTestTestResult* result);
// Helper function to encode attached test files
std::string EncodeFile(std::string file);
//! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length);

View File

@ -0,0 +1,57 @@
/*============================================================================
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 "cmCTestUploadCommand.h"
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
#include "cmCTestUploadHandler.h"
cmCTestGenericHandler* cmCTestUploadCommand::InitializeHandler()
{
cmCTestGenericHandler* handler
= this->CTest->GetInitializedHandler("upload");
if ( !handler )
{
this->SetError("internal CTest error. Cannot instantiate upload handler");
return 0;
}
static_cast<cmCTestUploadHandler*>(handler)->SetFiles(this->Files);
return handler;
}
//----------------------------------------------------------------------------
bool cmCTestUploadCommand::CheckArgumentKeyword(std::string const& arg)
{
return this->CheckArgumentValue(arg);
}
//----------------------------------------------------------------------------
bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg)
{
cmStdString filename(arg);
if(cmSystemTools::FileExists(filename.c_str()))
{
this->Files.insert(filename);
return true;
}
else
{
cmOStringStream e;
e << "File \"" << filename << "\" does not exist. Cannot submit "
<< "a non-existent file.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
}
}

View File

@ -0,0 +1,79 @@
/*============================================================================
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.
============================================================================*/
#ifndef cmCTestUploadCommand_h
#define cmCTestUploadCommand_h
#include "cmCTestHandlerCommand.h"
#include "cmCTest.h"
/** \class cmCTestUpload
* \brief Run a ctest script
*
* cmCTestUploadCommand defines the command to upload result files for
* the project.
*/
class cmCTestUploadCommand : public cmCTestHandlerCommand
{
public:
cmCTestUploadCommand()
{
}
/**
* This is a virtual constructor for the command.
*/
virtual cmCommand* Clone()
{
cmCTestUploadCommand* ni = new cmCTestUploadCommand;
ni->CTest = this->CTest;
ni->CTestScriptHandler = this->CTestScriptHandler;
return ni;
}
/**
* The name of the command as specified in CMakeList.txt.
*/
virtual const char* GetName() { return "ctest_upload";}
/**
* Succinct documentation.
*/
virtual const char* GetTerseDocumentation()
{
return "Upload files to a dashboard server.";
}
/**
* More documentation.
*/
virtual const char* GetFullDocumentation()
{
return
" ctest_upload(...)\n"
"Pass a list of files to be sent along with the build results to "
"the dashboard server.\n";
}
cmTypeMacro(cmCTestUploadCommand, cmCTestHandlerCommand);
protected:
cmCTestGenericHandler* InitializeHandler();
virtual bool CheckArgumentKeyword(std::string const& arg);
virtual bool CheckArgumentValue(std::string const& arg);
cmCTest::SetOfStrings Files;
};
#endif

View File

@ -0,0 +1,77 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2009 Kitware, Inc.
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 "cmCTestUploadHandler.h"
#include "cmGeneratedFileStream.h"
#include "cmVersion.h"
#include "cmXMLSafe.h"
//----------------------------------------------------------------------------
cmCTestUploadHandler::cmCTestUploadHandler()
{
this->Initialize();
}
//----------------------------------------------------------------------------
void cmCTestUploadHandler::Initialize()
{
this->Superclass::Initialize();
this->Files.clear();
}
void cmCTestUploadHandler::SetFiles(const cmCTest::SetOfStrings& files)
{
this->Files = files;
}
//----------------------------------------------------------------------------
int cmCTestUploadHandler::ProcessHandler()
{
cmGeneratedFileStream ofs;
if ( !this->CTest->OpenOutputFile(this->CTest->GetCurrentTag(),
"Upload.xml", ofs))
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot open Upload.xml file" << std::endl);
return -1;
}
cmCTest::SetOfStrings::const_iterator it;
ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<?xml-stylesheet type=\"text/xsl\" "
"href=\"Dart/Source/Server/XSL/Build.xsl "
"<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n"
<< "<Site BuildName=\""
<< this->CTest->GetCTestConfiguration("BuildName")
<< "\" BuildStamp=\""
<< this->CTest->GetCurrentTag() << "-"
<< this->CTest->GetTestModelString() << "\" Name=\""
<< this->CTest->GetCTestConfiguration("Site") << "\" Generator=\"ctest"
<< cmVersion::GetCMakeVersion()
<< "\">\n";
this->CTest->AddSiteProperties(ofs);
ofs << "<Files>\n";
for ( it = this->Files.begin(); it != this->Files.end(); it ++ )
{
cmCTestLog(this->CTest, OUTPUT,
"\tUpload file: " << it->c_str() << std::endl);
ofs << "<File filename=\"" << cmXMLSafe(*it) << "\">\n"
<< "<Content compression=\"tar/gzip\" encoding=\"base64\">\n";
ofs << this->CTest->Base64GzipEncodeFile(*it);
ofs << "\n</Content>\n"
<< "</File>\n";
}
ofs << "</Files>\n"
<< "</Site>\n";
return 0;
}

View File

@ -0,0 +1,45 @@
/*============================================================================
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.
============================================================================*/
#ifndef cmCTestUploadHandler_h
#define cmCTestUploadHandler_h
#include "cmCTestGenericHandler.h"
/** \class cmCTestUploadHandler
* \brief Helper class for CTest
*
* Submit arbitrary files
*
*/
class cmCTestUploadHandler : public cmCTestGenericHandler
{
public:
cmTypeMacro(cmCTestUploadHandler, cmCTestGenericHandler);
cmCTestUploadHandler();
~cmCTestUploadHandler() {}
/*
* The main entry point for this class
*/
int ProcessHandler();
void Initialize();
/** Specify a set of files to submit. */
void SetFiles(cmCTest::SetOfStrings const& files);
private:
cmCTest::SetOfStrings Files;
};
#endif

View File

@ -16,6 +16,7 @@
#include "cmMakefile.h"
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
#include <cmsys/Base64.h>
#include <cmsys/Directory.hxx>
#include <cmsys/SystemInformation.hxx>
#include "cmDynamicLoader.h"
@ -31,9 +32,10 @@
#include "cmCTestCoverageHandler.h"
#include "cmCTestMemCheckHandler.h"
#include "cmCTestScriptHandler.h"
#include "cmCTestSubmitHandler.h"
#include "cmCTestTestHandler.h"
#include "cmCTestUpdateHandler.h"
#include "cmCTestSubmitHandler.h"
#include "cmCTestUploadHandler.h"
#include "cmVersion.h"
@ -339,6 +341,7 @@ cmCTest::cmCTest()
this->Parts[PartSubmit].SetName("Submit");
this->Parts[PartNotes].SetName("Notes");
this->Parts[PartExtraFiles].SetName("ExtraFiles");
this->Parts[PartUpload].SetName("Upload");
// Fill the part name-to-id map.
for(Part p = PartStart; p != PartCount; p = Part(p+1))
@ -357,6 +360,7 @@ cmCTest::cmCTest()
this->TestingHandlers["configure"] = new cmCTestConfigureHandler;
this->TestingHandlers["memcheck"] = new cmCTestMemCheckHandler;
this->TestingHandlers["submit"] = new cmCTestSubmitHandler;
this->TestingHandlers["upload"] = new cmCTestUploadHandler;
cmCTest::t_TestingHandlers::iterator it;
for ( it = this->TestingHandlers.begin();
@ -1583,6 +1587,48 @@ int cmCTest::GenerateNotesFile(const char* cfiles)
return this->GenerateNotesFile(files);
}
//----------------------------------------------------------------------
std::string cmCTest::Base64GzipEncodeFile(std::string file)
{
std::string tarFile = file + "_temp.tar.gz";
std::vector<cmStdString> files;
files.push_back(file);
if(!cmSystemTools::CreateTar(tarFile.c_str(), files, true, false, false))
{
cmCTestLog(this, ERROR_MESSAGE, "Error creating tar while "
"encoding file: " << file << std::endl);
return "";
}
long len = cmSystemTools::FileLength(tarFile.c_str());
std::ifstream ifs(tarFile.c_str(), std::ios::in
#ifdef _WIN32
| std::ios::binary
#endif
);
unsigned char *file_buffer = new unsigned char [ len + 1 ];
ifs.read(reinterpret_cast<char*>(file_buffer), len);
ifs.close();
cmSystemTools::RemoveFile(tarFile.c_str());
unsigned char *encoded_buffer
= new unsigned char [ static_cast<int>(
static_cast<double>(len) * 1.5 + 5.0) ];
unsigned long rlen
= cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1);
std::string base64 = "";
for(unsigned long i = 0; i < rlen; i++)
{
base64 += encoded_buffer[i];
}
delete [] file_buffer;
delete [] encoded_buffer;
return base64;
}
//----------------------------------------------------------------------
bool cmCTest::SubmitExtraFiles(const std::vector<cmStdString> &files)
{

View File

@ -61,6 +61,7 @@ public:
PartSubmit,
PartNotes,
PartExtraFiles,
PartUpload,
PartCount // Update names in constructor when adding a part
};
@ -192,8 +193,11 @@ public:
///! Get the current time as string
std::string CurrentTime();
//! tar/gzip and then base 64 encode a file
std::string Base64GzipEncodeFile(std::string file);
/**
* Return the time remaianing that the script is allowed to run in
* Return the time remaining that the script is allowed to run in
* seconds if the user has set the variable CTEST_TIME_LIMIT. If that has
* not been set it returns 1e7 seconds
*/
@ -515,7 +519,7 @@ private:
//! Reread the configuration file
bool UpdateCTestConfiguration();
//! Create not from files.
//! Create note from files.
int GenerateCTestNotesOutput(std::ostream& os,
const VectorOfStrings& files);

View File

@ -1443,6 +1443,16 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
PASS_REGULAR_EXPRESSION "Could not find executable"
FAIL_REGULAR_EXPRESSION "SegFault")
CONFIGURE_FILE(
"${CMake_SOURCE_DIR}/Tests/CTestTestUpload/test.cmake.in"
"${CMake_BINARY_DIR}/Tests/CTestTestUpload/test.cmake"
@ONLY ESCAPE_QUOTES)
ADD_TEST(CTestTestUpload ${CMAKE_CTEST_COMMAND}
-S "${CMake_BINARY_DIR}/Tests/CTestTestUpload/test.cmake" -V
--output-log "${CMake_BINARY_DIR}/Tests/CTestTestUpload/testOut.log"
)
SET_TESTS_PROPERTIES(CTestTestUpload PROPERTIES
PASS_REGULAR_EXPRESSION "Upload\\.xml")
# Use macro, not function so that build can still be driven by CMake 2.4.
# After 2.6 is required, this could be a function without the extra 'set'

View File

@ -0,0 +1,4 @@
cmake_minimum_required (VERSION 2.6)
PROJECT(CTestTestUpload)
add_executable (Sleep sleep.c)

View File

@ -0,0 +1,7 @@
set (CTEST_PROJECT_NAME "CTestTestUpload")
set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT")
set (CTEST_DART_SERVER_VERSION "2")
set (CTEST_DROP_METHOD "http")
set (CTEST_DROP_SITE "www.cdash.org")
set (CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard")
set (CTEST_DROP_SITE_CDASH TRUE)

View File

@ -0,0 +1,21 @@
#if defined(_WIN32)
# include <windows.h>
#else
# include <unistd.h>
#endif
/* sleeps for n seconds, where n is the argument to the program */
int main(int argc, char** argv)
{
int time;
if(argc > 1)
{
time = atoi(argv[1]);
}
#if defined(_WIN32)
Sleep(time * 1000);
#else
sleep(time);
#endif
return 0;
}

View File

@ -0,0 +1,17 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.1)
# Settings:
SET(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTest")
SET(CTEST_SITE "@SITE@")
SET(CTEST_BUILD_NAME "CTestTest-@BUILDNAME@-Upload")
SET(CTEST_SOURCE_DIRECTORY "@CMake_SOURCE_DIR@/Tests/CTestTestUpload")
SET(CTEST_BINARY_DIRECTORY "@CMake_BINARY_DIR@/Tests/CTestTestUpload")
SET(CTEST_CMAKE_GENERATOR "@CMAKE_TEST_GENERATOR@")
SET(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}")
CTEST_START(Experimental)
CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}" RETURN_VALUE res)
CTEST_UPLOAD("${CTEST_SOURCE_DIRECTORY}/sleep.c" "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt")
CTEST_SUBMIT()