浏览代码

CTest-side changes to allow users to attach arbitrary files to test results that will be submitted to cdash using the ATTACHED_FILES test property.

Zach Mullen 16 年之前
父节点
当前提交
dc66139f7c
共有 3 个文件被更改,包括 100 次插入4 次删除
  1. 90 2
      Source/CTest/cmCTestTestHandler.cxx
  2. 5 0
      Source/CTest/cmCTestTestHandler.h
  3. 5 2
      Source/cmSetTestsPropertiesCommand.h

+ 90 - 2
Source/CTest/cmCTestTestHandler.cxx

@@ -1192,6 +1192,8 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os)
       << "</Value>\n"
       << "\t\t\t</Measurement>\n"
       << "\t\t</Results>\n";
+
+    this->AttachFiles(os, result);
     this->WriteTestResultFooter(os, result);
     }
 
@@ -1253,6 +1255,74 @@ void cmCTestTestHandler::WriteTestResultFooter(std::ostream& os,
     << "\t</Test>" << std::endl;
 }
 
+void cmCTestTestHandler::AttachFiles(std::ostream& os,
+                                     cmCTestTestResult* result)
+{
+  if(result->Properties->AttachedFiles.empty())
+    {
+    return;
+    }
+
+  std::string base64 = this->EncodeFiles(result);
+  if(base64 == "")
+    {
+    return;
+    }
+  os << "\t\t<AttachedFiles encoding=\"base64\" compression=\"tar/gzip\">\n"
+     << base64 << "\n"
+     << "\t\t</AttachedFiles>\n";
+}
+
+//----------------------------------------------------------------------
+std::string cmCTestTestHandler::EncodeFiles(cmCTestTestResult* result)
+{
+  //create the temp tar file
+  std::string tarFile = result->Name + "_attached.tar.gz";
+  std::vector<cmStdString> files;
+
+  for(std::vector<std::string>::iterator f = 
+      result->Properties->AttachedFiles.begin();
+      f != result->Properties->AttachedFiles.end(); ++f)
+    {
+    const cmStdString fname = f->c_str();
+    files.push_back(fname);
+    }
+
+  if(!cmSystemTools::CreateTar(tarFile.c_str(), files, true, false, false))
+    {
+    cmCTestLog(this->CTest, ERROR_MESSAGE, "Error creating tar while "
+      "attaching files to the following test: " << result->Name << 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>(len * 1.5 + 5) ];
+
+  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)
 {
@@ -2005,6 +2075,17 @@ bool cmCTestTestHandler::SetTestsProperties(
             {
             rtit->WillFail = cmSystemTools::IsOn(val.c_str());
             }
+          if ( key == "ATTACHED_FILES" )
+            {
+            std::vector<std::string> lval;
+            cmSystemTools::ExpandListArgument(val.c_str(), lval);
+
+            for(std::vector<std::string>::iterator f = lval.begin();
+                f != lval.end(); ++f)
+              {
+              rtit->AttachedFiles.push_back(*f);
+              }
+            }
           if ( key == "TIMEOUT" )
             {
             rtit->Timeout = atof(val.c_str());
@@ -2013,9 +2094,16 @@ bool cmCTestTestHandler::SetTestsProperties(
             {
             rtit->Cost = static_cast<float>(atof(val.c_str()));
             }
-          if ( key == "REQUIRED_FILE" )
+          if ( key == "REQUIRED_FILES" )
             {
-            rtit->RequiredFiles.push_back(val);
+            std::vector<std::string> lval;
+            cmSystemTools::ExpandListArgument(val.c_str(), lval);
+
+            for(std::vector<std::string>::iterator f = lval.begin();
+                f != lval.end(); ++f)
+              {
+              rtit->RequiredFiles.push_back(*f);
+              }
             }
           if ( key == "RUN_SERIAL" )
             {

+ 5 - 0
Source/CTest/cmCTestTestHandler.h

@@ -86,6 +86,7 @@ public:
     std::vector<std::string> Args;
     std::vector<std::string> RequiredFiles;
     std::vector<std::string> Depends;
+    std::vector<std::string> AttachedFiles;
     std::vector<std::pair<cmsys::RegularExpression,
                           std::string> > ErrorRegularExpressions;
     std::vector<std::pair<cmsys::RegularExpression,
@@ -143,6 +144,10 @@ protected:
 
   void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result);
   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 EncodeFiles(cmCTestTestResult* result);
 
   //! Clean test output to specified length
   bool CleanTestOutput(std::string& output, size_t length);

+ 5 - 2
Source/cmSetTestsPropertiesCommand.h

@@ -74,8 +74,11 @@ public:
       "RUN_SERIAL: If set to true, this test will not run in parallel with "
       "any other tests. This should be used in conjunction with "
       "the ctest_test PARALLEL_LEVEL option.\n"
-      "REQUIRED_FILE: Set this to a file that must exist in order for the "
-      "test to be run.\n";
+      "REQUIRED_FILES: Set this to a list of files that must exist in order "
+      "for the test to be run.\n"
+      "ATTACHED_FILES: Set this property to a list of files that will be "
+      "encoded and submitted to the dashboard as an addition to the test "
+      "result.\n";
     }
 
   cmTypeMacro(cmSetTestsPropertiesCommand, cmCommand);