From cd2f3a605674f792f26a7e91f9be39cb30394501 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 17 Sep 2019 16:29:00 +0200 Subject: [PATCH 1/4] fix tests depending on other components' tests --- src/Symfony/Bridge/Doctrine/composer.json | 2 +- .../Controller/ControllerResolverTest.php | 4 +- .../Bundle/FrameworkBundle/composer.json | 2 +- .../Form/Test/FormPerformanceTestCase.php | 2 - .../Form/{Tests => Test}/VersionAwareTest.php | 5 +- .../Form/Tests/AbstractLayoutTest.php | 1 + .../Extension/Core/Type/BaseTypeTest.php | 2 +- .../ContainerControllerResolverTestCase.php | 301 ++++++++++++++++ .../Controller/ControllerResolverTestCase.php | 328 ++++++++++++++++++ .../Controller/NullableController.php | 5 +- .../Controller/VariadicController.php | 5 +- .../Tests/Controller/ArgumentResolverTest.php | 4 +- .../ContainerControllerResolverTest.php | 284 +-------------- .../Controller/ControllerResolverTest.php | 311 +---------------- .../ArgumentMetadataFactoryTest.php | 4 +- 15 files changed, 655 insertions(+), 605 deletions(-) rename src/Symfony/Component/Form/{Tests => Test}/VersionAwareTest.php (92%) create mode 100644 src/Symfony/Component/HttpKernel/Test/Controller/ContainerControllerResolverTestCase.php create mode 100644 src/Symfony/Component/HttpKernel/Test/Controller/ControllerResolverTestCase.php rename src/Symfony/Component/HttpKernel/{Tests => Test}/Fixtures/Controller/NullableController.php (81%) rename src/Symfony/Component/HttpKernel/{Tests => Test}/Fixtures/Controller/VariadicController.php (78%) diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 1aa2315c60..0fb219a7d2 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -25,7 +25,7 @@ "doctrine/annotations": "~1.7", "symfony/stopwatch": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~3.4|~4.0", - "symfony/form": "^3.3.10|~4.0", + "symfony/form": "^3.4.32|^4.3.5", "symfony/http-kernel": "~2.8|~3.0|~4.0", "symfony/property-access": "~2.8|~3.0|~4.0", "symfony/property-info": "~2.8|3.0|~4.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php index 6af19862e6..a26dc13e19 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php @@ -20,9 +20,9 @@ use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Tests\Controller\ContainerControllerResolverTest; +use Symfony\Component\HttpKernel\Test\Controller\ContainerControllerResolverTestCase; -class ControllerResolverTest extends ContainerControllerResolverTest +class ControllerResolverTest extends ContainerControllerResolverTestCase { public function testGetControllerOnContainerAware() { diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index dae941c1f7..0a8ede5cdb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -25,7 +25,7 @@ "symfony/debug": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~3.4|~4.0", "symfony/http-foundation": "^3.4.13|~4.3", - "symfony/http-kernel": "^3.4.31|^4.3.4", + "symfony/http-kernel": "^3.4.32|^4.3.5", "symfony/polyfill-mbstring": "~1.0", "symfony/filesystem": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", diff --git a/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php b/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php index e11ce03357..859129ac56 100644 --- a/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php +++ b/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Form\Test; -use Symfony\Component\Form\Tests\VersionAwareTest; - /** * Base class for performance tests. * diff --git a/src/Symfony/Component/Form/Tests/VersionAwareTest.php b/src/Symfony/Component/Form/Test/VersionAwareTest.php similarity index 92% rename from src/Symfony/Component/Form/Tests/VersionAwareTest.php rename to src/Symfony/Component/Form/Test/VersionAwareTest.php index 2b8489a6a2..62d12c433d 100644 --- a/src/Symfony/Component/Form/Tests/VersionAwareTest.php +++ b/src/Symfony/Component/Form/Test/VersionAwareTest.php @@ -9,8 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Form\Tests; +namespace Symfony\Component\Form\Test; +/** + * @internal + */ trait VersionAwareTest { protected static $supportedFeatureSetVersion = 304; diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index 0165552f73..61d6bbf846 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Extension\Csrf\CsrfExtension; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Test\FormIntegrationTestCase; +use Symfony\Component\Form\Test\VersionAwareTest; abstract class AbstractLayoutTest extends FormIntegrationTestCase { diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php index 62654fc618..4380204c2b 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Test\TypeTestCase; -use Symfony\Component\Form\Tests\VersionAwareTest; +use Symfony\Component\Form\Test\VersionAwareTest; /** * @author Bernhard Schussek diff --git a/src/Symfony/Component/HttpKernel/Test/Controller/ContainerControllerResolverTestCase.php b/src/Symfony/Component/HttpKernel/Test/Controller/ContainerControllerResolverTestCase.php new file mode 100644 index 0000000000..5e5970705f --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Test/Controller/ContainerControllerResolverTestCase.php @@ -0,0 +1,301 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Test\Controller; + +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Debug\ErrorHandler; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; + +/** + * @internal + */ +class ContainerControllerResolverTestCase extends ControllerResolverTestCase +{ + public function testGetControllerService() + { + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with('foo') + ->willReturn(true); + $container->expects($this->once()) + ->method('get') + ->with('foo') + ->willReturn($this) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', 'foo:controllerMethod1'); + + $controller = $resolver->getController($request); + + $this->assertInstanceOf(\get_class($this), $controller[0]); + $this->assertSame('controllerMethod1', $controller[1]); + } + + public function testGetControllerInvokableService() + { + $invokableController = new InvokableController('bar'); + + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with('foo') + ->willReturn(true) + ; + $container->expects($this->once()) + ->method('get') + ->with('foo') + ->willReturn($invokableController) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', 'foo'); + + $controller = $resolver->getController($request); + + $this->assertEquals($invokableController, $controller); + } + + public function testGetControllerInvokableServiceWithClassNameAsName() + { + $invokableController = new InvokableController('bar'); + $className = __NAMESPACE__.'\InvokableController'; + + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with($className) + ->willReturn(true) + ; + $container->expects($this->once()) + ->method('get') + ->with($className) + ->willReturn($invokableController) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', $className); + + $controller = $resolver->getController($request); + + $this->assertEquals($invokableController, $controller); + } + + public function testNonInstantiableController() + { + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with(NonInstantiableController::class) + ->willReturn(false) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', [NonInstantiableController::class, 'action']); + + $controller = $resolver->getController($request); + + $this->assertSame([NonInstantiableController::class, 'action'], $controller); + } + + public function testNonConstructController() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('Controller "Symfony\Component\HttpKernel\Test\Controller\ImpossibleConstructController" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->at(0)) + ->method('has') + ->with(ImpossibleConstructController::class) + ->willReturn(true) + ; + + $container->expects($this->at(1)) + ->method('has') + ->with(ImpossibleConstructController::class) + ->willReturn(false) + ; + + $container->expects($this->atLeastOnce()) + ->method('getRemovedIds') + ->with() + ->willReturn([ImpossibleConstructController::class => true]) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', [ImpossibleConstructController::class, 'action']); + + if (\PHP_VERSION_ID < 70100) { + ErrorHandler::register(); + try { + $resolver->getController($request); + } finally { + restore_error_handler(); + restore_exception_handler(); + } + } else { + $resolver->getController($request); + } + } + + public function testNonInstantiableControllerWithCorrespondingService() + { + $service = new \stdClass(); + + $container = $this->createMockContainer(); + $container->expects($this->atLeastOnce()) + ->method('has') + ->with(NonInstantiableController::class) + ->willReturn(true) + ; + $container->expects($this->atLeastOnce()) + ->method('get') + ->with(NonInstantiableController::class) + ->willReturn($service) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', [NonInstantiableController::class, 'action']); + + $controller = $resolver->getController($request); + + $this->assertSame([$service, 'action'], $controller); + } + + public function testExceptionWhenUsingRemovedControllerService() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('Controller "app.my_controller" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->at(0)) + ->method('has') + ->with('app.my_controller') + ->willReturn(false) + ; + + $container->expects($this->atLeastOnce()) + ->method('getRemovedIds') + ->with() + ->willReturn(['app.my_controller' => true]) + ; + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'app.my_controller'); + $resolver->getController($request); + } + + public function testExceptionWhenUsingControllerWithoutAnInvokeMethod() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('Controller "app.my_controller" cannot be called without a method name. Did you forget an "__invoke" method?'); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->once()) + ->method('has') + ->with('app.my_controller') + ->willReturn(true) + ; + $container->expects($this->once()) + ->method('get') + ->with('app.my_controller') + ->willReturn(new ImpossibleConstructController('toto', 'controller')) + ; + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'app.my_controller'); + $resolver->getController($request); + } + + /** + * @dataProvider getUndefinedControllers + */ + public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null) + { + // All this logic needs to be duplicated, since calling parent::testGetControllerOnNonUndefinedFunction will override the expected excetion and not use the regex + $resolver = $this->createControllerResolver(); + $this->expectException($exceptionName); + $this->expectExceptionMessageRegExp($exceptionMessage); + + $request = Request::create('/'); + $request->attributes->set('_controller', $controller); + $resolver->getController($request); + } + + public function getUndefinedControllers() + { + return [ + ['foo', \LogicException::class, '/Controller not found: service "foo" does not exist\./'], + ['oof::bar', \InvalidArgumentException::class, '/Class "oof" does not exist\./'], + ['stdClass', \LogicException::class, '/Controller not found: service "stdClass" does not exist\./'], + [ + 'Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTest::bar', + \InvalidArgumentException::class, + '/.?[cC]ontroller(.*?) for URI "\/" is not callable\.( Expected method(.*) Available methods)?/', + ], + ]; + } + + protected function createControllerResolver(LoggerInterface $logger = null, ContainerInterface $container = null) + { + if (!$container) { + $container = $this->createMockContainer(); + } + + return new ContainerControllerResolver($container, $logger); + } + + protected function createMockContainer() + { + return $this->getMockBuilder(ContainerInterface::class)->getMock(); + } +} + +class InvokableController +{ + public function __construct($bar) // mandatory argument to prevent automatic instantiation + { + } + + public function __invoke() + { + } +} + +abstract class NonInstantiableController +{ + public static function action() + { + } +} + +class ImpossibleConstructController +{ + public function __construct($toto, $controller) + { + } + + public function action() + { + } +} diff --git a/src/Symfony/Component/HttpKernel/Test/Controller/ControllerResolverTestCase.php b/src/Symfony/Component/HttpKernel/Test/Controller/ControllerResolverTestCase.php new file mode 100644 index 0000000000..9d0a2eb229 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Test/Controller/ControllerResolverTestCase.php @@ -0,0 +1,328 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Test\Controller; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ControllerResolver; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\NullableController; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\VariadicController; + +/** + * @internal + */ +class ControllerResolverTestCase extends TestCase +{ + public function testGetControllerWithoutControllerParameter() + { + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $logger->expects($this->once())->method('warning')->with('Unable to look for the controller as the "_controller" parameter is missing.'); + $resolver = $this->createControllerResolver($logger); + + $request = Request::create('/'); + $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute'); + } + + public function testGetControllerWithLambda() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', $lambda = function () {}); + $controller = $resolver->getController($request); + $this->assertSame($lambda, $controller); + } + + public function testGetControllerWithObjectAndInvokeMethod() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', $this); + $controller = $resolver->getController($request); + $this->assertSame($this, $controller); + } + + public function testGetControllerWithObjectAndMethod() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', [$this, 'controllerMethod1']); + $controller = $resolver->getController($request); + $this->assertSame([$this, 'controllerMethod1'], $controller); + } + + public function testGetControllerWithClassAndMethod() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', ['Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTestCase', 'controllerMethod4']); + $controller = $resolver->getController($request); + $this->assertSame(['Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTestCase', 'controllerMethod4'], $controller); + } + + public function testGetControllerWithObjectAndMethodAsString() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTestCase::controllerMethod1'); + $controller = $resolver->getController($request); + $this->assertInstanceOf('Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTestCase', $controller[0], '->getController() returns a PHP callable'); + } + + public function testGetControllerWithClassAndInvokeMethod() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTestCase'); + $controller = $resolver->getController($request); + $this->assertInstanceOf('Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTestCase', $controller); + } + + public function testGetControllerOnObjectWithoutInvokeMethod() + { + $this->expectException('InvalidArgumentException'); + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', new \stdClass()); + $resolver->getController($request); + } + + public function testGetControllerWithFunction() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Test\Controller\some_controller_function'); + $controller = $resolver->getController($request); + $this->assertSame('Symfony\Component\HttpKernel\Test\Controller\some_controller_function', $controller); + } + + /** + * @dataProvider getUndefinedControllers + */ + public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null) + { + $resolver = $this->createControllerResolver(); + $this->expectException($exceptionName); + $this->expectExceptionMessage($exceptionMessage); + + $request = Request::create('/'); + $request->attributes->set('_controller', $controller); + $resolver->getController($request); + } + + public function getUndefinedControllers() + { + return [ + [1, 'InvalidArgumentException', 'Unable to find controller "1".'], + ['foo', 'InvalidArgumentException', 'Unable to find controller "foo".'], + ['oof::bar', 'InvalidArgumentException', 'Class "oof" does not exist.'], + ['stdClass', 'InvalidArgumentException', 'Unable to find controller "stdClass".'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest::staticsAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest", did you mean "staticAction"?'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest::privateAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest" should be public and non-abstract'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest::protectedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest" should be public and non-abstract'], + ['Symfony\Component\HttpKernel\Test\Controller\ControllerTest::undefinedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Test\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], + ]; + } + + /** + * @group legacy + */ + public function testGetArguments() + { + $resolver = $this->createControllerResolver(); + + $request = Request::create('/'); + $controller = [new self(), 'testGetArguments']; + $this->assertEquals([], $resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments'); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = [new self(), 'controllerMethod1']; + $this->assertEquals(['foo'], $resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method'); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = [new self(), 'controllerMethod2']; + $this->assertEquals(['foo', null], $resolver->getArguments($request, $controller), '->getArguments() uses default values if present'); + + $request->attributes->set('bar', 'bar'); + $this->assertEquals(['foo', 'bar'], $resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes'); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = function ($foo) {}; + $this->assertEquals(['foo'], $resolver->getArguments($request, $controller)); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = function ($foo, $bar = 'bar') {}; + $this->assertEquals(['foo', 'bar'], $resolver->getArguments($request, $controller)); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $controller = new self(); + $this->assertEquals(['foo', null], $resolver->getArguments($request, $controller)); + $request->attributes->set('bar', 'bar'); + $this->assertEquals(['foo', 'bar'], $resolver->getArguments($request, $controller)); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('foobar', 'foobar'); + $controller = 'Symfony\Component\HttpKernel\Test\Controller\some_controller_function'; + $this->assertEquals(['foo', 'foobar'], $resolver->getArguments($request, $controller)); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('foobar', 'foobar'); + $controller = [new self(), 'controllerMethod3']; + + try { + $resolver->getArguments($request, $controller); + $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); + } catch (\Exception $e) { + $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); + } + + $request = Request::create('/'); + $controller = [new self(), 'controllerMethod5']; + $this->assertEquals([$request], $resolver->getArguments($request, $controller), '->getArguments() injects the request'); + } + + /** + * @requires PHP 5.6 + * @group legacy + */ + public function testGetVariadicArguments() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('bar', ['foo', 'bar']); + $controller = [new VariadicController(), 'action']; + $this->assertEquals(['foo', 'foo', 'bar'], $resolver->getArguments($request, $controller)); + } + + public function testCreateControllerCanReturnAnyCallable() + { + $mock = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ControllerResolver')->setMethods(['createController'])->getMock(); + $mock->expects($this->once())->method('createController')->willReturn('Symfony\Component\HttpKernel\Test\Controller\some_controller_function'); + + $request = Request::create('/'); + $request->attributes->set('_controller', 'foobar'); + $mock->getController($request); + } + + /** + * @group legacy + */ + public function testIfExceptionIsThrownWhenMissingAnArgument() + { + $this->expectException('RuntimeException'); + $resolver = new ControllerResolver(); + $request = Request::create('/'); + + $controller = [$this, 'controllerMethod1']; + + $resolver->getArguments($request, $controller); + } + + /** + * @requires PHP 7.1 + * @group legacy + */ + public function testGetNullableArguments() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('bar', new \stdClass()); + $request->attributes->set('mandatory', 'mandatory'); + $controller = [new NullableController(), 'action']; + $this->assertEquals(['foo', new \stdClass(), 'value', 'mandatory'], $resolver->getArguments($request, $controller)); + } + + /** + * @requires PHP 7.1 + * @group legacy + */ + public function testGetNullableArgumentsWithDefaults() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('mandatory', 'mandatory'); + $controller = [new NullableController(), 'action']; + $this->assertEquals([null, null, 'value', 'mandatory'], $resolver->getArguments($request, $controller)); + } + + protected function createControllerResolver(LoggerInterface $logger = null) + { + return new ControllerResolver($logger); + } + + public function __invoke($foo, $bar = null) + { + } + + public function controllerMethod1($foo) + { + } + + protected function controllerMethod2($foo, $bar = null) + { + } + + protected function controllerMethod3($foo, $bar, $foobar) + { + } + + protected static function controllerMethod4() + { + } + + protected function controllerMethod5(Request $request) + { + } +} + +function some_controller_function($foo, $foobar) +{ +} + +class ControllerTest +{ + public function publicAction() + { + } + + private function privateAction() + { + } + + protected function protectedAction() + { + } + + public static function staticAction() + { + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php b/src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/NullableController.php similarity index 81% rename from src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php rename to src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/NullableController.php index 9db4df7b4c..8cf95f2f54 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php +++ b/src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/NullableController.php @@ -9,8 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller; +namespace Symfony\Component\HttpKernel\Test\Fixtures\Controller; +/** + * @internal + */ class NullableController { public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', $mandatory) diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/VariadicController.php b/src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/VariadicController.php similarity index 78% rename from src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/VariadicController.php rename to src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/VariadicController.php index c39812453b..0201f50759 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/VariadicController.php +++ b/src/Symfony/Component/HttpKernel/Test/Fixtures/Controller/VariadicController.php @@ -9,8 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller; +namespace Symfony\Component\HttpKernel\Test\Fixtures\Controller; +/** + * @internal + */ class VariadicController { public function action($foo, ...$bar) diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php index a964aaeb58..9818ab99f2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php @@ -20,10 +20,10 @@ use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\NullableController; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\VariadicController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingRequest; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingSession; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; class ArgumentResolverTest extends TestCase { diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php index 1f8ddb8314..2396ffd87d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php @@ -11,288 +11,8 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; -use Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Debug\ErrorHandler; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; +use Symfony\Component\HttpKernel\Test\Controller\ContainerControllerResolverTestCase; -class ContainerControllerResolverTest extends ControllerResolverTest +class ContainerControllerResolverTest extends ContainerControllerResolverTestCase { - public function testGetControllerService() - { - $container = $this->createMockContainer(); - $container->expects($this->once()) - ->method('has') - ->with('foo') - ->willReturn(true); - $container->expects($this->once()) - ->method('get') - ->with('foo') - ->willReturn($this) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', 'foo:controllerMethod1'); - - $controller = $resolver->getController($request); - - $this->assertInstanceOf(\get_class($this), $controller[0]); - $this->assertSame('controllerMethod1', $controller[1]); - } - - public function testGetControllerInvokableService() - { - $invokableController = new InvokableController('bar'); - - $container = $this->createMockContainer(); - $container->expects($this->once()) - ->method('has') - ->with('foo') - ->willReturn(true) - ; - $container->expects($this->once()) - ->method('get') - ->with('foo') - ->willReturn($invokableController) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', 'foo'); - - $controller = $resolver->getController($request); - - $this->assertEquals($invokableController, $controller); - } - - public function testGetControllerInvokableServiceWithClassNameAsName() - { - $invokableController = new InvokableController('bar'); - $className = __NAMESPACE__.'\InvokableController'; - - $container = $this->createMockContainer(); - $container->expects($this->once()) - ->method('has') - ->with($className) - ->willReturn(true) - ; - $container->expects($this->once()) - ->method('get') - ->with($className) - ->willReturn($invokableController) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', $className); - - $controller = $resolver->getController($request); - - $this->assertEquals($invokableController, $controller); - } - - public function testNonInstantiableController() - { - $container = $this->createMockContainer(); - $container->expects($this->once()) - ->method('has') - ->with(NonInstantiableController::class) - ->willReturn(false) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', [NonInstantiableController::class, 'action']); - - $controller = $resolver->getController($request); - - $this->assertSame([NonInstantiableController::class, 'action'], $controller); - } - - public function testNonConstructController() - { - $this->expectException('LogicException'); - $this->expectExceptionMessage('Controller "Symfony\Component\HttpKernel\Tests\Controller\ImpossibleConstructController" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); - $container = $this->getMockBuilder(Container::class)->getMock(); - $container->expects($this->at(0)) - ->method('has') - ->with(ImpossibleConstructController::class) - ->willReturn(true) - ; - - $container->expects($this->at(1)) - ->method('has') - ->with(ImpossibleConstructController::class) - ->willReturn(false) - ; - - $container->expects($this->atLeastOnce()) - ->method('getRemovedIds') - ->with() - ->willReturn([ImpossibleConstructController::class => true]) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', [ImpossibleConstructController::class, 'action']); - - if (\PHP_VERSION_ID < 70100) { - ErrorHandler::register(); - try { - $resolver->getController($request); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } else { - $resolver->getController($request); - } - } - - public function testNonInstantiableControllerWithCorrespondingService() - { - $service = new \stdClass(); - - $container = $this->createMockContainer(); - $container->expects($this->atLeastOnce()) - ->method('has') - ->with(NonInstantiableController::class) - ->willReturn(true) - ; - $container->expects($this->atLeastOnce()) - ->method('get') - ->with(NonInstantiableController::class) - ->willReturn($service) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', [NonInstantiableController::class, 'action']); - - $controller = $resolver->getController($request); - - $this->assertSame([$service, 'action'], $controller); - } - - public function testExceptionWhenUsingRemovedControllerService() - { - $this->expectException('LogicException'); - $this->expectExceptionMessage('Controller "app.my_controller" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); - $container = $this->getMockBuilder(Container::class)->getMock(); - $container->expects($this->at(0)) - ->method('has') - ->with('app.my_controller') - ->willReturn(false) - ; - - $container->expects($this->atLeastOnce()) - ->method('getRemovedIds') - ->with() - ->willReturn(['app.my_controller' => true]) - ; - - $resolver = $this->createControllerResolver(null, $container); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'app.my_controller'); - $resolver->getController($request); - } - - public function testExceptionWhenUsingControllerWithoutAnInvokeMethod() - { - $this->expectException('LogicException'); - $this->expectExceptionMessage('Controller "app.my_controller" cannot be called without a method name. Did you forget an "__invoke" method?'); - $container = $this->getMockBuilder(Container::class)->getMock(); - $container->expects($this->once()) - ->method('has') - ->with('app.my_controller') - ->willReturn(true) - ; - $container->expects($this->once()) - ->method('get') - ->with('app.my_controller') - ->willReturn(new ImpossibleConstructController('toto', 'controller')) - ; - - $resolver = $this->createControllerResolver(null, $container); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'app.my_controller'); - $resolver->getController($request); - } - - /** - * @dataProvider getUndefinedControllers - */ - public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null) - { - // All this logic needs to be duplicated, since calling parent::testGetControllerOnNonUndefinedFunction will override the expected excetion and not use the regex - $resolver = $this->createControllerResolver(); - $this->expectException($exceptionName); - $this->expectExceptionMessageRegExp($exceptionMessage); - - $request = Request::create('/'); - $request->attributes->set('_controller', $controller); - $resolver->getController($request); - } - - public function getUndefinedControllers() - { - return [ - ['foo', \LogicException::class, '/Controller not found: service "foo" does not exist\./'], - ['oof::bar', \InvalidArgumentException::class, '/Class "oof" does not exist\./'], - ['stdClass', \LogicException::class, '/Controller not found: service "stdClass" does not exist\./'], - [ - 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar', - \InvalidArgumentException::class, - '/.?[cC]ontroller(.*?) for URI "\/" is not callable\.( Expected method(.*) Available methods)?/', - ], - ]; - } - - protected function createControllerResolver(LoggerInterface $logger = null, ContainerInterface $container = null) - { - if (!$container) { - $container = $this->createMockContainer(); - } - - return new ContainerControllerResolver($container, $logger); - } - - protected function createMockContainer() - { - return $this->getMockBuilder(ContainerInterface::class)->getMock(); - } -} - -class InvokableController -{ - public function __construct($bar) // mandatory argument to prevent automatic instantiation - { - } - - public function __invoke() - { - } -} - -abstract class NonInstantiableController -{ - public static function action() - { - } -} - -class ImpossibleConstructController -{ - public function __construct($toto, $controller) - { - } - - public function action() - { - } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index e34427a32e..90dc626008 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -11,315 +11,8 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; -use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ControllerResolver; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; +use Symfony\Component\HttpKernel\Test\Controller\ControllerResolverTestCase; -class ControllerResolverTest extends TestCase -{ - public function testGetControllerWithoutControllerParameter() - { - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $logger->expects($this->once())->method('warning')->with('Unable to look for the controller as the "_controller" parameter is missing.'); - $resolver = $this->createControllerResolver($logger); - - $request = Request::create('/'); - $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute'); - } - - public function testGetControllerWithLambda() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', $lambda = function () {}); - $controller = $resolver->getController($request); - $this->assertSame($lambda, $controller); - } - - public function testGetControllerWithObjectAndInvokeMethod() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', $this); - $controller = $resolver->getController($request); - $this->assertSame($this, $controller); - } - - public function testGetControllerWithObjectAndMethod() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', [$this, 'controllerMethod1']); - $controller = $resolver->getController($request); - $this->assertSame([$this, 'controllerMethod1'], $controller); - } - - public function testGetControllerWithClassAndMethod() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', ['Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4']); - $controller = $resolver->getController($request); - $this->assertSame(['Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'], $controller); - } - - public function testGetControllerWithObjectAndMethodAsString() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::controllerMethod1'); - $controller = $resolver->getController($request); - $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller[0], '->getController() returns a PHP callable'); - } - - public function testGetControllerWithClassAndInvokeMethod() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest'); - $controller = $resolver->getController($request); - $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller); - } - - public function testGetControllerOnObjectWithoutInvokeMethod() - { - $this->expectException('InvalidArgumentException'); - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', new \stdClass()); - $resolver->getController($request); - } - - public function testGetControllerWithFunction() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'); - $controller = $resolver->getController($request); - $this->assertSame('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function', $controller); - } - - /** - * @dataProvider getUndefinedControllers - */ - public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null) - { - $resolver = $this->createControllerResolver(); - $this->expectException($exceptionName); - $this->expectExceptionMessage($exceptionMessage); - - $request = Request::create('/'); - $request->attributes->set('_controller', $controller); - $resolver->getController($request); - } - - public function getUndefinedControllers() - { - return [ - [1, 'InvalidArgumentException', 'Unable to find controller "1".'], - ['foo', 'InvalidArgumentException', 'Unable to find controller "foo".'], - ['oof::bar', 'InvalidArgumentException', 'Class "oof" does not exist.'], - ['stdClass', 'InvalidArgumentException', 'Unable to find controller "stdClass".'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::staticsAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest", did you mean "staticAction"?'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::privateAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::protectedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::undefinedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], - ]; - } - - /** - * @group legacy - */ - public function testGetArguments() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $controller = [new self(), 'testGetArguments']; - $this->assertEquals([], $resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments'); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = [new self(), 'controllerMethod1']; - $this->assertEquals(['foo'], $resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method'); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = [new self(), 'controllerMethod2']; - $this->assertEquals(['foo', null], $resolver->getArguments($request, $controller), '->getArguments() uses default values if present'); - - $request->attributes->set('bar', 'bar'); - $this->assertEquals(['foo', 'bar'], $resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes'); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = function ($foo) {}; - $this->assertEquals(['foo'], $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = function ($foo, $bar = 'bar') {}; - $this->assertEquals(['foo', 'bar'], $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = new self(); - $this->assertEquals(['foo', null], $resolver->getArguments($request, $controller)); - $request->attributes->set('bar', 'bar'); - $this->assertEquals(['foo', 'bar'], $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('foobar', 'foobar'); - $controller = 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'; - $this->assertEquals(['foo', 'foobar'], $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('foobar', 'foobar'); - $controller = [new self(), 'controllerMethod3']; - - try { - $resolver->getArguments($request, $controller); - $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); - } catch (\Exception $e) { - $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); - } - - $request = Request::create('/'); - $controller = [new self(), 'controllerMethod5']; - $this->assertEquals([$request], $resolver->getArguments($request, $controller), '->getArguments() injects the request'); - } - - /** - * @requires PHP 5.6 - * @group legacy - */ - public function testGetVariadicArguments() - { - $resolver = new ControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('bar', ['foo', 'bar']); - $controller = [new VariadicController(), 'action']; - $this->assertEquals(['foo', 'foo', 'bar'], $resolver->getArguments($request, $controller)); - } - - public function testCreateControllerCanReturnAnyCallable() - { - $mock = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ControllerResolver')->setMethods(['createController'])->getMock(); - $mock->expects($this->once())->method('createController')->willReturn('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'foobar'); - $mock->getController($request); - } - - /** - * @group legacy - */ - public function testIfExceptionIsThrownWhenMissingAnArgument() - { - $this->expectException('RuntimeException'); - $resolver = new ControllerResolver(); - $request = Request::create('/'); - - $controller = [$this, 'controllerMethod1']; - - $resolver->getArguments($request, $controller); - } - - /** - * @requires PHP 7.1 - * @group legacy - */ - public function testGetNullableArguments() - { - $resolver = new ControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('bar', new \stdClass()); - $request->attributes->set('mandatory', 'mandatory'); - $controller = [new NullableController(), 'action']; - $this->assertEquals(['foo', new \stdClass(), 'value', 'mandatory'], $resolver->getArguments($request, $controller)); - } - - /** - * @requires PHP 7.1 - * @group legacy - */ - public function testGetNullableArgumentsWithDefaults() - { - $resolver = new ControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('mandatory', 'mandatory'); - $controller = [new NullableController(), 'action']; - $this->assertEquals([null, null, 'value', 'mandatory'], $resolver->getArguments($request, $controller)); - } - - protected function createControllerResolver(LoggerInterface $logger = null) - { - return new ControllerResolver($logger); - } - - public function __invoke($foo, $bar = null) - { - } - - public function controllerMethod1($foo) - { - } - - protected function controllerMethod2($foo, $bar = null) - { - } - - protected function controllerMethod3($foo, $bar, $foobar) - { - } - - protected static function controllerMethod4() - { - } - - protected function controllerMethod5(Request $request) - { - } -} - -function some_controller_function($foo, $foobar) +class ControllerResolverTest extends ControllerResolverTestCase { } - -class ControllerTest -{ - public function publicAction() - { - } - - private function privateAction() - { - } - - protected function protectedAction() - { - } - - public static function staticAction() - { - } -} diff --git a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php index 1c0c4648a0..f58188ded5 100644 --- a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php @@ -15,9 +15,9 @@ use Fake\ImportedAndFake; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\NullableController; +use Symfony\Component\HttpKernel\Test\Fixtures\Controller\VariadicController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\BasicTypesController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; class ArgumentMetadataFactoryTest extends TestCase { From e2043ff53ee644004900b79b1b57622af5bbf276 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 18 Sep 2019 09:39:27 +0200 Subject: [PATCH 2/4] [Twig] Fix Twig config extra keys --- .../DependencyInjection/TwigExtension.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index a0000afa90..52ba0503e4 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -150,18 +150,20 @@ class TwigExtension extends Extension } } - unset( - $config['form'], - $config['globals'], - $config['extensions'] - ); - if (isset($config['autoescape_service']) && isset($config['autoescape_service_method'])) { $config['autoescape'] = [new Reference($config['autoescape_service']), $config['autoescape_service_method']]; } - unset($config['autoescape_service'], $config['autoescape_service_method']); - $container->getDefinition('twig')->replaceArgument(1, $config); + $container->getDefinition('twig')->replaceArgument(1, array_intersect_key($config, [ + 'debug' => true, + 'charset' => true, + 'base_template_class' => true, + 'strict_variables' => true, + 'autoescape' => true, + 'cache' => true, + 'auto_reload' => true, + 'optimizations' => true, + ])); $container->registerForAutoconfiguration(\Twig_ExtensionInterface::class)->addTag('twig.extension'); $container->registerForAutoconfiguration(\Twig_LoaderInterface::class)->addTag('twig.loader'); From 6a8ab6cb73fde983f732ff3b2c097cb506918b51 Mon Sep 17 00:00:00 2001 From: mmokhi Date: Wed, 11 Sep 2019 11:18:08 +0200 Subject: [PATCH 3/4] Call AssertEquals with proper parameters Since `$response->getContent()` returns string and our first parameter is already string as well, in some cases (with different precisions) it may "compare strings" as "strings" and this is not what the test wants. By changing the first parameter to actual number we force `AssertEquals` to compare them numerically rather than literally by string content. --- .../Component/HttpFoundation/Tests/JsonResponseTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php index fd045fb9c3..9642dc28d3 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php @@ -52,7 +52,7 @@ class JsonResponseTest extends TestCase $this->assertSame('0', $response->getContent()); $response = new JsonResponse(0.1); - $this->assertEquals('0.1', $response->getContent()); + $this->assertEquals(0.1, $response->getContent()); $this->assertIsString($response->getContent()); $response = new JsonResponse(true); @@ -141,7 +141,7 @@ class JsonResponseTest extends TestCase $response = JsonResponse::create(0.1); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); - $this->assertEquals('0.1', $response->getContent()); + $this->assertEquals(0.1, $response->getContent()); $this->assertIsString($response->getContent()); $response = JsonResponse::create(true); From 2d708b3e60e5e5e03ed9a028faaa999bcdd293c2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 18 Sep 2019 15:36:31 +0200 Subject: [PATCH 4/4] ensure compatibility with type resolver 0.5 --- .../Component/PropertyInfo/Util/PhpDocTypeHelper.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php index 0879a04590..c013062d54 100644 --- a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php +++ b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php @@ -55,7 +55,14 @@ final class PhpDocTypeHelper $varTypes = []; for ($typeIndex = 0; $varType->has($typeIndex); ++$typeIndex) { - $varTypes[] = (string) $varType->get($typeIndex); + $nestedVarType = $varType->get($typeIndex); + + if ($nestedVarType instanceof Nullable) { + $varTypes[] = (string) $nestedVarType->getActualType(); + $nullable = true; + } else { + $varTypes[] = (string) $nestedVarType; + } } // If null is present, all types are nullable