Note that there are some explanatory texts on larger screens.

plurals
  1. POUnserialize error when @runInSeparateProcess
    text
    copied!<p>I am implementing a module that will provide an API to work with and manage PHP sessions. I am testing the <code>Session\Manager</code> implementation that will allow users to start sessions, set IDs, get IDs, destroy sessions, etc. I am testing the methods in this class in a separate process, by using PHPUnit's <code>@runInSeparateProcess</code> annotation. When I use this annotation I get an exception thrown by PHPUnit due to an unserialization error. When I do not use the annotation the test runs as expected and fails on null not being equal to false.</p> <p>Here's the test causing the error. So far no implementation details have been made, all methods for the interface exist but perform no operations.</p> <pre class="lang-php prettyprint-override"><code>class ManagerTest extends PHPUnitTestCase { /** * Ensures that if the session has not been started yet the sessionExists * method returns false. * * @runInSeparateProcess */ public function testSessionExistsWhenSessionHasNotBeenStarted() { $Manager = new \Session\Manager(); $this-&gt;assertFalse($Manager-&gt;sessionExists()); } } </code></pre> <p>I was able to trace the problem down to the following <a href="https://github.com/sebastianbergmann/phpunit/blob/3.7/PHPUnit/Util/PHP.php#L159" rel="noreferrer"><code>PHPUnit_Util_PHP::runJob()</code></a> method. I am running PHPUnit 3.7.5 and the <code>runJob</code> method being invoked is:</p> <pre class="lang-php prettyprint-override"><code>/** * Runs a single job (PHP code) using a separate PHP process. * * @param string $job * @param PHPUnit_Framework_TestCase $test * @param PHPUnit_Framework_TestResult $result * @return array|null * @throws PHPUnit_Framework_Exception */ public function runJob($job, PHPUnit_Framework_Test $test = NULL, PHPUnit_Framework_TestResult $result = NULL) { $process = proc_open( $this-&gt;getPhpBinary(), array( 0 =&gt; array('pipe', 'r'), 1 =&gt; array('pipe', 'w'), 2 =&gt; array('pipe', 'w') ), $pipes ); if (!is_resource($process)) { throw new PHPUnit_Framework_Exception( 'Unable to create process for process isolation.' ); } if ($result !== NULL) { $result-&gt;startTest($test); } $this-&gt;process($pipes[0], $job); fclose($pipes[0]); $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]); $stderr = stream_get_contents($pipes[2]); fclose($pipes[2]); proc_close($process); $this-&gt;cleanup(); if ($result !== NULL) { $this-&gt;processChildResult($test, $result, $stdout, $stderr); } else { return array('stdout' =&gt; $stdout, 'stderr' =&gt; $stderr); } } </code></pre> <p>The line <code>$stdout = stream_get_contents($pipes[1]);</code> results in <code>$stdout</code> being equal to a long string of <code>?</code>. In <code>$this-&gt;processChildResult</code> the value in <code>$stdout</code> is unserialized and the invalid value passed to this function triggers a warning, resulting in an exception being thrown. I've also been able to determine that the return value of <code>$this-&gt;getPhpBinary()</code> is <code>/usr/bin/php</code>.</p> <p>Exception message thrown:</p> <pre><code>PHPUnit_Framework_Exception: ???...???"*???...?? Caused by ErrorException: unserialize(): Error at offset 0 of 10081 bytes </code></pre> <p>Thanks to hek2mgl the PHP code in <code>$job</code> can be reviewed <a href="https://gist.github.com/4ec1857829af37ad73c3" rel="noreferrer">at this gist holding the output of a var_dump on $job</a>. I created a link as it is a fair amount of code and this question is already quite long.</p> <p>I've reached the end of my knowledge for this particular domain and not sure how go about debugging this problem further. I'm not sure why the <code>@runInSeparateProcess</code> is failing and why the <code>$stdout</code> from running a separate process results in a long string of ? marks. What might be causing this issue and how could I go about resolving it? I'm at a standstill for this module as future tests will require running in a separate process to ensure sessions being started and destroyed don't impact tests.</p> <ul> <li>PHP: 5.3.15</li> <li>PHPUnit: 3.7.5</li> <li>Error caused in IDE and command line test runners</li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload