g2              Fri Jun 26 00:07:24 2009 UTC

  Added files:                 
    /phpruntests/src/taskScheduler      rtTaskInterface.php 
                                        rtTaskScheduler.php 
                                        rtTaskSchedulerFile.php rtTask.php 
                                        rtTaskSchedulerMsgQ.php 
                                        rtTaskTestGroup.php 
    /phpruntests/src/configuration/exceptions   rtException.php 
    /phpruntests/tests  rtTaskSchedulerTest.php 

  Modified files:              
    /phpruntests/src/configuration/exceptions   
                                                rtEnvironmentException.php 
                                                rtMissingArgumentException.php 
                                                rtUnknownOptionException.php 
                                                
rtUnknownIniSettingException.php 
    /phpruntests/src    run-tests.php rtClassMap.php 
    /phpruntests/src/configuration      rtCommandLineOptions.php 
    /phpruntests/src/testrun    rtPhpTestRun.php 
  Log:
  phpruntests - integrated taskScheduler into "rtPhpTestRun" - added argument 
for cmd-line-option 'z' (number of processes) - added rtExcpetion and a simple 
exception-hanlder
  
http://cvs.php.net/viewvc.cgi/phpruntests/src/configuration/exceptions/rtEnvironmentException.php?r1=1.2&r2=1.3&diff_format=u
Index: phpruntests/src/configuration/exceptions/rtEnvironmentException.php
diff -u phpruntests/src/configuration/exceptions/rtEnvironmentException.php:1.2 
phpruntests/src/configuration/exceptions/rtEnvironmentException.php:1.3
--- phpruntests/src/configuration/exceptions/rtEnvironmentException.php:1.2     
Mon Apr 20 20:24:30 2009
+++ phpruntests/src/configuration/exceptions/rtEnvironmentException.php Fri Jun 
26 00:07:24 2009
@@ -1,6 +1,6 @@
 <?php
 
-class rtEnvironmentException extends RunTimeException
+class rtEnvironmentException extends rtException
 {
 }
 ?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/configuration/exceptions/rtMissingArgumentException.php?r1=1.2&r2=1.3&diff_format=u
Index: phpruntests/src/configuration/exceptions/rtMissingArgumentException.php
diff -u 
phpruntests/src/configuration/exceptions/rtMissingArgumentException.php:1.2 
phpruntests/src/configuration/exceptions/rtMissingArgumentException.php:1.3
--- phpruntests/src/configuration/exceptions/rtMissingArgumentException.php:1.2 
Mon Apr 20 20:24:30 2009
+++ phpruntests/src/configuration/exceptions/rtMissingArgumentException.php     
Fri Jun 26 00:07:24 2009
@@ -1,6 +1,6 @@
 <?php
 
-class rtMissingArgumentException extends RuntimeException
+class rtMissingArgumentException extends rtException
 {
 }
 ?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/configuration/exceptions/rtUnknownOptionException.php?r1=1.2&r2=1.3&diff_format=u
Index: phpruntests/src/configuration/exceptions/rtUnknownOptionException.php
diff -u 
phpruntests/src/configuration/exceptions/rtUnknownOptionException.php:1.2 
phpruntests/src/configuration/exceptions/rtUnknownOptionException.php:1.3
--- phpruntests/src/configuration/exceptions/rtUnknownOptionException.php:1.2   
Mon Apr 20 20:24:30 2009
+++ phpruntests/src/configuration/exceptions/rtUnknownOptionException.php       
Fri Jun 26 00:07:24 2009
@@ -1,6 +1,6 @@
 <?php
 
-class rtUnknownOptionException extends RuntimeException
+class rtUnknownOptionException extends rtException
 {
 }
 ?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/configuration/exceptions/rtUnknownIniSettingException.php?r1=1.2&r2=1.3&diff_format=u
Index: phpruntests/src/configuration/exceptions/rtUnknownIniSettingException.php
diff -u 
phpruntests/src/configuration/exceptions/rtUnknownIniSettingException.php:1.2 
phpruntests/src/configuration/exceptions/rtUnknownIniSettingException.php:1.3
--- 
phpruntests/src/configuration/exceptions/rtUnknownIniSettingException.php:1.2   
    Mon Apr 20 20:24:30 2009
+++ phpruntests/src/configuration/exceptions/rtUnknownIniSettingException.php   
Fri Jun 26 00:07:24 2009
@@ -1,6 +1,6 @@
 <?php
 
-class rtUnknownIniSettingException extends RuntimeException
+class rtUnknownIniSettingException extends rtException
 {
 }
 ?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/run-tests.php?r1=1.3&r2=1.4&diff_format=u
