I am trying to generate code test coverage for my PHP project with PHPUnit and phpdbg using the following command:
phpdbg -dmemory_limit=512M -qrr ./bin/phpunit -c .phpunit.cover.xml
This works perfectly fine:
PHPUnit 6.2.4 by Sebastian Bergmann and contributors.
........ 8 / 8 (100%)
Time: 114 ms, Memory: 14.00MB
OK (8 tests, 13 assertions)
Generating code coverage report in HTML format ... done
However, when I use the exact same command in a docker container:
docker run -it --name YM4UPltmiPMjObaVULwsIPIkPL2bGL0T -e USER=sasan -v "/home/sasan/Project/phpredmin:/phpredmin" -w "/phpredmin" --user "1000:www-data" php:7.0-apache phpdbg -dmemory_limit=512M -qrr ./bin/phpunit -c .phpunit.cover.xml
I get the following error:
PHPUnit 6.2.4 by Sebastian Bergmann and contributors.
[PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 561514763337856 bytes) in /phpredmin/vendor/phpunit/phpunit/src/Util/GlobalState.php on line 166]
I don't understand why PHPUnit needs to allocate 561514763337856 bytes of memory. I suspect it gets stuck in a loop, but why this does not happen outside of the container? Here is my PHP version on my machine:
PHP 7.0.22-0ubuntu0.17.04.1 (cli) (built: Aug 8 2017 22:03:30) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.0.22-0ubuntu0.17.04.1, Copyright (c) 1999-2017, by Zend Technologies
And here is the .phpunit.cover.xml file:
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
cacheTokens="false"
colors="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="true"
stopOnFailure="true"
stopOnIncomplete="false"
stopOnSkipped="false"
stopOnRisky="false"
timeoutForSmallTests="1"
timeoutForMediumTests="10"
timeoutForLargeTests="60"
verbose="false">
<testsuites>
<testsuite name="PhpRedmin PHP source">
<directory>src-test/</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-html" target="cover/" lowUpperBound="35"
highLowerBound="70"/>
</logging>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src-test/</directory>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
</phpunit>
-- Edit1 --
I found that it has something to do with @runInSeparateProcess. When I remove the test that has @runInSeparateProcess then it starts to work. But still I don't know what is the problem
-- Edit2 --
Also I found out that If I don't mount my code directory in the Docker container everything works fine
Add '-d memory_limit=-1' before your test
if use composer use the below code
./vendor/bin/simple-phpunit -d memory_limit=-1 tests/
if you use phpdbg use the below code
phpdbg -d memory_limit=-1 -qrr vendor/bin/phpunit --coverage-text
When we use @runInSeparateProcess
, PHPUnit will attempt to serialize included files, ini settings, global variables, and constants to pass them to the new process. In this case, it looks like PHPUnit encountered a recursive scenario when serializing one of these items, which exhausted the memory available to the PHP process. We need to determine what changed between your local environment and the Docker container.
First, we can try disabling this serialization behavior to verify that we should proceed along this path. Add the following @preserveGlobalState
annotation to the test method that fails:
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testInSeparateProcess()
{
// ...
}
If this resolves the problem, or if we get a new error, we can begin looking for differences in the Docker container that may cause the issue. Without more visibility into the code and environment, it's hard to suggest where to start, but here are some ideas:
php -i
from each environment. Look out for PHP extensions that exist in one, but not the other. phpdbg
to set a breakpoint and step through the code. We're already using it to generate coverage, but it's also a useful debugging tool. We're looking for the item that causes the infinite recursion. Note that we'll need to set the breakpoint before PHPUnit executes the test case such as in the bootstrap file or PHPUnit source code (line 810 of TestCase
may work).www-data
user in the container has the same UID as the user that owns the files on the host. I couldn't reproduce this issue using a dummy test in a similar environment (as close as I could get—same container with volume), so the code under test may contribute to the problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With