Skip to content

Commit

Permalink
Merge branch '4.1' into 4.2
Browse files Browse the repository at this point in the history
* 4.1:
  Bump phpunit bridge cache id
  [appveyor] fix create-project phpunit
  Fix HttpKernel Debug requirement
  Fix heredoc
  use final annotation to allow mocking the class
  synchronise the form builder docblock
  Grammar fix in exception message
  fix tests
  forward the parse error to the calling code
  [Debug][DebugClassLoader] Match more cases for final, deprecated and internal classes / methods extends
  ensure compatibility with older PHPUnit mocks
  [Security] Do not mix usage of password_*() functions and sodium_*() ones
  • Loading branch information
nicolas-grekas committed Jan 24, 2019
2 parents 5564d73 + aff17e2 commit 61bf16c
Show file tree
Hide file tree
Showing 23 changed files with 149 additions and 77 deletions.
2 changes: 1 addition & 1 deletion phpunit
@@ -1,7 +1,7 @@
#!/usr/bin/env php
<?php

// Cache-Id: https://github.com/symfony/phpunit-bridge/commit/2155067dfc73e0e77dbc26f236af17e4df552de5
// Cache-Id: https://github.com/symfony/symfony/commit/aad0c58

if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) {
echo "Unable to find the `simple-phpunit` script in `vendor/symfony/phpunit-bridge/bin/`.\nPlease run `composer update` before running this command.\n";
Expand Down
Expand Up @@ -45,14 +45,14 @@ protected function tearDown()
$this->form = null;
}

protected function getBuilder($name = 'name')
protected function getBuilder()
{
return new FormBuilder($name, null, $this->dispatcher, $this->factory);
return new FormBuilder('name', null, $this->dispatcher, $this->factory);
}