Index: phpruntests/src/run-tests.php
diff -u phpruntests/src/run-tests.php:1.3 phpruntests/src/run-tests.php:1.4
--- phpruntests/src/run-tests.php:1.3   Tue May 12 16:05:00 2009
+++ phpruntests/src/run-tests.php       Fri Jun 26 00:07:24 2009
@@ -4,6 +4,22 @@
  */
 
 
+
+/**
+ * rtExceptionHandler
+ * 
+ * @param Exception $e
+ * @return unknown_type
+ */
+function rtExceptionHandler(Exception $e) {
+       
+       print $e;
+}
+
+set_exception_handler('rtExceptionHandler');
+
+
+
 /*
  * check the version of the running php-executable and
  * ensure that is 5.3 or higher
@@ -14,7 +30,13 @@
 
 require_once dirname(__FILE__) . '/rtAutoload.php';
 
+$s = microtime(true);
+
 $phpTestRun = new rtPhpTestRun($argv);
 $phpTestRun->run();
 
+$e = microtime(true);
+
+print "\n".($e-$s)." sec\n\n";
+
 ?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/rtClassMap.php?r1=1.13&r2=1.14&diff_format=u
Index: phpruntests/src/rtClassMap.php
diff -u phpruntests/src/rtClassMap.php:1.13 phpruntests/src/rtClassMap.php:1.14
--- phpruntests/src/rtClassMap.php:1.13 Tue Jun 23 12:59:51 2009
+++ phpruntests/src/rtClassMap.php      Fri Jun 26 00:07:24 2009
@@ -8,6 +8,7 @@
  */
 $rtClassMap = array(
     'rtEnvironmentException'                   => 
'configuration/exceptions/rtEnvironmentException.php',
+    'rtException'                              => 
'configuration/exceptions/rtException.php',
     'rtMissingArgumentException'               => 
'configuration/exceptions/rtMissingArgumentException.php',
     'rtUnknownIniSettingException'             => 
'configuration/exceptions/rtUnknownIniSettingException.php',
     'rtUnknownOptionException'                 => 
'configuration/exceptions/rtUnknownOptionException.php',
@@ -48,6 +49,12 @@
     'rtPhptFilterIterator'                     => 'rtPhptFilterIterator.php',
     'rtText'                                   => 'rtText.php',
     'rtUtil'                                   => 'rtUtil.php',
+    'rtTask'                                   => 'taskScheduler/rtTask.php',
+    'rtTaskInterface'                          => 
'taskScheduler/rtTaskInterface.php',
+    'rtTaskScheduler'                          => 
'taskScheduler/rtTaskScheduler.php',
+    'rtTaskSchedulerFile'                      => 
'taskScheduler/rtTaskSchedulerFile.php',
+    'rtTaskSchedulerMsgQ'                      => 
'taskScheduler/rtTaskSchedulerMsgQ.php',
+    'rtTaskTestGroup'                          => 
'taskScheduler/rtTaskTestGroup.php',
     'rtPhpRunnerException'                     => 
'testcase/exceptions/rtPhpRunnerException.php',
     'rtTestOutputWriterList'                   => 
'testcase/output/rtTestOutputWriterList.php',
     'rtTestOutputWriterXML'                    => 
'testcase/output/rtTestOutputWriterXML.php',
http://cvs.php.net/viewvc.cgi/phpruntests/src/configuration/rtCommandLineOptions.php?r1=1.5&r2=1.6&diff_format=u
Index: phpruntests/src/configuration/rtCommandLineOptions.php
diff -u phpruntests/src/configuration/rtCommandLineOptions.php:1.5 
phpruntests/src/configuration/rtCommandLineOptions.php:1.6
--- phpruntests/src/configuration/rtCommandLineOptions.php:1.5  Mon May 25 
08:56:23 2009
+++ phpruntests/src/configuration/rtCommandLineOptions.php      Fri Jun 26 
00:07:24 2009
@@ -24,8 +24,7 @@
         'q',
         'x',
         'v',
-        'h',
-        'z',  //parallel - run out of obvious letters
+        'h',        
     );
 
     /**
@@ -40,6 +39,7 @@
         'd',
         'p',
         's',
+       'z',  //parallel - run out of obvious letters
     );
 
     /**
http://cvs.php.net/viewvc.cgi/phpruntests/src/testrun/rtPhpTestRun.php?r1=1.11&r2=1.12&diff_format=u
Index: phpruntests/src/testrun/rtPhpTestRun.php
diff -u phpruntests/src/testrun/rtPhpTestRun.php:1.11 
phpruntests/src/testrun/rtPhpTestRun.php:1.12
--- phpruntests/src/testrun/rtPhpTestRun.php:1.11       Sun Jun  7 11:06:51 2009
+++ phpruntests/src/testrun/rtPhpTestRun.php    Fri Jun 26 00:07:24 2009
@@ -8,6 +8,7 @@
  * @package    RUNTESTS
  * @author     Zoe Slattery <z...@php.net>
  * @author     Stefan Priebsch <sprieb...@php.net>
+ * @author     Georg Gradwohl <g...@php.net>
  * @copyright  2009 The PHP Group
  * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
  *
@@ -39,16 +40,43 @@
         if ($runConfiguration->getSetting('TestDirectories') != null) {
 
             foreach ($runConfiguration->getSetting('TestDirectories') as 
$testDirectory) {
-
-                //make list of subdirectories which contain tests, includes 
the top level directory
-                $subDirectories = rtUtil::getDirectoryList($testDirectory);
-
-                //Run tests in each subdirectory in sequence
-                foreach ($subDirectories as $subDirectory) {
-                    $testGroup = new rtPhpTestGroup($runConfiguration, 
$subDirectory);
-                    $testGroup->runGroup($runConfiguration);
-                    $testGroup->writeGroup();
-                }
+               
+               // make list of subdirectories which contain tests, includes 
the top level directory
+               $subDirectories = rtUtil::parseDir($testDirectory);
+               
+               // check for the cmd-line-option 'z' which defines 
parellel-execution
+               if ($runConfiguration->hasCommandLineOption('z')) {
+                       
+                       $processCount = 
$runConfiguration->getCommandLineOption('z');
+                       
+                       if (!is_numeric($processCount) || $processCount <= 0) {
+                               $processCount = sizeof($subDirectories);
+                       }
+                       
+                       // create the task-list
+                       $taskList = array();
+                       foreach ($subDirectories as $subDirectory) {
+                               $taskList[] = new 
rtTaskTestGroup(&$runConfiguration, &$subDirectory);
+                       }
+
+                       
+                       // start the task-scheduler for multi-processing        
+                       $scheduler = rtTaskScheduler::getInstance();
+                       $scheduler->setTaskList($taskList);
+                       $scheduler->setProcessCount($processCount);
+                                       $scheduler->run();
+                                       $scheduler->printStatistic();
+ 
+               } else {
+                       
+                   //Run tests in each subdirectory in sequence
+                       foreach ($subDirectories as $subDirectory) {
+                           $testGroup = new rtPhpTestGroup($runConfiguration, 
$subDirectory);
+                           $testGroup->runGroup($runConfiguration);
+                           // $testGroup->writeGroup();
+                       }
+                       
+               }
             }
 
             //*have a directory or list of directories to test.

http://cvs.php.net/viewvc.cgi/phpruntests/src/taskScheduler/rtTaskInterface.php?view=markup&rev=1.1
Index: phpruntests/src/taskScheduler/rtTaskInterface.php
+++ phpruntests/src/taskScheduler/rtTaskInterface.php
<?php

interface rtTaskInterface
{
        public function run();
}

?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/taskScheduler/rtTaskScheduler.php?view=markup&rev=1.1
Index: phpruntests/src/taskScheduler/rtTaskScheduler.php
+++ phpruntests/src/taskScheduler/rtTaskScheduler.php
<?php
/**
 * rtTaskScheduler
 *
 * Main class of the TaskScheduler
 *
 * @category   Testing
 * @package    RUNTESTS
 * @author     Zoe Slattery <z...@php.net>
 * @author     Stefan Priebsch <sprieb...@php.net>
 * @author     Georg Gradwohl <g...@php.net>
 * @copyright  2009 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
 *
 */
