Merge branch '2.8' into 3.0

* 2.8:
  [Process] Fix stopping a process on Windows
  [PhpUnitBridge] Add weak-verbose mode and match against message instead of test name
  Added a note about the new requirement iconv.
  Improved error messages for Yaml Deprecations
  Added a test case for the Logger class.
  [Form] Fix choices defined as Traversable
  CS: general fixes
  Suggested Process dependency
This commit is contained in:
Christophe Coevoet 2015-12-05 18:45:07 +01:00
commit d553264958
19 changed files with 125 additions and 69 deletions

View File

@ -92,12 +92,16 @@ class DoctrineTokenProvider implements TokenProviderInterface
{
$sql = 'UPDATE rememberme_token SET value=:value, lastUsed=:lastUsed'
.' WHERE series=:series';
$paramValues = array('value' => $tokenValue,
'lastUsed' => $lastUsed,
'series' => $series,);
$paramTypes = array('value' => \PDO::PARAM_STR,
'lastUsed' => DoctrineType::DATETIME,
'series' => \PDO::PARAM_STR,);
$paramValues = array(
'value' => $tokenValue,
'lastUsed' => $lastUsed,
'series' => $series,
);
$paramTypes = array(
'value' => \PDO::PARAM_STR,
'lastUsed' => DoctrineType::DATETIME,
'series' => \PDO::PARAM_STR,
);
$updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes);
if ($updated < 1) {
throw new TokenNotFoundException('No token found.');
@ -112,16 +116,20 @@ class DoctrineTokenProvider implements TokenProviderInterface
$sql = 'INSERT INTO rememberme_token'
.' (class, username, series, value, lastUsed)'
.' VALUES (:class, :username, :series, :value, :lastUsed)';
$paramValues = array('class' => $token->getClass(),
'username' => $token->getUsername(),
'series' => $token->getSeries(),
'value' => $token->getTokenValue(),
'lastUsed' => $token->getLastUsed(),);
$paramTypes = array('class' => \PDO::PARAM_STR,
'username' => \PDO::PARAM_STR,
'series' => \PDO::PARAM_STR,
'value' => \PDO::PARAM_STR,
'lastUsed' => DoctrineType::DATETIME,);
$paramValues = array(
'class' => $token->getClass(),
'username' => $token->getUsername(),
'series' => $token->getSeries(),
'value' => $token->getTokenValue(),
'lastUsed' => $token->getLastUsed(),
);
$paramTypes = array(
'class' => \PDO::PARAM_STR,
'username' => \PDO::PARAM_STR,
'series' => \PDO::PARAM_STR,
'value' => \PDO::PARAM_STR,
'lastUsed' => DoctrineType::DATETIME,
);
$this->conn->executeUpdate($sql, $paramValues, $paramTypes);
}
}

View File

