Commit:    8c104424b9d647a530f545292b7ed117fb6d57d6
Author:    zoe slattery <z...@php.net>         Sat, 2 Mar 2013 20:32:36 +0000
Parents:   88dfb30b0348aff3a7989c11d4e64125d6d67deb
Branches:  master

Link:       
http://git.php.net/?p=phpruntests.git;a=commitdiff;h=8c104424b9d647a530f545292b7ed117fb6d57d6

Log:
Added a way of distributing the tasks across processors based on the times that 
they have taken to run in a previous run. This is invoked with the command line 
option -g. Also added the command line option --log filename, if enabled this 
will record the time taken for each group and which processor it was run on. 
Memory usage is also logged but only for serial runs

Changed paths:
  A  src/configuration/data/task_weight_file.csv
  A  src/configuration/data/task_weight_file.csv_fromserial
  M  src/configuration/rtCommandLineOptions.php
  M  src/configuration/rtRuntestsConfiguration.php
  M  src/rtUtil.php
  M  src/taskScheduler/rtTaskSchedulerFile.php
  M  src/taskScheduler/rtTaskTestGroup.php
  M  src/testgroup/rtGroupConfiguration.php
  M  src/testgroup/rtPhpTestGroup.php
  M  src/testrun/rtPhpTestRun.php
  M  tests/rtGroupConfigurationTest.php