class rtTaskScheduler
{
        protected $taskList = array();  // the list of the tasks to be executed
        protected $processCount = 0;    // the number of processes

        protected $time = 0;                    // the needed time
        protected $countPass = 0;               // counts the passed tasks
        protected $countFail = 0;               // counts the failed tasks
        
        protected $memStore = array();  // stores the mem-usage after an 
incomming task

        
        /**
         * the constructor
         * 
         * @param array $taskList               (optional)
         * @param int   $processCount   (optional)
         */
    public function __construct(array $taskList=NULL, $processCount=NULL)
        {
                if (is_array($taskList)) {
                        $this->setTaskList($taskList);
                }
                
                $this->setProcessCount($processCount);
    }
    
    
    public static function getInstance(array $taskList=NULL, $processCount=NUL, 
$useMsgQ=false)
    {
        // TODO: remove this statement and check this by runtime-config
        if (extension_loaded('pcntl')) {

                if ($useMsgQ === true) {
                
                        return new rtTaskSchedulerMsgQ($taskList, 
$processCount);
                }

                return new rtTaskSchedulerFile($taskList, $processCount);
        }
        
        return new rtTaskScheduler($taskList, $processCount);
    }

    
    /**
     * sets the task-list which has to be an array of task-objects.
         *
     * @param array $taskList
     */
        public function setTaskList(array $taskList)
        {
                $this->taskList = $taskList;
        }


