From b15aed5760094e33ed5ed4f806721bb090dbb30e Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole Date: Wed, 6 Nov 2013 19:58:22 +0000 Subject: [PATCH] Issue #1859684 by dawehner, effulgentsia: Expand routeBuilder unit test. --- .../lib/Drupal/Core/Routing/MatcherDumper.php | 6 +- .../Core/Routing/MatcherDumperInterface.php | 26 ++ core/lib/Drupal/Core/Routing/RouteBuilder.php | 37 ++- .../system/Tests/Routing/RoutingFixtures.php | 38 +++ .../Tests/Core/Routing/RouteBuilderTest.php | 243 ++++++++++++++++++ 5 files changed, 339 insertions(+), 11 deletions(-) create mode 100644 core/lib/Drupal/Core/Routing/MatcherDumperInterface.php create mode 100644 core/tests/Drupal/Tests/Core/Routing/RouteBuilderTest.php diff --git a/core/lib/Drupal/Core/Routing/MatcherDumper.php b/core/lib/Drupal/Core/Routing/MatcherDumper.php index 72c0bee6501..a1bfa3ec6e5 100644 --- a/core/lib/Drupal/Core/Routing/MatcherDumper.php +++ b/core/lib/Drupal/Core/Routing/MatcherDumper.php @@ -7,7 +7,6 @@ namespace Drupal\Core\Routing; -use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; use Symfony\Component\Routing\RouteCollection; use Drupal\Core\Database\Connection; @@ -59,10 +58,7 @@ class MatcherDumper implements MatcherDumperInterface { } /** - * Adds additional routes to be dumped. - * - * @param Symfony\Component\Routing\RouteCollection $routes - * A collection of routes to add to this dumper. + * {@inheritdoc} */ public function addRoutes(RouteCollection $routes) { if (empty($this->routes)) { diff --git a/core/lib/Drupal/Core/Routing/MatcherDumperInterface.php b/core/lib/Drupal/Core/Routing/MatcherDumperInterface.php new file mode 100644 index 00000000000..d4a464f0ee0 --- /dev/null +++ b/core/lib/Drupal/Core/Routing/MatcherDumperInterface.php @@ -0,0 +1,26 @@ +dumper = $dumper; @@ -72,6 +80,9 @@ class RouteBuilder { /** * Rebuilds the route info and dumps to dumper. + * + * @return bool + * Returns TRUE if the rebuild succeeds, FALSE otherwise. */ public function rebuild() { if (!$this->lock->acquire('router_rebuild')) { @@ -79,10 +90,10 @@ class RouteBuilder { // We choose to block here since otherwise the routes might not be // available, resulting in a 404. $this->lock->wait('router_rebuild'); - return; + return FALSE; } - $yaml_discovery = new YamlDiscovery('routing', $this->moduleHandler->getModuleDirectories()); + $yaml_discovery = $this->getYamlDiscovery(); foreach ($yaml_discovery->findAll() as $module => $routes) { $collection = new RouteCollection(); @@ -111,6 +122,20 @@ class RouteBuilder { $this->dumper->dump(array('route_set' => 'dynamic_routes')); $this->lock->release('router_rebuild'); + return TRUE; + } + + /** + * Returns the YAML discovery for getting all the .routing.yml files. + * + * @return \Drupal\Component\Discovery\YamlDiscovery + * The yaml discovery. + */ + protected function getYamlDiscovery() { + if (!isset($this->yamlDiscovery)) { + $this->yamlDiscovery = new YamlDiscovery('routing', $this->moduleHandler->getModuleDirectories()); + } + return $this->yamlDiscovery; } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/RoutingFixtures.php b/core/modules/system/lib/Drupal/system/Tests/Routing/RoutingFixtures.php index 06f09530009..99513ed8d7d 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Routing/RoutingFixtures.php +++ b/core/modules/system/lib/Drupal/system/Tests/Routing/RoutingFixtures.php @@ -43,6 +43,44 @@ class RoutingFixtures { } } + /** + * Returns a static version of the routes. + */ + public function staticSampleRouteCollection() { + $routes = array(); + $routes['route_a'] = array( + 'path' => '/path/one', + 'requirements' => array( + '_method' => 'GET', + ), + ); + $routes['route_b'] = array( + 'path' => '/path/one', + 'requirements' => array( + '_method' => 'PUT', + ), + ); + $routes['route_c'] = array( + 'path' => '/path/two', + 'requirements' => array( + '_method' => 'GET', + '_format' => 'json' + ), + ); + $routes['route_d'] = array( + 'path' => '/path/three', + ); + $routes['route_e'] = array( + 'path' => '/path/two', + 'requirements' => array( + '_method' => 'GET|HEAD', + '_format' => 'html' + ), + ); + + return $routes; + } + /** * Returns a standard set of routes for testing. * diff --git a/core/tests/Drupal/Tests/Core/Routing/RouteBuilderTest.php b/core/tests/Drupal/Tests/Core/Routing/RouteBuilderTest.php new file mode 100644 index 00000000000..7da52c00e90 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Routing/RouteBuilderTest.php @@ -0,0 +1,243 @@ + 'Route Builder', + 'description' => 'Tests the route builder.', + 'group' => 'Routing', + ); + } + + protected function setUp() { + $this->dumper = $this->getMock('Drupal\Core\Routing\MatcherDumperInterface'); + $this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface'); + $this->dispatcher = $this->getMock('\Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); + $this->yamlDiscovery = $this->getMockBuilder('\Drupal\Component\Discovery\YamlDiscovery') + ->disableOriginalConstructor() + ->getMock(); + + $this->routeBuilder = new TestRouteBuilder($this->dumper, $this->lock, $this->dispatcher, $this->moduleHandler); + $this->routeBuilder->setYamlDiscovery($this->yamlDiscovery); + } + + /** + * Tests that the route rebuilding both locks and unlocks. + */ + public function testRebuildLockingUnlocking() { + $this->lock->expects($this->once()) + ->method('acquire') + ->with('router_rebuild') + ->will($this->returnValue(TRUE)); + + $this->lock->expects($this->once()) + ->method('release') + ->with('router_rebuild'); + + $this->yamlDiscovery->expects($this->any()) + ->method('findAll') + ->will($this->returnValue(array())); + + $this->assertTrue($this->routeBuilder->rebuild()); + } + + /** + * Tests route rebuilding with a blocking lock. + */ + public function testRebuildBlockingLock() { + $this->lock->expects($this->once()) + ->method('acquire') + ->with('router_rebuild') + ->will($this->returnValue(FALSE)); + + $this->lock->expects($this->once()) + ->method('wait') + ->with('router_rebuild'); + + $this->lock->expects($this->never()) + ->method('release'); + + $this->yamlDiscovery->expects($this->never()) + ->method('findAll'); + + $this->assertFalse($this->routeBuilder->rebuild()); + } + + /** + * Tests that provided routes by a module is put into the dumper/dispatcher. + * + * @see \Drupal\Core\Routing\RouteBuilder::rebuild() + */ + public function testRebuildWithStaticModuleRoutes() { + $this->lock->expects($this->once()) + ->method('acquire') + ->with('router_rebuild') + ->will($this->returnValue(TRUE)); + + $routing_fixtures = new RoutingFixtures(); + $routes = $routing_fixtures->staticSampleRouteCollection(); + + $this->yamlDiscovery->expects($this->once()) + ->method('findAll') + ->will($this->returnValue(array('test_module' => $routes))); + + // Ensure that the dispatch events for altering are fired. + $this->dispatcher->expects($this->at(0)) + ->method('dispatch') + ->with($this->equalTo(RoutingEvents::ALTER), $this->isInstanceOf('Drupal\Core\Routing\RouteBuildEvent')); + + $empty_collection = new RouteCollection(); + $route_build_event = new RouteBuildEvent($empty_collection, 'dynamic_routes'); + + // Ensure that the dynamic routes events are fired. + $this->dispatcher->expects($this->at(1)) + ->method('dispatch') + ->with(RoutingEvents::DYNAMIC, $route_build_event); + + $this->dispatcher->expects($this->at(2)) + ->method('dispatch') + ->with(RoutingEvents::ALTER, $route_build_event); + + // Ensure that the routes are set to the dumper and dumped. + $this->dumper->expects($this->at(0)) + ->method('addRoutes') + ->with($routing_fixtures->sampleRouteCollection()); + $this->dumper->expects($this->at(1)) + ->method('dump') + ->with(array('route_set' => 'test_module')); + $this->dumper->expects($this->at(2)) + ->method('addRoutes') + ->with($empty_collection); + $this->dumper->expects($this->at(3)) + ->method('dump') + ->with(array('route_set' => 'dynamic_routes')); + + + $this->assertTrue($this->routeBuilder->rebuild()); + } + + /** + * Tests the rebuild with some dynamic routes. + * + * @see \Drupal\Core\Routing\RouteBuilder::rebuild() + */ + public function testRebuildWithDynamicRoutes() { + $this->lock->expects($this->once()) + ->method('acquire') + ->with('router_rebuild') + ->will($this->returnValue(TRUE)); + + $this->yamlDiscovery->expects($this->once()) + ->method('findAll') + ->will($this->returnValue(array())); + + $route_collection_filled = new RouteCollection(); + $route_collection_filled->add('test_route', new Route('/test-route')); + + $this->dispatcher->expects($this->at(0)) + ->method('dispatch') + ->with($this->equalTo(RoutingEvents::DYNAMIC)) + ->will($this->returnCallback(function ($object, RouteBuildEvent $event) { + $event->getRouteCollection()->add('test_route', new Route('/test-route')); + })); + + $this->dispatcher->expects($this->at(1)) + ->method('dispatch') + ->with($this->equalTo(RoutingEvents::ALTER)); + + $this->dumper->expects($this->once()) + ->method('addRoutes') + ->with($route_collection_filled); + $this->dumper->expects($this->once()) + ->method('dump') + ->with(array('route_set' => 'dynamic_routes')); + + $this->assertTrue($this->routeBuilder->rebuild()); + } + +} + +/** + * Extends the core route builder with a setter method for the yaml discovery. + */ +class TestRouteBuilder extends RouteBuilder { + + /** + * Sets the yaml discovery. + * + * @param \Drupal\Component\Discovery\YamlDiscovery $yaml_discovery + * The yaml discovery to set. + */ + public function setYamlDiscovery(YamlDiscovery $yaml_discovery) { + $this->yamlDiscovery = $yaml_discovery; + } + +}