From 132bba6d2495a413ebafb444875e9638d801bafb Mon Sep 17 00:00:00 2001 From: David Maicher Date: Wed, 7 Feb 2018 20:03:36 +0100 Subject: [PATCH 01/16] [Cache][WebProfiler] fix collecting cache stats with sub-requests + allow clearing calls --- .../Component/Cache/Adapter/TraceableAdapter.php | 11 ++++++----- .../Cache/DataCollector/CacheDataCollector.php | 3 +-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php index e8563521ba..98d0e52693 100644 --- a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php @@ -204,11 +204,12 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab public function getCalls() { - try { - return $this->calls; - } finally { - $this->calls = array(); - } + return $this->calls; + } + + public function clearCalls() + { + $this->calls = array(); } protected function start($name) diff --git a/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php b/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php index 62d502f01f..ceef45aa0b 100644 --- a/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php +++ b/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php @@ -57,8 +57,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter { $this->data = array(); foreach ($this->instances as $instance) { - // Calling getCalls() will clear the calls. - $instance->getCalls(); + $instance->clearCalls(); } } From dab422287fa0f2b89a95c2d705969081fe6c76b3 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 7 Feb 2018 21:12:42 +0100 Subject: [PATCH 02/16] do not mock the container builder in tests --- .../Compiler/AddCacheWarmerPassTest.php | 74 ++++-------- .../AddConstraintValidatorsPassTest.php | 76 ++++-------- .../LegacyFragmentRendererPassTest.php | 63 ++-------- .../Compiler/LoggingTranslatorPassTest.php | 73 ++++-------- .../Compiler/ProfilerPassTest.php | 63 +++------- .../Compiler/SerializerPassTest.php | 85 +++++--------- .../Compiler/TranslatorPassTest.php | 35 +++--- .../ConstraintValidatorFactoryTest.php | 38 +++--- .../Compiler/TwigLoaderPassTest.php | 100 ++++------------ .../Compiler/ExtensionCompilerPassTest.php | 60 +++++++--- .../Tests/Extension/ExtensionTest.php | 60 +++------- .../RegisterListenersPassTest.php | 61 ++-------- .../FragmentRendererPassTest.php | 110 ++++-------------- .../MergeExtensionConfigurationPassTest.php | 57 +++++---- 14 files changed, 295 insertions(+), 660 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php index 330deae646..e58ed97724 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass; @@ -19,73 +20,44 @@ class AddCacheWarmerPassTest extends TestCase { public function testThatCacheWarmersAreProcessedInPriorityOrder() { - $services = array( - 'my_cache_warmer_service1' => array(0 => array('priority' => 100)), - 'my_cache_warmer_service2' => array(0 => array('priority' => 200)), - 'my_cache_warmer_service3' => array(), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds', 'getDefinition', 'hasDefinition'))->getMock(); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - $container->expects($this->atLeastOnce()) - ->method('getDefinition') - ->with('cache_warmer') - ->will($this->returnValue($definition)); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_warmer') - ->will($this->returnValue(true)); - - $definition->expects($this->once()) - ->method('replaceArgument') - ->with(0, array( - new Reference('my_cache_warmer_service2'), - new Reference('my_cache_warmer_service1'), - new Reference('my_cache_warmer_service3'), - )); + $container = new ContainerBuilder(); + $cacheWarmerDefinition = $container->register('cache_warmer')->addArgument(array()); + $container->register('my_cache_warmer_service1')->addTag('kernel.cache_warmer', array('priority' => 100)); + $container->register('my_cache_warmer_service2')->addTag('kernel.cache_warmer', array('priority' => 200)); + $container->register('my_cache_warmer_service3')->addTag('kernel.cache_warmer'); $addCacheWarmerPass = new AddCacheWarmerPass(); $addCacheWarmerPass->process($container); + + $this->assertEquals( + array( + new Reference('my_cache_warmer_service2'), + new Reference('my_cache_warmer_service1'), + new Reference('my_cache_warmer_service3'), + ), + $cacheWarmerDefinition->getArgument(0) + ); } public function testThatCompilerPassIsIgnoredIfThereIsNoCacheWarmerDefinition() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->never())->method('findTaggedServiceIds'); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_warmer') - ->will($this->returnValue(false)); - $definition->expects($this->never())->method('replaceArgument'); + $container = new ContainerBuilder(); $addCacheWarmerPass = new AddCacheWarmerPass(); $addCacheWarmerPass->process($container); + + // we just check that the pass does not break if no cache warmer is registered + $this->addToAssertionCount(1); } public function testThatCacheWarmersMightBeNotDefined() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue(array())); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_warmer') - ->will($this->returnValue(true)); - - $definition->expects($this->never())->method('replaceArgument'); + $container = new ContainerBuilder(); + $cacheWarmerDefinition = $container->register('cache_warmer')->addArgument(array()); $addCacheWarmerPass = new AddCacheWarmerPass(); $addCacheWarmerPass->process($container); + + $this->assertSame(array(), $cacheWarmerDefinition->getArgument(0)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php index e58068900f..0be1f77d51 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php @@ -13,72 +13,40 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; class AddConstraintValidatorsPassTest extends TestCase { public function testThatConstraintValidatorServicesAreProcessed() { - $services = array( - 'my_constraint_validator_service1' => array(0 => array('alias' => 'my_constraint_validator_alias1')), - 'my_constraint_validator_service2' => array(), - ); - - $validatorFactoryDefinition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds', 'getDefinition', 'hasDefinition'))->getMock(); - - $validatorDefinition1 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock(); - $validatorDefinition2 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock(); - - $validatorDefinition1->expects($this->atLeastOnce()) - ->method('getClass') - ->willReturn('My\Fully\Qualified\Class\Named\Validator1'); - $validatorDefinition2->expects($this->atLeastOnce()) - ->method('getClass') - ->willReturn('My\Fully\Qualified\Class\Named\Validator2'); - - $container->expects($this->any()) - ->method('getDefinition') - ->with($this->anything()) - ->will($this->returnValueMap(array( - array('my_constraint_validator_service1', $validatorDefinition1), - array('my_constraint_validator_service2', $validatorDefinition2), - array('validator.validator_factory', $validatorFactoryDefinition), - ))); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('validator.validator_factory') - ->will($this->returnValue(true)); - - $validatorFactoryDefinition->expects($this->once()) - ->method('replaceArgument') - ->with(1, array( - 'My\Fully\Qualified\Class\Named\Validator1' => 'my_constraint_validator_service1', - 'my_constraint_validator_alias1' => 'my_constraint_validator_service1', - 'My\Fully\Qualified\Class\Named\Validator2' => 'my_constraint_validator_service2', - )); + $container = new ContainerBuilder(); + $constraintValidatorFactoryDefinition = $container->register('validator.validator_factory') + ->setArguments(array(new Reference('service_container'), array())); + $container->register('my_constraint_validator_service1', 'My\Fully\Qualified\Class\Named\Validator1') + ->addTag('validator.constraint_validator', array('alias' => 'my_constraint_validator_alias1')); + $container->register('my_constraint_validator_service2', 'My\Fully\Qualified\Class\Named\Validator2') + ->addTag('validator.constraint_validator'); $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); $addConstraintValidatorsPass->process($container); + + $this->assertEquals( + array( + 'My\Fully\Qualified\Class\Named\Validator1' => 'my_constraint_validator_service1', + 'my_constraint_validator_alias1' => 'my_constraint_validator_service1', + 'My\Fully\Qualified\Class\Named\Validator2' => 'my_constraint_validator_service2', + ), + $constraintValidatorFactoryDefinition->getArgument(1) + ); } public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->never())->method('findTaggedServiceIds'); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('validator.validator_factory') - ->will($this->returnValue(false)); - $definition->expects($this->never())->method('replaceArgument'); - $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); - $addConstraintValidatorsPass->process($container); + $addConstraintValidatorsPass->process(new ContainerBuilder()); + + // we just check that the pass does not fail if no constraint validator factory is registered + $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LegacyFragmentRendererPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LegacyFragmentRendererPassTest.php index d4f75ee95c..b275047939 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LegacyFragmentRendererPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LegacyFragmentRendererPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FragmentRendererPass; @@ -29,29 +30,10 @@ class LegacyFragmentRendererPassTest extends TestCase */ public function testContentRendererWithoutInterface() { - // one service, not implementing any interface - $services = array( - 'my_content_renderer' => array(), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('stdClass')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $builder = new ContainerBuilder(); + $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'stdClass') + ->addTag('kernel.fragment_renderer'); $pass = new FragmentRendererPass(); $pass->process($builder); @@ -59,38 +41,15 @@ class LegacyFragmentRendererPassTest extends TestCase public function testValidContentRenderer() { - $services = array( - 'my_content_renderer' => array(), - ); - - $renderer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $renderer - ->expects($this->once()) - ->method('addMethodCall') - ->with('addRenderer', array(new Reference('my_content_renderer'))) - ; - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\RendererService')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->onConsecutiveCalls($renderer, $definition)); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\RendererService') + ->addTag('kernel.fragment_renderer'); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals(array(array('addRenderer', array(new Reference('my_content_renderer')))), $fragmentHandlerDefinition->getMethodCalls()); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php index db6557913b..00da2724d1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php @@ -13,75 +13,52 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; class LoggingTranslatorPassTest extends TestCase { public function testProcess() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock(); - $parameterBag = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface')->getMock(); - - $container->expects($this->exactly(2)) - ->method('hasAlias') - ->will($this->returnValue(true)); - - $container->expects($this->once()) - ->method('getParameter') - ->will($this->returnValue(true)); - - $container->expects($this->once()) - ->method('getAlias') - ->will($this->returnValue('translation.default')); - - $container->expects($this->exactly(3)) - ->method('getDefinition') - ->will($this->returnValue($definition)); - - $container->expects($this->once()) - ->method('hasParameter') - ->with('translator.logging') - ->will($this->returnValue(true)); - - $definition->expects($this->once()) - ->method('getClass') - ->will($this->returnValue('%translator.class%')); - - $parameterBag->expects($this->once()) - ->method('resolveValue') - ->will($this->returnValue("Symfony\Bundle\FrameworkBundle\Translation\Translator")); - - $container->expects($this->once()) - ->method('getParameterBag') - ->will($this->returnValue($parameterBag)); + $container = new ContainerBuilder(); + $container->setParameter('translator.logging', true); + $container->setParameter('translator.class', 'Symfony\Component\Translation\Translator'); + $container->register('monolog.logger'); + $container->setAlias('logger', 'monolog.logger'); + $container->register('translator.default', '%translator.class%'); + $container->register('translator.logging', '%translator.class%'); + $container->setAlias('translator', 'translator.default'); + $translationWarmerDefinition = $container->register('translation.warmer')->addArgument(new Reference('translator')); $pass = new LoggingTranslatorPass(); $pass->process($container); + + $this->assertEquals(new Reference('translator.logging.inner'), $translationWarmerDefinition->getArgument(0)); } public function testThatCompilerPassIsIgnoredIfThereIsNotLoggerDefinition() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock(); - $container->expects($this->once()) - ->method('hasAlias') - ->will($this->returnValue(false)); + $container = new ContainerBuilder(); + $container->register('identity_translator'); + $container->setAlias('translator', 'identity_translator'); $pass = new LoggingTranslatorPass(); $pass->process($container); + + // we just check that the compiler pass does not break if a logger is not registered + $this->addToAssertionCount(1); } public function testThatCompilerPassIsIgnoredIfThereIsNotTranslatorDefinition() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock(); - $container->expects($this->at(0)) - ->method('hasAlias') - ->will($this->returnValue(true)); - - $container->expects($this->at(0)) - ->method('hasAlias') - ->will($this->returnValue(false)); + $container = new ContainerBuilder(); + $container->register('monolog.logger'); + $container->setAlias('logger', 'monolog.logger'); $pass = new LoggingTranslatorPass(); $pass->process($container); + + // we just check that the compiler pass does not break if a translator is not registered + $this->addToAssertionCount(1); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php index e064ce9f17..9fcae720b2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php @@ -12,18 +12,11 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; class ProfilerPassTest extends TestCase { - private $profilerDefinition; - - protected function setUp() - { - $this->profilerDefinition = new Definition('ProfilerClass'); - } - /** * Tests that collectors that specify a template but no "id" will throw * an exception (both are needed if the template is specified). @@ -31,17 +24,15 @@ class ProfilerPassTest extends TestCase * Thus, a fully-valid tag looks something like this: * * + * + * @expectedException \InvalidArgumentException */ public function testTemplateNoIdThrowsException() { - // one service, with a template key, but no id - $services = array( - 'my_collector_service' => array(0 => array('template' => 'foo')), - ); - - $builder = $this->createContainerMock($services); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); + $builder = new ContainerBuilder(); + $builder->register('profiler', 'ProfilerClass'); + $builder->register('my_collector_service') + ->addTag('data_collector', array('template' => 'foo')); $profilerPass = new ProfilerPass(); $profilerPass->process($builder); @@ -49,45 +40,19 @@ class ProfilerPassTest extends TestCase public function testValidCollector() { - // one service, with a template key, but no id - $services = array( - 'my_collector_service' => array(0 => array('template' => 'foo', 'id' => 'my_collector')), - ); - - $container = $this->createContainerMock($services); - - // fake the getDefinition() to return a Profiler definition - $container->expects($this->atLeastOnce()) - ->method('getDefinition'); - - // assert that the data_collector.templates parameter should be set - $container->expects($this->once()) - ->method('setParameter') - ->with('data_collector.templates', array('my_collector_service' => array('my_collector', 'foo'))); + $container = new ContainerBuilder(); + $profilerDefinition = $container->register('profiler', 'ProfilerClass'); + $container->register('my_collector_service') + ->addTag('data_collector', array('template' => 'foo', 'id' => 'my_collector')); $profilerPass = new ProfilerPass(); $profilerPass->process($container); + $this->assertSame(array('my_collector_service' => array('my_collector', 'foo')), $container->getParameter('data_collector.templates')); + // grab the method calls off of the "profiler" definition - $methodCalls = $this->profilerDefinition->getMethodCalls(); + $methodCalls = $profilerDefinition->getMethodCalls(); $this->assertCount(1, $methodCalls); $this->assertEquals('add', $methodCalls[0][0]); // grab the method part of the first call } - - private function createContainerMock($services) - { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'setParameter'))->getMock(); - $container->expects($this->any()) - ->method('hasDefinition') - ->with($this->equalTo('profiler')) - ->will($this->returnValue(true)); - $container->expects($this->any()) - ->method('getDefinition') - ->will($this->returnValue($this->profilerDefinition)); - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - return $container; - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php index 6fa27be17a..12e9e1c34b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass; @@ -22,48 +23,30 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass; */ class SerializerPassTest extends TestCase { + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage You must tag at least one service as "serializer.normalizer" to use the Serializer service + */ public function testThrowExceptionWhenNoNormalizers() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds'))->getMock(); - - $container->expects($this->once()) - ->method('hasDefinition') - ->with('serializer') - ->will($this->returnValue(true)); - - $container->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('serializer.normalizer') - ->will($this->returnValue(array())); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('RuntimeException'); + $container = new ContainerBuilder(); + $container->register('serializer'); $serializerPass = new SerializerPass(); $serializerPass->process($container); } + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage You must tag at least one service as "serializer.encoder" to use the Serializer service + */ public function testThrowExceptionWhenNoEncoders() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->once()) - ->method('hasDefinition') - ->with('serializer') - ->will($this->returnValue(true)); - - $container->expects($this->any()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls( - array('n' => array('serializer.normalizer')), - array() - )); - - $container->expects($this->once()) - ->method('getDefinition') - ->will($this->returnValue($definition)); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('RuntimeException'); + $container = new ContainerBuilder(); + $container->register('serializer') + ->addArgument(array()) + ->addArgument(array()); + $container->register('normalizer')->addTag('serializer.normalizer'); $serializerPass = new SerializerPass(); $serializerPass->process($container); @@ -71,34 +54,18 @@ class SerializerPassTest extends TestCase public function testServicesAreOrderedAccordingToPriority() { - $services = array( - 'n3' => array(array()), - 'n1' => array(array('priority' => 200)), - 'n2' => array(array('priority' => 100)), - ); - - $expected = array( - new Reference('n1'), - new Reference('n2'), - new Reference('n3'), - ); - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds'))->getMock(); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); + $container = new ContainerBuilder(); + $serializerDefinition = $container->register('serializer') + ->addArgument(array()) + ->addArgument(array()); + $container->register('normalizer3')->addTag('serializer.normalizer'); + $container->register('normalizer1')->addTag('serializer.normalizer', array('priority' => 200)); + $container->register('normalizer2')->addTag('serializer.normalizer', array('priority' => 100)); + $container->register('encoder')->addTag('serializer.encoder'); $serializerPass = new SerializerPass(); + $serializerPass->process($container); - $method = new \ReflectionMethod( - 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass', - 'findAndSortTaggedServices' - ); - $method->setAccessible(true); - - $actual = $method->invoke($serializerPass, 'tag', $container); - - $this->assertEquals($expected, $actual); + $this->assertEquals(array(new Reference('normalizer1'), new Reference('normalizer2'), new Reference('normalizer3')), $serializerDefinition->getArgument(0)); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php index 10a38aabdb..e176c7534a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass; @@ -19,28 +20,22 @@ class TranslatorPassTest extends TestCase { public function testValidCollector() { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->at(0)) - ->method('addMethodCall') - ->with('addLoader', array('xliff', new Reference('xliff'))); - $definition->expects($this->at(1)) - ->method('addMethodCall') - ->with('addLoader', array('xlf', new Reference('xliff'))); + $container = new ContainerBuilder(); + $container->register('translator.default') + ->setArguments(array(null, null, array())); + $translationLoaderDefinition = $container->register('translation.loader'); + $container->register('xliff') + ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf')); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'findDefinition'))->getMock(); - $container->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - $container->expects($this->once()) - ->method('getDefinition') - ->will($this->returnValue($definition)); - $container->expects($this->once()) - ->method('findTaggedServiceIds') - ->will($this->returnValue(array('xliff' => array(array('alias' => 'xliff', 'legacy-alias' => 'xlf'))))); - $container->expects($this->once()) - ->method('findDefinition') - ->will($this->returnValue($this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock())); $pass = new TranslatorPass(); $pass->process($container); + + $this->assertEquals( + array( + array('addLoader', array('xliff', new Reference('xliff'))), + array('addLoader', array('xlf', new Reference('xliff'))), + ), + $translationLoaderDefinition->getMethodCalls() + ); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php index 6cf9574ece..995048455f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Validator/ConstraintValidatorFactoryTest.php @@ -14,7 +14,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Validator; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Blank as BlankConstraint; +use Symfony\Component\Validator\ConstraintValidator; class ConstraintValidatorFactoryTest extends TestCase { @@ -42,26 +44,13 @@ class ConstraintValidatorFactoryTest extends TestCase public function testGetInstanceReturnsService() { - $service = 'validator_constraint_service'; - $alias = 'validator_constraint_alias'; - $validator = $this->getMockForAbstractClass('Symfony\\Component\\Validator\\ConstraintValidator'); + $validator = new DummyConstraintValidator(); - // mock ContainerBuilder b/c it implements TaggedContainerInterface - $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder')->setMethods(array('get'))->getMock(); - $container - ->expects($this->once()) - ->method('get') - ->with($service) - ->will($this->returnValue($validator)); - - $constraint = $this->getMockBuilder('Symfony\\Component\\Validator\\Constraint')->getMock(); - $constraint - ->expects($this->once()) - ->method('validatedBy') - ->will($this->returnValue($alias)); + $container = new Container(); + $container->set('validator_constraint_service', $validator); $factory = new ConstraintValidatorFactory($container, array('validator_constraint_alias' => 'validator_constraint_service')); - $this->assertSame($validator, $factory->getInstance($constraint)); + $this->assertSame($validator, $factory->getInstance(new ConstraintStub())); } /** @@ -79,3 +68,18 @@ class ConstraintValidatorFactoryTest extends TestCase $factory->getInstance($constraint); } } + +class ConstraintStub extends Constraint +{ + public function validatedBy() + { + return 'validator_constraint_alias'; + } +} + +class DummyConstraintValidator extends ConstraintValidator +{ + public function validate($value, Constraint $constraint) + { + } +} diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php index 10bcf3e8f6..b7870ac56c 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php @@ -12,13 +12,14 @@ namespace Symfony\Bundle\TwigBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\TwigLoaderPass; class TwigLoaderPassTest extends TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var ContainerBuilder */ private $builder; /** @@ -32,62 +33,33 @@ class TwigLoaderPassTest extends TestCase protected function setUp() { - $this->builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'setAlias', 'getDefinition'))->getMock(); + $this->builder = new ContainerBuilder(); + $this->builder->register('twig'); $this->chainLoader = new Definition('loader'); $this->pass = new TwigLoaderPass(); } - public function testMapperPassWithOneTaggedLoaders() + public function testMapperPassWithOneTaggedLoader() { - $serviceIds = array( - 'test_loader_1' => array( - array(), - ), - ); - - $this->builder->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $this->builder->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.loader') - ->will($this->returnValue($serviceIds)); - $this->builder->expects($this->once()) - ->method('setAlias') - ->with('twig.loader', 'test_loader_1'); + $this->builder->register('test_loader_1') + ->addTag('twig.loader'); $this->pass->process($this->builder); + + $this->assertSame('test_loader_1', (string) $this->builder->getAlias('twig.loader')); } public function testMapperPassWithTwoTaggedLoaders() { - $serviceIds = array( - 'test_loader_1' => array( - array(), - ), - 'test_loader_2' => array( - array(), - ), - ); - - $this->builder->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $this->builder->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.loader') - ->will($this->returnValue($serviceIds)); - $this->builder->expects($this->once()) - ->method('getDefinition') - ->with('twig.loader.chain') - ->will($this->returnValue($this->chainLoader)); - $this->builder->expects($this->once()) - ->method('setAlias') - ->with('twig.loader', 'twig.loader.chain'); + $this->builder->setDefinition('twig.loader.chain', $this->chainLoader); + $this->builder->register('test_loader_1') + ->addTag('twig.loader'); + $this->builder->register('test_loader_2') + ->addTag('twig.loader'); $this->pass->process($this->builder); + + $this->assertSame('twig.loader.chain', (string) $this->builder->getAlias('twig.loader')); $calls = $this->chainLoader->getMethodCalls(); $this->assertCount(2, $calls); $this->assertEquals('addLoader', $calls[0][0]); @@ -98,32 +70,15 @@ class TwigLoaderPassTest extends TestCase public function testMapperPassWithTwoTaggedLoadersWithPriority() { - $serviceIds = array( - 'test_loader_1' => array( - array('priority' => 100), - ), - 'test_loader_2' => array( - array('priority' => 200), - ), - ); - - $this->builder->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $this->builder->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.loader') - ->will($this->returnValue($serviceIds)); - $this->builder->expects($this->once()) - ->method('getDefinition') - ->with('twig.loader.chain') - ->will($this->returnValue($this->chainLoader)); - $this->builder->expects($this->once()) - ->method('setAlias') - ->with('twig.loader', 'twig.loader.chain'); + $this->builder->setDefinition('twig.loader.chain', $this->chainLoader); + $this->builder->register('test_loader_1') + ->addTag('twig.loader', array('priority' => 100)); + $this->builder->register('test_loader_2') + ->addTag('twig.loader', array('priority' => 200)); $this->pass->process($this->builder); + + $this->assertSame('twig.loader.chain', (string) $this->builder->getAlias('twig.loader')); $calls = $this->chainLoader->getMethodCalls(); $this->assertCount(2, $calls); $this->assertEquals('addLoader', $calls[0][0]); @@ -137,15 +92,6 @@ class TwigLoaderPassTest extends TestCase */ public function testMapperPassWithZeroTaggedLoaders() { - $this->builder->expects($this->once()) - ->method('hasDefinition') - ->with('twig') - ->will($this->returnValue(true)); - $this->builder->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('twig.loader') - ->will($this->returnValue(array())); - $this->pass->process($this->builder); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php index e083611458..f4c4353abe 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ExtensionCompilerPassTest.php @@ -12,7 +12,10 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ExtensionCompilerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; /** * @author Wouter J @@ -24,33 +27,52 @@ class ExtensionCompilerPassTest extends TestCase protected function setUp() { - $this->container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->getMock(); + $this->container = new ContainerBuilder(); $this->pass = new ExtensionCompilerPass(); } public function testProcess() { - $extension1 = $this->createExtensionMock(true); - $extension1->expects($this->once())->method('process'); - $extension2 = $this->createExtensionMock(false); - $extension3 = $this->createExtensionMock(false); - $extension4 = $this->createExtensionMock(true); - $extension4->expects($this->once())->method('process'); + $extension1 = new CompilerPassExtension('extension1'); + $extension2 = new DummyExtension('extension2'); + $extension3 = new DummyExtension('extension3'); + $extension4 = new CompilerPassExtension('extension4'); - $this->container->expects($this->any()) - ->method('getExtensions') - ->will($this->returnValue(array($extension1, $extension2, $extension3, $extension4))) - ; + $this->container->registerExtension($extension1); + $this->container->registerExtension($extension2); + $this->container->registerExtension($extension3); + $this->container->registerExtension($extension4); $this->pass->process($this->container); - } - private function createExtensionMock($hasInlineCompile) - { - return $this->getMockBuilder('Symfony\Component\DependencyInjection\\'.( - $hasInlineCompile - ? 'Compiler\CompilerPassInterface' - : 'Extension\ExtensionInterface' - ))->getMock(); + $this->assertCount(2, $this->container->getDefinitions()); } } + +class DummyExtension extends Extension +{ + private $alias; + + public function __construct($alias) + { + $this->alias = $alias; + } + + public function getAlias() + { + return $this->alias; + } + + public function load(array $configs, ContainerBuilder $container) + { + } + + public function process(ContainerBuilder $container) + { + $container->register($this->alias); + } +} + +class CompilerPassExtension extends DummyExtension implements CompilerPassInterface +{ +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php b/src/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php index 90852c359e..9f66bfd7c6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php @@ -12,6 +12,8 @@ namespace Symfony\Component\DependencyInjection\Tests\Extension; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; class ExtensionTest extends TestCase { @@ -20,36 +22,8 @@ class ExtensionTest extends TestCase */ public function testIsConfigEnabledReturnsTheResolvedValue($enabled) { - $pb = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\ParameterBag') - ->setMethods(array('resolveValue')) - ->getMock() - ; - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder') - ->setMethods(array('getParameterBag')) - ->getMock() - ; - - $pb->expects($this->once()) - ->method('resolveValue') - ->with($this->equalTo($enabled)) - ->will($this->returnValue($enabled)) - ; - - $container->expects($this->once()) - ->method('getParameterBag') - ->will($this->returnValue($pb)) - ; - - $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension') - ->setMethods(array()) - ->getMockForAbstractClass() - ; - - $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled'); - $r->setAccessible(true); - - $r->invoke($extension, $container, array('enabled' => $enabled)); + $extension = new EnableableExtension(); + $this->assertSame($enabled, $extension->isConfigEnabled(new ContainerBuilder(), array('enabled' => $enabled))); } public function getResolvedEnabledFixtures() @@ -66,18 +40,20 @@ class ExtensionTest extends TestCase */ public function testIsConfigEnabledOnNonEnableableConfig() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder') - ->getMock() - ; + $extension = new EnableableExtension(); - $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension') - ->setMethods(array()) - ->getMockForAbstractClass() - ; - - $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled'); - $r->setAccessible(true); - - $r->invoke($extension, $container, array()); + $extension->isConfigEnabled(new ContainerBuilder(), array()); + } +} + +class EnableableExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + } + + public function isConfigEnabled(ContainerBuilder $container, array $config) + { + return parent::isConfigEnabled($container, $config); } } diff --git a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php index 53d7282b37..7490d0d25f 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php @@ -25,32 +25,10 @@ class RegisterListenersPassTest extends TestCase */ public function testEventSubscriberWithoutInterface() { - // one service, not implementing any interface - $services = array( - 'my_event_subscriber' => array(0 => array()), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('isPublic') - ->will($this->returnValue(true)); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('stdClass')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.event_listener here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls(array(), $services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $builder = new ContainerBuilder(); + $builder->register('event_dispatcher'); + $builder->register('my_event_subscriber', 'stdClass') + ->addTag('kernel.event_subscriber'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($builder); @@ -62,34 +40,15 @@ class RegisterListenersPassTest extends TestCase 'my_event_subscriber' => array(0 => array()), ); - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('isPublic') - ->will($this->returnValue(true)); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition', 'findDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.event_listener here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls(array(), $services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); - - $builder->expects($this->atLeastOnce()) - ->method('findDefinition') - ->will($this->returnValue($definition)); + $builder = new ContainerBuilder(); + $eventDispatcherDefinition = $builder->register('event_dispatcher'); + $builder->register('my_event_subscriber', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService') + ->addTag('kernel.event_subscriber'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($builder); + + $this->assertEquals(array(array('addSubscriberService', array('my_event_subscriber', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService'))), $eventDispatcherDefinition->getMethodCalls()); } /** diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php index 2a27fcac21..8bac207d17 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/FragmentRendererPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass; @@ -24,118 +25,47 @@ class FragmentRendererPassTest extends TestCase */ public function testLegacyFragmentRedererWithoutAlias() { - // no alias - $services = array( - 'my_content_renderer' => array(array()), - ); - - $renderer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $renderer - ->expects($this->once()) - ->method('addMethodCall') - ->with('addRenderer', array(new Reference('my_content_renderer'))) - ; - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService')); - $definition - ->expects($this->once()) - ->method('isPublic') - ->will($this->returnValue(true)) - ; - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->onConsecutiveCalls($renderer, $definition)); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService') + ->addTag('kernel.fragment_renderer'); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals(array(array('addRenderer', array(new Reference('my_content_renderer')))), $fragmentHandlerDefinition->getMethodCalls()); } /** * Tests that content rendering not implementing FragmentRendererInterface - * trigger an exception. + * triggers an exception. * * @expectedException \InvalidArgumentException */ public function testContentRendererWithoutInterface() { - // one service, not implementing any interface - $services = array( - 'my_content_renderer' => array(array('alias' => 'foo')), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Component\DependencyInjection\Definition') + ->addTag('kernel.fragment_renderer', array('alias' => 'foo')); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals(array(array('addRendererService', array('foo', 'my_content_renderer'))), $fragmentHandlerDefinition->getMethodCalls()); } public function testValidContentRenderer() { - $services = array( - 'my_content_renderer' => array(array('alias' => 'foo')), - ); - - $renderer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $renderer - ->expects($this->once()) - ->method('addMethodCall') - ->with('addRendererService', array('foo', 'my_content_renderer')) - ; - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService')); - $definition - ->expects($this->once()) - ->method('isPublic') - ->will($this->returnValue(true)) - ; - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->onConsecutiveCalls($renderer, $definition)); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService') + ->addTag('kernel.fragment_renderer', array('alias' => 'foo')); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals(array(array('addRendererService', array('foo', 'my_content_renderer'))), $fragmentHandlerDefinition->getMethodCalls()); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php index 81fc8b455d..ae421d919b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php @@ -12,44 +12,39 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; class MergeExtensionConfigurationPassTest extends TestCase { public function testAutoloadMainExtension() { - $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder')->setMethods(array('getExtensionConfig', 'loadFromExtension', 'getParameterBag', 'getDefinitions', 'getAliases', 'getExtensions'))->getMock(); - $params = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag')->getMock(); + $container = new ContainerBuilder(); + $container->registerExtension(new LoadedExtension()); + $container->registerExtension(new NotLoadedExtension()); + $container->loadFromExtension('loaded', array()); - $container->expects($this->at(0)) - ->method('getExtensionConfig') - ->with('loaded') - ->will($this->returnValue(array(array()))); - $container->expects($this->at(1)) - ->method('getExtensionConfig') - ->with('notloaded') - ->will($this->returnValue(array())); - $container->expects($this->once()) - ->method('loadFromExtension') - ->with('notloaded', array()); - - $container->expects($this->any()) - ->method('getParameterBag') - ->will($this->returnValue($params)); - $params->expects($this->any()) - ->method('all') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getDefinitions') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getAliases') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getExtensions') - ->will($this->returnValue(array())); - - $configPass = new MergeExtensionConfigurationPass(array('loaded', 'notloaded')); + $configPass = new MergeExtensionConfigurationPass(array('loaded', 'not_loaded')); $configPass->process($container); + + $this->assertTrue($container->hasDefinition('loaded.foo')); + $this->assertTrue($container->hasDefinition('not_loaded.bar')); + } +} + +class LoadedExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $container->register('loaded.foo'); + } +} + +class NotLoadedExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $container->register('not_loaded.bar'); } } From aeffc5fdffcfac52333d8b0761a8b30dc2fe4746 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Fri, 9 Feb 2018 13:00:05 +0100 Subject: [PATCH 03/16] Bump default PHPUnit version from 6.3 to 6.5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR bumps the default PHPUnit version for php ≥ 7.2 from the outdated 6.3 to the currently maintained version 6.5. --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index fbcedeca8c..fd7c800fed 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -17,7 +17,7 @@ error_reporting(-1); if (PHP_VERSION_ID >= 70200) { // PHPUnit 6 is required for PHP 7.2+ - $PHPUNIT_VERSION = getenv('SYMFONY_PHPUNIT_VERSION') ?: '6.3'; + $PHPUNIT_VERSION = getenv('SYMFONY_PHPUNIT_VERSION') ?: '6.5'; } elseif (PHP_VERSION_ID >= 50600) { // PHPUnit 4 does not support PHP 7 $PHPUNIT_VERSION = getenv('SYMFONY_PHPUNIT_VERSION') ?: '5.7'; From ed42760b4115cef776dadb88cd5f9b4a0e08d5d0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 10 Feb 2018 11:55:44 +0100 Subject: [PATCH 04/16] [Routing] fix typo --- .../Component/Routing/Tests/Fixtures/dumper/url_matcher4.php | 2 +- .../Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php index 89f2b10e22..182fcd8f23 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php @@ -62,7 +62,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher not_get_and_head: // post_and_head - if ('/post_and_get' === $pathinfo) { + if ('/post_and_head' === $pathinfo) { if (!in_array($requestMethod, array('POST', 'HEAD'))) { $allow = array_merge($allow, array('POST', 'HEAD')); goto not_post_and_head; diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php index e4c18c47b1..f29a6d6a30 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php @@ -354,7 +354,7 @@ class PhpMatcherDumperTest extends TestCase array('GET', 'HEAD') )); $headMatchCasesCollection->add('post_and_head', new Route( - '/post_and_get', + '/post_and_head', array(), array(), array(), From b4259a6bf369e27ec22ad6b60bea27c355c70766 Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Sat, 10 Feb 2018 12:14:07 +0100 Subject: [PATCH 05/16] Use 0 for unlimited expiry --- .../Component/Cache/Traits/FilesystemTrait.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Cache/Traits/FilesystemTrait.php b/src/Symfony/Component/Cache/Traits/FilesystemTrait.php index bcb940cb0f..23974b3bc5 100644 --- a/src/Symfony/Component/Cache/Traits/FilesystemTrait.php +++ b/src/Symfony/Component/Cache/Traits/FilesystemTrait.php @@ -36,9 +36,9 @@ trait FilesystemTrait continue; } - if ($time >= (int) $expiresAt = fgets($h)) { + if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) { fclose($h); - $pruned = isset($expiresAt[0]) && @unlink($file) && !file_exists($file) && $pruned; + $pruned = @unlink($file) && !file_exists($file) && $pruned; } else { fclose($h); } @@ -60,11 +60,9 @@ trait FilesystemTrait if (!file_exists($file) || !$h = @fopen($file, 'rb')) { continue; } - if ($now >= (int) $expiresAt = fgets($h)) { + if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) { fclose($h); - if (isset($expiresAt[0])) { - @unlink($file); - } + @unlink($file); } else { $i = rawurldecode(rtrim(fgets($h))); $value = stream_get_contents($h); @@ -94,7 +92,7 @@ trait FilesystemTrait protected function doSave(array $values, $lifetime) { $ok = true; - $expiresAt = time() + ($lifetime ?: 31557600); // 31557600s = 1 year + $expiresAt = $lifetime ? (time() + $lifetime) : 0; foreach ($values as $id => $value) { $ok = $this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".serialize($value), $expiresAt) && $ok; From 48e8249da93e135cca356c9152744200dea7c1a1 Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Sat, 10 Feb 2018 00:41:50 +0100 Subject: [PATCH 06/16] Make kernel build time optionally deterministic --- src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php | 3 ++- src/Symfony/Component/HttpKernel/Kernel.php | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 0e34dc43da..9461e1ccb5 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -119,6 +119,7 @@ class PhpDumper extends Dumper 'debug' => true, 'hot_path_tag' => 'container.hot_path', 'inline_class_loader_parameter' => 'container.dumper.inline_class_loader', + 'build_time' => time(), ), $options); $this->namespace = $options['namespace']; @@ -216,7 +217,7 @@ EOF; array_pop($code); $code["Container{$hash}/{$options['class']}.php"] = substr_replace($files[$options['class'].'.php'], "namespace ? "\nnamespace {$this->namespace};\n" : ''; - $time = time(); + $time = $options['build_time']; $id = hash('crc32', $hash.$time); $code[$options['class'].'.php'] = << true, 'debug' => $this->debug, 'inline_class_loader_parameter' => \PHP_VERSION_ID >= 70000 && !$this->loadClassCache && !class_exists(ClassCollectionLoader::class, false) ? 'container.dumper.inline_class_loader' : null, + 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), )); $rootCode = array_pop($content); From 09b9eb2395aa0ea5f5fe55b732e27134e7256df3 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sun, 11 Feb 2018 01:53:06 +0100 Subject: [PATCH 07/16] [HttpKernel] don't try to wire Request argument with controller.service_arguments This does not make sense as Request is not a service and it's already handled by RequestValueResolver. --- .../RegisterControllerArgumentLocatorsPass.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index 985dfb71d7..cb88594e3a 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -22,6 +22,7 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Component\HttpFoundation\Request; /** * Creates the service-locators required by ServiceValueResolver. @@ -148,6 +149,10 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface continue; } + if (Request::class === $type) { + continue; + } + if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, false)) { $message = sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type); From e88e1ff494f9fdd3a91407993d8b4a918698c340 Mon Sep 17 00:00:00 2001 From: Matthieu Napoli Date: Sat, 10 Feb 2018 18:16:30 +0100 Subject: [PATCH 08/16] Document explicitly that dotfiles and vcs files are ignored by default This change makes it clear whether or not each of those two options are enabled by default. Without this documentation one has to look into the code. --- src/Symfony/Component/Finder/Finder.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 5784df439b..7b4d71d74e 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -402,6 +402,8 @@ class Finder implements \IteratorAggregate, \Countable /** * Excludes "hidden" directories and files (starting with a dot). * + * This option is enabled by default. + * * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not * * @return $this @@ -422,6 +424,8 @@ class Finder implements \IteratorAggregate, \Countable /** * Forces the finder to ignore version control directories. * + * This option is enabled by default. + * * @param bool $ignoreVCS Whether to exclude VCS files or not * * @return $this From 37fbbca086ae9f7519ed95f141becb1110a6e091 Mon Sep 17 00:00:00 2001 From: Gaylord Poillon Date: Fri, 9 Feb 2018 14:55:34 +0100 Subject: [PATCH 09/16] isCsrfTokenValid() replace string by ?string --- .../Bundle/FrameworkBundle/Controller/ControllerTrait.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php index 6fc94bc8a2..1fb263f00f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -370,12 +370,12 @@ trait ControllerTrait /** * Checks the validity of a CSRF token. * - * @param string $id The id used when generating the token - * @param string $token The actual token sent with the request that should be validated + * @param string $id The id used when generating the token + * @param string|null $token The actual token sent with the request that should be validated * * @final since version 3.4 */ - protected function isCsrfTokenValid(string $id, string $token): bool + protected function isCsrfTokenValid(string $id, ?string $token): bool { if (!$this->container->has('security.csrf.token_manager')) { throw new \LogicException('CSRF protection is not enabled in your application. Enable it with the "csrf_protection" key in "config/packages/framework.yaml".'); From a9568d7c60a5251c651cb0f4d46f8acc8a6a4003 Mon Sep 17 00:00:00 2001 From: Zan Baldwin Date: Thu, 8 Feb 2018 14:20:36 +0000 Subject: [PATCH 10/16] Update Repository Symlink Helper Add workaround for GLOB_BRACE, which is unavailable on certain platforms (such as Alpine). --- link | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/link b/link index a5030d0683..6a2ec15e22 100755 --- a/link +++ b/link @@ -37,7 +37,12 @@ if (!is_dir("$argv[1]/vendor/symfony")) { $sfPackages = array('symfony/symfony' => __DIR__); $filesystem = new Filesystem(); -foreach (glob(__DIR__.'/src/Symfony/{Bundle,Bridge,Component,Component/Security}/*', GLOB_BRACE | GLOB_ONLYDIR | GLOB_NOSORT) as $dir) { +$braces = array('Bundle', 'Bridge', 'Component', 'Component/Security'); +$directories = call_user_func_array('array_merge', array_values(array_map(function ($part) { + return glob(__DIR__.'/src/Symfony/'.$part.'/*', GLOB_ONLYDIR | GLOB_NOSORT); +}, $braces))); + +foreach ($directories as $dir) { if ($filesystem->exists($composer = "$dir/composer.json")) { $sfPackages[json_decode(file_get_contents($composer))->name] = $dir; } From 6f8d5e263edcd8df82c4502c6651e0f1c954320b Mon Sep 17 00:00:00 2001 From: andrey1s Date: Sun, 4 Feb 2018 23:55:07 +0300 Subject: [PATCH 11/16] add context to serialize and deserialize --- src/Symfony/Component/Serializer/CHANGELOG.md | 1 + src/Symfony/Component/Serializer/Serializer.php | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 057275e11b..450640d160 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG * added getter for extra attributes in `ExtraAttributesException` * improved `CsvEncoder` to handle variable nested structures * CSV headers can be passed to the `CsvEncoder` via the `csv_headers` serialization context variable + * added `$context` when checking for encoding, decoding and normalizing in `Serializer` 3.3.0 ----- diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 8a689dc61d..1b244177c7 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -108,11 +108,11 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz */ final public function serialize($data, $format, array $context = array()) { - if (!$this->supportsEncoding($format)) { + if (!$this->supportsEncoding($format, $context)) { throw new NotEncodableValueException(sprintf('Serialization for the format %s is not supported', $format)); } - if ($this->encoder->needsNormalization($format)) { + if ($this->encoder->needsNormalization($format, $context)) { $data = $this->normalize($data, $format, $context); } @@ -124,7 +124,7 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz */ final public function deserialize($data, $type, $format, array $context = array()) { - if (!$this->supportsDecoding($format)) { + if (!$this->supportsDecoding($format, $context)) { throw new NotEncodableValueException(sprintf('Deserialization for the format %s is not supported', $format)); } From 2a74edb0f987abd1d132f8d9db79d47d6ef08161 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Fri, 2 Feb 2018 13:35:25 +0100 Subject: [PATCH 12/16] [Lock] Log already-locked errors as "notice" instead of "warning" --- src/Symfony/Component/Lock/Lock.php | 10 +++---- src/Symfony/Component/Lock/Tests/LockTest.php | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Lock/Lock.php b/src/Symfony/Component/Lock/Lock.php index e81878a437..77fd032bf1 100644 --- a/src/Symfony/Component/Lock/Lock.php +++ b/src/Symfony/Component/Lock/Lock.php @@ -89,7 +89,7 @@ final class Lock implements LockInterface, LoggerAwareInterface return true; } catch (LockConflictedException $e) { $this->dirty = false; - $this->logger->warning('Failed to acquire the "{resource}" lock. Someone else already acquired the lock.', array('resource' => $this->key)); + $this->logger->notice('Failed to acquire the "{resource}" lock. Someone else already acquired the lock.', array('resource' => $this->key)); if ($blocking) { throw $e; @@ -97,7 +97,7 @@ final class Lock implements LockInterface, LoggerAwareInterface return false; } catch (\Exception $e) { - $this->logger->warning('Failed to acquire the "{resource}" lock.', array('resource' => $this->key, 'exception' => $e)); + $this->logger->notice('Failed to acquire the "{resource}" lock.', array('resource' => $this->key, 'exception' => $e)); throw new LockAcquiringException(sprintf('Failed to acquire the "%s" lock.', $this->key), 0, $e); } } @@ -123,10 +123,10 @@ final class Lock implements LockInterface, LoggerAwareInterface $this->logger->info('Expiration defined for "{resource}" lock for "{ttl}" seconds.', array('resource' => $this->key, 'ttl' => $this->ttl)); } catch (LockConflictedException $e) { $this->dirty = false; - $this->logger->warning('Failed to define an expiration for the "{resource}" lock, someone else acquired the lock.', array('resource' => $this->key)); + $this->logger->notice('Failed to define an expiration for the "{resource}" lock, someone else acquired the lock.', array('resource' => $this->key)); throw $e; } catch (\Exception $e) { - $this->logger->warning('Failed to define an expiration for the "{resource}" lock.', array('resource' => $this->key, 'exception' => $e)); + $this->logger->notice('Failed to define an expiration for the "{resource}" lock.', array('resource' => $this->key, 'exception' => $e)); throw new LockAcquiringException(sprintf('Failed to define an expiration for the "%s" lock.', $this->key), 0, $e); } } @@ -148,7 +148,7 @@ final class Lock implements LockInterface, LoggerAwareInterface $this->dirty = false; if ($this->store->exists($this->key)) { - $this->logger->warning('Failed to release the "{resource}" lock.', array('resource' => $this->key)); + $this->logger->notice('Failed to release the "{resource}" lock.', array('resource' => $this->key)); throw new LockReleasingException(sprintf('Failed to release the "%s" lock.', $this->key)); } } diff --git a/src/Symfony/Component/Lock/Tests/LockTest.php b/src/Symfony/Component/Lock/Tests/LockTest.php index ece5cf6679..7913644b9a 100644 --- a/src/Symfony/Component/Lock/Tests/LockTest.php +++ b/src/Symfony/Component/Lock/Tests/LockTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Lock\Tests; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; use Symfony\Component\Lock\Exception\LockConflictedException; use Symfony\Component\Lock\Key; use Symfony\Component\Lock\Lock; @@ -192,6 +193,35 @@ class LockTest extends TestCase $lock->release(); } + /** + * @expectedException \Symfony\Component\Lock\Exception\LockReleasingException + */ + public function testReleaseThrowsAndLog() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); + $lock = new Lock($key, $store, 10, true); + $lock->setLogger($logger); + + $logger->expects($this->atLeastOnce()) + ->method('notice') + ->with('Failed to release the "{resource}" lock.', array('resource' => $key)); + + $store + ->expects($this->once()) + ->method('delete') + ->with($key); + + $store + ->expects($this->once()) + ->method('exists') + ->with($key) + ->willReturn(true); + + $lock->release(); + } + /** * @dataProvider provideExpiredDates */ From a175a25d972b8f5eb758988da9d42ad39dc99191 Mon Sep 17 00:00:00 2001 From: Douglas Greenshields Date: Fri, 2 Feb 2018 15:21:07 +0000 Subject: [PATCH 13/16] [PhpBridge] add PHPUnit 7 support to SymfonyTestsListener --- .../Bridge/PhpUnit/SymfonyTestsListener.php | 6 +- .../SymfonyTestsListenerWithReturnTypes.php | 69 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/SymfonyTestsListenerWithReturnTypes.php diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php index c11fde9526..7115f31485 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php +++ b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php @@ -16,10 +16,12 @@ use PHPUnit\Framework\Test; use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\Warning; -if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { - class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); // Using an early return instead of a else does not work when using the PHPUnit phar due to some weird PHP behavior (the class // gets defined without executing the code before it and so the definition is not properly conditional) +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { + class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); +} elseif (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0', '>=')) { + class_alias('Symfony\Bridge\PhpUnit\SymfonyTestsListenerWithReturnTypes', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); } else { /** * Collects and replays skipped tests. diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListenerWithReturnTypes.php b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListenerWithReturnTypes.php new file mode 100644 index 0000000000..dfe13afb3f --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListenerWithReturnTypes.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestListenerDefaultImplementation; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; + +/** + * Collects and replays skipped tests. + * + * (Version of SymfonyTestsListener for PHPUnit 7+, and PHP 7.1+.) + * + * @author Nicolas Grekas + * + * @final + */ +class SymfonyTestsListenerWithReturnTypes implements TestListener +{ + use TestListenerDefaultImplementation; + + private $trait; + + public function __construct(array $mockedNamespaces = array()) + { + $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces); + } + + public function globalListenerDisabled() + { + $this->trait->globalListenerDisabled(); + } + + public function startTestSuite(TestSuite $suite): void + { + $this->trait->startTestSuite($suite); + } + + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + $this->trait->addSkippedTest($test, $t, $time); + } + + public function startTest(Test $test): void + { + $this->trait->startTest($test); + } + + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->trait->addWarning($test, $e, $time); + } + + public function endTest(Test $test, float $time): void + { + $this->trait->endTest($test, $time); + } +} From c41681cb800194fd084f3e0a96e5615c0b5bcaa3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 11 Feb 2018 15:19:16 +0100 Subject: [PATCH 14/16] [Bridge\PhpUnit] Cleanup BC layer --- ...ener.php => SymfonyTestsListenerForV5.php} | 12 ++-- .../Legacy/SymfonyTestsListenerForV6.php | 64 +++++++++++++++++++ .../SymfonyTestsListenerForV7.php} | 8 +-- .../Bridge/PhpUnit/SymfonyTestsListener.php | 60 ++--------------- 4 files changed, 77 insertions(+), 67 deletions(-) rename src/Symfony/Bridge/PhpUnit/Legacy/{SymfonyTestsListener.php => SymfonyTestsListenerForV5.php} (76%) create mode 100644 src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV6.php rename src/Symfony/Bridge/PhpUnit/{SymfonyTestsListenerWithReturnTypes.php => Legacy/SymfonyTestsListenerForV7.php} (86%) diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV5.php similarity index 76% rename from src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListener.php rename to src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV5.php index 5ed545a512..2da40f2c20 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListener.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV5.php @@ -18,7 +18,7 @@ namespace Symfony\Bridge\PhpUnit\Legacy; * * @internal */ -class SymfonyTestsListener extends \PHPUnit_Framework_BaseTestListener +class SymfonyTestsListenerForV5 extends \PHPUnit_Framework_BaseTestListener { private $trait; @@ -34,26 +34,26 @@ class SymfonyTestsListener extends \PHPUnit_Framework_BaseTestListener public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) { - return $this->trait->startTestSuite($suite); + $this->trait->startTestSuite($suite); } public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) { - return $this->trait->addSkippedTest($test, $e, $time); + $this->trait->addSkippedTest($test, $e, $time); } public function startTest(\PHPUnit_Framework_Test $test) { - return $this->trait->startTest($test); + $this->trait->startTest($test); } public function addWarning(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time) { - return $this->trait->addWarning($test, $e, $time); + $this->trait->addWarning($test, $e, $time); } public function endTest(\PHPUnit_Framework_Test $test, $time) { - return $this->trait->endTest($test, $time); + $this->trait->endTest($test, $time); } } diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV6.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV6.php new file mode 100644 index 0000000000..d8e74e8192 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV6.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\Framework\BaseTestListener; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; + +/** + * Collects and replays skipped tests. + * + * @author Nicolas Grekas + * + * @internal + */ +class SymfonyTestsListenerForV6 extends BaseTestListener +{ + private $trait; + + public function __construct(array $mockedNamespaces = array()) + { + $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces); + } + + public function globalListenerDisabled() + { + $this->trait->globalListenerDisabled(); + } + + public function startTestSuite(TestSuite $suite) + { + $this->trait->startTestSuite($suite); + } + + public function addSkippedTest(Test $test, \Exception $e, $time) + { + $this->trait->addSkippedTest($test, $e, $time); + } + + public function startTest(Test $test) + { + $this->trait->startTest($test); + } + + public function addWarning(Test $test, Warning $e, $time) + { + $this->trait->addWarning($test, $e, $time); + } + + public function endTest(Test $test, $time) + { + $this->trait->endTest($test, $time); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListenerWithReturnTypes.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV7.php similarity index 86% rename from src/Symfony/Bridge/PhpUnit/SymfonyTestsListenerWithReturnTypes.php rename to src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV7.php index dfe13afb3f..d3acd53960 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListenerWithReturnTypes.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerForV7.php @@ -20,13 +20,11 @@ use PHPUnit\Framework\Warning; /** * Collects and replays skipped tests. * - * (Version of SymfonyTestsListener for PHPUnit 7+, and PHP 7.1+.) - * * @author Nicolas Grekas * - * @final + * @internal */ -class SymfonyTestsListenerWithReturnTypes implements TestListener +class SymfonyTestsListenerForV7 implements TestListener { use TestListenerDefaultImplementation; @@ -34,7 +32,7 @@ class SymfonyTestsListenerWithReturnTypes implements TestListener public function __construct(array $mockedNamespaces = array()) { - $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces); + $this->trait = new SymfonyTestsListenerTrait($mockedNamespaces); } public function globalListenerDisabled() diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php index 7115f31485..d46a79e00e 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php +++ b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php @@ -11,62 +11,10 @@ namespace Symfony\Bridge\PhpUnit; -use PHPUnit\Framework\BaseTestListener; -use PHPUnit\Framework\Test; -use PHPUnit\Framework\TestSuite; -use PHPUnit\Framework\Warning; - -// Using an early return instead of a else does not work when using the PHPUnit phar due to some weird PHP behavior (the class -// gets defined without executing the code before it and so the definition is not properly conditional) if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { - class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); -} elseif (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0', '>=')) { - class_alias('Symfony\Bridge\PhpUnit\SymfonyTestsListenerWithReturnTypes', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); + class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV5', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); +} elseif (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0', '<')) { + class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV6', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); } else { - /** - * Collects and replays skipped tests. - * - * @author Nicolas Grekas - * - * @final - */ - class SymfonyTestsListener extends BaseTestListener - { - private $trait; - - public function __construct(array $mockedNamespaces = array()) - { - $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces); - } - - public function globalListenerDisabled() - { - $this->trait->globalListenerDisabled(); - } - - public function startTestSuite(TestSuite $suite) - { - return $this->trait->startTestSuite($suite); - } - - public function addSkippedTest(Test $test, \Exception $e, $time) - { - return $this->trait->addSkippedTest($test, $e, $time); - } - - public function startTest(Test $test) - { - return $this->trait->startTest($test); - } - - public function addWarning(Test $test, Warning $e, $time) - { - return $this->trait->addWarning($test, $e, $time); - } - - public function endTest(Test $test, $time) - { - return $this->trait->endTest($test, $time); - } - } + class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV7', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); } From 97370a3dd9b34bc6447b8921be611d200cdbac14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Thu, 1 Feb 2018 23:45:44 +0100 Subject: [PATCH 15/16] [Bridge\PhpUnit] Exit as late as possible People might want to register other shutdown functions that should be able to control the exit code themselves, without the deprecation error handler taking over. The php manual says: > If you call exit() within one registered shutdown function, processing > will stop completely and no other registered shutdown functions will be > called. See https://secure.php.net/manual/en/function.register-shutdown-function.php --- .../PhpUnit/DeprecationErrorHandler.php | 53 +++++++---- .../DeprecationErrorHandler/default.phpt | 5 + .../shutdown_deprecations.phpt | 91 +++++++++++++++++++ 3 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index f73690db00..b0f241c862 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -127,32 +127,53 @@ class DeprecationErrorHandler return $b['count'] - $a['count']; }; - foreach (array('unsilenced', 'remaining', 'legacy', 'other') as $group) { - if ($deprecations[$group.'Count']) { - echo "\n", $colorize(sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), 'legacy' !== $group), "\n"; + $displayDeprecations = function ($deprecations) use ($colorize, $cmp) { + foreach (array('unsilenced', 'remaining', 'legacy', 'other') as $group) { + if ($deprecations[$group.'Count']) { + echo "\n", $colorize(sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), 'legacy' !== $group), "\n"; - uasort($deprecations[$group], $cmp); + uasort($deprecations[$group], $cmp); - foreach ($deprecations[$group] as $msg => $notices) { - echo "\n ", $notices['count'], 'x: ', $msg, "\n"; + foreach ($deprecations[$group] as $msg => $notices) { + echo "\n ", $notices['count'], 'x: ', $msg, "\n"; - arsort($notices); + arsort($notices); - foreach ($notices as $method => $count) { - if ('count' !== $method) { - echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n"; + foreach ($notices as $method => $count) { + if ('count' !== $method) { + echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n"; + } } } } } - } - if (!empty($notices)) { - echo "\n"; + if (!empty($notices)) { + echo "\n"; + } + }; + + $displayDeprecations($deprecations); + + // store failing status + $isFailing = 'weak' !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other']); + + // reset deprecations array + foreach ($deprecations as $group => $arrayOrInt) { + $deprecations[$group] = is_int($arrayOrInt) ? 0 : array(); } - if ('weak' !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other'])) { - exit(1); - } + register_shutdown_function(function () use (&$deprecations, $isFailing, $displayDeprecations, $mode) { + foreach ($deprecations as $group => $arrayOrInt) { + if (0 < (is_int($arrayOrInt) ? $arrayOrInt : count($arrayOrInt))) { + echo "Shutdown-time deprecations:\n"; + break; + } + } + $displayDeprecations($deprecations); + if ($isFailing || 'weak' !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other'])) { + exit(1); + } + }); }); } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt index 39a3e98586..7a0595a7dd 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt @@ -59,6 +59,10 @@ $foo = new FooTestCase(); $foo->testLegacyFoo(); $foo->testNonLegacyBar(); +register_shutdown_function(function () { + exit('I get precedence over any exit statements inside the deprecation error handler.'); +}); + ?> --EXPECTF-- Unsilenced deprecation notices (3) @@ -80,3 +84,4 @@ Other deprecation notices (1) 1x: root deprecation +I get precedence over any exit statements inside the deprecation error handler. diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt new file mode 100644 index 0000000000..fddeed6085 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt @@ -0,0 +1,91 @@ +--TEST-- +Test DeprecationErrorHandler in default mode +--FILE-- +testLegacyFoo(); +$foo->testNonLegacyBar(); + +register_shutdown_function(function () { + @trigger_error('root deprecation during shutdown', E_USER_DEPRECATED); +}); + +?> +--EXPECTF-- +Unsilenced deprecation notices (3) + + 2x: unsilenced foo deprecation + 2x in FooTestCase::testLegacyFoo + + 1x: unsilenced bar deprecation + 1x in FooTestCase::testNonLegacyBar + +Remaining deprecation notices (1) + + 1x: silenced bar deprecation + 1x in FooTestCase::testNonLegacyBar + +Legacy deprecation notices (1) + +Other deprecation notices (1) + + 1x: root deprecation + +Shutdown-time deprecations: + +Other deprecation notices (1) + + 1x: root deprecation during shutdown From aa956636ab538d7ad5210b69087dbc6af5b12d28 Mon Sep 17 00:00:00 2001 From: Thomas Counsell Date: Tue, 6 Feb 2018 16:18:24 +0000 Subject: [PATCH 16/16] [YAML] Issue #26065: leading spaces in YAML multi-line string literals --- src/Symfony/Component/Yaml/Dumper.php | 5 ++++- src/Symfony/Component/Yaml/Tests/DumperTest.php | 11 +++++++++++ ...s_as_literal_block_leading_space_in_first_line.yml | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Yaml/Tests/Fixtures/multiple_lines_as_literal_block_leading_space_in_first_line.yml diff --git a/src/Symfony/Component/Yaml/Dumper.php b/src/Symfony/Component/Yaml/Dumper.php index 41562358bc..0513044d2f 100644 --- a/src/Symfony/Component/Yaml/Dumper.php +++ b/src/Symfony/Component/Yaml/Dumper.php @@ -98,7 +98,10 @@ class Dumper foreach ($input as $key => $value) { if ($inline >= 1 && Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && is_string($value) && false !== strpos($value, "\n") && false === strpos($value, "\r\n")) { - $output .= sprintf("%s%s%s |\n", $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', ''); + // If the first line starts with a space character, the spec requires a blockIndicationIndicator + // http://www.yaml.org/spec/1.2/spec.html#id2793979 + $blockIndentationIndicator = (' ' === substr($value, 0, 1)) ? (string) $this->indentation : ''; + $output .= sprintf("%s%s%s |%s\n", $prefix, $dumpAsMap ? Inline::dump($key, $flags).':' : '-', '', $blockIndentationIndicator); foreach (preg_split('/\n|\r\n/', $value) as $row) { $output .= sprintf("%s%s%s\n", $prefix, str_repeat(' ', $this->indentation), $row); diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index a29dff20f7..b474391132 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -454,6 +454,17 @@ YAML; $this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); } + public function testDumpMultiLineStringAsScalarBlockWhenFirstLineHasLeadingSpace() + { + $data = array( + 'data' => array( + 'multi_line' => " the first line has leading spaces\nThe second line does not.", + ), + ); + + $this->assertSame(file_get_contents(__DIR__.'/Fixtures/multiple_lines_as_literal_block_leading_space_in_first_line.yml'), $this->dumper->dump($data, 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); + } + public function testCarriageReturnIsMaintainedWhenDumpingAsMultiLineLiteralBlock() { $this->assertSame("- \"a\\r\\nb\\nc\"\n", $this->dumper->dump(array("a\r\nb\nc"), 2, 0, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK)); diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/multiple_lines_as_literal_block_leading_space_in_first_line.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/multiple_lines_as_literal_block_leading_space_in_first_line.yml new file mode 100644 index 0000000000..3f2dedd10e --- /dev/null +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/multiple_lines_as_literal_block_leading_space_in_first_line.yml @@ -0,0 +1,4 @@ +data: + multi_line: |4 + the first line has leading spaces + The second line does not.