        /**
         * @return array $taskList
         */
        public function getTaskList()
        {
                return $this->taskList;
        }
        
        
        /**
         * sets the number of child-processes.
         * in the case of using a multidimensional task-list this parameter is
         * ignored and set to the number of task-groups.
         *  
         * @param int $count
         */
        public function setProcessCount($processCount)
        {
                if (is_numeric($processCount) && $processCount >= 0) {
                        $this->processCount = $processCount;
                }
        }

        
        /**
         * executes the tasks in a simple loop 
         * 
         * @return void
         */
        public function run()
        {
                $s = microtime(true);
                
                for ($i=0; $i<sizeof($this->taskList); $i++) {
                        
                        $task = $this->taskList[$i];
                        
                        if ($task->run() === true) {                    
                                $task->setState(task::PASS);
                                $this->countPass++;
                        } else {
                                $task->setState(task::FAIL);
                                $this->countFail++;
                        }
                        
                        $this->memStore[] = memory_get_usage(true);
                        
                        print ".";
                        flush();
                        
                        $this->taskList[$i] = $task;
                }
                
                $error = microtime(true);
                
                $this->time = round($error-$s,5);

                return;
        }

        
        /**
         * prints the statistic
         * 
         * @return void
         */
        public function printStatistic()
        {
                print "\n----------------------------------------\n";
                
                /*
                if (is_array($this->taskList[0])) {
                
                        $count = 0;
                        foreach ($this->taskList as $list) {
                                $count += sizeof($list);
                        }
                        
                        print "Groups:\t\t".sizeof($this->taskList)."\n";
                        print "Tasks:\t\t".$count."\n";

                } else {
                        
                        $count = sizeof($this->taskList);
                        print "Tasks:\t\t".$count."\n";
                }

                print "PASSED:\t\t".$this->countPass." 
("....@round($this->countPass/$count*100,2)."%)\n";
                print "FAILED:\t\t".$this->countFail." 
("....@round($this->countFail/$count*100,2)."%)\n";
                */
                
                $count = sizeof($this->taskList);
                print "Test-Groups:\t".$count."\n";
                print "Processes:\t".$this->processCount."\n";
                print "Seconds:\t".$this->time."\n";
                
                if ($this->processCount > 0 && sizeof($this->memStore) > 0) {
                        print "AVG 
sec/task:\t"....@round($this->time/$this->processCount,5)."\n";
                        print 
"Memory-MAX:\t".number_format(@max($this->memStore))."\n";
                        print 
"Memory-MIN:\t".number_format(@min($this->memStore))."\n";
                        $avg = 
array_sum($this->memStore)/sizeof($this->memStore);
                        print "Memory-AVG:\t".number_format($avg)."\n";
                }

                print "----------------------------------------\n";
                flush();
        }
        
        
        /**
         * prints a overview of the faild tasks
         * 
         * @return void
         */
        public function printFailedTasks()
        {
                if ($this->countFail > 0) {
                
                        print "FAILED TASKS";
                        print "\n----------------------------------------\n";
                        
                        for ($i=0; $i<sizeof($this->taskList); $i++) {
        
                                $task = $this->taskList[$i];
                                
                                if ($task->getState() == task::FAIL) {
                                        print "Task $i: 
".$task->getMessage()."\n";
                                }
                        }
                        
                        print "----------------------------------------\n";
                        flush();
                }
        }
        
        
        
        public function printMemStatistic($int=10)
        {
                print "MEMORY-USAGE";
                print "\n----------------------------------------\n";
                
                $int = ceil(sizeof($this->memStore)/$int);
                
                $title = "TASK:\t";
                $body = "kB:\t";
                
                for ($i=0; $i<sizeof($this->memStore); $i+=$int) {
                        
                        $title .= "$i\t";
                        $body .= round($this->memStore[$i]/1000)."\t";
                }
                
                print $title."\n".$body;
                
                print "\n----------------------------------------\n";
                flush();                
        }
        
}

?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/taskScheduler/rtTaskSchedulerFile.php?view=markup&rev=1.1
Index: phpruntests/src/taskScheduler/rtTaskSchedulerFile.php
+++ phpruntests/src/taskScheduler/rtTaskSchedulerFile.php
<?php
/**
 * rtTaskSchedulerFile
 *
 * extention of TaskScheduler, implements a ipc via temporary files
 *
 * @category   Testing
 * @package    RUNTESTS
 * @author     Zoe Slattery <z...@php.net>
 * @author     Stefan Priebsch <sprieb...@php.net>
 * @author     Georg Gradwohl <g...@php.net>
 * @copyright  2009 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
 *
 */