@ -53,6 +53,19 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
$this->assertSame(4, $logger->countErrors());
}
public function testGetLogs()
{
$logger = new Logger('test');
$logger->pushHandler(new DebugHandler());
$logger->addInfo('test');
$this->assertCount(1, $logger->getLogs());
list($record) = $logger->getLogs();
$this->assertEquals('test', $record['message']);
$this->assertEquals(Logger::INFO, $record['priority']);
}
public function testCountErrorsWithoutDebugHandler()
{
$handler = new TestHandler();

View File

@ -18,6 +18,9 @@ namespace Symfony\Bridge\PhpUnit;
*/
class DeprecationErrorHandler
{
const MODE_WEAK = 'weak';
const MODE_WEAK_VERBOSE = 'weak-verbose';
private static $isRegistered = false;
public static function register($mode = false)
@ -64,7 +67,7 @@ class DeprecationErrorHandler
$group = 'remaining';
}
if (isset($mode[0]) && '/' === $mode[0] && preg_match($mode, $class.'::'.$method)) {
if (isset($mode[0]) && '/' === $mode[0] && preg_match($mode, $msg)) {
$e = new \Exception($msg);
$r = new \ReflectionProperty($e, 'trace');
$r->setAccessible(true);
@ -78,7 +81,7 @@ class DeprecationErrorHandler
exit(1);
}
if ('legacy' !== $group && 'weak' !== $mode) {
if ('legacy' !== $group && self::MODE_WEAK !== $mode) {
$ref = &$deprecations[$group][$msg]['count'];
++$ref;
$ref = &$deprecations[$group][$msg][$class.'::'.$method];
@ -144,7 +147,7 @@ class DeprecationErrorHandler
if (!empty($notices)) {
echo "\n";
}
if ('weak' !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other'])) {
if (self::MODE_WEAK !== $mode && self::MODE_WEAK_VERBOSE !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other'])) {
exit(1);
}
});

View File

@ -14,9 +14,9 @@ It comes with the following features:
By default any non-legacy-tagged or any non-@-silenced deprecation notices will
make tests fail.
This can be changed by setting the `SYMFONY_DEPRECATIONS_HELPER` environment
variable to `weak`. This will make the bridge ignore deprecation notices and
is useful to projects that must use deprecated interfaces for backward
compatibility reasons.
variable to `weak` or `weak-verbose`. This will make the bridge ignore
deprecation notices and is useful to projects that must use deprecated interfaces
for backward compatibility reasons.
A summary of deprecation notices is displayed at the end of the test suite:
@ -53,8 +53,9 @@ You have to decide either to:
forward compatibility;
* or move them to the **Legacy** section (by using one of the above way).
In case you need to inspect the stack trace of a particular deprecation triggered by
one of your unit tests, you can set the `SYMFONY_DEPRECATIONS_HELPER` env var to
a regexp that matches this test case's `class::method` name. For example,
`SYMFONY_DEPRECATIONS_HELPER=/^MyTest::testMethod$/ phpunit` will stop your test
suite once a deprecation is triggered by the `MyTest::testMethod` test.
In case you need to inspect the stack trace of a particular deprecation triggered
by your unit tests, you can set the `SYMFONY_DEPRECATIONS_HELPER` env var to a
regular expression that matches this deprecation's message, encapsed between `/`.
For example, `SYMFONY_DEPRECATIONS_HELPER=/foobar/ phpunit` will stop your test
suite once a deprecation notice is triggered whose message contains the "foobar"
string.

View File

@ -31,7 +31,7 @@ class TranslationExtensionTest extends \PHPUnit_Framework_TestCase
public function testTrans($template, $expected, array $variables = array())
{
if ($expected != $this->getTemplate($template)->render($variables)) {
print $template."\n";
echo $template."\n";
$loader = new \Twig_Loader_Array(array('index' => $template));
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
$twig->addExtension(new TranslationExtension(new Translator('en', new MessageSelector())));

View File

@ -58,7 +58,8 @@
"symfony/serializer": "For using the serializer service",
"symfony/validator": "For using validation",
"symfony/yaml": "For using the debug:config and lint:yaml commands",
"symfony/property-info": "For using the property_info_extractor service"
"symfony/property-info": "For using the property_info_extractor service",
"symfony/process": "For using the server:run command"
},
"autoload": {
"psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" },

View File

@ -48,9 +48,9 @@ class TemplateManagerTest extends TestCase
$profiler = $this->mockProfiler();
$twigEnvironment = $this->mockTwigEnvironment();
$templates = array(
'data_collector.foo' => array('foo','FooBundle:Collector:foo'),
'data_collector.bar' => array('bar','FooBundle:Collector:bar'),
'data_collector.baz' => array('baz','FooBundle:Collector:baz'),
'data_collector.foo' => array('foo', 'FooBundle:Collector:foo'),
'data_collector.bar' => array('bar', 'FooBundle:Collector:bar'),
'data_collector.baz' => array('baz', 'FooBundle:Collector:baz'),
);
$this->templateManager = new TemplateManager($profiler, $twigEnvironment, $templates);

View File

@ -97,7 +97,7 @@ class ClassLoader
$paths
));
} elseif (!in_array($paths, $this->prefixes[$prefix])) {
$this->prefixes[$prefix][] = $paths;
$this->prefixes[$prefix][] = $paths;
}
} else {
$this->prefixes[$prefix] = array_unique((array) $paths);

View File

@ -50,7 +50,7 @@ class StringInputTest extends \PHPUnit_Framework_TestCase
array('"quoted"', array('quoted'), '->tokenize() parses quoted arguments'),
array("'quoted'", array('quoted'), '->tokenize() parses quoted arguments'),
array("'a\rb\nc\td'", array("a\rb\nc\td"), '->tokenize() parses whitespace chars in strings'),
array("'a'\r'b'\n'c'\t'd'", array('a','b','c','d'), '->tokenize() parses whitespace chars between args as spaces'),
array("'a'\r'b'\n'c'\t'd'", array('a', 'b', 'c', 'd'), '->tokenize() parses whitespace chars between args as spaces'),
array('\"quoted\"', array('"quoted"'), '->tokenize() parses escaped-quoted arguments'),
array("\'quoted\'", array('\'quoted\''), '->tokenize() parses escaped-quoted arguments'),
array('-a', array('-a'), '->tokenize() parses short options'),

View File

@ -29,7 +29,7 @@ class ElementNodeTest extends AbstractNodeTest
return array(
array(new ElementNode(), 0),
array(new ElementNode(null, 'element'), 1),
array(new ElementNode('namespace', 'element'),1),
array(new ElementNode('namespace', 'element'), 1),
);
}
}

