Version 1
[yaffs-website] / vendor / symfony / routing / Tests / RouteCompilerTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Routing\Tests;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Routing\Route;
16 use Symfony\Component\Routing\RouteCompiler;
17
18 class RouteCompilerTest extends TestCase
19 {
20     /**
21      * @dataProvider provideCompileData
22      */
23     public function testCompile($name, $arguments, $prefix, $regex, $variables, $tokens)
24     {
25         $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route');
26         $route = $r->newInstanceArgs($arguments);
27
28         $compiled = $route->compile();
29         $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)');
30         $this->assertEquals($regex, $compiled->getRegex(), $name.' (regex)');
31         $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)');
32         $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)');
33     }
34
35     public function provideCompileData()
36     {
37         return array(
38             array(
39                 'Static route',
40                 array('/foo'),
41                 '/foo', '#^/foo$#s', array(), array(
42                     array('text', '/foo'),
43                 ),
44             ),
45
46             array(
47                 'Route with a variable',
48                 array('/foo/{bar}'),
49                 '/foo', '#^/foo/(?P<bar>[^/]++)$#s', array('bar'), array(
50                     array('variable', '/', '[^/]++', 'bar'),
51                     array('text', '/foo'),
52                 ),
53             ),
54
55             array(
56                 'Route with a variable that has a default value',
57                 array('/foo/{bar}', array('bar' => 'bar')),
58                 '/foo', '#^/foo(?:/(?P<bar>[^/]++))?$#s', array('bar'), array(
59                     array('variable', '/', '[^/]++', 'bar'),
60                     array('text', '/foo'),
61                 ),
62             ),
63
64             array(
65                 'Route with several variables',
66                 array('/foo/{bar}/{foobar}'),
67                 '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array(
68                     array('variable', '/', '[^/]++', 'foobar'),
69                     array('variable', '/', '[^/]++', 'bar'),
70                     array('text', '/foo'),
71                 ),
72             ),
73
74             array(
75                 'Route with several variables that have default values',
76                 array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')),
77                 '/foo', '#^/foo(?:/(?P<bar>[^/]++)(?:/(?P<foobar>[^/]++))?)?$#s', array('bar', 'foobar'), array(
78                     array('variable', '/', '[^/]++', 'foobar'),
79                     array('variable', '/', '[^/]++', 'bar'),
80                     array('text', '/foo'),
81                 ),
82             ),
83
84             array(
85                 'Route with several variables but some of them have no default values',
86                 array('/foo/{bar}/{foobar}', array('bar' => 'bar')),
87                 '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array(
88                     array('variable', '/', '[^/]++', 'foobar'),
89                     array('variable', '/', '[^/]++', 'bar'),
90                     array('text', '/foo'),
91                 ),
92             ),
93
94             array(
95                 'Route with an optional variable as the first segment',
96                 array('/{bar}', array('bar' => 'bar')),
97                 '', '#^/(?P<bar>[^/]++)?$#s', array('bar'), array(
98                     array('variable', '/', '[^/]++', 'bar'),
99                 ),
100             ),
101
102             array(
103                 'Route with a requirement of 0',
104                 array('/{bar}', array('bar' => null), array('bar' => '0')),
105                 '', '#^/(?P<bar>0)?$#s', array('bar'), array(
106                     array('variable', '/', '0', 'bar'),
107                 ),
108             ),
109
110             array(
111                 'Route with an optional variable as the first segment with requirements',
112                 array('/{bar}', array('bar' => 'bar'), array('bar' => '(foo|bar)')),
113                 '', '#^/(?P<bar>(foo|bar))?$#s', array('bar'), array(
114                     array('variable', '/', '(foo|bar)', 'bar'),
115                 ),
116             ),
117
118             array(
119                 'Route with only optional variables',
120                 array('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar')),
121                 '', '#^/(?P<foo>[^/]++)?(?:/(?P<bar>[^/]++))?$#s', array('foo', 'bar'), array(
122                     array('variable', '/', '[^/]++', 'bar'),
123                     array('variable', '/', '[^/]++', 'foo'),
124                 ),
125             ),
126
127             array(
128                 'Route with a variable in last position',
129                 array('/foo-{bar}'),
130                 '/foo', '#^/foo\-(?P<bar>[^/]++)$#s', array('bar'), array(
131                     array('variable', '-', '[^/]++', 'bar'),
132                     array('text', '/foo'),
133                 ),
134             ),
135
136             array(
137                 'Route with nested placeholders',
138                 array('/{static{var}static}'),
139                 '/{static', '#^/\{static(?P<var>[^/]+)static\}$#s', array('var'), array(
140                     array('text', 'static}'),
141                     array('variable', '', '[^/]+', 'var'),
142                     array('text', '/{static'),
143                 ),
144             ),
145
146             array(
147                 'Route without separator between variables',
148                 array('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '(y|Y)')),
149                 '', '#^/(?P<w>[^/\.]+)(?P<x>[^/\.]+)(?P<y>(y|Y))(?:(?P<z>[^/\.]++)(?:\.(?P<_format>[^/]++))?)?$#s', array('w', 'x', 'y', 'z', '_format'), array(
150                     array('variable', '.', '[^/]++', '_format'),
151                     array('variable', '', '[^/\.]++', 'z'),
152                     array('variable', '', '(y|Y)', 'y'),
153                     array('variable', '', '[^/\.]+', 'x'),
154                     array('variable', '/', '[^/\.]+', 'w'),
155                 ),
156             ),
157
158             array(
159                 'Route with a format',
160                 array('/foo/{bar}.{_format}'),
161                 '/foo', '#^/foo/(?P<bar>[^/\.]++)\.(?P<_format>[^/]++)$#s', array('bar', '_format'), array(
162                     array('variable', '.', '[^/]++', '_format'),
163                     array('variable', '/', '[^/\.]++', 'bar'),
164                     array('text', '/foo'),
165                 ),
166             ),
167         );
168     }
169
170     /**
171      * @expectedException \LogicException
172      */
173     public function testRouteWithSameVariableTwice()
174     {
175         $route = new Route('/{name}/{name}');
176
177         $compiled = $route->compile();
178     }
179
180     /**
181      * @dataProvider getVariableNamesStartingWithADigit
182      * @expectedException \DomainException
183      */
184     public function testRouteWithVariableNameStartingWithADigit($name)
185     {
186         $route = new Route('/{'.$name.'}');
187         $route->compile();
188     }
189
190     public function getVariableNamesStartingWithADigit()
191     {
192         return array(
193            array('09'),
194            array('123'),
195            array('1e2'),
196         );
197     }
198
199     /**
200      * @dataProvider provideCompileWithHostData
201      */
202     public function testCompileWithHost($name, $arguments, $prefix, $regex, $variables, $pathVariables, $tokens, $hostRegex, $hostVariables, $hostTokens)
203     {
204         $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route');
205         $route = $r->newInstanceArgs($arguments);
206
207         $compiled = $route->compile();
208         $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)');
209         $this->assertEquals($regex, str_replace(array("\n", ' '), '', $compiled->getRegex()), $name.' (regex)');
210         $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)');
211         $this->assertEquals($pathVariables, $compiled->getPathVariables(), $name.' (path variables)');
212         $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)');
213         $this->assertEquals($hostRegex, str_replace(array("\n", ' '), '', $compiled->getHostRegex()), $name.' (host regex)');
214         $this->assertEquals($hostVariables, $compiled->getHostVariables(), $name.' (host variables)');
215         $this->assertEquals($hostTokens, $compiled->getHostTokens(), $name.' (host tokens)');
216     }
217
218     public function provideCompileWithHostData()
219     {
220         return array(
221             array(
222                 'Route with host pattern',
223                 array('/hello', array(), array(), array(), 'www.example.com'),
224                 '/hello', '#^/hello$#s', array(), array(), array(
225                     array('text', '/hello'),
226                 ),
227                 '#^www\.example\.com$#si', array(), array(
228                     array('text', 'www.example.com'),
229                 ),
230             ),
231             array(
232                 'Route with host pattern and some variables',
233                 array('/hello/{name}', array(), array(), array(), 'www.example.{tld}'),
234                 '/hello', '#^/hello/(?P<name>[^/]++)$#s', array('tld', 'name'), array('name'), array(
235                     array('variable', '/', '[^/]++', 'name'),
236                     array('text', '/hello'),
237                 ),
238                 '#^www\.example\.(?P<tld>[^\.]++)$#si', array('tld'), array(
239                     array('variable', '.', '[^\.]++', 'tld'),
240                     array('text', 'www.example'),
241                 ),
242             ),
243             array(
244                 'Route with variable at beginning of host',
245                 array('/hello', array(), array(), array(), '{locale}.example.{tld}'),
246                 '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
247                     array('text', '/hello'),
248                 ),
249                 '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array(
250                     array('variable', '.', '[^\.]++', 'tld'),
251                     array('text', '.example'),
252                     array('variable', '', '[^\.]++', 'locale'),
253                 ),
254             ),
255             array(
256                 'Route with host variables that has a default value',
257                 array('/hello', array('locale' => 'a', 'tld' => 'b'), array(), array(), '{locale}.example.{tld}'),
258                 '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array(
259                     array('text', '/hello'),
260                 ),
261                 '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array(
262                     array('variable', '.', '[^\.]++', 'tld'),
263                     array('text', '.example'),
264                     array('variable', '', '[^\.]++', 'locale'),
265                 ),
266             ),
267         );
268     }
269
270     /**
271      * @expectedException \DomainException
272      */
273     public function testRouteWithTooLongVariableName()
274     {
275         $route = new Route(sprintf('/{%s}', str_repeat('a', RouteCompiler::VARIABLE_MAXIMUM_LENGTH + 1)));
276         $route->compile();
277     }
278 }