<commit_before><?php

use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use Illuminate\Routing\Router;
use Symfony\Component\HttpFoundation\Response;

class RoutingRouteTest extends PHPUnit_Framework_TestCase
{
    public function testBasicDispatchingOfRoutes()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { throw new Illuminate\Http\Exception\HttpResponseException(new Response('hello')); });
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $route = $router->get('foo/bar', ['domain' => 'api.{name}.bar', function ($name) { return $name; }]);
        $route = $router->get('foo/bar', ['domain' => 'api.{name}.baz', function ($name) { return $name; }]);
        $this->assertEquals('taylor', $router->dispatch(Request::create('http://api.taylor.bar/foo/bar', 'GET'))->getContent());
        $this->assertEquals('dayle', $router->dispatch(Request::create('http://api.dayle.baz/foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $route = $router->get('foo/{age}', ['domain' => 'api.{name}.bar', function ($name, $age) { return $name.$age; }]);
        $this->assertEquals('taylor25', $router->dispatch(Request::create('http://api.taylor.bar/foo/25', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->post('foo/bar', function () { return 'post hello'; });
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertEquals('post hello', $router->dispatch(Request::create('foo/bar', 'POST'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $this->assertEquals('taylor', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/{bar}/{baz?}', function ($name, $age = 25) { return $name.$age; });
        $this->assertEquals('taylor25', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/{name}/boom/{age?}/{location?}', function ($name, $age = 25, $location = 'AR') { return $name.$age.$location; });
        $this->assertEquals('taylor30AR', $router->dispatch(Request::create('foo/taylor/boom/30', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('{bar}/{baz?}', function ($name, $age = 25) { return $name.$age; });
        $this->assertEquals('taylor25', $router->dispatch(Request::create('taylor', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('{baz?}', function ($age = 25) { return $age; });
        $this->assertEquals('25', $router->dispatch(Request::create('/', 'GET'))->getContent());
        $this->assertEquals('30', $router->dispatch(Request::create('30', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('{foo?}/{baz?}', ['as' => 'foo', function ($name = 'taylor', $age = 25) { return $name.$age; }]);
        $this->assertEquals('taylor25', $router->dispatch(Request::create('/', 'GET'))->getContent());
        $this->assertEquals('fred25', $router->dispatch(Request::create('fred', 'GET'))->getContent());
        $this->assertEquals('fred30', $router->dispatch(Request::create('fred/30', 'GET'))->getContent());
        $this->assertTrue($router->currentRouteNamed('foo'));
        $this->assertTrue($router->is('foo'));
        $this->assertFalse($router->is('bar'));

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $this->assertEquals('', $router->dispatch(Request::create('foo/bar', 'HEAD'))->getContent());

        $router = $this->getRouter();
        $router->any('foo/bar', function () { return 'hello'; });
        $this->assertEquals('', $router->dispatch(Request::create('foo/bar', 'HEAD'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'first'; });
        $router->get('foo/bar', function () { return 'second'; });
        $this->assertEquals('second', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar/åαф', function () { return 'hello'; });
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar/%C3%A5%CE%B1%D1%84', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['boom' => 'auth', function () { return 'closure'; }]);
        $this->assertEquals('closure', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
    }

    public function testMacro()
    {
        $router = $this->getRouter();
        $router->macro('webhook', function () use ($router) {
            $router->match(['GET', 'POST'], 'webhook', function () { return 'OK'; });
        });
        $router->webhook();
        $this->assertEquals('OK', $router->dispatch(Request::create('webhook', 'GET'))->getContent());
        $this->assertEquals('OK', $router->dispatch(Request::create('webhook', 'POST'))->getContent());
    }

    public function testClassesCanBeInjectedIntoRoutes()
    {
        unset($_SERVER['__test.route_inject']);
        $router = $this->getRouter();
        $router->get('foo/{var}', function (stdClass $foo, $var) {
            $_SERVER['__test.route_inject'] = func_get_args();

            return 'hello';
        });

        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertInstanceOf('stdClass', $_SERVER['__test.route_inject'][0]);
        $this->assertEquals('bar', $_SERVER['__test.route_inject'][1]);

        unset($_SERVER['__test.route_inject']);
    }

    public function testOptionsResponsesAreGeneratedByDefault()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->post('foo/bar', function () { return 'hello'; });
        $response = $router->dispatch(Request::create('foo/bar', 'OPTIONS'));

        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('GET,HEAD,POST', $response->headers->get('Allow'));
    }

    public function testHeadDispatcher()
    {
        $router = $this->getRouter();
        $router->match(['GET', 'POST'], 'foo', function () { return 'bar'; });

        $response = $router->dispatch(Request::create('foo', 'OPTIONS'));
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('GET,HEAD,POST', $response->headers->get('Allow'));

        $response = $router->dispatch(Request::create('foo', 'HEAD'));
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('', $response->getContent());

        $router = $this->getRouter();
        $router->match(['GET'], 'foo', function () { return 'bar'; });

        $response = $router->dispatch(Request::create('foo', 'OPTIONS'));
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('GET,HEAD', $response->headers->get('Allow'));

        $router = $this->getRouter();
        $router->match(['POST'], 'foo', function () { return 'bar'; });

        $response = $router->dispatch(Request::create('foo', 'OPTIONS'));
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('POST', $response->headers->get('Allow'));
    }

    public function testNonGreedyMatches()
    {
        $route = new Route('GET', 'images/{id}.{ext}', function () {});

        $request1 = Request::create('images/1.png', 'GET');
        $this->assertTrue($route->matches($request1));
        $route->bind($request1);
        $this->assertTrue($route->hasParameter('id'));
        $this->assertFalse($route->hasParameter('foo'));
        $this->assertEquals('1', $route->parameter('id'));
        $this->assertEquals('png', $route->parameter('ext'));

        $request2 = Request::create('images/12.png', 'GET');
        $this->assertTrue($route->matches($request2));
        $route->bind($request2);
        $this->assertEquals('12', $route->parameter('id'));
        $this->assertEquals('png', $route->parameter('ext'));

        // Test parameter() default value
        $route = new Route('GET', 'foo/{foo?}', function () {});

        $request3 = Request::create('foo', 'GET');
        $this->assertTrue($route->matches($request3));
        $route->bind($request3);
        $this->assertEquals('bar', $route->parameter('foo', 'bar'));
    }

    /**
     * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException
     */
    public function testRoutesDontMatchNonMatchingPathsWithLeadingOptionals()
    {
        $router = $this->getRouter();
        $router->get('{baz?}', function ($age = 25) { return $age; });
        $this->assertEquals('25', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
    }

    /**
     * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException
     */
    public function testRoutesDontMatchNonMatchingDomain()
    {
        $router = $this->getRouter();
        $route = $router->get('foo/bar', ['domain' => 'api.foo.bar', function () { return 'hello'; }]);
        $this->assertEquals('hello', $router->dispatch(Request::create('http://api.baz.boom/foo/bar', 'GET'))->getContent());
    }

    public function testBasicBeforeFilters()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->before(function () { return 'foo!'; });
        $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->before('RouteTestFilterStub');
        $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->before('RouteTestFilterStub@handle');
        $this->assertEquals('handling!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo', function () { return 'hello'; }]);
        $router->filter('foo', function () { return 'foo!'; });
        $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:25', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $age) { return $age; });
        $this->assertEquals('25', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:0,taylor', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $age, $name) { return $age.$name; });
        $this->assertEquals('0taylor', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:bar,baz', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $bar, $baz) { return $bar.$baz; });
        $this->assertEquals('barbaz', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:bar,baz|bar:boom', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $bar, $baz) { return; });
        $router->filter('bar', function ($route, $request, $boom) { return $boom; });
        $this->assertEquals('boom', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        /*
         * Basic filter parameter
         */
        unset($_SERVER['__route.filter']);
        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:bar', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $value = null) { $_SERVER['__route.filter'] = $value; });
        $router->dispatch(Request::create('foo/bar', 'GET'));
        $this->assertEquals('bar', $_SERVER['__route.filter']);

        /*
         * Optional filter parameter
         */
        unset($_SERVER['__route.filter']);
        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $value = null) { $_SERVER['__route.filter'] = $value; });
        $router->dispatch(Request::create('foo/bar', 'GET'));
        $this->assertNull($_SERVER['__route.filter']);
    }

    public function testGlobalAfterFilters()
    {
        unset($_SERVER['__filter.after']);
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->after(function () { $_SERVER['__filter.after'] = true;

return 'foo!'; });

        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertTrue($_SERVER['__filter.after']);
    }

    public function testBasicAfterFilters()
    {
        unset($_SERVER['__filter.after']);
        $router = $this->getRouter();
        $router->get('foo/bar', ['after' => 'foo', function () { return 'hello'; }]);
        $router->filter('foo', function () { $_SERVER['__filter.after'] = true;

return 'foo!'; });

        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertTrue($_SERVER['__filter.after']);
    }

    public function testPatternBasedFilters()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->when('foo/*', 'foo:bar');
        $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->when('bar/*', 'foo:bar');
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->when('foo/*', 'foo:bar', ['post']);
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->when('foo/*', 'foo:bar', ['get']);
        $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request) {});
        $router->filter('bar', function ($route, $request) { return 'bar'; });
        $router->when('foo/*', 'foo|bar', ['get']);
        $this->assertEquals('bar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
    }

    public function testRegexBasedFilters()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->get('bar/foo', function () { return 'hello'; });
        $router->get('baz/foo', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->whenRegex('/^(foo|bar).*/', 'foo:bar');
        $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertEquals('foobar', $router->dispatch(Request::create('bar/foo', 'GET'))->getContent());
        $this->assertEquals('hello', $router->dispatch(Request::create('baz/foo', 'GET'))->getContent());
    }

    public function testGroupFiltersAndRouteFilters()
    {
        $router = $this->getRouter();
        $router->group(['before' => ['foo']], function () use ($router) {
            $router->get('foo/bar', function () { return 'hello'; })->before('bar');
        });
        $router->filter('foo', function ($route, $request) { return 'foo'; });
        $router->filter('bar', function ($route, $request) { return 'bar'; });
        $this->assertEquals('foo', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
    }

    public function testRegexBasedFiltersWithVariables()
    {
        $router = $this->getRouter();
        $router->get('{var}/bar', function ($var) { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->whenRegex('/^(foo|bar).*/', 'foo:bar');
        $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertEquals('foobar', $router->dispatch(Request::create('bar/bar', 'GET'))->getContent());
        $this->assertEquals('hello', $router->dispatch(Request::create('baz/bar', 'GET'))->getContent());
    }

    public function testMatchesMethodAgainstRequests()
    {
        /*
         * Basic
         */
        $request = Request::create('foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', function () {});
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/bar', 'GET');
        $route = new Route('GET', 'foo', function () {});
        $this->assertFalse($route->matches($request));

        /*
         * Method checks
         */
        $request = Request::create('foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', function () {});
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/bar', 'POST');
        $route = new Route('GET', 'foo', function () {});
        $this->assertFalse($route->matches($request));

        /*
         * Domain checks
         */
        $request = Request::create('http://something.foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['domain' => '{foo}.foo.com', function () {}]);
        $this->assertTrue($route->matches($request));

        $request = Request::create('http://something.bar.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['domain' => '{foo}.foo.com', function () {}]);
        $this->assertFalse($route->matches($request));

        /*
         * HTTPS checks
         */
        $request = Request::create('https://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['https', function () {}]);
        $this->assertTrue($route->matches($request));

        $request = Request::create('https://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['https', 'baz' => true, function () {}]);
        $this->assertTrue($route->matches($request));

        $request = Request::create('http://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['https', function () {}]);
        $this->assertFalse($route->matches($request));

        /*
         * HTTP checks
         */
        $request = Request::create('https://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['http', function () {}]);
        $this->assertFalse($route->matches($request));

        $request = Request::create('http://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['http', function () {}]);
        $this->assertTrue($route->matches($request));

        $request = Request::create('http://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['baz' => true, function () {}]);
        $this->assertTrue($route->matches($request));
    }

    public function testWherePatternsProperlyFilter()
    {
        $request = Request::create('foo/123', 'GET');
        $route = new Route('GET', 'foo/{bar}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123abc', 'GET');
        $route = new Route('GET', 'foo/{bar}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertFalse($route->matches($request));

        $request = Request::create('foo/123abc', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['where' => ['bar' => '[0-9]+'], function () {}]);
        $route->where('bar', '[0-9]+');
        $this->assertFalse($route->matches($request));

        /*
         * Optional
         */
        $request = Request::create('foo/123', 'GET');
        $route = new Route('GET', 'foo/{bar?}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123', 'GET');
        $route = new Route('GET', 'foo/{bar?}', ['where' => ['bar' => '[0-9]+'], function () {}]);
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123', 'GET');
        $route = new Route('GET', 'foo/{bar?}/{baz?}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123/foo', 'GET');
        $route = new Route('GET', 'foo/{bar?}/{baz?}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123abc', 'GET');
        $route = new Route('GET', 'foo/{bar?}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertFalse($route->matches($request));
    }

    public function testDotDoesNotMatchEverything()
    {
        $route = new Route('GET', 'images/{id}.{ext}', function () {});

        $request1 = Request::create('images/1.png', 'GET');
        $this->assertTrue($route->matches($request1));
        $route->bind($request1);
        $this->assertEquals('1', $route->parameter('id'));
        $this->assertEquals('png', $route->parameter('ext'));

        $request2 = Request::create('images/12.png', 'GET');
        $this->assertTrue($route->matches($request2));
        $route->bind($request2);
        $this->assertEquals('12', $route->parameter('id'));
        $this->assertEquals('png', $route->parameter('ext'));
    }

    public function testRouteBinding()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->bind('bar', function ($value) { return strtoupper($value); });
        $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
    }

    public function testRouteClassBinding()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->bind('bar', 'RouteBindingStub');
        $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
    }

    public function testRouteClassMethodBinding()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->bind('bar', 'RouteBindingStub@find');
        $this->assertEquals('dragon', $router->dispatch(Request::create('foo/Dragon', 'GET'))->getContent());
    }

    public function testModelBinding()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->model('bar', 'RouteModelBindingStub');
        $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
    }

    /**
     * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException
     */
    public function testModelBindingWithNullReturn()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->model('bar', 'RouteModelBindingNullStub');
        $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent();
    }

    public function testModelBindingWithCustomNullReturn()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->model('bar', 'RouteModelBindingNullStub', function () { return 'missing'; });
        $this->assertEquals('missing', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
    }

    public function testModelBindingWithBindingClosure()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->model('bar', 'RouteModelBindingNullStub', function ($value) { return (new RouteModelBindingClosureStub())->findAlternate($value); });
        $this->assertEquals('tayloralt', $router->dispatch(Request::create('foo/TAYLOR', 'GET'))->getContent());
    }

    public function testGroupMerging()
    {
        $old = ['prefix' => 'foo/bar/'];
        $this->assertEquals(['prefix' => 'foo/bar/baz', 'namespace' => null, 'where' => []], Router::mergeGroup(['prefix' => 'baz'], $old));

        $old = ['domain' => 'foo'];
        $this->assertEquals(['domain' => 'baz', 'prefix' => null, 'namespace' => null, 'where' => []], Router::mergeGroup(['domain' => 'baz'], $old));

        $old = ['where' => ['var1' => 'foo', 'var2' => 'bar']];
        $this->assertEquals(['prefix' => null, 'namespace' => null, 'where' => [
            'var1' => 'foo', 'var2' => 'baz', 'var3' => 'qux',
        ]], Router::mergeGroup(['where' => ['var2' => 'baz', 'var3' => 'qux']], $old));

        $old = [];
        $this->assertEquals(['prefix' => null, 'namespace' => null, 'where' => [
            'var1' => 'foo', 'var2' => 'bar',
        ]], Router::mergeGroup(['where' => ['var1' => 'foo', 'var2' => 'bar']], $old));
    }

    public function testRouteGrouping()
    {
        /*
         * Inhereting Filters
         */
        $router = $this->getRouter();
        $router->group(['before' => 'foo'], function () use ($router) {
            $router->get('foo/bar', function () { return 'hello'; });
        });
        $router->filter('foo', function () { return 'foo!'; });
        $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        /*
         * Merging Filters
         */
        $router = $this->getRouter();
        $router->group(['before' => 'foo'], function () use ($router) {
            $router->get('foo/bar', ['before' => 'bar', function () { return 'hello'; }]);
        });
        $router->filter('foo', function () {});
        $router->filter('bar', function () { return 'foo!'; });<commit_msg>Typo in "inheriting".<commit_after><?php

use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use Illuminate\Routing\Router;
use Symfony\Component\HttpFoundation\Response;

class RoutingRouteTest extends PHPUnit_Framework_TestCase
{
    public function testBasicDispatchingOfRoutes()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { throw new Illuminate\Http\Exception\HttpResponseException(new Response('hello')); });
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $route = $router->get('foo/bar', ['domain' => 'api.{name}.bar', function ($name) { return $name; }]);
        $route = $router->get('foo/bar', ['domain' => 'api.{name}.baz', function ($name) { return $name; }]);
        $this->assertEquals('taylor', $router->dispatch(Request::create('http://api.taylor.bar/foo/bar', 'GET'))->getContent());
        $this->assertEquals('dayle', $router->dispatch(Request::create('http://api.dayle.baz/foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $route = $router->get('foo/{age}', ['domain' => 'api.{name}.bar', function ($name, $age) { return $name.$age; }]);
        $this->assertEquals('taylor25', $router->dispatch(Request::create('http://api.taylor.bar/foo/25', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->post('foo/bar', function () { return 'post hello'; });
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertEquals('post hello', $router->dispatch(Request::create('foo/bar', 'POST'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $this->assertEquals('taylor', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/{bar}/{baz?}', function ($name, $age = 25) { return $name.$age; });
        $this->assertEquals('taylor25', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/{name}/boom/{age?}/{location?}', function ($name, $age = 25, $location = 'AR') { return $name.$age.$location; });
        $this->assertEquals('taylor30AR', $router->dispatch(Request::create('foo/taylor/boom/30', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('{bar}/{baz?}', function ($name, $age = 25) { return $name.$age; });
        $this->assertEquals('taylor25', $router->dispatch(Request::create('taylor', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('{baz?}', function ($age = 25) { return $age; });
        $this->assertEquals('25', $router->dispatch(Request::create('/', 'GET'))->getContent());
        $this->assertEquals('30', $router->dispatch(Request::create('30', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('{foo?}/{baz?}', ['as' => 'foo', function ($name = 'taylor', $age = 25) { return $name.$age; }]);
        $this->assertEquals('taylor25', $router->dispatch(Request::create('/', 'GET'))->getContent());
        $this->assertEquals('fred25', $router->dispatch(Request::create('fred', 'GET'))->getContent());
        $this->assertEquals('fred30', $router->dispatch(Request::create('fred/30', 'GET'))->getContent());
        $this->assertTrue($router->currentRouteNamed('foo'));
        $this->assertTrue($router->is('foo'));
        $this->assertFalse($router->is('bar'));

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $this->assertEquals('', $router->dispatch(Request::create('foo/bar', 'HEAD'))->getContent());

        $router = $this->getRouter();
        $router->any('foo/bar', function () { return 'hello'; });
        $this->assertEquals('', $router->dispatch(Request::create('foo/bar', 'HEAD'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'first'; });
        $router->get('foo/bar', function () { return 'second'; });
        $this->assertEquals('second', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar/åαф', function () { return 'hello'; });
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar/%C3%A5%CE%B1%D1%84', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['boom' => 'auth', function () { return 'closure'; }]);
        $this->assertEquals('closure', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
    }

    public function testMacro()
    {
        $router = $this->getRouter();
        $router->macro('webhook', function () use ($router) {
            $router->match(['GET', 'POST'], 'webhook', function () { return 'OK'; });
        });
        $router->webhook();
        $this->assertEquals('OK', $router->dispatch(Request::create('webhook', 'GET'))->getContent());
        $this->assertEquals('OK', $router->dispatch(Request::create('webhook', 'POST'))->getContent());
    }

    public function testClassesCanBeInjectedIntoRoutes()
    {
        unset($_SERVER['__test.route_inject']);
        $router = $this->getRouter();
        $router->get('foo/{var}', function (stdClass $foo, $var) {
            $_SERVER['__test.route_inject'] = func_get_args();

            return 'hello';
        });

        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertInstanceOf('stdClass', $_SERVER['__test.route_inject'][0]);
        $this->assertEquals('bar', $_SERVER['__test.route_inject'][1]);

        unset($_SERVER['__test.route_inject']);
    }

    public function testOptionsResponsesAreGeneratedByDefault()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->post('foo/bar', function () { return 'hello'; });
        $response = $router->dispatch(Request::create('foo/bar', 'OPTIONS'));

        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('GET,HEAD,POST', $response->headers->get('Allow'));
    }

    public function testHeadDispatcher()
    {
        $router = $this->getRouter();
        $router->match(['GET', 'POST'], 'foo', function () { return 'bar'; });

        $response = $router->dispatch(Request::create('foo', 'OPTIONS'));
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('GET,HEAD,POST', $response->headers->get('Allow'));

        $response = $router->dispatch(Request::create('foo', 'HEAD'));
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('', $response->getContent());

        $router = $this->getRouter();
        $router->match(['GET'], 'foo', function () { return 'bar'; });

        $response = $router->dispatch(Request::create('foo', 'OPTIONS'));
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('GET,HEAD', $response->headers->get('Allow'));

        $router = $this->getRouter();
        $router->match(['POST'], 'foo', function () { return 'bar'; });

        $response = $router->dispatch(Request::create('foo', 'OPTIONS'));
        $this->assertEquals(200, $response->getStatusCode());
        $this->assertEquals('POST', $response->headers->get('Allow'));
    }

    public function testNonGreedyMatches()
    {
        $route = new Route('GET', 'images/{id}.{ext}', function () {});

        $request1 = Request::create('images/1.png', 'GET');
        $this->assertTrue($route->matches($request1));
        $route->bind($request1);
        $this->assertTrue($route->hasParameter('id'));
        $this->assertFalse($route->hasParameter('foo'));
        $this->assertEquals('1', $route->parameter('id'));
        $this->assertEquals('png', $route->parameter('ext'));

        $request2 = Request::create('images/12.png', 'GET');
        $this->assertTrue($route->matches($request2));
        $route->bind($request2);
        $this->assertEquals('12', $route->parameter('id'));
        $this->assertEquals('png', $route->parameter('ext'));

        // Test parameter() default value
        $route = new Route('GET', 'foo/{foo?}', function () {});

        $request3 = Request::create('foo', 'GET');
        $this->assertTrue($route->matches($request3));
        $route->bind($request3);
        $this->assertEquals('bar', $route->parameter('foo', 'bar'));
    }

    /**
     * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException
     */
    public function testRoutesDontMatchNonMatchingPathsWithLeadingOptionals()
    {
        $router = $this->getRouter();
        $router->get('{baz?}', function ($age = 25) { return $age; });
        $this->assertEquals('25', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
    }

    /**
     * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException
     */
    public function testRoutesDontMatchNonMatchingDomain()
    {
        $router = $this->getRouter();
        $route = $router->get('foo/bar', ['domain' => 'api.foo.bar', function () { return 'hello'; }]);
        $this->assertEquals('hello', $router->dispatch(Request::create('http://api.baz.boom/foo/bar', 'GET'))->getContent());
    }

    public function testBasicBeforeFilters()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->before(function () { return 'foo!'; });
        $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->before('RouteTestFilterStub');
        $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->before('RouteTestFilterStub@handle');
        $this->assertEquals('handling!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo', function () { return 'hello'; }]);
        $router->filter('foo', function () { return 'foo!'; });
        $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:25', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $age) { return $age; });
        $this->assertEquals('25', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:0,taylor', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $age, $name) { return $age.$name; });
        $this->assertEquals('0taylor', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:bar,baz', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $bar, $baz) { return $bar.$baz; });
        $this->assertEquals('barbaz', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:bar,baz|bar:boom', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $bar, $baz) { return; });
        $router->filter('bar', function ($route, $request, $boom) { return $boom; });
        $this->assertEquals('boom', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        /*
         * Basic filter parameter
         */
        unset($_SERVER['__route.filter']);
        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo:bar', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $value = null) { $_SERVER['__route.filter'] = $value; });
        $router->dispatch(Request::create('foo/bar', 'GET'));
        $this->assertEquals('bar', $_SERVER['__route.filter']);

        /*
         * Optional filter parameter
         */
        unset($_SERVER['__route.filter']);
        $router = $this->getRouter();
        $router->get('foo/bar', ['before' => 'foo', function () { return 'hello'; }]);
        $router->filter('foo', function ($route, $request, $value = null) { $_SERVER['__route.filter'] = $value; });
        $router->dispatch(Request::create('foo/bar', 'GET'));
        $this->assertNull($_SERVER['__route.filter']);
    }

    public function testGlobalAfterFilters()
    {
        unset($_SERVER['__filter.after']);
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->after(function () { $_SERVER['__filter.after'] = true;

return 'foo!'; });

        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertTrue($_SERVER['__filter.after']);
    }

    public function testBasicAfterFilters()
    {
        unset($_SERVER['__filter.after']);
        $router = $this->getRouter();
        $router->get('foo/bar', ['after' => 'foo', function () { return 'hello'; }]);
        $router->filter('foo', function () { $_SERVER['__filter.after'] = true;

return 'foo!'; });

        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertTrue($_SERVER['__filter.after']);
    }

    public function testPatternBasedFilters()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->when('foo/*', 'foo:bar');
        $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->when('bar/*', 'foo:bar');
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->when('foo/*', 'foo:bar', ['post']);
        $this->assertEquals('hello', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->when('foo/*', 'foo:bar', ['get']);
        $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request) {});
        $router->filter('bar', function ($route, $request) { return 'bar'; });
        $router->when('foo/*', 'foo|bar', ['get']);
        $this->assertEquals('bar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
    }

    public function testRegexBasedFilters()
    {
        $router = $this->getRouter();
        $router->get('foo/bar', function () { return 'hello'; });
        $router->get('bar/foo', function () { return 'hello'; });
        $router->get('baz/foo', function () { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->whenRegex('/^(foo|bar).*/', 'foo:bar');
        $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertEquals('foobar', $router->dispatch(Request::create('bar/foo', 'GET'))->getContent());
        $this->assertEquals('hello', $router->dispatch(Request::create('baz/foo', 'GET'))->getContent());
    }

    public function testGroupFiltersAndRouteFilters()
    {
        $router = $this->getRouter();
        $router->group(['before' => ['foo']], function () use ($router) {
            $router->get('foo/bar', function () { return 'hello'; })->before('bar');
        });
        $router->filter('foo', function ($route, $request) { return 'foo'; });
        $router->filter('bar', function ($route, $request) { return 'bar'; });
        $this->assertEquals('foo', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
    }

    public function testRegexBasedFiltersWithVariables()
    {
        $router = $this->getRouter();
        $router->get('{var}/bar', function ($var) { return 'hello'; });
        $router->filter('foo', function ($route, $request, $bar) { return 'foo'.$bar; });
        $router->whenRegex('/^(foo|bar).*/', 'foo:bar');
        $this->assertEquals('foobar', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());
        $this->assertEquals('foobar', $router->dispatch(Request::create('bar/bar', 'GET'))->getContent());
        $this->assertEquals('hello', $router->dispatch(Request::create('baz/bar', 'GET'))->getContent());
    }

    public function testMatchesMethodAgainstRequests()
    {
        /*
         * Basic
         */
        $request = Request::create('foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', function () {});
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/bar', 'GET');
        $route = new Route('GET', 'foo', function () {});
        $this->assertFalse($route->matches($request));

        /*
         * Method checks
         */
        $request = Request::create('foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', function () {});
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/bar', 'POST');
        $route = new Route('GET', 'foo', function () {});
        $this->assertFalse($route->matches($request));

        /*
         * Domain checks
         */
        $request = Request::create('http://something.foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['domain' => '{foo}.foo.com', function () {}]);
        $this->assertTrue($route->matches($request));

        $request = Request::create('http://something.bar.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['domain' => '{foo}.foo.com', function () {}]);
        $this->assertFalse($route->matches($request));

        /*
         * HTTPS checks
         */
        $request = Request::create('https://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['https', function () {}]);
        $this->assertTrue($route->matches($request));

        $request = Request::create('https://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['https', 'baz' => true, function () {}]);
        $this->assertTrue($route->matches($request));

        $request = Request::create('http://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['https', function () {}]);
        $this->assertFalse($route->matches($request));

        /*
         * HTTP checks
         */
        $request = Request::create('https://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['http', function () {}]);
        $this->assertFalse($route->matches($request));

        $request = Request::create('http://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['http', function () {}]);
        $this->assertTrue($route->matches($request));

        $request = Request::create('http://foo.com/foo/bar', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['baz' => true, function () {}]);
        $this->assertTrue($route->matches($request));
    }

    public function testWherePatternsProperlyFilter()
    {
        $request = Request::create('foo/123', 'GET');
        $route = new Route('GET', 'foo/{bar}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123abc', 'GET');
        $route = new Route('GET', 'foo/{bar}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertFalse($route->matches($request));

        $request = Request::create('foo/123abc', 'GET');
        $route = new Route('GET', 'foo/{bar}', ['where' => ['bar' => '[0-9]+'], function () {}]);
        $route->where('bar', '[0-9]+');
        $this->assertFalse($route->matches($request));

        /*
         * Optional
         */
        $request = Request::create('foo/123', 'GET');
        $route = new Route('GET', 'foo/{bar?}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123', 'GET');
        $route = new Route('GET', 'foo/{bar?}', ['where' => ['bar' => '[0-9]+'], function () {}]);
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123', 'GET');
        $route = new Route('GET', 'foo/{bar?}/{baz?}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123/foo', 'GET');
        $route = new Route('GET', 'foo/{bar?}/{baz?}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertTrue($route->matches($request));

        $request = Request::create('foo/123abc', 'GET');
        $route = new Route('GET', 'foo/{bar?}', function () {});
        $route->where('bar', '[0-9]+');
        $this->assertFalse($route->matches($request));
    }

    public function testDotDoesNotMatchEverything()
    {
        $route = new Route('GET', 'images/{id}.{ext}', function () {});

        $request1 = Request::create('images/1.png', 'GET');
        $this->assertTrue($route->matches($request1));
        $route->bind($request1);
        $this->assertEquals('1', $route->parameter('id'));
        $this->assertEquals('png', $route->parameter('ext'));

        $request2 = Request::create('images/12.png', 'GET');
        $this->assertTrue($route->matches($request2));
        $route->bind($request2);
        $this->assertEquals('12', $route->parameter('id'));
        $this->assertEquals('png', $route->parameter('ext'));
    }

    public function testRouteBinding()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->bind('bar', function ($value) { return strtoupper($value); });
        $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
    }

    public function testRouteClassBinding()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->bind('bar', 'RouteBindingStub');
        $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
    }

    public function testRouteClassMethodBinding()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->bind('bar', 'RouteBindingStub@find');
        $this->assertEquals('dragon', $router->dispatch(Request::create('foo/Dragon', 'GET'))->getContent());
    }

    public function testModelBinding()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->model('bar', 'RouteModelBindingStub');
        $this->assertEquals('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
    }

    /**
     * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException
     */
    public function testModelBindingWithNullReturn()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->model('bar', 'RouteModelBindingNullStub');
        $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent();
    }

    public function testModelBindingWithCustomNullReturn()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->model('bar', 'RouteModelBindingNullStub', function () { return 'missing'; });
        $this->assertEquals('missing', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
    }

    public function testModelBindingWithBindingClosure()
    {
        $router = $this->getRouter();
        $router->get('foo/{bar}', function ($name) { return $name; });
        $router->model('bar', 'RouteModelBindingNullStub', function ($value) { return (new RouteModelBindingClosureStub())->findAlternate($value); });
        $this->assertEquals('tayloralt', $router->dispatch(Request::create('foo/TAYLOR', 'GET'))->getContent());
    }

    public function testGroupMerging()
    {
        $old = ['prefix' => 'foo/bar/'];
        $this->assertEquals(['prefix' => 'foo/bar/baz', 'namespace' => null, 'where' => []], Router::mergeGroup(['prefix' => 'baz'], $old));

        $old = ['domain' => 'foo'];
        $this->assertEquals(['domain' => 'baz', 'prefix' => null, 'namespace' => null, 'where' => []], Router::mergeGroup(['domain' => 'baz'], $old));

        $old = ['where' => ['var1' => 'foo', 'var2' => 'bar']];
        $this->assertEquals(['prefix' => null, 'namespace' => null, 'where' => [
            'var1' => 'foo', 'var2' => 'baz', 'var3' => 'qux',
        ]], Router::mergeGroup(['where' => ['var2' => 'baz', 'var3' => 'qux']], $old));

        $old = [];
        $this->assertEquals(['prefix' => null, 'namespace' => null, 'where' => [
            'var1' => 'foo', 'var2' => 'bar',
        ]], Router::mergeGroup(['where' => ['var1' => 'foo', 'var2' => 'bar']], $old));
    }

    public function testRouteGrouping()
    {
        /*
         * Inheriting Filters
         */
        $router = $this->getRouter();
        $router->group(['before' => 'foo'], function () use ($router) {
            $router->get('foo/bar', function () { return 'hello'; });
        });
        $router->filter('foo', function () { return 'foo!'; });
        $this->assertEquals('foo!', $router->dispatch(Request::create('foo/bar', 'GET'))->getContent());

        /*
         * Merging Filters
         */
        $router = $this->getRouter();
        $router->group(['before' => 'foo'], function () use ($router) {
            $router->get('foo/bar', ['before' => 'bar', function () { return 'hello'; }]);
        });
        $router->filter('foo', function () {});
        $router->filter('bar', function () { return 'foo!'; });
{'fraction_non_alphanumeric': 0.23959799357655803, 'fraction_numerical': 0.005449099635523799, 'mean_word_length': 3.3764213518635504, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 1033, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3610394', 'n_tokens_mistral': 16419, 'n_tokens_neox': 16176, 'n_words': 2642}