View File

@ -340,7 +340,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
array('json', array('application/json', 'application/x-json')),
array('xml', array('text/xml', 'application/xml', 'application/x-xml')),
array('rdf', array('application/rdf+xml')),
array('atom',array('application/atom+xml')),
array('atom', array('application/atom+xml')),
);
}

View File

@ -169,8 +169,16 @@ class Process
public function __destruct()
{
// stop() will check if we have a process running.
$this->stop();
if ($this->isRunning()) {
$this->doSignal(15, false);
usleep(10000);
}
if ($this->isRunning()) {
usleep(100000);
$this->doSignal(9, false);
}
// Don't call ->stop() nor ->close() since we don't want to wait for the subprocess here
}
public function __clone()
@ -1429,7 +1437,7 @@ class Process
if ('\\' === DIRECTORY_SEPARATOR) {
exec(sprintf('taskkill /F /T /PID %d 2>&1', $this->getPid()), $output, $exitCode);
if ($exitCode) {
if ($exitCode && $this->isRunning()) {
if ($throwException) {
throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
}

View File

@ -194,6 +194,10 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
}
/**
* @expectedException \Symfony\Component\Process\Exception\LogicException
* @expectedExceptionMessage Input can not be set while the process is running.
*/
public function testSetInputWhileRunningThrowsAnException()
{
$process = $this->getProcess(self::$phpBin.' -r "usleep(500000);"');
@ -203,9 +207,10 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$process->stop();
$this->fail('A LogicException should have been raised.');
} catch (LogicException $e) {
$this->assertEquals('Input can not be set while the process is running.', $e->getMessage());
}
$process->stop();
throw $e;
}
/**
@ -738,6 +743,10 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$this->assertNotEquals($process1->getOutput(), $process2->getOutput());
}
/**
* @expectedException Symfony\Component\Process\Exception\RuntimeException
* @expectedExceptionMessage The process timed-out.
*/
public function testRunProcessWithTimeout()
{
$timeout = 0.5;
@ -751,14 +760,13 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
}
$duration = microtime(true) - $start;
if ('\\' === DIRECTORY_SEPARATOR) {
// Windows is a bit slower as it read file handles, then allow twice the precision
$maxDuration = $timeout + 2 * Process::TIMEOUT_PRECISION;
} else {
if ('\\' !== DIRECTORY_SEPARATOR) {
// On Windows, timers are too transient
$maxDuration = $timeout + Process::TIMEOUT_PRECISION;
$this->assertLessThan($maxDuration, $duration);
}
$this->assertLessThan($maxDuration, $duration);
throw $e;
}
public function testCheckTimeoutOnNonStartedProcess()
@ -774,6 +782,10 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$process->checkTimeout();
}
/**
* @expectedException Symfony\Component\Process\Exception\RuntimeException
* @expectedExceptionMessage The process timed-out.
*/
public function testCheckTimeoutOnStartedProcess()
{
$timeout = 0.5;
@ -796,6 +808,8 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$this->assertLessThan($timeout + $precision, $duration);
$this->assertFalse($process->isSuccessful());
throw $e;
}
public function testIdleTimeout()
@ -834,6 +848,10 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
}
}
/**
* @expectedException \Symfony\Component\Process\Exception\ProcessTimedOutException
* @expectedExceptionMessage exceeded the timeout of 0.1 seconds.
*/
public function testStartAfterATimeout()
{
$process = $this->getProcess(sprintf('%s -r %s', self::$phpBin, escapeshellarg('$n = 1000; while ($n--) {echo \'\'; usleep(1000); }')));
@ -847,6 +865,8 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$process->start();
usleep(1000);
$process->stop();
throw $e;
}
public function testGetPid()
@ -876,14 +896,14 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$this->markTestSkipped('Extension pcntl is required.');
}
$process = $this->getProcess('exec php -f '.__DIR__.'/SignalListener.php');
$process = $this->getProcess('exec '.self::$phpBin.' '.__DIR__.'/SignalListener.php');
$process->start();
usleep(500000);
$process->signal(SIGUSR1);
while ($process->isRunning() && false === strpos($process->getOutput(), 'Caught SIGUSR1')) {
usleep(10000);
while (false === strpos($process->getOutput(), 'Caught')) {
usleep(1000);
}
$process->signal(SIGUSR1);
$process->wait();
$this->assertEquals('Caught SIGUSR1', $process->getOutput());
}
@ -944,6 +964,8 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
/**
* @dataProvider provideMethodsThatNeedATerminatedProcess
* @expectedException Symfony\Component\Process\Exception\LogicException
* @expectedExceptionMessage Process must be terminated before calling
*/
public function testMethodsThatNeedATerminatedProcess($method)
{
@ -954,10 +976,10 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
$process->stop(0);
$this->fail('A LogicException must have been thrown');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\Component\Process\Exception\LogicException', $e);
$this->assertEquals(sprintf('Process must be terminated before calling %s.', $method), $e->getMessage());
}
$process->stop(0);
throw $e;
}
public function provideMethodsThatNeedATerminatedProcess()