class rtTaskSchedulerFile extends rtTaskScheduler
{
        const TMP_FILE = 'taskFile';
        
        private $inputQueue = NULL;             // the input-queue (only used 
by the sender)
        private $pidStore = array();    // stores the pids of all 
child-processes
        private $groupTasks = false;    // are the tasks stored in groups?
        
        private $tmpTaskList = array();
        
        /**
         * the constructor
         * 
         * @param array $taskList               (optional)
         * @param int   $processCount   (optional)
         */
    public function __construct(array $taskList=NULL, $processCount=NULL)
        {
                if (is_array($taskList)) {
                        $this->setTaskList($taskList);
                }
                
                $this->setProcessCount($processCount);
    }

    
    /**
     * sets the task-list which has to be an array of task-objects.
     * it's also possible to use a multidimensional array. in this case the
     * tasks are distributed to the child-processes exactly in the way as they
     * are grouped in the list. the first-level index strictly has to be
     * numeric and continuous starting with zero.
     * 
     * @param array $taskList
     * @Overrides
     */
        public function setTaskList(array $taskList)
        {
                if (is_array($taskList[0])) {
                        $this->groupTasks = true;
                        $this->processCount = sizeof($taskList);
                }
                
                $this->taskList = $taskList;
        }

        
        
        /**
         * sets the number of child-processes.
         * in the case of using a multidimensional task-list this parameter is
         * ignored and set to the number of task-groups.
         *  
         * @param int $count
         * @Overrides
         */
        public function setProcessCount($processCount)
        {
                if ($this->groupTasks !== true && is_numeric($processCount) && 
$processCount >= 0) {
                        $this->processCount = $processCount;
                }
        }


        
        /**
         * starts the sender, the receiver and forks the defined
         * number of child-processes.
         * 
         * @return void
         * @Overrides
         */
        public function run()
        {
                if ($this->processCount == 0) {
                        return parent::run();
                }

                $startTime = microtime(true);

                // trim the processCount if nesecarry
                if ($this->processCount > sizeof($this->taskList)) {
                        $this->processCount = sizeof($this->taskList);
                }

                $this->createTaskFiles();
                

                // fork the child-processes
                for ($i=0; $i<$this->processCount; $i++) {

                        $this->pidStore[$i] = pcntl_fork();

                        switch ($this->pidStore[$i]) {
                                
                                case -1:        // failure
                                        die("could not fork"); 
                                        break;
                                
                                case 0:         // child
                                        $this->child($i);
                                        break;
                                        
                                default:        // parent
                                        break;
                        }
                }

                // wait until all child-processes are terminated
                for ($i=0; $i<$this->processCount; $i++) {
                        pcntl_waitpid($this->pidStore[$i], $status);
                }
                
                // ensure that the tmp-files are completly written
                sleep(1);
                
                // collecting the results
                $this->receiver();

                $endTime = microtime(true);
                $this->time = round($endTime-$startTime,5);

                return;
        }
        
        
        
        /**
         * creates a temporary file for each child which stores the allocated 
         * array-indices.
         * 
         */
        private function createTaskFiles() {

                $taskStr = array();

                if ($this->groupTasks == true) { 

                        $c = 0;
                        
                        foreach ($this->taskList as $key => $list) {
                                
                                for ($i=0; $i<sizeof($list); $i++) {

                                        $taskStr[$key] .= $i.';';
                                }
                        }
                         
                } else {

                        for ($i=0; $i<sizeof($this->taskList); $i++) {

                                $taskStr[$i%$this->processCount] .= $i.';';
                        }
                }

                for ($i=0; $i<$this->processCount; $i++) {
                                                
                        file_put_contents(self::TMP_FILE.$i, $taskStr[$i]);
                }
        }

        
        
        /**
         * @return void
         */
        private function receiver()
        {
                for ($cid=0; $cid<$this->processCount; $cid++) {
                
                        $response = file_get_contents(self::TMP_FILE.$cid);
                        $response = explode("\n", $response);
                        array_pop($response);

                        foreach ($response as $task) {
                                
                                $task = unserialize($task);
                                
                                if ($task->getState() == rtTask::PASS) {
                                        $this->countPass++;
                                } else {
                                        $this->countFail++;
                                }
                                
                                $index = $task->getIndex();
                                
                                if ($this->groupTasks == true) { 
                                        
                                        $this->taskList[$cid][$index] = $task;  
                                
                                } else {
                                        
                                        $this->taskList[$index] = $task;
                                }
                        }
                        
                        unlink(self::TMP_FILE.$cid);
                }
                
                return;         
        }
        

        
        /**
         * @param  int  $cid    the child-id
         * @return void
         */
        private function child($cid)
        {
                $indexList = file_get_contents(self::TMP_FILE.$cid);
                $indexList = explode(';', $indexList);
                array_pop($indexList);
                
                $response = '';

                foreach ($indexList as $index) {

                        if ($this->groupTasks == true) { 
                                $task = $this->taskList[$cid][$index]; 
                        } else {
                                $task = $this->taskList[$index];
                        }

                        if ($task->run() === true) {                    
                                $task->setState(rtTask::PASS);
                                
                        } else {
                                $task->setState(rtTask::FAIL);
                        }
                        
                        $task->setIndex($index);

                        $response .= serialize($task)."\n";
                }
                
                file_put_contents(self::TMP_FILE.$cid, $response);

                exit(0);
        }

        
}

