Handle recursive and repeated arrays more gracefully when exporting #773

Merged
merged 12 commits into from Jan 8, 2013

Projects

None yet

2 participants

@LawnGnome
Contributor

This PR largely replaces PHPUnit_Util_Type::recursiveExport() with a more robust implementation that doesn't rely on print_r() to detect array recursion.

Test suites that have heavily nested arrays don't seem to have recursion picked up completely reliably — this seems to particularly manifest itself when dealing with codebases that use Symfony 2 and Doctrine ORM, where the proxied entity objects often include recursed and repeated arrays. As a result, when an assertion fails and the data structure has to be exported, PHP typically runs out of memory while looping infinitely. (For example, my memory_limit is set to 8G. At the risk of invoking Bill Gates, that should be enough for anyone.)

This implementation uses a completely userland approach to detect array recursion, and keeps the list of previously seen arrays and objects in a new context object (which also uses SplObjectStorage for more efficient storage of the seen object set).

The output format of recursiveExport() has changed in this PR: arrays now include a numeric ID, and objects now include a hexadecimal hash from spl_object_hash(). The initial reference to an array or object will dump the entire array or object as it does now, while subsequent references will simply show the ID/hash.

@sebastianbergmann sebastianbergmann merged commit 9267b0b into sebastianbergmann:master Jan 8, 2013

1 check passed

default The Travis build passed
Details
@sebastianbergmann
Owner

Thanks!

I do get the following failure on my machine:

➜  phpunit git:(master) phpunit
PHPUnit 3.8-g562045c by Sebastian Bergmann.

Configuration read from /usr/local/src/phpunit/phpunit.xml.dist

...............................................................  63 / 939 (  6%)
............................................................... 126 / 939 ( 13%)
............................................................... 189 / 939 ( 20%)
............................................................... 252 / 939 ( 26%)
............................................................... 315 / 939 ( 33%)
............................................................... 378 / 939 ( 40%)
............................................................... 441 / 939 ( 46%)
............................................................... 504 / 939 ( 53%)
............................................................... 567 / 939 ( 60%)
............................................................... 630 / 939 ( 67%)
.............F................................................. 693 / 939 ( 73%)
............................................................... 756 / 939 ( 80%)
............................................................... 819 / 939 ( 87%)
............................................................... 882 / 939 ( 93%)
.........................................................

Time: 38 seconds, Memory: 64.50Mb

There was 1 failure:

1) Framework_ConstraintTest::testConstraintIsEqual2 with data set #13 (SplObjectStorage, SplObjectStorage, 'Failed asserting that two objects are equal.
--- Expected
+++ Actual
@@ @@
-SplObjectStorage Object &000000006725cab800000000778c5e15 (
-    \'000000006725caa600000000778df095\' => Array &0 (
-        \'obj\' => stdClass Object &000000006725caa600000000778df095 (
-            \'foo\' => \'bar\'
-        )
+SplObjectStorage Object &000000006725cab900000000778c5e15 (
+    \'000000006725caa700000000778df095\' => Array &0 (
+        \'obj\' => stdClass Object &000000006725caa700000000778df095 ()
         \'inf\' => null
     )
-    \'000000006725caa700000000778df095\' => Array &0
 )
')
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
 -SplObjectStorage Object &000000006725cab800000000778c5e15 (
--    '000000006725caa600000000778df095' => Array &0 (
--        'obj' => stdClass Object &000000006725caa600000000778df095 (
++SplObjectStorage Object &000000006725cab900000000778c5e15 (
+     Binary String: 0x00676364617461 => Array &0 (
+-        0 => stdClass Object &000000006725caa600000000778df095 (
 -            'foo' => 'bar'
 -        )
-+SplObjectStorage Object &000000006725cab900000000778c5e15 (
-+    '000000006725caa700000000778df095' => Array &0 (
-+        'obj' => stdClass Object &000000006725caa700000000778df095 ()
-         'inf' => null
++        0 => stdClass Object &000000006725caa700000000778df095 ()
+         1 => null
+-        2 => stdClass Object &000000006725caa700000000778df095 ()
+-        3 => null
      )
--    '000000006725caa700000000778df095' => Array &0
+-    '000000006725caa600000000778df095' => Array &0
+     '000000006725caa700000000778df095' => Array &0
  )
 '

/usr/local/src/phpunit/PHPUnit/Framework/Constraint/IsEqual.php:170
/usr/local/src/phpunit/PHPUnit/Framework/Assert.php:2134
/usr/local/src/phpunit/PHPUnit/Framework/Assert.php:475
/usr/local/src/phpunit/Tests/Framework/ConstraintTest.php:946
/usr/local/src/phpunit/PHPUnit/Framework/TestCase.php:975
/usr/local/src/phpunit/PHPUnit/Framework/TestCase.php:830
/usr/local/src/phpunit/PHPUnit/Framework/TestResult.php:646
/usr/local/src/phpunit/PHPUnit/Framework/TestCase.php:775
/usr/local/src/phpunit/PHPUnit/Framework/TestSuite.php:775
/usr/local/src/phpunit/PHPUnit/Framework/TestSuite.php:745
/usr/local/src/phpunit/PHPUnit/Framework/TestSuite.php:705
/usr/local/src/phpunit/PHPUnit/Framework/TestSuite.php:705
/usr/local/src/phpunit/PHPUnit/TextUI/TestRunner.php:350
/usr/local/src/phpunit/PHPUnit/TextUI/Command.php:176
/usr/local/src/phpunit/PHPUnit/TextUI/Command.php:129

FAILURES!
Tests: 939, Assertions: 1523, Failures: 1.

Generating code coverage report in Clover XML format ... done

Generating code coverage report in HTML format ... done

Any idea?

@LawnGnome
Contributor

I can't reproduce it locally. What version of PHP are you running?

@sebastianbergmann
Owner
➜  ~  php -v
PHP 5.4.12-dev (cli) (built: Jan  9 2013 06:13:47) (DEBUG)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
    with Xdebug v2.3.0dev, Copyright (c) 2002-2012, by Derick Rethans

➜  ~  php-5.5 -v         
PHP 5.5.0-dev (cli) (built: Jan  9 2013 06:15:05) (DEBUG)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0-dev, Copyright (c) 1998-2013 Zend Technologies
    with Xdebug v2.3.0dev, Copyright (c) 2002-2012, by Derick Rethans
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment