Merge branch '5.0' into 5.1

* 5.0:
  Parse and render anonymous classes correctly on php 8
  Enable APCu for the php 8 build.
  [Process] Fix failing test on php 8.
  [HttpKernel] fix test
  Make PHP 8 green on Travis
  Revert "[Cache] allow DBAL v3"
  [PropertyAccessor] Added missing property path on php 8.
  Don't execute tests with DBAL 2.x on php 8.
This commit is contained in:
Nicolas Grekas 2020-05-24 10:49:09 +02:00
commit 2ed4e0efce
27 changed files with 156 additions and 41 deletions

View File

@ -122,6 +122,23 @@ before_install:
}
export -f tpecl
install_apcu_dev () {
local ref=$1
local INI=$2
wget https://github.com/krakjoe/apcu/archive/${ref}.zip
unzip ${ref}.zip
cd apcu-${ref}
phpize
./configure
make
mv modules/apcu.so $(php -r "echo ini_get('extension_dir');")
echo 'extension = apcu.so' >> $INI
cd ..
rm -rf apcu-${ref} ${ref}.zip
}
export -f install_apcu_dev
- |
# Install sigchild-enabled PHP to test the Process component on the lowest PHP matrix line
if [[ ! $deps && $TRAVIS_PHP_VERSION = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then
@ -155,6 +172,7 @@ before_install:
fi
if [[ $PHP = nightly ]]; then
tfold ext.memcached tpecl memcached-3.1.5 memcached.so $INI
tfold ext.apcu install_apcu_dev 9c36db45100d4d27ec33072f4be90f1f5a0108b7 $INI
else
tfold ext.apcu tpecl apcu-5.1.18 apcu.so $INI
tfold ext.mongodb tpecl mongodb-1.6.16 mongodb.so $INI
@ -236,6 +254,7 @@ install:
# Set composer's platform to php 7.4 if we're on php 8.
if [[ $PHP = nightly ]]; then
composer config platform.php 7.4.99
export SYMFONY_DEPRECATIONS_HELPER=weak
fi
- |

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Cache\Tests\Adapter;
use Doctrine\DBAL\Version;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\Adapter\PdoAdapter;
use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait;
@ -30,6 +31,10 @@ class PdoAdapterTest extends AdapterTestCase
self::markTestSkipped('Extension pdo_sqlite required.');
}
if (\PHP_VERSION_ID >= 80000 && class_exists(Version::class)) {
self::markTestSkipped('Doctrine DBAL 2.x is incompatible with PHP 8.');
}
self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache');
$pool = new PdoAdapter('sqlite:'.self::$dbFile);

View File

@ -15,6 +15,7 @@ use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Version;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\Adapter\PdoAdapter;
use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait;
@ -34,6 +35,10 @@ class PdoDbalAdapterTest extends AdapterTestCase
self::markTestSkipped('Extension pdo_sqlite required.');
}
if (\PHP_VERSION_ID >= 80000 && class_exists(Version::class)) {
self::markTestSkipped('Doctrine DBAL 2.x is incompatible with PHP 8.');
}
self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache');
}

View File

@ -883,7 +883,8 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->register('foo')->setCode(function () {
throw new class('') extends \InvalidArgumentException { };
throw new class('') extends \InvalidArgumentException {
};
});
$tester = new ApplicationTester($application);
@ -893,7 +894,8 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->register('foo')->setCode(function () {
throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', get_debug_type(new class() { })));
throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', \get_class(new class() {
})));
});
$tester = new ApplicationTester($application);
@ -906,7 +908,8 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->register('foo')->setCode(function () {
throw new class('') extends \InvalidArgumentException { };
throw new class('') extends \InvalidArgumentException {
};
});
$tester = new ApplicationTester($application);
@ -916,7 +919,8 @@ class ApplicationTest extends TestCase
$application = new Application();
$application->setAutoExit(false);
$application->register('foo')->setCode(function () {
throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', get_debug_type(new class() { })));
throw new \InvalidArgumentException(sprintf('Dummy type "%s" is invalid.', \get_class(new class() {
})));
});
$tester = new ApplicationTester($application);

View File

