PEAR is discontinued

This is a static archive preserving historical releases and metadata. No new packages or updates will be published. For updates to existing packages, or to publish new packages, please use Composer and Packagist.

Home » Testing » PHPUnit2 » Bug #8275

PHPUnit2_Framework_TestResult::removeListener() not removing.

Details

Request #8275PHPUnit2_Framework_TestResult::removeListener() not removing.
Submitted2006-07-24 15:40 UTC
Fromsaggnic at gmail dot com
Assignedsebastian
StatusClosed
PackagePHPUnit2
PHP Version5.1.4
OSLinux
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.