diff --git a/src/configuration/data/task_weight_file.csv 
b/src/configuration/data/task_weight_file.csv
new file mode 100644
index 0000000..e6d5f61
--- /dev/null
+++ b/src/configuration/data/task_weight_file.csv
@@ -0,0 +1,69 @@
+sapi/tests/:0.05
+ext/standard/tests/file/windows_links/:0.09
+ext/standard/tests/:0.12
+tests/strings/:0.26
+Zend/tests/multibyte/:0.29
+tests/run-test/:0.28
+ext/standard/tests/assert/:0.32
+ext/standard/tests/time/:0.87
+ext/standard/tests/filters/:0.55
+ext/pdo_sqlite/tests/:0.97
+ext/standard/tests/image/:1
+ext/standard/tests/streams/:1.36
+ext/fileinfo/tests/:1.33
+ext/pdo/tests/:1.43
+ext/xmlwriter/tests/:1.47
+ext/tokenizer/tests/:1.56
+ext/json/tests/:1.8
+ext/ereg/tests/:2.04
+ext/mysql/tests/:1.57
+ext/phar/tests/cache_list/:2.75
+ext/standard/tests/dir/:2.67
+ext/sqlite3/tests/:3
+ext/filter/tests/:3.49
+ext/xml/tests/:3.28
+ext/standard/tests/misc/:5
+tests/func/:7.68
+tests/lang/:8.57
+ext/zlib/tests/:8.34
+ext/reflection/tests/:7.35
+ext/session/tests/:8.75
+ext/spl/tests/:17.96
+ext/standard/tests/array/:28.74
+ext/date/tests/:34.35
+Zend/tests/:162.74
+ext/standard/tests/file/:99.67
+ext/phar/tests/:33.23
+ext/standard/tests/strings/:33.58
+ext/standard/tests/general_functions/:127.13
+ext/phar/tests/tar/:14.64
+tests/classes/:11.93
+ext/dom/tests/:8.03
+ext/mysqli/tests/:8.16
+ext/standard/tests/math/:6.69
+ext/phar/tests/zip/:6.11
+ext/posix/tests/:4.82
+ext/ctype/tests/:3.3
+sapi/cli/tests/:4.03
+ext/iconv/tests/:3.41
+ext/pcre/tests/:3.07
+tests/security/:2.51
+Zend/tests/traits/:2.55
+ext/pdo_mysql/tests/:2.32
+ext/standard/tests/network/:2.59
+tests/lang/operators/:1.88
+ext/standard/tests/class_object/:1.71
+tests/basic/:1.75
+tests/output/:1.62
+ext/standard/tests/serialize/:1.41
+ext/standard/tests/url/:1.02
+ext/xmlreader/tests/:0.81
+ext/standard/tests/mail/:0.76
+ext/libxml/tests/:0.68
+sapi/cgi/tests/:0.51
+ext/standard/tests/http/:0.33
+Zend/tests/traits/bugs/:0.34
+Zend/tests/constants/:0.14
+ext/standard/tests/file/windows_acls/:0.12
+ext/standard/tests/directory/:0.11
+ext/standard/tests/versioning/:0.08
diff --git a/src/configuration/data/task_weight_file.csv_fromserial 
b/src/configuration/data/task_weight_file.csv_fromserial
new file mode 100644
index 0000000..2ddced3
--- /dev/null
+++ b/src/configuration/data/task_weight_file.csv_fromserial
@@ -0,0 +1,70 @@
+#Group weightings are just run time in seconds from a serial run
+Zend/tests/:123.59
+Zend/tests/constants/:0.29
+Zend/tests/multibyte/:0.32
+Zend/tests/traits/:2.77
+Zend/tests/traits/bugs/:0.35
+ext/ctype/tests/:4.49
+ext/date/tests/:42.11
+ext/dom/tests/:9.55
+ext/ereg/tests/:2.57
+ext/fileinfo/tests/:1.83
+ext/filter/tests/:4.15
+ext/iconv/tests/:3.79
+ext/json/tests/:2.32
+ext/libxml/tests/:0.83
+ext/mysql/tests/:2.7
+ext/mysqli/tests/:8.9
+ext/pcre/tests/:3.59
+ext/pdo/tests/:1.94
+ext/pdo_mysql/tests/:2.59
+ext/pdo_sqlite/tests/:1.2
+ext/phar/tests/:48.94
+ext/phar/tests/cache_list/:3.17
+ext/phar/tests/tar/:11.45
+ext/phar/tests/zip/:6.04
+ext/posix/tests/:5.05
+ext/reflection/tests/:8.95
+ext/session/tests/:9.83
+ext/spl/tests/:17.66
+ext/sqlite3/tests/:3.9
+ext/standard/tests/array/:24.73
+ext/standard/tests/assert/:0.41
+ext/standard/tests/:0.14
+ext/standard/tests/class_object/:2.02
+ext/standard/tests/dir/:3.34
+ext/standard/tests/directory/:0.13
+ext/standard/tests/file/:98.3
+ext/standard/tests/file/windows_acls/:0.15
+ext/standard/tests/file/windows_links/:0.14
+ext/standard/tests/filters/:0.84
+ext/standard/tests/general_functions/:19.32
+ext/standard/tests/http/:0.38
+ext/standard/tests/image/:1.22
+ext/standard/tests/mail/:0.88
+ext/standard/tests/math/:7.35
+ext/standard/tests/misc/:5.23
+ext/standard/tests/network/:2.44
+ext/standard/tests/serialize/:1.6
+ext/standard/tests/streams/:1.64
+ext/standard/tests/strings/:28.75
+ext/standard/tests/time/:0.8
+ext/standard/tests/url/:1.21
+ext/standard/tests/versioning/:0.1
+ext/tokenizer/tests/:2.32
+ext/xml/tests/:4.2
+ext/xmlreader/tests/:0.93
+ext/xmlwriter/tests/:1.97
+ext/zlib/tests/:8.45
+sapi/cgi/tests/:0.57
+sapi/cli/tests/:4.09
+sapi/tests/:0.06
+tests/basic/:1.95
+tests/classes/:10.54
+tests/func/:5.5
+tests/lang/:8.3
+tests/lang/operators/:2.15
+tests/output/:1.93
+tests/run-test/:0.38
+tests/security/:2.84
+tests/strings/:0.32
diff --git a/src/configuration/rtCommandLineOptions.php 
b/src/configuration/rtCommandLineOptions.php
index 7f11481..dcb1277 100644
--- a/src/configuration/rtCommandLineOptions.php
+++ b/src/configuration/rtCommandLineOptions.php
@@ -24,6 +24,7 @@ class rtCommandLineOptions
         'q', // quiet, no user interaction
         'v', // verbose-mode level 1
         'h', // help
