Преглед изворни кода

ENH: Use CMake for parsing DartTestfile.txt

Andy Cedilnik пре 20 година
родитељ
комит
33f9780ade
2 измењених фајлова са 267 додато и 115 уклоњено
  1. 256 110
      Source/CTest/cmCTestTestHandler.cxx
  2. 11 5
      Source/CTest/cmCTestTestHandler.h

+ 256 - 110
Source/CTest/cmCTestTestHandler.cxx

@@ -24,11 +24,150 @@
 #include <cmsys/RegularExpression.hxx>
 #include <cmsys/Base64.h>
 #include "cmMakefile.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmCommand.h"
 
 #include <stdlib.h> 
 #include <math.h>
 #include <float.h>
 
+#include <memory> // auto_ptr
+
+//----------------------------------------------------------------------
+class cmCTestSubdirCommand : public cmCommand
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone() 
+    {
+    cmCTestSubdirCommand* c = new cmCTestSubdirCommand;
+    c->m_TestHandler = m_TestHandler;
+    return c;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const& args);
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "SUBDIRS";}
+
+  // Unused methods
+  virtual const char* GetTerseDocumentation() { return ""; }
+  virtual const char* GetFullDocumentation() { return ""; }
+
+  cmTypeMacro(cmCTestSubdirCommand, cmCommand);
+
+  cmCTestTestHandler* m_TestHandler;
+};
+
+//----------------------------------------------------------------------
+bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args)
+{
+  if(args.size() < 1 )
+    {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+    }
+  std::vector<std::string>::const_iterator it;
+  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); 
+  for ( it = args.begin(); it != args.end(); ++ it )
+    {
+    std::string fname = cwd;
+    fname += "/";
+    fname += *it;
+ 
+    if ( !cmSystemTools::FileExists(fname.c_str()) )
+      {
+      std::string m = "Could not find directory: ";
+      m += fname;
+      this->SetError(m.c_str());
+      return false;
+      }
+    cmSystemTools::ChangeDirectory(fname.c_str());
+    const char* testFilename = 0;
+    if( cmSystemTools::FileExists("CTestTestfile.cmake") )
+      {
+      // does the CTestTestfile.cmake exist ?
+      testFilename = "CTestTestfile.cmake";
+      }
+    else if( cmSystemTools::FileExists("DartTestfile.txt") )
+      {
+      // does the DartTestfile.txt exist ?
+      testFilename = "DartTestfile.txt";
+      }
+    else
+      {
+      cmSystemTools::ChangeDirectory(cwd.c_str());
+      return false;
+      }
+    fname += "/";
+    fname += testFilename;
+    bool readit = m_Makefile->ReadListFile( m_Makefile->GetCurrentListFile(), fname.c_str());
+    cmSystemTools::ChangeDirectory(cwd.c_str());
+    if(!readit)
+      {
+      std::string m = "Could not find include file: ";
+      m += fname;
+      this->SetError(m.c_str());
+      return false;
+      }
+    }
+  return true;
+}
+
+//----------------------------------------------------------------------
+class cmCTestAddTestCommand : public cmCommand
+{
+public:
+  /**
+   * This is a virtual constructor for the command.
+   */
+  virtual cmCommand* Clone() 
+    {
+    cmCTestAddTestCommand* c = new cmCTestAddTestCommand;
+    c->m_TestHandler = m_TestHandler;
+    return c;
+    }
+
+  /**
+   * This is called when the command is first encountered in
+   * the CMakeLists.txt file.
+   */
+  virtual bool InitialPass(std::vector<std::string> const&);
+
+  /**
+   * The name of the command as specified in CMakeList.txt.
+   */
+  virtual const char* GetName() { return "ADD_TEST";}
+
+  // Unused methods
+  virtual const char* GetTerseDocumentation() { return ""; }
+  virtual const char* GetFullDocumentation() { return ""; }
+
+  cmTypeMacro(cmCTestAddTestCommand, cmCommand);
+
+  cmCTestTestHandler* m_TestHandler;
+};
+
+//----------------------------------------------------------------------
+bool cmCTestAddTestCommand::InitialPass(std::vector<std::string> const& args)
+{
+  if ( args.size() < 2 )
+    {
+    this->SetError("called with incorrect number of arguments");
+    return false;
+    }
+  return m_TestHandler->AddTest(args);
+}
+
 //----------------------------------------------------------------------
 bool TryExecutable(const char *dir, const char *file,
                    std::string *fullPath, const char *subdir)
