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 <[email protected]>
* @author Stefan Priebsch <[email protected]>
+ * @author Georg Gradwohl <[email protected]>
* @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 <[email protected]>
* @author Stefan Priebsch <[email protected]>
* @author Georg Gradwohl <[email protected]>
* @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 <[email protected]>
* @author Stefan Priebsch <[email protected]>
* @author Georg Gradwohl <[email protected]>
* @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 <[email protected]>
* @author Stefan Priebsch <[email protected]>
* @author Georg Gradwohl <[email protected]>
* @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 <[email protected]>
* @author Stefan Priebsch <[email protected]>
* @author Georg Gradwohl <[email protected]>
* @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