?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/taskScheduler/rtTask.php?view=markup&rev=1.1
Index: phpruntests/src/taskScheduler/rtTask.php
+++ phpruntests/src/taskScheduler/rtTask.php
<?php

abstract class rtTask
{
        const NOEX = 0;
        const PASS = 1;
        const FAIL = -1;

        private $state = self::NOEX;
        private $index = NULL;
        private $message = NULL;
        
        
        public function setState($state)
        {
                $this->state = $state;          
        }
        
        public function getState()
        {
                return $this->state;
        }
        
        
        public function setMessage($msg)
        {
                $this->message = $msg;
        }

        public function getMessage()
        {
                return $this->message;
        }

        
        public function setIndex($index)
        {
                $this->index = $index;
        }

        public function getIndex()
        {
                return $this->index;
        }
        
}

?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/taskScheduler/rtTaskSchedulerMsgQ.php?view=markup&rev=1.1
Index: phpruntests/src/taskScheduler/rtTaskSchedulerMsgQ.php
+++ phpruntests/src/taskScheduler/rtTaskSchedulerMsgQ.php
<?php
/**
 * rtTaskSchedulerMsgQ
 *
 * extention of TaskScheduler, implements a ipc via message-queues
 *
 * @category   Testing
 * @package    RUNTESTS
 * @author     Zoe Slattery <z...@php.net>
 * @author     Stefan Priebsch <sprieb...@php.net>
 * @author     Georg Gradwohl <g...@php.net>
 * @copyright  2009 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
 *
 */
declare(ticks=true);

class rtTaskSchedulerMsgQ extends rtTaskScheduler
{
        const MSG_QUEUE_KEY = 1234;             // id of the message-queue
        const MSG_QUEUE_SIZE = 1024;    // max-size of a single message
        const KILL_CHILD = 'killBill';  // kill-signal to terminate a child

        private $inputQueue = NULL;             // the input-queue (only used 
by the sender)
        private $pidStore = array();    // stores the pids of all 