@@ -316,9 +455,10 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
 {
   std::string current_dir = cmSystemTools::GetCurrentWorkingDirectory();
   cmsys::RegularExpression dartStuff("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
-  tm_ListOfTests testlist;
-  this->GetListOfTests(&testlist);
-  tm_ListOfTests::size_type tmsize = testlist.size();
+  m_TestList.clear();
+
+  this->GetListOfTests();
+  tm_ListOfTests::size_type tmsize = m_TestList.size();
 
   cmGeneratedFileStream ofs;
   cmGeneratedFileStream *olog = 0;
@@ -342,7 +482,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
   // how many tests are in based on RegExp?
   int inREcnt = 0;
   tm_ListOfTests::iterator it;
-  for ( it = testlist.begin(); it != testlist.end(); it ++ )
+  for ( it = m_TestList.begin(); it != m_TestList.end(); it ++ )
     {
     if (it->m_IsInBasedOnREOptions)
       {
@@ -362,7 +502,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
   int cnt = 0;
   inREcnt = 0;
   std::string last_directory = "";
-  for ( it = testlist.begin(); it != testlist.end(); it ++ )
+  for ( it = m_TestList.begin(); it != m_TestList.end(); it ++ )
     {
     cnt ++;
     if (it->m_IsInBasedOnREOptions)
@@ -370,7 +510,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
       inREcnt++;
       }
     const std::string& testname = it->m_Name;
-    tm_VectorOfListFileArgs& args = it->m_Args;
+    std::vector<std::string>& args = it->m_Args;
     cmCTestTestResult cres;
     cres.m_Status = cmCTestTestHandler::NOT_RUN;
     cres.m_TestCount = cnt;
@@ -420,16 +560,16 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
       cmCTestLog(m_CTest, HANDLER_OUTPUT, outname.c_str());
       }
     
-    cmCTestLog(m_CTest, DEBUG, "Testing " << args[0].Value.c_str() << " ... ");
+    cmCTestLog(m_CTest, DEBUG, "Testing " << args[0].c_str() << " ... ");
     // find the test executable
-    std::string actualCommand = this->FindTheExecutable(args[1].Value.c_str());
+    std::string actualCommand = this->FindTheExecutable(args[1].c_str());
     std::string testCommand = cmSystemTools::ConvertToOutputPath(actualCommand.c_str());
 
     // continue if we did not find the executable
     if (testCommand == "")
       {
       cmCTestLog(m_CTest, ERROR_MESSAGE, "Unable to find executable: "
-        << args[1].Value.c_str() << std::endl);
+        << args[1].c_str() << std::endl);
       if ( !m_CTest->GetShowOnly() )
         {
         cres.m_FullCommandLine = actualCommand;
@@ -440,7 +580,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
       }
 
     // add the arguments
-    tm_VectorOfListFileArgs::const_iterator j = args.begin();
+    std::vector<std::string>::const_iterator j = args.begin();
     ++j;
     ++j;
     std::vector<const char*> arguments;
@@ -449,8 +589,8 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
     for(;j != args.end(); ++j)
       {
       testCommand += " ";
-      testCommand += cmSystemTools::EscapeSpaces(j->Value.c_str());
-      arguments.push_back(j->Value.c_str());
+      testCommand += cmSystemTools::EscapeSpaces(j->c_str());
+      arguments.push_back(j->c_str());
       }
     arguments.push_back(0);
 
@@ -787,8 +927,34 @@ std::string cmCTestTestHandler::FindTheExecutable(const char *exe)
 
 
 //----------------------------------------------------------------------
-void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist)
+void cmCTestTestHandler::GetListOfTests()
 {
+  if ( !m_IncludeRegExp.empty() )
+    {
+    m_IncludeTestsRegularExpression.compile(m_IncludeRegExp.c_str());
+    }
+  if ( !m_ExcludeRegExp.empty() )
+    {
+    m_ExcludeTestsRegularExpression.compile(m_ExcludeRegExp.c_str());
+    }
+  cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Constructing a list of tests" << std::endl);
+  cmake cm;
+  cmGlobalGenerator gg;
+  gg.SetCMakeInstance(&cm);
+  std::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
+  lg->SetGlobalGenerator(&gg);
+  cmMakefile *mf = lg->GetMakefile();
+
+  // Add handler for ADD_TEST
+  cmCTestAddTestCommand* newCom1 = new cmCTestAddTestCommand;
+  newCom1->m_TestHandler = this;
+  cm.AddCommand(newCom1);
+
+  // Add handler for SUBDIR 
+  cmCTestSubdirCommand* newCom2 = new cmCTestSubdirCommand;
+  newCom2->m_TestHandler = this;
+  cm.AddCommand(newCom2);
+
   const char* testFilename = 0;
   if( cmSystemTools::FileExists("CTestTestfile.cmake") )
     {
@@ -805,108 +971,15 @@ void cmCTestTestHandler::GetListOfTests(tm_ListOfTests* testlist)
     return;
     }
 
-  // parse the file
-  std::ifstream fin(testFilename);
-  if(!fin)
+  if ( !mf->ReadListFile(0, testFilename) )
     {
     return;
     }
-
-  cmsys::RegularExpression ireg(this->m_IncludeRegExp.c_str());
-  cmsys::RegularExpression ereg(this->m_ExcludeRegExp.c_str());
-
-  cmListFileCache cache;
-  cmListFile* listFile = cache.GetFileCache(testFilename, false);
-  for(std::vector<cmListFileFunction>::const_iterator f =
-    listFile->m_Functions.begin(); f != listFile->m_Functions.end(); ++f)
+  if ( cmSystemTools::GetErrorOccuredFlag() )
     {
-    const cmListFileFunction& lff = *f;
-    const std::string& name = lff.m_Name;
-    const tm_VectorOfListFileArgs& args = lff.m_Arguments;
-    if (name == "SUBDIRS")
-      {
-      std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
-      for(tm_VectorOfListFileArgs::const_iterator j = args.begin();
-        j != args.end(); ++j)
-        {
-        std::string nwd = cwd + "/";
-        nwd += j->Value;
-        if (cmSystemTools::FileIsDirectory(nwd.c_str()))
-          {
-          cmSystemTools::ChangeDirectory(nwd.c_str());
-          this->GetListOfTests(testlist);
-          }
-        }
-      // return to the original directory
-      cmSystemTools::ChangeDirectory(cwd.c_str());
-      }
-
-    if (name == "ADD_TEST")
-      {
-      const std::string& testname = args[0].Value;
-      if (this->m_UseExcludeRegExp &&
-        this->m_UseExcludeRegExpFirst &&
-        ereg.find(testname.c_str()))
-        {
-        continue;
-        }
-      if ( m_MemCheck )
-        {
-        std::vector<cmStdString>::iterator it;
-        bool found = false;
-        for ( it = m_CustomTestsIgnore.begin(); 
-          it != m_CustomTestsIgnore.end(); ++ it )
-          {
-          if ( *it == testname )
-            {
-            found = true;
-            break;
-            }
-          }
-        if ( found )
-          {
-          cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Ignore memcheck: " << *it << std::endl);
-          continue;
-          }
-        }
-      else
-        {
-        std::vector<cmStdString>::iterator it;
-        bool found = false;
-        for ( it = m_CustomTestsIgnore.begin(); 
-          it != m_CustomTestsIgnore.end(); ++ it )
-          {
-          if ( *it == testname )
-            {
-            found = true;
-            break;
-            }
-          }
-        if ( found )
-          {
-          cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Ignore test: " << *it << std::endl);
-          continue;
-          }
-        }
-
-      cmCTestTestProperties test;
-      test.m_Name = testname;
-      test.m_Args = args;
-      test.m_Directory = cmSystemTools::GetCurrentWorkingDirectory();
-      test.m_IsInBasedOnREOptions = true;
-      if (this->m_UseIncludeRegExp && !ireg.find(testname.c_str()))
-        {
-        test.m_IsInBasedOnREOptions = false;
-        }
-      else if (this->m_UseExcludeRegExp &&
-               !this->m_UseExcludeRegExpFirst &&
-               ereg.find(testname.c_str()))
-        {
-        test.m_IsInBasedOnREOptions = false;
-        }
-      testlist->push_back(test);
-      }
+    return;
     }
+  cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Done constructing a list of tests" << std::endl);
 }
 
 //----------------------------------------------------------------------
@@ -1270,3 +1343,76 @@ bool cmCTestTestHandler::CleanTestOutput(std::string& output, size_t remove_thre
   return true;
 }
 
+//----------------------------------------------------------------------
+bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
+{
+  const std::string& testname = args[0];
+  if (this->m_UseExcludeRegExp &&
+    this->m_UseExcludeRegExpFirst )
+    {
+    abort();
+    }
+  if (this->m_UseExcludeRegExp &&
+    this->m_UseExcludeRegExpFirst &&
+    m_ExcludeTestsRegularExpression.find(testname.c_str()))
+    {
+    return true;
+    }
+  if ( m_MemCheck )
+    {
+    std::vector<cmStdString>::iterator it;
+    bool found = false;
+    for ( it = m_CustomTestsIgnore.begin(); 
+      it != m_CustomTestsIgnore.end(); ++ it )
+      {
+      if ( *it == testname )
+        {
+        found = true;
+        break;
+        }
+      }
+    if ( found )
+      {
+      cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Ignore memcheck: " << *it << std::endl);
+      return true;
+      }
+    }
+  else
+    {
+    std::vector<cmStdString>::iterator it;
+    bool found = false;
+    for ( it = m_CustomTestsIgnore.begin(); 
+      it != m_CustomTestsIgnore.end(); ++ it )
+      {
+      if ( *it == testname )
+        {
+        found = true;
+        break;
+        }
+      }
+    if ( found )
+      {
+      cmCTestLog(m_CTest, HANDLER_VERBOSE_OUTPUT, "Ignore test: " << *it << std::endl);
+      return true;
+      }
+    }
+
+  cmCTestTestProperties test;
+  test.m_Name = testname;
+  test.m_Args = args;
+  test.m_Directory = cmSystemTools::GetCurrentWorkingDirectory();
+  test.m_IsInBasedOnREOptions = true;
+  if (this->m_UseIncludeRegExp && !m_IncludeTestsRegularExpression.find(testname.c_str()))
+    {
+    test.m_IsInBasedOnREOptions = false;
+    }
+  else if (this->m_UseExcludeRegExp &&
+    !this->m_UseExcludeRegExpFirst &&
+    m_ExcludeTestsRegularExpression.find(testname.c_str()))
+    {
+    test.m_IsInBasedOnREOptions = false;
+    }
+  m_TestList.push_back(test);
+  return true;
+}
+

+ 11 - 5
Source/CTest/cmCTestTestHandler.h

@@ -20,7 +20,7 @@
 
 
 #include "cmCTestGenericHandler.h"
-#include "cmListFileCache.h"
+#include <cmsys/RegularExpression.hxx>
 
 class cmMakefile;
 
@@ -62,6 +62,11 @@ public:
 
   cmCTestTestHandler();
 
+  /*
+   * Add the test to the list of tests to be executed
+   */
+  bool AddTest(const std::vector<std::string>& args);
+
   struct cmCTestTestResult
   {
     std::string m_Name;
@@ -76,14 +81,12 @@ public:
     int         m_TestCount;
   };
 
-  typedef std::vector<cmListFileArgument> tm_VectorOfListFileArgs;
-
 protected:
   struct cmCTestTestProperties
   {
     cmStdString m_Name;
     cmStdString m_Directory;
-    tm_VectorOfListFileArgs m_Args;
+    std::vector<std::string> m_Args;
     bool m_IsInBasedOnREOptions;
   };
 
@@ -134,7 +137,7 @@ private:
   /**
    * Get the list of tests in directory and subdirectories.
    */
-  void GetListOfTests(tm_ListOfTests* testlist);
+  void GetListOfTests();
 
   /**
    * Find the executable for a test
@@ -157,6 +160,8 @@ private:
   bool m_UseExcludeRegExpFirst;
   std::string m_IncludeRegExp;
   std::string m_ExcludeRegExp;
+  cmsys::RegularExpression m_IncludeTestsRegularExpression;
+  cmsys::RegularExpression m_ExcludeTestsRegularExpression;
 
   std::string GenerateRegressionImages(const std::string& xml);
 
@@ -165,6 +170,7 @@ private:
 
   std::string TestsToRunString;
   bool m_UseUnion;
+  tm_ListOfTests m_TestList;
 };
 
 #endif