This repository has been archived on 2025-01-19. You can view files and clone it, but cannot push or open issues or pull requests.
drupalcampbristol/vendor/symfony-cmf/routing/Tests/Routing/ChainRouterTest.php
2018-11-23 12:29:20 +00:00

798 lines
24 KiB
PHP

<?php
/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2015 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Cmf\Component\Routing\Tests\Routing;
use Symfony\Cmf\Component\Routing\VersatileGeneratorInterface;
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\ChainRouter;
use Symfony\Cmf\Component\Routing\Test\CmfUnitTestCase;
use Symfony\Component\Routing\RouterInterface;
class ChainRouterTest extends CmfUnitTestCase
{
/**
* @var ChainRouter
*/
private $router;
/**
* @var RequestContext|\PHPUnit_Framework_MockObject_MockObject
*/
private $context;
public function setUp()
{
$this->router = new ChainRouter($this->getMock('Psr\Log\LoggerInterface'));
$this->context = $this->getMock('Symfony\Component\Routing\RequestContext');
}
public function testPriority()
{
$this->assertEquals(array(), $this->router->all());
list($low, $high) = $this->createRouterMocks();
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->assertEquals(array(
$high,
$low,
), $this->router->all());
}
public function testHasRouters()
{
$this->assertEquals(array(), $this->router->all());
$this->assertFalse($this->router->hasRouters());
list($low, $high) = $this->createRouterMocks();
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->assertTrue($this->router->hasRouters());
}
/**
* Routers are supposed to be sorted only once.
* This test will check that by trying to get all routers several times.
*
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::sortRouters
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::all
*/
public function testSortRouters()
{
list($low, $medium, $high) = $this->createRouterMocks();
// We're using a mock here and not $this->router because we need to ensure that the sorting operation is done only once.
/** @var $router ChainRouter|\PHPUnit_Framework_MockObject_MockObject */
$router = $this->buildMock('Symfony\Cmf\Component\Routing\ChainRouter', array('sortRouters'));
$router
->expects($this->once())
->method('sortRouters')
->will(
$this->returnValue(
array($high, $medium, $low)
)
)
;
$router->add($low, 10);
$router->add($medium, 50);
$router->add($high, 100);
$expectedSortedRouters = array($high, $medium, $low);
// Let's get all routers 5 times, we should only sort once.
for ($i = 0; $i < 5; ++$i) {
$this->assertSame($expectedSortedRouters, $router->all());
}
}
/**
* This test ensures that if a router is being added on the fly, the sorting is reset.
*
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::sortRouters
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::all
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::add
*/
public function testReSortRouters()
{
list($low, $medium, $high) = $this->createRouterMocks();
$highest = clone $high;
// We're using a mock here and not $this->router because we need to ensure that the sorting operation is done only once.
/** @var $router ChainRouter|\PHPUnit_Framework_MockObject_MockObject */
$router = $this->buildMock('Symfony\Cmf\Component\Routing\ChainRouter', array('sortRouters'));
$router
->expects($this->at(0))
->method('sortRouters')
->will(
$this->returnValue(
array($high, $medium, $low)
)
)
;
// The second time sortRouters() is called, we're supposed to get the newly added router ($highest)
$router
->expects($this->at(1))
->method('sortRouters')
->will(
$this->returnValue(
array($highest, $high, $medium, $low)
)
)
;
$router->add($low, 10);
$router->add($medium, 50);
$router->add($high, 100);
$this->assertSame(array($high, $medium, $low), $router->all());
// Now adding another router on the fly, sorting must have been reset
$router->add($highest, 101);
$this->assertSame(array($highest, $high, $medium, $low), $router->all());
}
/**
* context must be propagated to chained routers and be stored locally.
*/
public function testContext()
{
list($low, $high) = $this->createRouterMocks();
$low
->expects($this->once())
->method('setContext')
->with($this->context)
;
$high
->expects($this->once())
->method('setContext')
->with($this->context)
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->setContext($this->context);
$this->assertSame($this->context, $this->router->getContext());
}
/**
* context must be propagated also when routers are added after context is set.
*/
public function testContextOrder()
{
list($low, $high) = $this->createRouterMocks();
$low
->expects($this->once())
->method('setContext')
->with($this->context)
;
$high
->expects($this->once())
->method('setContext')
->with($this->context)
;
$this->router->setContext($this->context);
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->all();
$this->assertSame($this->context, $this->router->getContext());
}
/**
* The first usable match is used, no further routers are queried once a match is found.
*/
public function testMatch()
{
$url = '/test';
list($lower, $low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException()))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->returnValue(array('test')))
;
$lower
->expects($this->never())
->method('match');
$this->router->add($lower, 5);
$this->router->add($low, 10);
$this->router->add($high, 100);
$result = $this->router->match('/test');
$this->assertEquals(array('test'), $result);
}
/**
* The first usable match is used, no further routers are queried once a match is found.
*/
public function testMatchRequest()
{
$url = '/test';
list($lower, $low, $high) = $this->createRouterMocks();
$highest = $this->getMock('Symfony\Cmf\Component\Routing\Tests\Routing\RequestMatcher');
$request = Request::create('/test');
$highest
->expects($this->once())
->method('matchRequest')
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException()))
;
$high
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException()))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->returnValue(array('test')))
;
$lower
->expects($this->never())
->method('match')
;
$this->router->add($lower, 5);
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->add($highest, 200);
$result = $this->router->matchRequest($request);
$this->assertEquals(array('test'), $result);
}
/**
* Call match on ChainRouter that has RequestMatcher in the chain.
*/
public function testMatchWithRequestMatchers()
{
$url = '/test';
list($low) = $this->createRouterMocks();
$high = $this->getMock('Symfony\Cmf\Component\Routing\Tests\Routing\RequestMatcher');
$high
->expects($this->once())
->method('matchRequest')
->with($this->callback(function (Request $r) use ($url) {
return $r->getPathInfo() === $url;
}))
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException()))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->returnValue(array('test')))
;
$this->router->add($low, 10);
$this->router->add($high, 20);
$result = $this->router->match($url);
$this->assertEquals(array('test'), $result);
}
public function provideBaseUrl()
{
return array(
array(''),
array('/web'),
);
}
/**
* Call match on ChainRouter that has RequestMatcher in the chain.
*
* @dataProvider provideBaseUrl
*/
public function testMatchWithRequestMatchersAndContext($baseUrl)
{
$url = '//test';
list($low) = $this->createRouterMocks();
$high = $this->getMock('Symfony\Cmf\Component\Routing\Tests\Routing\RequestMatcher');
$high
->expects($this->once())
->method('matchRequest')
->with($this->callback(function (Request $r) use ($url, $baseUrl) {
return true === $r->isSecure()
&& 'foobar.com' === $r->getHost()
&& 4433 === $r->getPort()
&& $baseUrl === $r->getBaseUrl()
&& $url === $r->getPathInfo()
;
}))
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException()))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->returnValue(array('test')))
;
$this->router->add($low, 10);
$this->router->add($high, 20);
$requestContext = new RequestContext();
$requestContext->setScheme('https');
$requestContext->setHost('foobar.com');
$requestContext->setHttpsPort(4433);
$requestContext->setBaseUrl($baseUrl);
$this->router->setContext($requestContext);
$result = $this->router->match($url);
$this->assertEquals(array('test'), $result);
}
/**
* If there is a method not allowed but another router matches, that one is used.
*/
public function testMatchAndNotAllowed()
{
$url = '/test';
list($low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new \Symfony\Component\Routing\Exception\MethodNotAllowedException(array())))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->returnValue(array('test')))
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$result = $this->router->match('/test');
$this->assertEquals(array('test'), $result);
}
/**
* If there is a method not allowed but another router matches, that one is used.
*/
public function testMatchRequestAndNotAllowed()
{
$url = '/test';
list($low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new \Symfony\Component\Routing\Exception\MethodNotAllowedException(array())))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->returnValue(array('test')))
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$result = $this->router->matchRequest(Request::create('/test'));
$this->assertEquals(array('test'), $result);
}
/**
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
*/
public function testMatchNotFound()
{
$url = '/test';
list($low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new ResourceNotFoundException()))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new ResourceNotFoundException()))
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->match('/test');
}
/**
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
*/
public function testMatchRequestNotFound()
{
$url = '/test';
list($low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new ResourceNotFoundException()))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new ResourceNotFoundException()))
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->matchRequest(Request::create('/test'));
}
/**
* Call match on ChainRouter that has RequestMatcher in the chain.
*
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
* @expectedExceptionMessage None of the routers in the chain matched url '/test'
*/
public function testMatchWithRequestMatchersNotFound()
{
$url = '/test';
$request = Request::create('/test');
$high = $this->getMock('Symfony\Cmf\Component\Routing\Tests\Routing\RequestMatcher');
$high
->expects($this->once())
->method('matchRequest')
->with($request)
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException()))
;
$this->router->add($high, 20);
$this->router->match($url);
}
/**
* If any of the routers throws a not allowed exception and no other matches, we need to see this.
*
* @expectedException \Symfony\Component\Routing\Exception\MethodNotAllowedException
*/
public function testMatchMethodNotAllowed()
{
$url = '/test';
list($low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new MethodNotAllowedException(array())))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new ResourceNotFoundException()))
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->match('/test');
}
/**
* If any of the routers throws a not allowed exception and no other matches, we need to see this.
*
* @expectedException \Symfony\Component\Routing\Exception\MethodNotAllowedException
*/
public function testMatchRequestMethodNotAllowed()
{
$url = '/test';
list($low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new MethodNotAllowedException(array())))
;
$low
->expects($this->once())
->method('match')
->with($url)
->will($this->throwException(new ResourceNotFoundException()))
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->matchRequest(Request::create('/test'));
}
public function testGenerate()
{
$url = '/test';
$name = 'test';
$parameters = array('test' => 'value');
list($lower, $low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('generate')
->with($name, $parameters, UrlGeneratorInterface::ABSOLUTE_PATH)
->will($this->throwException(new RouteNotFoundException()))
;
$low
->expects($this->once())
->method('generate')
->with($name, $parameters, UrlGeneratorInterface::ABSOLUTE_PATH)
->will($this->returnValue($url))
;
$lower
->expects($this->never())
->method('generate')
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$result = $this->router->generate($name, $parameters);
$this->assertEquals($url, $result);
}
/**
* @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
*/
public function testGenerateNotFound()
{
$name = 'test';
$parameters = array('test' => 'value');
list($low, $high) = $this->createRouterMocks();
$high
->expects($this->once())
->method('generate')
->with($name, $parameters, UrlGeneratorInterface::ABSOLUTE_PATH)
->will($this->throwException(new RouteNotFoundException()))
;
$low->expects($this->once())
->method('generate')
->with($name, $parameters, UrlGeneratorInterface::ABSOLUTE_PATH)
->will($this->throwException(new RouteNotFoundException()))
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->generate($name, $parameters);
}
/**
* Route is an object but no versatile generator around to do the debug message.
*
* @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
*/
public function testGenerateObjectNotFound()
{
$name = new \stdClass();
$parameters = array('test' => 'value');
$defaultRouter = $this->getMock('Symfony\Component\Routing\RouterInterface');
$defaultRouter
->expects($this->never())
->method('generate')
;
$this->router->add($defaultRouter, 200);
$this->router->generate($name, $parameters);
}
/**
* A versatile router will generate the debug message.
*
* @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
*/
public function testGenerateObjectNotFoundVersatile()
{
$name = new \stdClass();
$parameters = array('test' => 'value');
$chainedRouter = $this->getMock('Symfony\Cmf\Component\Routing\Tests\Routing\VersatileRouter');
$chainedRouter
->expects($this->once())
->method('supports')
->will($this->returnValue(true))
;
$chainedRouter->expects($this->once())
->method('generate')
->with($name, $parameters, UrlGeneratorInterface::ABSOLUTE_PATH)
->will($this->throwException(new RouteNotFoundException()))
;
$chainedRouter->expects($this->once())
->method('getRouteDebugMessage')
->with($name, $parameters)
->will($this->returnValue('message'))
;
$this->router->add($chainedRouter, 10);
$this->router->generate($name, $parameters);
}
public function testGenerateObjectName()
{
$name = new \stdClass();
$parameters = array('test' => 'value');
$defaultRouter = $this->getMock('Symfony\Component\Routing\RouterInterface');
$chainedRouter = $this->getMock('Symfony\Cmf\Component\Routing\Tests\Routing\VersatileRouter');
$defaultRouter
->expects($this->never())
->method('generate')
;
$chainedRouter
->expects($this->once())
->method('supports')
->will($this->returnValue(true))
;
$chainedRouter
->expects($this->once())
->method('generate')
->with($name, $parameters, UrlGeneratorInterface::ABSOLUTE_PATH)
->will($this->returnValue($name))
;
$this->router->add($defaultRouter, 200);
$this->router->add($chainedRouter, 100);
$result = $this->router->generate($name, $parameters);
$this->assertEquals($name, $result);
}
public function testWarmup()
{
$dir = 'test_dir';
list($low) = $this->createRouterMocks();
$low
->expects($this->never())
->method('warmUp')
;
$high = $this->getMock('Symfony\Cmf\Component\Routing\Tests\Routing\WarmableRouterMock');
$high
->expects($this->once())
->method('warmUp')
->with($dir)
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$this->router->warmUp($dir);
}
public function testRouteCollection()
{
list($low, $high) = $this->createRouterMocks();
$lowcol = new RouteCollection();
$lowcol->add('low', $this->buildMock('Symfony\Component\Routing\Route'));
$highcol = new RouteCollection();
$highcol->add('high', $this->buildMock('Symfony\Component\Routing\Route'));
$low
->expects($this->once())
->method('getRouteCollection')
->will($this->returnValue($lowcol))
;
$high
->expects($this->once())
->method('getRouteCollection')
->will($this->returnValue($highcol))
;
$this->router->add($low, 10);
$this->router->add($high, 100);
$collection = $this->router->getRouteCollection();
$this->assertInstanceOf('Symfony\Component\Routing\RouteCollection', $collection);
$names = array();
foreach ($collection->all() as $name => $route) {
$this->assertInstanceOf('Symfony\Component\Routing\Route', $route);
$names[] = $name;
}
$this->assertEquals(array('high', 'low'), $names);
}
/**
* @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
*/
public function testSupport()
{
$router = $this->getMock('Symfony\Cmf\Component\Routing\Tests\Routing\VersatileRouter');
$router
->expects($this->once())
->method('supports')
->will($this->returnValue(false))
;
$router
->expects($this->never())
->method('generate')
->will($this->returnValue(false))
;
$this->router->add($router);
$this->router->generate('foobar');
}
/**
* @return RouterInterface[]|\PHPUnit_Framework_MockObject_MockObject[]
*/
protected function createRouterMocks()
{
return array(
$this->getMock('Symfony\Component\Routing\RouterInterface'),
$this->getMock('Symfony\Component\Routing\RouterInterface'),
$this->getMock('Symfony\Component\Routing\RouterInterface'),
);
}
}
abstract class WarmableRouterMock implements RouterInterface, WarmableInterface
{
}
abstract class RequestMatcher implements RouterInterface, RequestMatcherInterface
{
}
abstract class VersatileRouter implements VersatileGeneratorInterface, RequestMatcherInterface
{
}