child-processes
        private $groupTasks = false;    // are the tasks stored in groups?
        
        
        

    
    /**
     * sets the task-list which has to be an array of task-objects.
     * it's also possible to use a multidimensional array. in this case the
     * tasks are distributed to the child-processes exactly in the way as they
     * are grouped in the list. the first-level index strictly has to be
     * numeric and continuous starting with zero.
     * 
     * @param array $taskList
     * @Overrides
     */
        public function setTaskList(array $taskList)
        {
                if (is_array($taskList[0])) {
                        $this->groupTasks = true;
                        $this->processCount = sizeof($taskList);
                }
                
                $this->taskList = $taskList;
        }

        
        
        /**
         * sets the number of child-processes.
         * in the case of using a multidimensional task-list this parameter is
         * ignored and set to the number of task-groups.
         *  
         * @param int $count
         * @Overrides
         */
        public function setProcessCount($processCount)
        {
                if ($this->groupTasks !== true && is_numeric($processCount) && 
$processCount >= 0) {
                        $this->processCount = $processCount;
                }
        }

        
        /**
         * removes the used message-queues.
         */
    private static function cleanUp()
    {
                @msg_remove_queue(msg_get_queue(self::MSG_QUEUE_KEY));
                @msg_remove_queue(msg_get_queue(self::MSG_QUEUE_KEY+1));
    }

    
        /**
         * the signal-handler is called by the interrupt- or quit-signal and 
calls
         * the cleanUp-method. 
         * 
         * @param int $signal
         */
        public static function signalHandler($signal)
        {
                switch($signal) {
                        
                        case SIGINT:
                        case SIGQUIT:
                                self::cleanUp();
                                die("\n");
                                break;
                                
                        default:
                                break;
                }
        }

        
        /**
         * starts the sender, the receiver and forks the defined
         * number of child-processes.
         * 
         * @return void
         * @Overrides
         */
        public function run()
        {
                if ($this->processCount == 0) {
                        return parent::run();
                }
                
                $startTime = microtime(true);
                
                // register signal-handler
                pcntl_signal(SIGINT, "taskSchedulerMsgQ::signalHandler");
                pcntl_signal(SIGQUIT, "taskSchedulerMsgQ::signalHandler");

                // trim the processCount if nesecarry
                if ($this->processCount > sizeof($this->taskList)) {
                        $this->processCount = sizeof($this->taskList);
                }
                                
                // fork the child-processes
                for ($i=0; $i<=$this->processCount; $i++) {

                        $this->pidStore[$i] = pcntl_fork();

                        switch ($this->pidStore[$i]) {
                                
                                case -1:        // failure
                                        die("could not fork"); 
                                        break;
                                
                                case 0:         // child
                                        if ($i==0) {
                                                $this->sender();
                                        } else {                                
        
                                                $cid = ($this->groupTasks == 
true) ? $i : NULL;
                                                $this->child($cid);
                                        }
                                        break;
                                        
                                default:        // parent
                                        break;
                        }
                }

                // start the receiver
                $this->receiver();

                // wait until all child-processes are terminated
                for ($i=0; $i<=$this->processCount; $i++) {
                        pcntl_waitpid($this->pidStore[$i], $status);
                }

                $endTime = microtime(true);
                $this->time = round($endTime-$startTime,5);
                
                // remove the msg-queue
                self::cleanUp();

                return;
        }
        
        
        /**
         * the receiver is listening to the result-queue and stores the 
incomming
         * tasks back to the task-list.
         * when finished it sends the kill-signal to all children and terminates
         * itself.
         * 
         * @return void
         */
        private function receiver()
        {
                $resultQueue = msg_get_queue(self::MSG_QUEUE_KEY+1);

                $task = '';
                $type = 1;
                
                if ($this->groupTasks == true) { 
                        $limit = 0;
                        foreach ($this->taskList as $list) {
                                $limit += sizeof($list);
                        } 
                } else {
                        $limit = sizeof($this->taskList);  
                }

                for ($i=0; $i<$limit; $i++) {
                        
                        $this->memStore[] = memory_get_usage(true);
                
                        if (msg_receive($resultQueue, 0, $type, 
self::MSG_QUEUE_SIZE, $task, true, NULL, $error)) {

                                // check state
                                if ($task->getState() == rtTask::PASS) {
                                        $this->countPass++;
                                } else {
                                        $this->countFail++;
                                }

                                // store result                         
                                $index = $task->getIndex();
                                
                                if ($this->groupTasks == true) {
                                        $this->taskList[$type-2][$index] = 
$task;
                                } else {
                                        $this->taskList[$index] = $task;
                                }
                                
                        } else {
                                
                                print "RECEIVER ERROR $error\n";
                        }
                }
                
                $inputQueue = msg_get_queue(self::MSG_QUEUE_KEY);
                
                for ($i=1; $i<=$this->processCount; $i++) {

                        if (msg_send($inputQueue, $i, self::KILL_CHILD, true, 
true, $error)) {

                        } else {
                                
                                print "RECEIVER ERROR $error\n";
                        }
                }

                return;
        }

        
        /**
         * the sender is passes through the task-list and distributes the single
         * tasks to the child-processes using the input-queue.
         * when finished it terminates itself.
         * 
         * @return void
         */
        private function sender()
        {
                $this->inputQueue = msg_get_queue(self::MSG_QUEUE_KEY);

                for ($i=0; $i<sizeof($this->taskList); $i++) {

                        if ($this->groupTasks == true) {
                                
                                for ($j=0; $j<sizeof($this->taskList[$i]); 
$j++) {

                                        
$this->sendTask($this->taskList[$i][$j], $j, $i+1);
                                }

                        } else {
                                
                                $this->sendTask($this->taskList[$i], $i);
                        }
                }

                exit(0);
        }
        
        
        /**
         * helper-class of sender.
         * sends a task to a child-process using the input-queue.
         * 
         * @param  task $task   the task to send
         * @param  int  $index  the task's index in the taskList 
         * @param  int  $type   the message-type (default=1)
         * @return void
         */
        private function sendTask(task $task, $index, $type=1)
        {
                $task->setIndex($index);

                if (msg_send($this->inputQueue, $type, $task, true, true, 
$error)) {

                } else {
                        
                        print "SENDER ERROR $error\n";
                }
                
                return;
        }

        
        /**
         * the child is listening to the input-queue and executes the incomming
         * tasks. afterwards it setts the task-state and sends it back to the
         * receiver via the result-queue.
         * after receiving the kill-signal from the receiver it terminates 
itself. 
         * 
         * @param  int  $cid    the child-id (default=NULL)
         * @return void
         */
        private function child($cid=NULL)
        {
                if (is_null($cid)) {
                        $cid = 0;
                }

                $inputQueue = msg_get_queue(self::MSG_QUEUE_KEY);
                $resultQueue = msg_get_queue(self::MSG_QUEUE_KEY+1);

                $type = 1;

                while (true) {

                        if (msg_receive($inputQueue, $cid, $type, 
self::MSG_QUEUE_SIZE, $task, true, NULL, $error)) {

                                if ($task == self::KILL_CHILD)
                                        break;

                                $index = $task->getIndex();

                                if ($task->run() === true) {                    
                                        $task->setState(rtTask::PASS);
                                } else {
                                        $task->setState(rtTask::FAIL);
                                }
                                
                                print ".";
                                flush();

                                if (msg_send($resultQueue, $cid+1, $task, true, 
true, $error)) {

                                } else {
                                        
                                        print "CHILD ERROR $error\n";
                                }
        
                        } else {
                                        
                                print "CHILD ERROR $error\n";
                        }
                }

                exit(0);
        }


}

