From 350546db3aa956e34487bd38dd048fe9a0689e4a Mon Sep 17 00:00:00 2001 From: Zach Mullen Date: Fri, 18 Feb 2011 12:11:51 -0500 Subject: Implement ctest_upload command --- Source/CMakeLists.txt | 2 + Source/CTest/cmCTestScriptHandler.cxx | 2 + Source/CTest/cmCTestSubmitHandler.cxx | 1 + Source/CTest/cmCTestTestHandler.cxx | 44 +----------------- Source/CTest/cmCTestTestHandler.h | 2 - Source/CTest/cmCTestUploadCommand.cxx | 57 ++++++++++++++++++++++++ Source/CTest/cmCTestUploadCommand.h | 79 +++++++++++++++++++++++++++++++++ Source/CTest/cmCTestUploadHandler.cxx | 77 ++++++++++++++++++++++++++++++++ Source/CTest/cmCTestUploadHandler.h | 45 +++++++++++++++++++ Source/cmCTest.cxx | 48 +++++++++++++++++++- Source/cmCTest.h | 8 +++- Tests/CMakeLists.txt | 10 +++++ Tests/CTestTestUpload/CMakeLists.txt | 4 ++ Tests/CTestTestUpload/CTestConfig.cmake | 7 +++ Tests/CTestTestUpload/sleep.c | 21 +++++++++ Tests/CTestTestUpload/test.cmake.in | 17 +++++++ 16 files changed, 376 insertions(+), 48 deletions(-) create mode 100644 Source/CTest/cmCTestUploadCommand.cxx create mode 100644 Source/CTest/cmCTestUploadCommand.h create mode 100644 Source/CTest/cmCTestUploadHandler.cxx create mode 100644 Source/CTest/cmCTestUploadHandler.h create mode 100644 Tests/CTestTestUpload/CMakeLists.txt create mode 100644 Tests/CTestTestUpload/CTestConfig.cmake create mode 100644 Tests/CTestTestUpload/sleep.c create mode 100644 Tests/CTestTestUpload/test.cmake.in diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 278d4df..e284967 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -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 diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 12d5fd1..5841b8d 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -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( diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 43441c0..142bb46 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -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; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index f87c929..bad26c5 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -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" @@ -1293,48 +1293,6 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os, } //---------------------------------------------------------------------- -std::string cmCTestTestHandler::EncodeFile(std::string file) -{ - std::string tarFile = file + "_temp.tar.gz"; - std::vector 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(file_buffer), len); - ifs.close(); - cmSystemTools::RemoveFile(tarFile.c_str()); - - unsigned char *encoded_buffer - = new unsigned char [ static_cast( - static_cast(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& vec) { std::vector::iterator it; diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 2c4b230..3089d35 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -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); diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx new file mode 100644 index 0000000..9f0954b --- /dev/null +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -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(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; + } +} diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h new file mode 100644 index 0000000..b8c9d9f --- /dev/null +++ b/Source/CTest/cmCTestUploadCommand.h @@ -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 diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx new file mode 100644 index 0000000..d5f6ab6 --- /dev/null +++ b/Source/CTest/cmCTestUploadHandler.cxx @@ -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 << "\n" + << " \"?>\n" + << "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 << "\n"; + + for ( it = this->Files.begin(); it != this->Files.end(); it ++ ) + { + cmCTestLog(this->CTest, OUTPUT, + "\tUpload file: " << it->c_str() << std::endl); + ofs << "\n" + << "\n"; + ofs << this->CTest->Base64GzipEncodeFile(*it); + ofs << "\n\n" + << "\n"; + } + ofs << "\n" + << "\n"; + return 0; +} diff --git a/Source/CTest/cmCTestUploadHandler.h b/Source/CTest/cmCTestUploadHandler.h new file mode 100644 index 0000000..23ed35a --- /dev/null +++ b/Source/CTest/cmCTestUploadHandler.h @@ -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 diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 2e05883..5827167 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -16,6 +16,7 @@ #include "cmMakefile.h" #include "cmLocalGenerator.h" #include "cmGlobalGenerator.h" +#include #include #include #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(); @@ -1584,6 +1588,48 @@ int cmCTest::GenerateNotesFile(const char* cfiles) } //---------------------------------------------------------------------- +std::string cmCTest::Base64GzipEncodeFile(std::string file) +{ + std::string tarFile = file + "_temp.tar.gz"; + std::vector 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(file_buffer), len); + ifs.close(); + cmSystemTools::RemoveFile(tarFile.c_str()); + + unsigned char *encoded_buffer + = new unsigned char [ static_cast( + static_cast(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 &files) { std::vector::const_iterator it; diff --git a/Source/cmCTest.h b/Source/cmCTest.h index e54a205..4bd628f 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -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); diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 6da06f6..eb15fdb 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -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' diff --git a/Tests/CTestTestUpload/CMakeLists.txt b/Tests/CTestTestUpload/CMakeLists.txt new file mode 100644 index 0000000..bc164b1 --- /dev/null +++ b/Tests/CTestTestUpload/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required (VERSION 2.6) +PROJECT(CTestTestUpload) + +add_executable (Sleep sleep.c) diff --git a/Tests/CTestTestUpload/CTestConfig.cmake b/Tests/CTestTestUpload/CTestConfig.cmake new file mode 100644 index 0000000..89c5b94 --- /dev/null +++ b/Tests/CTestTestUpload/CTestConfig.cmake @@ -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) diff --git a/Tests/CTestTestUpload/sleep.c b/Tests/CTestTestUpload/sleep.c new file mode 100644 index 0000000..b589647 --- /dev/null +++ b/Tests/CTestTestUpload/sleep.c @@ -0,0 +1,21 @@ +#if defined(_WIN32) +# include +#else +# include +#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; +} diff --git a/Tests/CTestTestUpload/test.cmake.in b/Tests/CTestTestUpload/test.cmake.in new file mode 100644 index 0000000..2ab98d7 --- /dev/null +++ b/Tests/CTestTestUpload/test.cmake.in @@ -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() -- cgit v0.12