From: Ori Livneh Date: Wed, 11 May 2016 11:12:46 +0000 (-0700) Subject: In MediaWikiTestCase::stashMwGlobals(), prefer shallow copies X-Git-Tag: 1.31.0-rc.0~6927^2 X-Git-Url: http://git.cyclocoop.org/%24image?a=commitdiff_plain;h=49b162cac179a67842e15e62eeb9deb7953827eb;p=lhc%2Fweb%2Fwiklou.git In MediaWikiTestCase::stashMwGlobals(), prefer shallow copies MediaWikiTestCase::stashMwGlobals() performs a deep copy of globals by serializing and then unserializing them. This is actually unwarranted in the common case of simple scalar values and flat arrays -- and it's expensive, too. So before attempting a deep copy, first check if a shallow copy will do. Change-Id: Iaba1c8e1f6bae9de0a7a1fb411cac94f7e4dfb23 --- diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php index 9f3aa11a7c..176ec2ca4c 100644 --- a/tests/phpunit/MediaWikiTestCase.php +++ b/tests/phpunit/MediaWikiTestCase.php @@ -597,6 +597,29 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { } } + /** + * Check if we can back up a value by performing a shallow copy. + * Values which fail this test are copied recursively. + * + * @param mixed $value + * @return bool True if a shallow copy will do; false if a deep copy + * is required. + */ + private static function canShallowCopy( $value ) { + if ( is_scalar( $value ) || $value === null ) { + return true; + } + if ( is_array( $value ) ) { + foreach ( $value as $subValue ) { + if ( !is_scalar( $subValue ) && $subValue !== null ) { + return false; + } + } + return true; + } + return false; + } + /** * Stashes the global, will be restored in tearDown() * @@ -632,13 +655,22 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { // NOTE: we serialize then unserialize the value in case it is an object // this stops any objects being passed by reference. We could use clone // and if is_object but this does account for objects within objects! - try { - $this->mwGlobals[$globalKey] = unserialize( serialize( $GLOBALS[$globalKey] ) ); - } - // NOTE; some things such as Closures are not serializable - // in this case just set the value! - catch ( Exception $e ) { + if ( self::canShallowCopy( $GLOBALS[$globalKey] ) ) { $this->mwGlobals[$globalKey] = $GLOBALS[$globalKey]; + } elseif ( + // Many MediaWiki types are safe to clone. These are the + // ones that are most commonly stashed. + $GLOBALS[$globalKey] instanceof Language || + $GLOBALS[$globalKey] instanceof User || + $GLOBALS[$globalKey] instanceof FauxRequest + ) { + $this->mwGlobals[$globalKey] = clone $GLOBALS[$globalKey]; + } else { + try { + $this->mwGlobals[$globalKey] = unserialize( serialize( $GLOBALS[$globalKey] ) ); + } catch ( Exception $e ) { + $this->mwGlobals[$globalKey] = $GLOBALS[$globalKey]; + } } } }