?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/taskScheduler/rtTaskTestGroup.php?view=markup&rev=1.1
Index: phpruntests/src/taskScheduler/rtTaskTestGroup.php
+++ phpruntests/src/taskScheduler/rtTaskTestGroup.php
<?php
/**
 * rtTaskTestGroup
 *
 * @category   Testing
 * @package    RUNTESTS
 * @author     Zoe Slattery <z...@php.net>
 * @author     Stefan Priebsch <sprieb...@php.net>
 * @author     Georg Gradwohl <g...@php.net>
 * @copyright  2009 The PHP Group
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
 *
 */
class rtTaskTestGroup extends rtTask implements rtTaskInterface
{
        private $runConfiguration;
        private $subDirectory;
        
        
        public function __construct($runConfiguration, $subDirectory)
        {
                $this->runConfiguration = $runConfiguration;
                $this->subDirectory = $subDirectory;
        }
                
        public function run()
        {
                $testGroup = new rtPhpTestGroup($this->runConfiguration, 
$this->subDirectory);
                $testGroup->runGroup($this->runConfiguration);
                // $testGroup->writeGroup();
                return true;
        }
                
        public function getDir()
        {
                return $this->subDirectory;
        }
        
}


?>
http://cvs.php.net/viewvc.cgi/phpruntests/src/configuration/exceptions/rtException.php?view=markup&rev=1.1
Index: phpruntests/src/configuration/exceptions/rtException.php
+++ phpruntests/src/configuration/exceptions/rtException.php
<?php

class rtException extends RuntimeException
{
        public function __toString() {
                
                $r = 
"\n--------------------------------------------------------------------------------\n";
                $r .= "EXCEPTION\n";
                $r .= $this->getMessage()." (CODE ".$this->getCode().")\n";
                $r .= $this->getFile().":".$this->getLine()."\n\n";
                $r .= $this->getTraceAsString();
                $r .= 
"\n--------------------------------------------------------------------------------\n";
                
                return $r;
        }
}

?>
http://cvs.php.net/viewvc.cgi/phpruntests/tests/rtTaskSchedulerTest.php?view=markup&rev=1.1
Index: phpruntests/tests/rtTaskSchedulerTest.php
+++ phpruntests/tests/rtTaskSchedulerTest.php
<?php

require_once 'PHPUnit/Framework.php';
require_once dirname(__FILE__) . '/../src/rtAutoload.php';

class rtTaskSchedulerTest extends PHPUnit_Framework_TestCase
{
        public function testResult()
    {
        // create 10 tasks with random numbers
        $taskList = array();
        $expected = array();
        
        for ($i=0; $i<10; $i++) {
                $n = rand(0,9);
                $expected[$i] = $n+1;
                $taskList[$i] = new rtTaskIncTest($n);
        }
        
        // run the task-scheduler
                $scheduler = rtTaskScheduler::getInstance();
                $scheduler->setTaskList($taskList);
                $scheduler->setProcessCount(3);
                $scheduler->run();
                
                // get the results from the manupilated task-list
                $results = array();
                
                foreach ($scheduler->getTaskList() as $task) {
                        $results[] = $task->getNumber();
                }
                
                $this->assertEquals($expected, $results);
    }
}


/**
 * rtTaskIncTest
 * 
 * nested helper-class for rtTaskSchedulerTest
 */
class rtTaskIncTest extends rtTask implements rtTaskInterface
{
        private $num = null;
        
        public function __construct($num)
        {
                $this->num = $num;
        }
        
        public function run()
        {
                $this->num++;
                return true;
        }
        
        public function getNumber()
        {
                return $this->num;
        }       
}


?>

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to