protected function getForm($name = 'name')
protected function getForm()
{
return $this->getBuilder($name)
return $this->getBuilder()
->setData($this->collection)
->addEventSubscriber(new MergeDoctrineCollectionListener())
->getForm();
Expand Down
4 changes: 3 additions & 1 deletion src/Symfony/Bridge/PhpUnit/bin/simple-phpunit
Expand Up @@ -90,7 +90,9 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
@mkdir($PHPUNIT_DIR, 0777, true);
chdir($PHPUNIT_DIR);
if (file_exists("phpunit-$PHPUNIT_VERSION")) {
passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? '(del /S /F /Q %s & rmdir %1$s) >nul': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION"));
passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s > NUL': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION.old"));
rename("phpunit-$PHPUNIT_VERSION", "phpunit-$PHPUNIT_VERSION.old");
passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION.old"));
}
passthru("$COMPOSER create-project --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit phpunit-$PHPUNIT_VERSION \"$PHPUNIT_VERSION.*\"");
chdir("phpunit-$PHPUNIT_VERSION");
Expand Down
Expand Up @@ -15,6 +15,7 @@
use Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\JsonResponse;
Expand Down Expand Up @@ -487,7 +488,8 @@ public function testCreateNotFoundException()

public function testCreateForm()
{
$form = $this->getMockBuilder('Symfony\Component\Form\FormInterface')->getMock();
$config = $this->getMockBuilder('Symfony\Component\Form\FormConfigInterface')->getMock();
$form = new Form($config);

$formFactory = $this->getMockBuilder('Symfony\Component\Form\FormFactoryInterface')->getMock();
$formFactory->expects($this->once())->method('create')->willReturn($form);
Expand Down
6 changes: 3 additions & 3 deletions src/Symfony/Component/Debug/DebugClassLoader.php
Expand Up @@ -232,8 +232,8 @@ public function checkAnnotations(\ReflectionClass $refl, $class)
// Detect annotations on the class
if (false !== $doc = $refl->getDocComment()) {
foreach (['final', 'deprecated', 'internal'] as $annotation) {
if (false !== \strpos($doc, $annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) {
self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
}
}
}
Expand Down Expand Up @@ -325,7 +325,7 @@ public function checkAnnotations(\ReflectionClass $refl, $class)

foreach (['final', 'internal'] as $annotation) {
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
$message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
$message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message];
$finalOrInternal = true;
}
Expand Down
38 changes: 23 additions & 15 deletions src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php
Expand Up @@ -198,24 +198,31 @@ class_exists('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent', true

public function testExtendedFinalClass()
{
set_error_handler(function () { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
$deprecations = [];
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);

require __DIR__.'/Fixtures/FinalClasses.php';

class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true);
$i = 1;
while(class_exists($finalClass = __NAMESPACE__.'\\Fixtures\\FinalClass'.$i++, false)) {
spl_autoload_call($finalClass);
class_exists('Test\\'.__NAMESPACE__.'\\Extends'.substr($finalClass, strrpos($finalClass, '\\') + 1), true);
}

error_reporting($e);
restore_error_handler();

$lastError = error_get_last();
unset($lastError['file'], $lastError['line']);

$xError = [
'type' => E_USER_DEPRECATED,
'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".',
];

$this->assertSame($xError, $lastError);
$this->assertSame([
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass1" class is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass1".',
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass2" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass2".',
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass3" class is considered final comment with @@@ and ***. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass3".',
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass4" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass4".',
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass5" class is considered final multiline comment. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass5".',
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass6" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass6".',
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass7" class is considered final another multiline comment... It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass7".',
'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass8" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass8".',
], $deprecations);
}

public function testExtendedFinalMethod()
Expand Down Expand Up @@ -343,8 +350,9 @@ public function findFile($class)
eval('namespace Test\\'.__NAMESPACE__.'; class NonDeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\NonDeprecatedInterface {}');
} elseif ('Test\\'.__NAMESPACE__.'\Float' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class Float {}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}');
} elseif (0 === strpos($class, 'Test\\'.__NAMESPACE__.'\ExtendsFinalClass')) {
$classShortName = substr($class, strrpos($class, '\\') + 1);
eval('namespace Test\\'.__NAMESPACE__.'; class '.$classShortName.' extends \\'.__NAMESPACE__.'\Fixtures\\'.substr($classShortName, 7).' {}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass {
public function deprecatedMethod() { }
Expand Down
10 changes: 0 additions & 10 deletions src/Symfony/Component/Debug/Tests/Fixtures/FinalClass.php

This file was deleted.

84 changes: 84 additions & 0 deletions src/Symfony/Component/Debug/Tests/Fixtures/FinalClasses.php
@@ -0,0 +1,84 @@
<?php

namespace Symfony\Component\Debug\Tests\Fixtures;

/**
* @final since version 3.3.
*/
class FinalClass1
{
// simple comment
}

/**
* @final
*/
class FinalClass2
{
// no comment
}

/**
* @final comment with @@@ and ***
*
* @author John Doe
*/
class FinalClass3
{
// with comment and a tag after
}

/**
* @final
* @author John Doe
*/
class FinalClass4
{
// without comment and a tag after
}

/**
* @author John Doe
*
*
* @final multiline
* comment
*/
class FinalClass5
{
// with comment and a tag before
}

/**
* @author John Doe
*
* @final
*/
class FinalClass6
{
// without comment and a tag before
}

/**
* @author John Doe
*
* @final another
*
* multiline comment...
*
* @return string
*/
class FinalClass7
{
// with comment and a tag before and after
}

/**
* @author John Doe
* @final
* @return string
*/
class FinalClass8
{
// without comment and a tag before and after
}
Expand Up @@ -395,7 +395,7 @@ private function parseFileToDOM($file)
try {
$dom = XmlUtils::loadFile($file, [$this, 'validateSchema']);
} catch (\InvalidArgumentException $e) {
throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e);
throw new InvalidArgumentException(sprintf('Unable to parse file "%s": %s', $file, $e->getMessage()), $e->getCode(), $e);
}

$this->validateExtensions($dom, $file);
Expand Down
Expand Up @@ -630,7 +630,7 @@ protected function loadFile($file)
try {
$configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS);
} catch (ParseException $e) {
throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e);
throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: %s', $file, $e->getMessage()), 0, $e);
}