@ -26,6 +26,7 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\FooVariadic;
use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\MultipleArgumentsOptionalScalarNotReallyOptional;
use Symfony\Component\DependencyInjection\TypedReference;
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
@ -452,6 +453,9 @@ class AutowirePassTest extends TestCase
}
}
/**
* @requires PHP < 8
*/
public function testOptionalScalarNotReallyOptionalUsesDefaultValue()
{
$container = new ContainerBuilder();

View File

@ -0,0 +1,14 @@
<?php
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\includes;
use Symfony\Component\DependencyInjection\Tests\Compiler\A;
use Symfony\Component\DependencyInjection\Tests\Compiler\Lille;
class MultipleArgumentsOptionalScalarNotReallyOptional
{
public function __construct(A $a, $foo = 'default_val', Lille $lille)
{
}
}

View File

@ -186,12 +186,6 @@ class MultipleArgumentsOptionalScalarLast
{
}
}
class MultipleArgumentsOptionalScalarNotReallyOptional
{
public function __construct(A $a, $foo = 'default_val', Lille $lille)
{
}
}
/*
* Classes used for testing createResourceForClass

View File

@ -75,7 +75,7 @@ class FlattenException
$e->setStatusCode($statusCode);
$e->setHeaders($headers);
$e->setTraceFromThrowable($exception);
$e->setClass(\get_class($exception));
$e->setClass(get_debug_type($exception));
$e->setFile($exception->getFile());
$e->setLine($exception->getLine());

View File

@ -365,6 +365,26 @@ class ErrorHandlerTest extends TestCase
}
}
public function testHandleErrorWithAnonymousClass()
{
$handler = ErrorHandler::register();
$handler->throwAt(3, true);
try {
$handler->handleError(3, 'foo '.\get_class(new class() extends \stdClass {
}).' bar', 'foo.php', 12);
$this->fail('Exception expected.');
} catch (\ErrorException $e) {
} finally {
restore_error_handler();
restore_exception_handler();
}
$this->assertSame('foo stdClass@anonymous bar', $e->getMessage());
$this->assertSame(3, $e->getSeverity());
$this->assertSame('foo.php', $e->getFile());
$this->assertSame(12, $e->getLine());
}
public function testHandleDeprecation()
{
$logArgCheck = function ($level, $message, $context) {
@ -433,6 +453,10 @@ class ErrorHandlerTest extends TestCase
{
return [
['Uncaught Exception: foo', new \Exception('foo')],
['Uncaught Exception: foo', new class('foo') extends \RuntimeException {
}],
['Uncaught Exception: foo stdClass@anonymous bar', new \RuntimeException('foo '.\get_class(new class() extends \stdClass {
}).' bar')],
['Uncaught Error: bar', new \Error('bar')],
['Uncaught ccc', new \ErrorException('ccc')],
];

View File

@ -359,6 +359,11 @@ class FlattenExceptionTest extends TestCase
$this->assertSame('RuntimeException@anonymous', $flattened->getClass());
$flattened->setClass(\get_class(new class('Oops') extends NotFoundHttpException {
}));
$this->assertSame('Symfony\Component\HttpKernel\Exception\NotFoundHttpException@anonymous', $flattened->getClass());
$flattened = FlattenException::createFromThrowable(new \Exception(sprintf('Class "%s" blah.', \get_class(new class() extends \RuntimeException {
}))));

View File

@ -223,9 +223,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
public function getBundle(string $name)
{
if (!isset($this->bundles[$name])) {
$class = get_debug_type($this);
throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the "registerBundles()" method of your "%s.php" file?', $name, $class));
throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the "registerBundles()" method of your "%s.php" file?', $name, get_debug_type($this)));
}
return $this->bundles[$name];
@ -400,6 +398,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
$class = static::class;
$class = false !== strpos($class, "@anonymous\0") ? get_parent_class($class).str_replace('.', '_', ContainerBuilder::hash($class)) : $class;
$class = str_replace('\\', '_', $class).ucfirst($this->environment).($this->debug ? 'Debug' : '').'Container';
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $class)) {
throw new \InvalidArgumentException(sprintf('The environment "%s" contains invalid characters, it can only contain characters allowed in PHP class names.', $this->environment));
}

View File

@ -204,19 +204,19 @@ class ArgumentResolverTest extends TestCase
$request = Request::create('/');
$request->attributes->set('foo', 'foo');
$request->attributes->set('bar', new \stdClass());
$request->attributes->set('mandatory', 'mandatory');
$request->attributes->set('last', 'last');
$controller = [new NullableController(), 'action'];
$this->assertEquals(['foo', new \stdClass(), 'value', 'mandatory'], self::$resolver->getArguments($request, $controller));
$this->assertEquals(['foo', new \stdClass(), 'value', 'last'], self::$resolver->getArguments($request, $controller));
}
public function testGetNullableArgumentsWithDefaults()
{
$request = Request::create('/');
$request->attributes->set('mandatory', 'mandatory');
$request->attributes->set('last', 'last');
$controller = [new NullableController(), 'action'];
$this->assertEquals([null, null, 'value', 'mandatory'], self::$resolver->getArguments($request, $controller));
$this->assertEquals([null, null, 'value', 'last'], self::$resolver->getArguments($request, $controller));
}
public function testGetSessionArguments()

View File

@ -80,7 +80,7 @@ class ArgumentMetadataFactoryTest extends TestCase
$this->assertEquals([
new ArgumentMetadata('foo', 'array', false, true, null, true),
new ArgumentMetadata('bar', null, false, false, null),
new ArgumentMetadata('bar', null, false, true, null, true),
], $arguments);
}
@ -113,7 +113,7 @@ class ArgumentMetadataFactoryTest extends TestCase
new ArgumentMetadata('foo', 'string', false, false, null, true),
new ArgumentMetadata('bar', \stdClass::class, false, false, null, true),
new ArgumentMetadata('baz', 'string', false, true, 'value', true),
new ArgumentMetadata('mandatory', null, false, false, null, true),
new ArgumentMetadata('last', 'string', false, true, '', false),
], $arguments);
}
@ -133,7 +133,7 @@ class ArgumentMetadataFactoryTest extends TestCase
{
}
private function signature5(array $foo = null, $bar)
private function signature5(array $foo = null, $bar = null)
{
}
}

View File

@ -13,7 +13,7 @@ namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller;
class NullableController
{
public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', $mandatory)
public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', string $last = '')
{
}
}

View File

@ -536,6 +536,27 @@ EOF;
$this->assertGreaterThan($preReBoot, $kernel->getStartTime());
}
public function testAnonymousKernelGeneratesValidContainerClass(): void
{
$kernel = new class('test', true) extends Kernel {
public function registerBundles(): iterable
{
return [];
}
public function registerContainerConfiguration(LoaderInterface $loader): void
{
}
public function getContainerClass(): string
{
return parent::getContainerClass();
}
};
$this->assertRegExp('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*TestDebugContainer$/', $kernel->getContainerClass());
}
/**
* Returns a mock for the BundleInterface.
*/

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Lock\Tests\Store;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Version;
use Symfony\Component\Lock\PersistingStoreInterface;
use Symfony\Component\Lock\Store\PdoStore;
@ -32,6 +33,10 @@ class PdoDbalStoreTest extends AbstractStoreTest
{
self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_lock');
if (\PHP_VERSION_ID >= 80000 && class_exists(Version::class)) {
self::markTestSkipped('Doctrine DBAL 2.x is incompatible with PHP 8.');
}
$store = new PdoStore(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]));
$store->createTable();
}

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Lock\Tests\Store;
use Doctrine\DBAL\Version;
use Symfony\Component\Lock\Key;
use Symfony\Component\Lock\PersistingStoreInterface;
use Symfony\Component\Lock\Store\PdoStore;
@ -30,6 +31,10 @@ class PdoStoreTest extends AbstractStoreTest
{
self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_lock');
if (\PHP_VERSION_ID >= 80000 && class_exists(Version::class)) {
self::markTestSkipped('Doctrine DBAL 2.x is incompatible with PHP 8.');
}
$store = new PdoStore('sqlite:'.self::$dbFile);
$store->createTable();
}