View File

@ -112,6 +112,10 @@ class SigchildEnabledProcessTest extends AbstractProcessTest
$this->markTestSkipped('Signal is not supported in sigchild environment');
}
/**
* @expectedException \Symfony\Component\Process\Exception\ProcessTimedOutException
* @expectedExceptionMessage exceeded the timeout of 0.1 seconds.
*/
public function testStartAfterATimeout()
{
if ('\\' === DIRECTORY_SEPARATOR) {

View File

@ -9,17 +9,13 @@
* file that was distributed with this source code.
*/
// required for signal handling
declare (ticks = 1);
pcntl_signal(SIGUSR1, function () {echo 'SIGUSR1'; exit;});
pcntl_signal(SIGUSR1, function () {echo 'Caught SIGUSR1'; exit;});
echo 'Caught ';
$n = 0;
// ticks require activity to work - sleep(4); does not work
while ($n < 400) {
while ($n++ < 400) {
usleep(10000);
++$n;
pcntl_signal_dispatch();
}
return;

View File

@ -86,7 +86,7 @@ class PhpGeneratorDumperTest extends \PHPUnit_Framework_TestCase
public function testDumpWithTooManyRoutes()
{
$this->routeCollection->add('Test', new Route('/testing/{foo}'));
for ( $i = 0; $i < 32769; ++$i ) {
for ($i = 0; $i < 32769; ++$i) {
$this->routeCollection->add('route_'.$i, new Route('/route_'.$i));
}
$this->routeCollection->add('Test2', new Route('/testing2'));

View File

@ -97,7 +97,7 @@ class InMemoryUserProvider implements UserProviderInterface
/**
* Returns the user by given username.
*
* @param string $username The username.
* @param string $username The username.
*
* @return User
*

View File

@ -74,7 +74,7 @@ class XmlEncoderTest extends \PHPUnit_Framework_TestCase
'@Type' => 'test',
),
'föo_bär' => 'a',
'Bar' => array(1,2,3),
'Bar' => array(1, 2, 3),
'a' => 'b',
);
$expected = '<?xml version="1.0"?>'."\n".
@ -384,7 +384,7 @@ XML;
'@Type' => 'test',
),
'föo_bär' => 'a',
'Bar' => array(1,2,3),
'Bar' => array(1, 2, 3),
'a' => 'b',
);
$expected = array(
@ -397,7 +397,7 @@ XML;
'@Type' => 'test',
),
'föo_bär' => 'a',
'Bar' => array(1,2,3),
'Bar' => array(1, 2, 3),
'a' => 'b',
);
$xml = $this->encoder->encode($obj, 'xml');

View File

@ -60,10 +60,10 @@ class PluralizationRulesTest extends \PHPUnit_Framework_TestCase
public function successLangcodes()
{
return array(
array('1', array('ay','bo', 'cgg','dz','id', 'ja', 'jbo', 'ka','kk','km','ko','ky')),
array('1', array('ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky')),
array('2', array('nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM')),
array('3', array('be','bs','cs','hr')),
array('4', array('cy','mt', 'sl')),
array('3', array('be', 'bs', 'cs', 'hr')),
array('4', array('cy', 'mt', 'sl')),
array('5', array()),
array('6', array('ar')),
);
@ -83,7 +83,7 @@ class PluralizationRulesTest extends \PHPUnit_Framework_TestCase
array('1', array('fa')),
array('2', array('jbo')),
array('3', array('cbs')),
array('4', array('gd','kw')),
array('4', array('gd', 'kw')),
array('5', array('ga')),
array('6', array()),
);