+        'g', // attempt to group tasks for parallel run
     );
 
     /**
@@ -54,7 +55,7 @@ class rtCommandLineOptions
         'keep-out',   // keep only out files
         'keep-exp',   // keep only exp files
         'no-clean',   // do not execute clean section
-        'debug',   // do not execute clean section 
+        'debug'   // extra debug info     
     );
 
     /**
@@ -62,6 +63,7 @@ class rtCommandLineOptions
      */
     protected $longOptionsWithArgs = array(
         'mopts',       // memory-options (valgrind)
+        'log',     //log to a file name
     );
                               
     /**
diff --git a/src/configuration/rtRuntestsConfiguration.php 
b/src/configuration/rtRuntestsConfiguration.php
index 7db80ad..16a28d7 100644
--- a/src/configuration/rtRuntestsConfiguration.php
+++ b/src/configuration/rtRuntestsConfiguration.php
@@ -22,9 +22,11 @@ abstract class rtRuntestsConfiguration
     protected $settings;
     protected $environmentVariables;
     protected $commandLine;
-    protected $operatingSystem;
-    
+    protected $operatingSystem;    
     protected $memoryTool = null;
+    protected $taskWeightings = array();
+    const WEIGHT_FILE = "/data/task_weight_file.csv";
+    
 
     protected $settingNames = array (
     
@@ -60,6 +62,10 @@ abstract class rtRuntestsConfiguration
 
         //create object to hold environment variables
         $this->environmentVariables = 
rtEnvironmentVariables::getInstance($this->operatingSystem);
+        
+        if($this->commandLine->hasOption('z')) {
+            $this->setTaskWeightings();
+        }
     }
 
     /**
@@ -168,6 +174,17 @@ abstract class rtRuntestsConfiguration
         return $this->memoryTool->getCommand();
     }
     
+    public function setTaskWeightings() {      
+        $this->taskWeightings =  rtUtil::readConfigurationFile(__DIR__ 
.self::WEIGHT_FILE);  
+    }     
+         
     
+    public function hasWeight($k) {
+        return array_key_exists($k, $this->taskWeightings);
+    }
+    
+    public function getWeight($k) {
+        return $this->taskWeightings[$k];
+    }
 }
 ?>
diff --git a/src/rtUtil.php b/src/rtUtil.php
index f7573d5..da6be7c 100644
--- a/src/rtUtil.php
+++ b/src/rtUtil.php
@@ -50,37 +50,37 @@ class rtUtil
     }
 
 
-       /**
-        * returns a list of directories containing a phpt-file
-        *
+    /**
+     * returns a list of directories containing a phpt-file
+     *
      * @param $path
      * @return array
-        */
-       public static function parseDir($path)
-       {
-               $list = array();
-               $found = false;
-               foreach (scandir($path) as $file) { 
-               
-       
-                       if (substr($file, 0, 1) != '.' && $file != 'CVS') {
-       
-                               if (is_dir($path.'/'.$file)) {
-       
-                                       $list = array_merge($list, 
rtUtil::parseDir($path.'/'.$file));
-
-                               } elseif ($found === false && strpos($file, 
'.phpt') !== false) {
-                                               
-                                       $list[] = $path.'/';
-                                       $found = true;
-                               }
-                       } 
-               }
-               
-               return $list;
-       }
-    
-       
+     */
+    public static function parseDir($path)
+    {
+        $list = array();
+        $found = false;
+        foreach (scandir($path) as $file) {
+
+
+            if (substr($file, 0, 1) != '.' && $file != 'CVS') {
+
+                if (is_dir($path.'/'.$file)) {
+
+                    $list = array_merge($list, 
rtUtil::parseDir($path.'/'.$file));
+
+                } elseif ($found === false && strpos($file, '.phpt') !== 
false) {
+
+                    $list[] = $path.'/';
+                    $found = true;
+                }
+            }
+        }
+
+        return $list;
+    }
+
+
     /**
      * This is the original version of getDirectoryList which uses 
PhptFilterIterator
      */
@@ -109,5 +109,47 @@ class rtUtil
         return array_unique($result);
     }
 
+    /*
+     * Returns the index associated with the minimum value in an array
+     *
+     */
+    public static function getMin($a) {
+        $x = array_keys($a, min($a));
+        return $x[0];
+    }
+    /*
+     * Strip any part of the path name before one of the recognised levels
+     * TODO What happens when just running tests? This is only used to match
+     * up with a weighting table. Assume no weight will be matched.
+     * Would it be better to have some other way to check that it's being run 
from
+     * the root of the PHP source? Do this in rtCommandLineOptions anyway(?)
+     */
+    public static function stripPath($t) {
+        $topLevelDirectory = array("Zend", "sapi", "ext", "tests");
+        foreach($topLevelDirectory as $tld) {
+            if(preg_match("/\W{1}$tld\W{1}/", $t, $matches, 
PREG_OFFSET_CAPTURE)) {
+                $offset = $matches[0][1] + 1;
+                return substr($t, $offset);
+            }
+        }
+        return "";
+    }
+
+    /*
+     * Standard code to read a configuration file and return results as a 
key->value array
+     */
+    public static function readConfigurationFile($fileName) {
+
+        $a = array();
+        $fc = file($fileName);
+
+        foreach($fc as $line) {
+            if(substr($line, 0, 1) != '#') {
+                list($key, $value) = explode(':',trim($line));
+                $a[$key] = $value;
+            }
+        }
+        return $a;
+    }
 }
 ?>