View File

@ -21,7 +21,7 @@
"symfony/polyfill-php80": "^1.15"
},
"require-dev": {
"doctrine/dbal": "~2.5",
"doctrine/dbal": "^2.5|^3.0",
"mongodb/mongodb": "~1.1",
"predis/predis": "~1.0"
},

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Messenger\Bridge\Doctrine\Tests\Transport;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Version;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Bridge\Doctrine\Tests\Fixtures\DummyMessage;
use Symfony\Component\Messenger\Bridge\Doctrine\Transport\Connection;
@ -28,6 +29,13 @@ class DoctrineIntegrationTest extends TestCase
/** @var string */
private $sqliteFile;
public static function setUpBeforeClass(): void
{
if (\PHP_VERSION_ID >= 80000 && class_exists(Version::class)) {
self::markTestSkipped('Doctrine DBAL 2.x is incompatible with PHP 8.');
}
}
protected function setUp(): void
{
$this->sqliteFile = sys_get_temp_dir().'/symfony.messenger.sqlite';

View File

@ -21,7 +21,7 @@
"symfony/service-contracts": "^1.1|^2"
},
"require-dev": {
"doctrine/dbal": "^2.6",
"doctrine/dbal": "^2.6|^3.0",
"doctrine/orm": "^2.6.3",
"doctrine/persistence": "^1.3",
"symfony/property-access": "^4.4|^5.0",

View File

@ -30,14 +30,16 @@ class TraceableMiddlewareTest extends MiddlewareTestCase
$busId = 'command_bus';
$envelope = new Envelope(new DummyMessage('Hello'));
$middleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$middleware->expects($this->once())
->method('handle')
->with($envelope, $this->anything())
->willReturnCallback(function ($envelope, StackInterface $stack) {
$middleware = new class() implements MiddlewareInterface {
public $calls = 0;
public function handle(Envelope $envelope, StackInterface $stack): Envelope
{
++$this->calls;
return $stack->next()->handle($envelope, $stack);
})
;
}
};
$stopwatch = $this->createMock(Stopwatch::class);
$stopwatch->expects($this->once())->method('isStarted')->willReturn(true);
@ -51,7 +53,7 @@ class TraceableMiddlewareTest extends MiddlewareTestCase
$stopwatch->expects($this->exactly(2))
->method('stop')
->withConsecutive(
[$this->matches('"%sMiddlewareInterface%s" on "command_bus"')],
['"Symfony\Component\Messenger\Middleware\MiddlewareInterface@anonymous" on "command_bus"'],
['Tail on "command_bus"']
)
;
@ -59,6 +61,7 @@ class TraceableMiddlewareTest extends MiddlewareTestCase
$traced = new TraceableMiddleware($stopwatch, $busId);
$traced->handle($envelope, new StackMiddleware(new \ArrayIterator([null, $middleware])));
$this->assertSame(1, $middleware->calls);
}
public function testHandleWithException()

