From a516040579bbcd101731f02afcc715480c8d301c Mon Sep 17 00:00:00 2001
From: Zach Mullen <zach.mullen@kitware.com>
Date: Tue, 8 Sep 2009 17:10:35 -0400
Subject: ENH: ctest now writes time cost data to a file after a test set is
 run, and uses these time costs to schedule the processes the next time ctest
 is run in that build tree.

---
 Source/CTest/cmCTestMultiProcessHandler.cxx | 60 +++++++++++++++++++++++++++--
 Source/CTest/cmCTestMultiProcessHandler.h   |  6 ++-
 Source/CTest/cmCTestTestHandler.cxx         |  4 +-
 3 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 8002c05..637c2d5 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -30,11 +30,9 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
   // Set the tests
 void 
 cmCTestMultiProcessHandler::SetTests(TestMap& tests,
-                                     TestCostMap& testCosts,
                                      PropertiesMap& properties)
 {
   this->Tests = tests;
-  this->TestCosts = testCosts;
   this->Properties = properties;
   this->Total = this->Tests.size();
   // set test run map to false for all
@@ -44,6 +42,8 @@ cmCTestMultiProcessHandler::SetTests(TestMap& tests,
     this->TestRunningMap[i->first] = false;
     this->TestFinishMap[i->first] = false;
     }
+  this->ReadCostData();
+  this->CreateTestCostList();
 }
 
   // Set the max number of tests that can be run at the same time.
@@ -271,6 +271,7 @@ bool cmCTestMultiProcessHandler::CheckOutput()
     this->TestRunningMap[test] = false;
     this->RunningTests.erase(p);
     this->WriteCheckpoint(test);
+    this->WriteCostData(test, p->GetTestResults().ExecutionTime);
     this->RunningCount -= GetProcessorsUsed(test);
     delete p;
     }
@@ -278,6 +279,56 @@ bool cmCTestMultiProcessHandler::CheckOutput()
 }
 
 //---------------------------------------------------------
+void cmCTestMultiProcessHandler::ReadCostData()
+{
+  std::string fname = this->CTest->GetBinaryDir()
+    + "/Testing/Temporary/CTestCostData.txt";
+
+  if(cmSystemTools::FileExists(fname.c_str(), true)
+     && this->ParallelLevel > 1)
+    {       
+    std::ifstream fin;
+    fin.open(fname.c_str());
+    std::string line;
+    while(std::getline(fin, line))
+      {
+      std::vector<cmsys::String> parts = 
+        cmSystemTools::SplitString(line.c_str(), ' ');
+
+      int index = atoi(parts[0].c_str());
+      float cost = atof(parts[1].c_str());
+      if(this->Properties[index] && this->Properties[index]->Cost == 0)
+        {
+        this->Properties[index]->Cost = cost;
+        }
+      }
+    fin.close();
+    }
+  cmSystemTools::RemoveFile(fname.c_str());
+}
+
+//---------------------------------------------------------
+void cmCTestMultiProcessHandler::CreateTestCostList()
+{
+  for(TestMap::iterator i = this->Tests.begin();
+      i != this->Tests.end(); ++i)
+    {
+    this->TestCosts[this->Properties[i->first]->Cost].insert(i->first);
+    }
+}
+
+//---------------------------------------------------------
+void cmCTestMultiProcessHandler::WriteCostData(int index, float cost)
+{
+  std::string fname = this->CTest->GetBinaryDir()
+    + "/Testing/Temporary/CTestCostData.txt";
+  std::fstream fout;
+  fout.open(fname.c_str(), std::ios::app);
+  fout << index << " " << cost << "\n";
+  fout.close();
+}
+
+//---------------------------------------------------------
 void cmCTestMultiProcessHandler::WriteCheckpoint(int index)
 {
   std::string fname = this->CTest->GetBinaryDir()
@@ -288,6 +339,7 @@ void cmCTestMultiProcessHandler::WriteCheckpoint(int index)
   fout.close();
 }
 
+//---------------------------------------------------------
 void cmCTestMultiProcessHandler::MarkFinished()
 {
   std::string fname = this->CTest->GetBinaryDir()
@@ -295,7 +347,7 @@ void cmCTestMultiProcessHandler::MarkFinished()
   cmSystemTools::RemoveFile(fname.c_str());
 }
 
-//---------------------------------------------------------------------
+//---------------------------------------------------------
 //For ShowOnly mode
 void cmCTestMultiProcessHandler::PrintTestList()
 {
@@ -330,7 +382,7 @@ void cmCTestMultiProcessHandler::PrintTestList()
     }
 }
 
-//----------------------------------------------------------------
+//---------------------------------------------------------
 void cmCTestMultiProcessHandler::CheckResume()
 {
   std::string fname = this->CTest->GetBinaryDir()
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index 97af2f3..ff1141c 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -37,8 +37,7 @@ public:
 
   cmCTestMultiProcessHandler();
   // Set the tests
-  void SetTests(TestMap& tests, TestCostMap& testCosts,
-                PropertiesMap& properties);
+  void SetTests(TestMap& tests, PropertiesMap& properties);
   // Set the max number of tests that can be run at the same time.
   void SetParallelLevel(size_t);
   void RunTests();
@@ -70,6 +69,9 @@ protected:
   bool StartTest(int test);
   // Mark the checkpoint for the given test
   void WriteCheckpoint(int index);
+  void WriteCostData(int index, float cost);
+  void ReadCostData();
+  void CreateTestCostList();
   // Removes the checkpoint file
   void MarkFinished();
   void EraseTest(int index);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 3cf2d12..229f92a 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1010,7 +1010,6 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
     << std::endl;
 
   cmCTestMultiProcessHandler::TestMap tests;
-  cmCTestMultiProcessHandler::TestCostMap testCosts;
   cmCTestMultiProcessHandler::PropertiesMap properties;
   
   for (ListOfTests::iterator it = this->TestList.begin();
@@ -1037,9 +1036,8 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
       }
     tests[it->Index] = depends;
     properties[it->Index] = &*it;
-    testCosts[p.Cost].insert(p.Index);
     }
-  parallel.SetTests(tests, testCosts, properties);
+  parallel.SetTests(tests, properties);
   parallel.SetPassFailVectors(&passed, &failed);
   this->TestResults.clear();
   parallel.SetTestResults(&this->TestResults);
-- 
cgit v0.12