Merge branch '2.4' into 2.5
* 2.4: [HttpKernel] added an analyze of environment parameters for built-in server. change command to which available under most unix systems add way to test command under windows fix shell command injection [Form] allowed CallbackTransformer to use callable [Process] Added process synchronization to the incremental output tests
This commit is contained in:
commit
5ca28c0d71
@ -25,6 +25,7 @@ if (is_file($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$_SERVER['SCRIPT_NAME'
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$_SERVER = array_merge($_SERVER, $_ENV);
|
||||||
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.'app_dev.php';
|
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.'app_dev.php';
|
||||||
|
|
||||||
require 'app_dev.php';
|
require 'app_dev.php';
|
||||||
|
@ -25,6 +25,7 @@ if (is_file($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$_SERVER['SCRIPT_NAME'
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$_SERVER = array_merge($_SERVER, $_ENV);
|
||||||
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.'app.php';
|
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.'app.php';
|
||||||
|
|
||||||
require 'app.php';
|
require 'app.php';
|
||||||
|
@ -50,17 +50,19 @@ class Shell
|
|||||||
*/
|
*/
|
||||||
public function testCommand($command)
|
public function testCommand($command)
|
||||||
{
|
{
|
||||||
if (self::TYPE_WINDOWS === $this->type) {
|
|
||||||
// todo: find a way to test if Windows command exists
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('exec')) {
|
if (!function_exists('exec')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: find a better way (command could not be available)
|
// todo: find a better way (command could not be available)
|
||||||
exec('command -v '.$command, $output, $code);
|
$testCommand = 'which ';
|
||||||
|
if (self::TYPE_WINDOWS === $this->type) {
|
||||||
|
$testCommand = 'where ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$command = escapeshellcmd($command);
|
||||||
|
|
||||||
|
exec($testCommand.$command, $output, $code);
|
||||||
|
|
||||||
return 0 === $code && count($output) > 0;
|
return 0 === $code && count($output) > 0;
|
||||||
}
|
}
|
||||||
|
@ -18,24 +18,33 @@ class CallbackTransformer implements DataTransformerInterface
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The callback used for forward transform
|
* The callback used for forward transform
|
||||||
* @var \Closure
|
* @var callable
|
||||||
*/
|
*/
|
||||||
private $transform;
|
private $transform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The callback used for reverse transform
|
* The callback used for reverse transform
|
||||||
* @var \Closure
|
* @var callable
|
||||||
*/
|
*/
|
||||||
private $reverseTransform;
|
private $reverseTransform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param \Closure $transform The forward transform callback
|
* @param callable $transform The forward transform callback
|
||||||
* @param \Closure $reverseTransform The reverse transform callback
|
* @param callable $reverseTransform The reverse transform callback
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException when the given callbacks is invalid
|
||||||
*/
|
*/
|
||||||
public function __construct(\Closure $transform, \Closure $reverseTransform)
|
public function __construct($transform, $reverseTransform)
|
||||||
{
|
{
|
||||||
|
if (!is_callable($transform)) {
|
||||||
|
throw new \InvalidArgumentException('Argument 1 should be a callable');
|
||||||
|
}
|
||||||
|
if (!is_callable($reverseTransform)) {
|
||||||
|
throw new \InvalidArgumentException('Argument 2 should be a callable');
|
||||||
|
}
|
||||||
|
|
||||||
$this->transform = $transform;
|
$this->transform = $transform;
|
||||||
$this->reverseTransform = $reverseTransform;
|
$this->reverseTransform = $reverseTransform;
|
||||||
}
|
}
|
||||||
@ -47,7 +56,7 @@ class CallbackTransformer implements DataTransformerInterface
|
|||||||
*
|
*
|
||||||
* @return mixed The value in the transformed representation
|
* @return mixed The value in the transformed representation
|
||||||
*
|
*
|
||||||
* @throws UnexpectedTypeException when the argument is not a string
|
* @throws UnexpectedTypeException when the argument is not of the expected type
|
||||||
* @throws TransformationFailedException when the transformation fails
|
* @throws TransformationFailedException when the transformation fails
|
||||||
*/
|
*/
|
||||||
public function transform($data)
|
public function transform($data)
|
||||||
|
37
src/Symfony/Component/Form/Tests/CallbackTransformerTest.php
Normal file
37
src/Symfony/Component/Form/Tests/CallbackTransformerTest.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Form\Tests;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\CallbackTransformer;
|
||||||
|
|
||||||
|
class CallbackTransformerTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testTransform()
|
||||||
|
{
|
||||||
|
$transformer = new CallbackTransformer(
|
||||||
|
function($value) { return $value.' has been transformed'; },
|
||||||
|
function($value) { return $value.' has reversely been transformed'; }
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals('foo has been transformed', $transformer->transform('foo'));
|
||||||
|
$this->assertEquals('bar has reversely been transformed', $transformer->reverseTransform('bar'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider invalidCallbacksProvider
|
||||||
|
*
|
||||||
|
* @expectedException \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testConstructorWithInvalidCallbacks($transformCallback, $reverseTransformCallback)
|
||||||
|
{
|
||||||
|
new CallbackTransformer($transformCallback, $reverseTransformCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function invalidCallbacksProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array( null, function(){} ),
|
||||||
|
array( function(){}, null ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -260,13 +260,23 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testGetIncrementalErrorOutput()
|
public function testGetIncrementalErrorOutput()
|
||||||
{
|
{
|
||||||
$p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { usleep(100000); file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));
|
// use a lock file to toggle between writing ("W") and reading ("R") the
|
||||||
|
// error stream
|
||||||
|
$lock = tempnam(sys_get_temp_dir(), get_class($this).'Lock');
|
||||||
|
file_put_contents($lock, 'W');
|
||||||
|
|
||||||
|
$p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { if (\'W\' === file_get_contents('.var_export($lock, true).')) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; file_put_contents('.var_export($lock, true).', \'R\'); } usleep(100); }')));
|
||||||
|
|
||||||
$p->start();
|
$p->start();
|
||||||
while ($p->isRunning()) {
|
while ($p->isRunning()) {
|
||||||
|
if ('R' === file_get_contents($lock)) {
|
||||||
$this->assertLessThanOrEqual(1, preg_match_all('/ERROR/', $p->getIncrementalErrorOutput(), $matches));
|
$this->assertLessThanOrEqual(1, preg_match_all('/ERROR/', $p->getIncrementalErrorOutput(), $matches));
|
||||||
usleep(20000);
|
file_put_contents($lock, 'W');
|
||||||
}
|
}
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink($lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFlushErrorOutput()
|
public function testFlushErrorOutput()
|
||||||
@ -280,7 +290,7 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testGetOutput()
|
public function testGetOutput()
|
||||||
{
|
{
|
||||||
$p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++; usleep(500); }')));
|
$p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { echo \' foo \'; $n++; }')));
|
||||||
|
|
||||||
$p->run();
|
$p->run();
|
||||||
$this->assertEquals(3, preg_match_all('/foo/', $p->getOutput(), $matches));
|
$this->assertEquals(3, preg_match_all('/foo/', $p->getOutput(), $matches));
|
||||||
@ -288,13 +298,23 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testGetIncrementalOutput()
|
public function testGetIncrementalOutput()
|
||||||
{
|
{
|
||||||
$p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) { echo \' foo \'; usleep(50000); $n++; }')));
|
// use a lock file to toggle between writing ("W") and reading ("R") the
|
||||||
|
// output stream
|
||||||
|
$lock = tempnam(sys_get_temp_dir(), get_class($this).'Lock');
|
||||||
|
file_put_contents($lock, 'W');
|
||||||
|
|
||||||
|
$p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { if (\'W\' === file_get_contents('.var_export($lock, true).')) { echo \' foo \'; $n++; file_put_contents('.var_export($lock, true).', \'R\'); } usleep(100); }')));
|
||||||
|
|
||||||
$p->start();
|
$p->start();
|
||||||
while ($p->isRunning()) {
|
while ($p->isRunning()) {
|
||||||
|
if ('R' === file_get_contents($lock)) {
|
||||||
$this->assertLessThanOrEqual(1, preg_match_all('/foo/', $p->getIncrementalOutput(), $matches));
|
$this->assertLessThanOrEqual(1, preg_match_all('/foo/', $p->getIncrementalOutput(), $matches));
|
||||||
usleep(20000);
|
file_put_contents($lock, 'W');
|
||||||
}
|
}
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink($lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testFlushOutput()
|
public function testFlushOutput()
|
||||||
|
Reference in New Issue
Block a user