View File

@ -17,6 +17,7 @@
],
"require": {
"php": ">=7.2.5",
"psr/log": "^1.0",
"symfony/polyfill-php80": "^1.15"
},
"conflict": {

View File

@ -988,21 +988,20 @@ class ProcessTest extends TestCase
public function testWrongSignal()
{
$this->expectException('Symfony\Component\Process\Exception\RuntimeException');
if ('\\' === \DIRECTORY_SEPARATOR) {
$this->markTestSkipped('POSIX signals do not work on Windows');
}
$this->expectException(RuntimeException::class);
$process = $this->getProcessForCode('sleep(38);');
$process->start();
try {
$process->signal(-4);
$this->fail('A RuntimeException must have been thrown');
} catch (RuntimeException $e) {
} finally {
$process->stop(0);
}
throw $e;
}
public function testDisableOutputDisablesTheOutput()

View File

@ -211,7 +211,7 @@ class PropertyAccessor implements PropertyAccessorInterface
if (preg_match('/^\S+::\S+\(\): Argument #\d+ \(\$\S+\) must be of type (\S+), (\S+) given/', $message, $matches)) {
list(, $expectedType, $actualType) = $matches;
throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given.', $expectedType, 'NULL' === $actualType ? 'null' : $actualType), 0, $previous);
throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous);
}
}

View File

@ -237,7 +237,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
*
* @return string[]
*/
protected function getAttributes($object, string $format = null, array $context)
protected function getAttributes($object, ?string $format, array $context)
{
$class = $this->objectClassResolver ? ($this->objectClassResolver)($object) : \get_class($object);
$key = $class.'-'.$context['cache_key'];

View File

@ -603,7 +603,7 @@ class GetConstructorArgsWithDefaultValueDummy
protected $foo;
protected $bar;
public function __construct($foo = [], $bar)
public function __construct($foo = [], $bar = null)
{
$this->foo = $foo;
$this->bar = $bar;

View File

@ -784,7 +784,7 @@ class ObjectConstructorArgsWithDefaultValueDummy
protected $foo;
protected $bar;
public function __construct($foo = [], $bar)
public function __construct($foo = [], $bar = null)
{
$this->foo = $foo;
$this->bar = $bar;
@ -934,7 +934,7 @@ class DummyWithConstructorObjectAndDefaultValue
private $foo;
private $inner;
public function __construct($foo = 'a', ObjectInner $inner)
public function __construct($foo = 'a', ObjectInner $inner = null)
{
$this->foo = $foo;
$this->inner = $inner;