diff --git a/src/taskScheduler/rtTaskSchedulerFile.php 
b/src/taskScheduler/rtTaskSchedulerFile.php
index dabe233..475eba6 100644
--- a/src/taskScheduler/rtTaskSchedulerFile.php
+++ b/src/taskScheduler/rtTaskSchedulerFile.php
@@ -16,6 +16,7 @@
 class rtTaskSchedulerFile extends rtTaskScheduler
 {
        const TMP_FILE = 'taskFile';
+       const LOG_FILE = '/tmp/parallellog.csv';
        
        protected $pidStore = array();  // stores the pids of all 
child-processes
        protected $groupTasks = false;  // are the tasks already grouped by 
target processor
@@ -80,6 +81,9 @@ class rtTaskSchedulerFile extends rtTaskScheduler
         */
        public function run()
        {
+           //clears the logfile            
+           //file_put_contents(self::LOG_FILE, "");
+           
                if ($this->processCount == 0) {
                        return parent::run();
                }
@@ -146,10 +150,8 @@ class rtTaskSchedulerFile extends rtTaskScheduler
 
                if ($this->groupTasks == true) { 
 
-                       foreach ($this->taskList as $cid => $list) {
-                               
+                       foreach ($this->taskList as $cid => $list) {            
                
                                for ($i=0; $i<sizeof($list); $i++) {
-
                                        $str = serialize($list[$i])."[END]";
                                        file_put_contents(self::TMP_FILE.$cid, 
$str, FILE_APPEND);
                                }
@@ -158,7 +160,6 @@ class rtTaskSchedulerFile extends rtTaskScheduler
                } else {
 
                        for ($i=0; $i<sizeof($this->taskList); $i++) {
-
                                $cid = $i%$this->processCount;
                                $str = serialize($this->taskList[$i])."[END]";
                                file_put_contents(self::TMP_FILE.$cid, $str, 
FILE_APPEND);
@@ -213,7 +214,6 @@ class rtTaskSchedulerFile extends rtTaskScheduler
                file_put_contents(self::TMP_FILE.$cid, '');
         $count = 0;
                foreach ($taskList as $task) {
-
                        $s = microtime(true);
                        
                        $task = unserialize($task);
@@ -223,11 +223,16 @@ class rtTaskSchedulerFile extends rtTaskScheduler
                                continue;
                        }
                        
-                       
                        $task->run();
                        
                        $e = microtime(true);
                        
+                       //$t = round($e - $s, 2);
+                       
+                       //$logstring = $task->getSubDirectory() . ", " .$cid . 
", " .   $s . ", " . $e . ", " . $t . "\n";
+                       
+                       //file_put_contents(self::LOG_FILE, $logstring, 
FILE_APPEND);
+                                               
                        $taskResult = $task->getResult();
                
                        //StatusList is an array 'testname=>statusObject'
diff --git a/src/taskScheduler/rtTaskTestGroup.php 
b/src/taskScheduler/rtTaskTestGroup.php
index c8a3d6b..6a2ed51 100644
--- a/src/taskScheduler/rtTaskTestGroup.php
+++ b/src/taskScheduler/rtTaskTestGroup.php
@@ -42,6 +42,10 @@ class rtTaskTestGroup extends rtTask implements 
rtTaskInterface
                return true;
        }
        
+       public function getSubDirectory() {
+           return $this->subDirectory;
+       }
+       
 
 }
 
diff --git a/src/testgroup/rtGroupConfiguration.php 
b/src/testgroup/rtGroupConfiguration.php
index 95a61cb..45ada45 100644
--- a/src/testgroup/rtGroupConfiguration.php
+++ b/src/testgroup/rtGroupConfiguration.php
@@ -24,6 +24,8 @@ class rtGroupConfiguration
        protected $skipFile = "";
        protected $hasSkipCode = false;
        
+       const SKIP_FILE_NAME = "skip_group_if.inc";
+       
 
     public function __construct($directory)
     {          
@@ -44,7 +46,7 @@ class rtGroupConfiguration
         $this->environmentVariables = $setup['ENV'];
         
         
-        //Remove trailing white space and add a slash to teh directory name
+        //Remove trailing white space and add a slash to the directory name
         //Will need modification if we wanted to be able to give it a list of 
test directories.
         
         $dir = trim($setup['TESTS']);
@@ -96,15 +98,14 @@ class rtGroupConfiguration
     }
     
     public function parseConfiguration() {
-       //Here insert code to read a config file from the test directory that 
determines whether the set of tests should be run
-       //in parallel or not?
-       $this->serialGroup = false;
-       
-       
+       //TODO Could insert code to read a config file from the test directory 
that determines whether the set of tests should be run
+       //in parallel or not.
+               
         //Code to read the directory skipif, run it and skip the directory
-       if(file_exists($this->testDirectory. "/skip_group_if.inc")) {
+        //TODO- this makes a miniscule difference to timing.
+       if(file_exists($this->testDirectory. "/" . self::SKIP_FILE_NAME)) {
                $this->hasSkipCode = true;
-               $this->skipFile = $this->testDirectory."/skip_group_if.inc";    
+               $this->skipFile = $this->testDirectory. "/" 
.self::SKIP_FILE_NAME;  
        }
        return;
        
@@ -129,8 +130,8 @@ class rtGroupConfiguration
     public function hasSkipCode() {
        return $this->hasSkipCode;
     } 
-     public function getSkipFile() {
-        
+     public function getSkipFile() { 
+            
        return $this->skipFile;
     } 
 }
diff --git a/src/testgroup/rtPhpTestGroup.php b/src/testgroup/rtPhpTestGroup.php
index 900141c..da16e61 100644
--- a/src/testgroup/rtPhpTestGroup.php
+++ b/src/testgroup/rtPhpTestGroup.php
@@ -46,8 +46,7 @@ class rtPhpTestGroup extends rtTask implements rtTaskInterface
             }
         }
          
-        if($this->groupConfiguration->hasSkipCode()) {
-               
+        if($this->groupConfiguration->hasSkipCode()) {                 
             //If there is some 'skip' code run it to see if the tests should 
be skipped and then do nothing else
 
             $phpCommand = $this->runConfiguration->getSetting('PhpExecutable');
@@ -58,9 +57,10 @@ class rtPhpTestGroup extends rtTask implements 
rtTaskInterface
             $runner = new rtPhpRunner($phpCommand);
             $result = $runner->runphp();
              
-
             if (preg_match('/^\s*skip\s*(.+)\s*/i', $result, $matches)) {
                 $this->groupResults->setSkip(true);
+                $this->groupResults->setAbsTime(microtime(true));
+                $this->groupResults->setTime(0);
 
             }
         }
@@ -73,9 +73,6 @@ class rtPhpTestGroup extends rtTask implements rtTaskInterface
             $redirectFromID = $this->groupConfiguration->getRedirectFromID();
 
             foreach ($this->testFiles as $testFileName) {
-                //echo "\n" .memory_get_usage() . ", setup start". 
$testFileName . "\n";
-             
-                //testFiles is a list of file names relative to the current 
working directory
 
                 if (!file_exists($testFileName)) {
                     echo rtText::get('invalidTestFileName', 
array($testFileName));
@@ -118,8 +115,7 @@ class rtPhpTestGroup extends rtTask implements 
rtTaskInterface
                     
$this->groupResults->setTestStatus($testFile->getTestName(), $testStatus);
                  
                 }
-                
-            //echo "\n" .memory_get_usage() . ", setup complete". 
$testFileName . "\n";
+          
             }
         }
     }
@@ -129,6 +125,9 @@ class rtPhpTestGroup extends rtTask implements 
rtTaskInterface
         $s=microtime(true);
          
         if (count($this->testCases) == 0) {
+            $e=microtime(true);
+            $this->groupResults->setTime($e-$s);
+            $this->groupResults->setAbsTime($e);            
             return;
         }
 
@@ -151,6 +150,7 @@ class rtPhpTestGroup extends rtTask implements 
rtTaskInterface
 
         $this->groupResults->setTime($e-$s);
         $this->groupResults->setAbsTime($e);
+     
     }
 
     public function writeGroup($outType, $cid=null)
diff --git a/src/testrun/rtPhpTestRun.php b/src/testrun/rtPhpTestRun.php
index f26b1f3..59cf9b6 100644
--- a/src/testrun/rtPhpTestRun.php
+++ b/src/testrun/rtPhpTestRun.php
@@ -27,6 +27,8 @@ class rtPhpTestRun
     protected $processorCount;
     protected $runStartTime;
     protected $skippedGroups = array();
+    protected $logFileName;
+    protected $groupTasks = false;
 
     public function __construct($argv)
     {
@@ -40,7 +42,7 @@ class rtPhpTestRun
 
         // check the operation-system (win/unix)
         $os = (substr(PHP_OS, 0, 3) == "WIN") ? 'Windows' : 'Unix';
-            
+
         //Configure the test environment
         $this->runConfiguration = 
rtRuntestsConfiguration::getInstance($this->commandLineArguments, $os);
         $this->runConfiguration->getUserEnvironment();
@@ -71,17 +73,26 @@ class rtPhpTestRun
 
         $this->processorCount = $this->requestedProcessorCount();
 
+        if($this->runConfiguration->hasCommandLineOption('log')) {
+            $this->logFileName = 
$this->runConfiguration->getCommandLineOption('log');
+            file_put_contents($this->logFileName, "");
+        }
+         
+        if($this->runConfiguration->hasCommandlineOption('g')) {
+            $this->groupTasks = true;
+        }
+
 
         /*
          * Main decision point. Either we start this with a directory (or set 
of directories, in which case tests are
          * run as a group (and in parallel if required) or......
          */
         if ($this->runConfiguration->getSetting('TestDirectories') != null) {
-                
+
             $this->doGroupRuns();
-                
+
         } else {
-                
+
             /*
              *... the input is a test file, or list of files and are just run 
as single tests
              * and not in parallel
@@ -97,18 +108,18 @@ class rtPhpTestRun
         if(count($this->redirectedTestCases) > 0) {
             $this->doRedirectedRuns();
         }
-      
+
         if(($this->numberOfSerialGroups != 0) || 
($this->numberOfParallelGroups != 0))    {
             $this->createRunOutput();
         }
-      
+
     }
 
     public function doGroupRuns() {
 
         $subDirectories = 
$this->buildSubDirectoryList($this->runConfiguration->getSetting('TestDirectories'));
-        
-        //An array of group configuration objects, one for each subdirectory. 
+
+        //An array of group configuration objects, one for each subdirectory.
         $groupConfigurations = 
$this->buildGroupConfigurations($subDirectories);
 
 
@@ -134,11 +145,11 @@ class rtPhpTestRun
                         $parallelGroups[] = $key;
                     }
                 }
-                    
+
                 if(isset($serialGroups)) {$this->numberOfSerialGroups = 
count($serialGroups);}
-                    
+
                 $this->numberOfParallelGroups = count($parallelGroups);
-                    
+
                 $this->run_parallel_groups($parallelGroups, 
$groupConfigurations, $this->processorCount);
                 if($this->numberOfSerialGroups > 0)    {
                     $this->run_serial_groups($serialGroups, 
$groupConfigurations);
@@ -150,27 +161,33 @@ class rtPhpTestRun
 
     public function doRedirectedRuns() {
         foreach($this->redirectedTestCases as $testCase){
-       
+             
             $groupConfig = new rtGroupConfiguration(null);
             $groupConfig->parseRedirect($testCase);
-       
+             
             $group = $groupConfig->getTestDirectory();
-       
+             
             $this->run_serial_groups(array($group), 
array($group=>$groupConfig));
-       
+             
             $this->numberOfSerialGroups++;
              
         }
     }
 
     public function run_parallel_groups($testDirectories, 
$groupConfigurations, $processCount) {
-            
-        // create the task-list
+
+        //Create the task list to be executed in parallel. Either randomly or 
trying to order it.
         $taskList = array();
-        foreach($testDirectories as $testGroup) {
-            $taskList[] = new rtTaskTestGroup($this->runConfiguration, 
$testGroup, $groupConfigurations[$testGroup]);
+        if($this->groupTasks == false) {
+            foreach($testDirectories as $testGroup) {
+                $taskList[] = new rtTaskTestGroup($this->runConfiguration, 
$testGroup, $groupConfigurations[$testGroup]);
+            }
+        }else {
+            $taskList = $this->groupTasksByWeight($testDirectories, 
$groupConfigurations);
+
         }
 
+
         // run the task-scheduler
         $scheduler = rtTaskScheduler::getInstance();
         $scheduler->setTaskList($taskList);
@@ -179,24 +196,29 @@ class rtPhpTestRun
         $scheduler->run();
 
         foreach($scheduler->getResultList() as $groupResult) {
-            
-            if($groupResult->isSkipGroup()) {                
-                 $this->skippedGroups[] = $groupResult->getGroupName();
+
+            if($groupResult->isSkipGroup()) {
+                $this->skippedGroups[] = $groupResult->getGroupName();
             } else {
                 $this->resultList[] = $groupResult->getTestStatusList();
             }
 
-            // Debug - get which group was run by which processor and how long 
each took
-            //
+            // Logging - get which group was run by which processor and how 
long each took
 
-            if($this->runConfiguration->hasCommandLineOption('debug')) {
-                $time = round($groupResult->getTime(), 2);
+            if($this->runConfiguration->hasCommandLineOption('log')) {
 
-                $absTime = $groupResult->getAbsTime() - $this->runStartTime;
+                $groupTime = round($groupResult->getTime(), 2);
+                $runTime = $groupResult->getAbsTime() - $this->runStartTime;
+               
+                $runTime = round($runTime, 2);
 
-                $absTime = round($absTime, 2);
+                $string = "PARLOG," . $groupResult->getGroupName() .
+                          "," . $groupTime . 
+                          "," . $runTime .
+                          "," . $groupResult->getProcessorId() . 
+                          "," . $groupResult->getRunOrder() ."\n";
 
-                echo "\nPARDBG," . $absTime. "," . $time . "," . 
$groupResult->getProcessorId() . "," . $groupResult->getRunOrder() . "," . 
$groupResult->getGroupName();
+                file_put_contents($this->logFileName, $string, FILE_APPEND);
 
             }
 
@@ -212,68 +234,61 @@ class rtPhpTestRun
 
     public function run_serial_groups($testDirectories, $groupConfigurations) {
 
-        $count = 0;
-
-        foreach($testDirectories as $subDirectory) {             
+        $groupCount = 0;
 
-            // Memory usage debugging
-            //$startm = memory_get_usage();
+        foreach($testDirectories as $subDirectory) {
 
-          
+            // Memory usage logging
+            $startMemory = memory_get_usage();
 
             $testGroup = new rtPhpTestGroup($this->runConfiguration, 
$subDirectory, $groupConfigurations[$subDirectory]);
-           
-            
-            if($testGroup->isSkipGroup() == true) {
+         
+
+            if($testGroup->isSkipGroup() === true) {
                 $this->skippedGroups[] = $testGroup->getGroupName();
-            } else {
-                    
+                continue;
+            }
 
-                $testGroup->run();
-                    
-                    
-                // Memory usage debugging
-                //$midm = memory_get_usage();
+            $testGroup->run();
 
-                
rtTestOutputWriter::flushResult($testGroup->getGroupResults()->getTestStatusList(),
 $this->reportStatus);
-                $this->resultList[] = 
$testGroup->getGroupResults()->getTestStatusList();
+            
rtTestOutputWriter::flushResult($testGroup->getGroupResults()->getTestStatusList(),
 $this->reportStatus);
+            $this->resultList[] = 
$testGroup->getGroupResults()->getTestStatusList();
+             
+            if($this->runConfiguration->hasCommandLineOption('log')) {
                  
-                if($this->runConfiguration->hasCommandLineOption('debug')) {
-                     
-                    $time = round($testGroup->getGroupResults()->getTime(), 2);
+                $time = round($testGroup->getGroupResults()->getTime(), 2);
 
-                    $absTime = ($testGroup->getGroupResults()->getAbsTime()) - 
$this->runStartTime;
-                    $absTime = round($absTime, 2);
+                $absTime = ($testGroup->getGroupResults()->getAbsTime()) - 
$this->runStartTime;
+                
+                $absTime = round($absTime, 2);
+                               
 
+                $string =  "SERLOG," . $testGroup->getGroupName() . "," .
+                $time . "," .
+                $absTime . "," .
+                $testGroup->getGroupResults()->getProcessorId() . "," .
+                $groupCount . "\n";
 
-                    echo "\nSERDBG," . $absTime . "," . $time . "," . 
$testGroup->getGroupResults()->getProcessorId() . "," . $count . "," . 
$testGroup->getGroupResults()->getGroupName();
+                file_put_contents($this->logFileName, $string, FILE_APPEND);
 
-                }
-                 
-                // Memory usage debugging
-                //$midm2 = memory_get_usage();
-                 
-                $redirects = 
$testGroup->getGroupResults()->getRedirectedTestCases();
-                foreach($redirects as $testCase) {
-                    $this->redirectedTestCases[] = $testCase;
-                }
-                 
-                 
-                 
-                // Memory usage debugging
-                //$midm3 = memory_get_usage();
-                 
-                    
-                $testGroup->__destruct();
-                unset($testGroup);
-                 
-                // Memory usage debugging
-                //echo "\n" . $startm . ", " . $midm. ", " .$midm2. ", " 
.$midm3. ", " .memory_get_usage() . ", ". $subDirectory . "\n";
-                $count++;
             }
-        }
+             
+            $redirects = 
$testGroup->getGroupResults()->getRedirectedTestCases();
+            foreach($redirects as $testCase) {
+                $this->redirectedTestCases[] = $testCase;
+            }
 
-        //xdebug_stop_trace();
+             
+            $testGroup->__destruct();
+            unset($testGroup);
+             
+            if($this->runConfiguration->hasCommandLineOption('log')) {
+                $string = "MEMLOG," . $subDirectory . ", " . $startMemory. ", 
" .memory_get_usage() . "\n";
+                file_put_contents($this->logFileName, $string, FILE_APPEND);
+            }
+            
+            $groupCount++;          
+        }
     }
 
     public function run_tests($testNames) {
@@ -286,19 +301,19 @@ class rtPhpTestRun
                 echo rtText::get('invalidTestFileName', array($testName));
                 exit();
             }
-                
-                
+
+
             //Read the test file
             $testFile = new rtPhpTestFile();
             $testFile->doRead($testName);
             $testFile->normaliseLineEndings();
-                
+
             $testStatus = new rtTestStatus($testFile->getTestName());
 
 
             if ($testFile->arePreconditionsMet()) {
                 $testCase = new rtPhpTest($testFile->getContents(), 
$testFile->getTestName(), $testFile->getSectionHeadings(), 
$this->runConfiguration, $testStatus);
-                    
+
                 //Setup and set the local environment for the test case
                 $testCase->executeTest($this->runConfiguration);
 
@@ -307,12 +322,12 @@ class rtPhpTestRun
                 $summaryResults = array($testFile->getTestName() => 
$results->getStatus());
 
             } elseif (in_array("REDIRECTTEST", 
$testFile->getSectionHeadings())) {
-                    
+
                 //Redirect handler
                 //Build a list of redirected test cases
-                    
+
                 $this->redirectedTestCases[] = new 
rtPhpTest($testFile->getContents(), $testFile->getTestName(), 
$testFile->getSectionHeadings(), $this->runConfiguration, $testStatus);
-                    
+
                 $testStatus->setTrue('redirected');
                 $testStatus->setMessage('redirected', 
$testFile->getExitMessage());
                 $summaryResults = array($testFile->getTestName() => 
$testStatus);
@@ -324,7 +339,7 @@ class rtPhpTestRun
             }
              
             rtTestOutputWriter::flushResult($summaryResults, 3);
-                
+
         }
     }
 
@@ -419,6 +434,55 @@ class rtPhpTestRun
         }
         return $groupSummary;
     }
+    /*
+     * This, invoked by using the -g command line option,
+     * makes an attempt to distribute tests evenly across the processors
+     * based on 'weightings'. The weightings are actually just timings from a 
previous
+     * parallel run.
+     */
+    public function groupTasksByWeight($testDirectories, $groupConfigurations) 
{
+
+        //First set weights.
+        $weightedDirectoryList = array();
+        $processorWeightSum = array();
+        $taskListByProcessor = array();
+
+        foreach($testDirectories as $subDir) {
+            $key = rtUtil::stripPath($subDir);
+            if($this->runConfiguration->hasWeight($key)) {
+                $weightedDirectoryList[$subDir] = 
$this->runConfiguration->getWeight($key);
+            } else {
+                $weightedDirectoryList[$subDir] = 1;
+            }
+        }
+
+        //Order subditrectories by decreasing weight.
+        arsort($weightedDirectoryList, SORT_NUMERIC);
+
+        //Assign the first n tasks across n processors. Having ordered the 
tasls these will be the longest running tasks
+        for($i=0; $i<$this->processorCount; $i++) {
+            list($key, $value) = each($weightedDirectoryList);
+            $processorWeightSum[$i] =$value;
+            $task = new rtTaskTestGroup($this->runConfiguration, $key, 
$groupConfigurations[$key]);
+            $taskListByProcessor[$i] = array($task);
+        }
 
+        //Continue to assign tasks to processors based on an estimate of how 
long each one will take.
+        for ($i=$this->processorCount; $i<count($weightedDirectoryList); $i++) 
{
+            list($key, $value) = each($weightedDirectoryList);
+            $procID = rtUtil::getMin($processorWeightSum);
+            $processorWeightSum[$procID] += $value;
+            $task = new rtTaskTestGroup($this->runConfiguration, $key, 
$groupConfigurations[$key]);
+            array_push($taskListByProcessor[$procID], $task);
+        }
+
+        //Reverse the order of even numbered lists so that not all processors 
are runnung big tasks at the same time
+        //This seems to work better - possibly the longer running tasks are 
resource constrined by something other than CPU?
+        for($i=0; $i<$this->processorCount; $i+=2) {
+            $taskListByProcessor[$procID] = 
array_reverse($taskListByProcessor[$procID]);
+        }
+
+        return $taskListByProcessor;
+    }
 }
 ?>
diff --git a/tests/rtGroupConfigurationTest.php 
b/tests/rtGroupConfigurationTest.php
index 7d4d6cd..def901b 100644
--- a/tests/rtGroupConfigurationTest.php
+++ b/tests/rtGroupConfigurationTest.php
@@ -8,12 +8,12 @@ class rtGroupConfigurationTest extends 
PHPUnit_Framework_TestCase
     protected $path_to_group;
     
     public function setUp() {
-        $this->path_to_group = realpath(dirname(__FILE__) . 
'/../phpt-tests/group_of_tests');        
+        $this->path_to_group = realpath(dirname(__FILE__) . 
'/../phpt-tests/group_of_tests/');        
     }
     
        public function testCreateInstance()
     {
-       $config = rtRuntestsConfiguration::getInstance(array('run-tests.php', 
'-p', RT_PHP_PATH, 'testgroup'));
+       $config = rtRuntestsConfiguration::getInstance(array('run-tests.php', 
'-p', RT_PHP_PATH, $this->path_to_group));
        
         $config->configure();
-- 
PHP Quality Assurance Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to