return $this->validate($configuration, $file);
Expand Down
Expand Up @@ -68,7 +68,7 @@ public function testParseFile()
$this->fail('->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'parameters.ini'), $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s": .+.$#', 'parameters.ini'), $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');

$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
Expand All @@ -82,7 +82,7 @@ public function testParseFile()
$this->fail('->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'nonvalid.xml'), $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s": .+.$#', 'nonvalid.xml'), $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');

$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
Expand Down Expand Up @@ -428,7 +428,7 @@ public function testExtensions()
$this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services3.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s": .+.$#', 'services3.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');

$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
Expand Down Expand Up @@ -465,7 +465,7 @@ public function testExtensionInPhar()
$this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services7.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s": .+.$#', 'services7.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');

$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
Expand Down Expand Up @@ -516,7 +516,7 @@ public function testDocTypeIsNotAllowed()
$this->fail('->load() throws an InvalidArgumentException if the configuration contains a document type');
} catch (\Exception $e) {
$this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'withdoctype.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');
$this->assertRegExp(sprintf('#^Unable to parse file ".+%s": .+.$#', 'withdoctype.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');

$e = $e->getPrevious();
$this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Dotenv/Dotenv.php
Expand Up @@ -212,7 +212,7 @@ private function lexVarname()
}

if (' ' === $this->data[$this->cursor] || "\t" === $this->data[$this->cursor]) {
throw $this->createFormatException('Whitespace are not supported after the variable name');
throw $this->createFormatException('Whitespace characters are not supported after the variable name');
}

if ('=' !== $this->data[$this->cursor]) {
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Dotenv/Tests/DotenvTest.php
Expand Up @@ -36,7 +36,7 @@ public function getEnvDataWithFormatErrors()
{
$tests = [
['FOO=BAR BAZ', "A value containing spaces must be surrounded by quotes in \".env\" at line 1.\n...FOO=BAR BAZ...\n ^ line 1 offset 11"],
['FOO BAR=BAR', "Whitespace are not supported after the variable name in \".env\" at line 1.\n...FOO BAR=BAR...\n ^ line 1 offset 3"],
['FOO BAR=BAR', "Whitespace characters are not supported after the variable name in \".env\" at line 1.\n...FOO BAR=BAR...\n ^ line 1 offset 3"],
['FOO', "Missing = in the environment variable declaration in \".env\" at line 1.\n...FOO...\n ^ line 1 offset 3"],
['FOO="foo', "Missing quote to end the value in \".env\" at line 1.\n...FOO=\"foo...\n ^ line 1 offset 8"],
['FOO=\'foo', "Missing quote to end the value in \".env\" at line 1.\n...FOO='foo...\n ^ line 1 offset 8"],
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Form/ResolvedFormType.php
Expand Up @@ -205,7 +205,7 @@ public function getOptionsResolver()
* Override this method if you want to customize the builder class.
*
* @param string $name The name of the builder
* @param string $dataClass The data class
* @param string|null $dataClass The data class
* @param FormFactoryInterface $factory The current form factory
* @param array $options The builder options
*
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Form/Test/TypeTestCase.php
Expand Up @@ -32,7 +32,7 @@ protected function setUp()
parent::setUp();

$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory);
$this->builder = new FormBuilder('', null, $this->dispatcher, $this->factory);
}

protected function tearDown()
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Form/Tests/AbstractFormTest.php
Expand Up @@ -55,7 +55,7 @@ abstract protected function createForm();
/**
* @param string $name
* @param EventDispatcherInterface $dispatcher
* @param string $dataClass
* @param string|null $dataClass
* @param array $options
*
* @return FormBuilder
Expand Down

0 comments on commit 61bf16c

Please sign in to comment.