Home » Testing » PHPUnit2 » Bug #8275
PHPUnit2_Framework_TestResult::removeListener() not removing.
Details
| Request #8275 | PHPUnit2_Framework_TestResult::removeListener() not removing. |
|---|---|
| Submitted | 2006-07-24 15:40 UTC |
| From | saggnic at gmail dot com |
| Assigned | sebastian |
| Status | Closed |
| Package | PHPUnit2 |
| PHP Version | 5.1.4 |
| OS | Linux |
| Roadmaps | (Not assigned) |
Comments
[2006-07-24 15:40 UTC] saggnic at gmail dot com
Description:
------------
Problem description and fix included here.
The original body of removeListener() is a for statement, which suffers from the problem. The solution is to replace it with a foreach() statement. The description is in comments in the method's body below.
public function removeListener(PHPUnit2_Framework_TestListener $listener) {
//for ($i = 0; $i < sizeof($this->listeners); $i++) {
// if ($this->listeners[$i] === $listener) {
// unset($this->listeners[$i]);
// }
//}
// The foreach below does the same thing as the commented-out for statement, above.
// The for statement, however, has a problem in the following scenario.
// 1) A listener is added and then removed.
// 2) A second listener is added.
// 3) The second listener is removed.
// Step 3 is not carried out because the 0th index (key) is no longer accessible in the array
// because of the unset() operation. (Yes, unset($myArray[0]) actually gets rid of both the
// element and the index so that executing statement $myArray[]='a' assigns 'a' to $myArray[1],
// as opposed to assigning it to $myArray[0] as one might expect.) Because of this, step 3
// fails, producing "PHP Notice: Undefined offset: 0 in ..." and not removing the second
// listener. The foreach statement is immune to that particular behavior of unset(), which is
// probably not a bug.
//
// Note: An alternate solution would be to use the following statement before the original
// for statement: "$this->listeners = array_merge($this->listeners);" array_merge() will
// make the indexes continuous and start at 0.
//
foreach( $this->listeners as $key => $currListener ) {
if ($currListener === $listener) {
unset($this->listeners[$key]);
}
}
//print_r($this->listeners)."\n"; // For testing purposes.
}
Test script:
---------------
The behavior of PHP's unset(), which causes the problem for the for statement is reproduced by the script below.
<?php
// Problem Scenario:
$arr[] = 'a';
unset($arr[0]);
$arr[] = 'a'; // Will 'a' be assigned to $arr[0]? Unfortunately, no.
// Using array_merge() fixes the problem that unset() leaves, in the
// above scenario, for the for statement.
//$arr = array_merge($arr); // Fixes the problem.
// If array_merge() is not used to fix the problem, the following for loop
// will fail and produce: "PHP Notice: Undefined offset: 0 in ..."
print "for-statement output:\n";
for( $i=0; $i < count($arr); $i++ )
{
print "[$i] = ". $arr[$i];
}
// foreach is immune to the problem.
print "\n\nforeach-statement output:\n";
foreach( $arr as $key => $val )
{
print "[$key] = $val";
}
print "\n\nArray content:\n".print_r($arr,true);
?>
Expected result:
----------------
Refer to the comments in the script. They explain what's going on.
[2006-08-01 07:50 UTC] sebastian at php dot net
Moved to http://www.phpunit.de/ticket/30.