Yaffs site version 1.1
[yaffs-website] / vendor / symfony / dependency-injection / Tests / Loader / XmlFileLoaderTest.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\DependencyInjection\Tests\Loader;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\DependencyInjection\ContainerInterface;
16 use Symfony\Component\DependencyInjection\ContainerBuilder;
17 use Symfony\Component\DependencyInjection\Reference;
18 use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
19 use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
20 use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
21 use Symfony\Component\Config\Loader\LoaderResolver;
22 use Symfony\Component\Config\FileLocator;
23 use Symfony\Component\ExpressionLanguage\Expression;
24
25 class XmlFileLoaderTest extends TestCase
26 {
27     protected static $fixturesPath;
28
29     public static function setUpBeforeClass()
30     {
31         self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
32         require_once self::$fixturesPath.'/includes/foo.php';
33         require_once self::$fixturesPath.'/includes/ProjectExtension.php';
34         require_once self::$fixturesPath.'/includes/ProjectWithXsdExtension.php';
35     }
36
37     public function testLoad()
38     {
39         $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
40
41         try {
42             $loader->load('foo.xml');
43             $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist');
44         } catch (\Exception $e) {
45             $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist');
46             $this->assertStringStartsWith('The file "foo.xml" does not exist (in:', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist');
47         }
48     }
49
50     public function testParseFile()
51     {
52         $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
53         $r = new \ReflectionObject($loader);
54         $m = $r->getMethod('parseFileToDOM');
55         $m->setAccessible(true);
56
57         try {
58             $m->invoke($loader, self::$fixturesPath.'/ini/parameters.ini');
59             $this->fail('->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
60         } catch (\Exception $e) {
61             $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
62             $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'parameters.ini'), $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
63
64             $e = $e->getPrevious();
65             $this->assertInstanceOf('InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
66             $this->assertStringStartsWith('[ERROR 4] Start tag expected, \'<\' not found (in', $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
67         }
68
69         $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/xml'));
70
71         try {
72             $m->invoke($loader, self::$fixturesPath.'/xml/nonvalid.xml');
73             $this->fail('->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
74         } catch (\Exception $e) {
75             $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
76             $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'nonvalid.xml'), $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file is not a valid XML file');
77
78             $e = $e->getPrevious();
79             $this->assertInstanceOf('InvalidArgumentException', $e, '->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
80             $this->assertStringStartsWith('[ERROR 1845] Element \'nonvalid\': No matching global declaration available for the validation root. (in', $e->getMessage(), '->parseFileToDOM() throws an InvalidArgumentException if the loaded file does not validate the XSD');
81         }
82
83         $xml = $m->invoke($loader, self::$fixturesPath.'/xml/services1.xml');
84         $this->assertInstanceOf('DOMDocument', $xml, '->parseFileToDOM() returns an SimpleXMLElement object');
85     }
86
87     public function testLoadWithExternalEntitiesDisabled()
88     {
89         $disableEntities = libxml_disable_entity_loader(true);
90
91         $containerBuilder = new ContainerBuilder();
92         $loader = new XmlFileLoader($containerBuilder, new FileLocator(self::$fixturesPath.'/xml'));
93         $loader->load('services2.xml');
94
95         libxml_disable_entity_loader($disableEntities);
96
97         $this->assertTrue(count($containerBuilder->getParameterBag()->all()) > 0, 'Parameters can be read from the config file.');
98     }
99
100     public function testLoadParameters()
101     {
102         $container = new ContainerBuilder();
103         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
104         $loader->load('services2.xml');
105
106         $actual = $container->getParameterBag()->all();
107         $expected = array(
108             'a string',
109             'foo' => 'bar',
110             'values' => array(
111                 0,
112                 'integer' => 4,
113                 100 => null,
114                 'true',
115                 true,
116                 false,
117                 'on',
118                 'off',
119                 'float' => 1.3,
120                 1000.3,
121                 'a string',
122                 array('foo', 'bar'),
123             ),
124             'mixedcase' => array('MixedCaseKey' => 'value'),
125             'constant' => PHP_EOL,
126         );
127
128         $this->assertEquals($expected, $actual, '->load() converts XML values to PHP ones');
129     }
130
131     public function testLoadImports()
132     {
133         $container = new ContainerBuilder();
134         $resolver = new LoaderResolver(array(
135             new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')),
136             new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yml')),
137             $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
138         ));
139         $loader->setResolver($resolver);
140         $loader->load('services4.xml');
141
142         $actual = $container->getParameterBag()->all();
143         $expected = array(
144             'a string',
145             'foo' => 'bar',
146             'values' => array(
147                 0,
148                 'integer' => 4,
149                 100 => null,
150                 'true',
151                 true,
152                 false,
153                 'on',
154                 'off',
155                 'float' => 1.3,
156                 1000.3,
157                 'a string',
158                 array('foo', 'bar'),
159             ),
160             'mixedcase' => array('MixedCaseKey' => 'value'),
161             'constant' => PHP_EOL,
162             'bar' => '%foo%',
163             'imported_from_ini' => true,
164             'imported_from_yaml' => true,
165         );
166
167         $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');
168
169         // Bad import throws no exception due to ignore_errors value.
170         $loader->load('services4_bad_import.xml');
171     }
172
173     public function testLoadAnonymousServices()
174     {
175         $container = new ContainerBuilder();
176         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
177         $loader->load('services5.xml');
178         $services = $container->getDefinitions();
179         $this->assertCount(6, $services, '->load() attributes unique ids to anonymous services');
180
181         // anonymous service as an argument
182         $args = $services['foo']->getArguments();
183         $this->assertCount(1, $args, '->load() references anonymous services as "normal" ones');
184         $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $args[0], '->load() converts anonymous services to references to "normal" services');
185         $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones');
186         $inner = $services[(string) $args[0]];
187         $this->assertEquals('BarClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');
188         $this->assertFalse($inner->isPublic());
189
190         // inner anonymous services
191         $args = $inner->getArguments();
192         $this->assertCount(1, $args, '->load() references anonymous services as "normal" ones');
193         $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $args[0], '->load() converts anonymous services to references to "normal" services');
194         $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones');
195         $inner = $services[(string) $args[0]];
196         $this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');
197         $this->assertFalse($inner->isPublic());
198
199         // anonymous service as a property
200         $properties = $services['foo']->getProperties();
201         $property = $properties['p'];
202         $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Reference', $property, '->load() converts anonymous services to references to "normal" services');
203         $this->assertTrue(isset($services[(string) $property]), '->load() makes a reference to the created ones');
204         $inner = $services[(string) $property];
205         $this->assertEquals('BuzClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');
206         $this->assertFalse($inner->isPublic());
207
208         // "wild" service
209         $service = $container->findTaggedServiceIds('biz_tag');
210         $this->assertCount(1, $service);
211
212         foreach ($service as $id => $tag) {
213             $service = $container->getDefinition($id);
214         }
215         $this->assertEquals('BizClass', $service->getClass(), '->load() uses the same configuration as for the anonymous ones');
216         $this->assertTrue($service->isPublic());
217
218         // anonymous services are shared when using decoration definitions
219         $container->compile();
220         $services = $container->getDefinitions();
221         $fooArgs = $services['foo']->getArguments();
222         $barArgs = $services['bar']->getArguments();
223         $this->assertSame($fooArgs[0], $barArgs[0]);
224     }
225
226     /**
227      * @group legacy
228      */
229     public function testLegacyLoadServices()
230     {
231         $container = new ContainerBuilder();
232         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
233         $loader->load('legacy-services6.xml');
234         $services = $container->getDefinitions();
235         $this->assertEquals('FooClass', $services['constructor']->getClass());
236         $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod());
237         $this->assertNull($services['factory_service']->getClass());
238         $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService());
239         $this->assertEquals('getInstance', $services['factory_service']->getFactoryMethod());
240         $this->assertEquals('container', $services['scope.container']->getScope());
241         $this->assertEquals('custom', $services['scope.custom']->getScope());
242         $this->assertEquals('prototype', $services['scope.prototype']->getScope());
243         $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
244         $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
245         $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag');
246         $this->assertNull($services['request']->getDecoratedService());
247     }
248
249     public function testLoadServices()
250     {
251         $container = new ContainerBuilder();
252         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
253         $loader->load('services6.xml');
254         $services = $container->getDefinitions();
255         $this->assertTrue(isset($services['foo']), '->load() parses <service> elements');
256         $this->assertFalse($services['not_shared']->isShared(), '->load() parses shared flag');
257         $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Definition', $services['foo'], '->load() converts <service> element to Definition instances');
258         $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute');
259         $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag');
260         $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags');
261         $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag');
262         $this->assertEquals(array(new Reference('baz', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag');
263         $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag');
264         $this->assertEquals(array(array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag');
265         $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
266         $this->assertEquals('factory', $services['new_factory1']->getFactory(), '->load() parses the factory tag');
267         $this->assertEquals(array(new Reference('baz', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false), 'getClass'), $services['new_factory2']->getFactory(), '->load() parses the factory tag');
268         $this->assertEquals(array('BazClass', 'getInstance'), $services['new_factory3']->getFactory(), '->load() parses the factory tag');
269
270         $aliases = $container->getAliases();
271         $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses <service> elements');
272         $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
273         $this->assertTrue($aliases['alias_for_foo']->isPublic());
274         $this->assertTrue(isset($aliases['another_alias_for_foo']));
275         $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
276         $this->assertFalse($aliases['another_alias_for_foo']->isPublic());
277
278         $this->assertEquals(array('decorated', null, 0), $services['decorator_service']->getDecoratedService());
279         $this->assertEquals(array('decorated', 'decorated.pif-pouf', 0), $services['decorator_service_with_name']->getDecoratedService());
280         $this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService());
281     }
282
283     public function testParsesTags()
284     {
285         $container = new ContainerBuilder();
286         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
287         $loader->load('services10.xml');
288
289         $services = $container->findTaggedServiceIds('foo_tag');
290         $this->assertCount(1, $services);
291
292         foreach ($services as $id => $tagAttributes) {
293             foreach ($tagAttributes as $attributes) {
294                 $this->assertArrayHasKey('other_option', $attributes);
295                 $this->assertEquals('lorem', $attributes['other_option']);
296                 $this->assertArrayHasKey('other-option', $attributes, 'unnormalized tag attributes should not be removed');
297
298                 $this->assertEquals('ciz', $attributes['some_option'], 'no overriding should be done when normalizing');
299                 $this->assertEquals('cat', $attributes['some-option']);
300
301                 $this->assertArrayNotHasKey('an_other_option', $attributes, 'normalization should not be done when an underscore is already found');
302             }
303         }
304     }
305
306     /**
307      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
308      */
309     public function testParseTagsWithoutNameThrowsException()
310     {
311         $container = new ContainerBuilder();
312         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
313         $loader->load('tag_without_name.xml');
314     }
315
316     /**
317      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
318      * @expectedExceptionMessageRegExp /The tag name for service ".+" in .* must be a non-empty string/
319      */
320     public function testParseTagWithEmptyNameThrowsException()
321     {
322         $container = new ContainerBuilder();
323         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
324         $loader->load('tag_with_empty_name.xml');
325     }
326
327     public function testDeprecated()
328     {
329         $container = new ContainerBuilder();
330         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
331         $loader->load('services_deprecated.xml');
332
333         $this->assertTrue($container->getDefinition('foo')->isDeprecated());
334         $message = 'The "foo" service is deprecated. You should stop using it, as it will soon be removed.';
335         $this->assertSame($message, $container->getDefinition('foo')->getDeprecationMessage('foo'));
336
337         $this->assertTrue($container->getDefinition('bar')->isDeprecated());
338         $message = 'The "bar" service is deprecated.';
339         $this->assertSame($message, $container->getDefinition('bar')->getDeprecationMessage('bar'));
340     }
341
342     public function testConvertDomElementToArray()
343     {
344         $doc = new \DOMDocument('1.0');
345         $doc->loadXML('<foo>bar</foo>');
346         $this->assertEquals('bar', XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
347
348         $doc = new \DOMDocument('1.0');
349         $doc->loadXML('<foo foo="bar" />');
350         $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
351
352         $doc = new \DOMDocument('1.0');
353         $doc->loadXML('<foo><foo>bar</foo></foo>');
354         $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
355
356         $doc = new \DOMDocument('1.0');
357         $doc->loadXML('<foo><foo>bar<foo>bar</foo></foo></foo>');
358         $this->assertEquals(array('foo' => array('value' => 'bar', 'foo' => 'bar')), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
359
360         $doc = new \DOMDocument('1.0');
361         $doc->loadXML('<foo><foo></foo></foo>');
362         $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
363
364         $doc = new \DOMDocument('1.0');
365         $doc->loadXML('<foo><foo><!-- foo --></foo></foo>');
366         $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
367
368         $doc = new \DOMDocument('1.0');
369         $doc->loadXML('<foo><foo foo="bar"/><foo foo="bar"/></foo>');
370         $this->assertEquals(array('foo' => array(array('foo' => 'bar'), array('foo' => 'bar'))), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
371     }
372
373     public function testExtensions()
374     {
375         $container = new ContainerBuilder();
376         $container->registerExtension(new \ProjectExtension());
377         $container->registerExtension(new \ProjectWithXsdExtension());
378         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
379
380         // extension without an XSD
381         $loader->load('extensions/services1.xml');
382         $container->compile();
383         $services = $container->getDefinitions();
384         $parameters = $container->getParameterBag()->all();
385
386         $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
387         $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');
388
389         $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
390         $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');
391
392         // extension with an XSD
393         $container = new ContainerBuilder();
394         $container->registerExtension(new \ProjectExtension());
395         $container->registerExtension(new \ProjectWithXsdExtension());
396         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
397         $loader->load('extensions/services2.xml');
398         $container->compile();
399         $services = $container->getDefinitions();
400         $parameters = $container->getParameterBag()->all();
401
402         $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
403         $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');
404
405         $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
406         $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');
407
408         $container = new ContainerBuilder();
409         $container->registerExtension(new \ProjectExtension());
410         $container->registerExtension(new \ProjectWithXsdExtension());
411         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
412
413         // extension with an XSD (does not validate)
414         try {
415             $loader->load('extensions/services3.xml');
416             $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
417         } catch (\Exception $e) {
418             $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
419             $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services3.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
420
421             $e = $e->getPrevious();
422             $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
423             $this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
424         }
425
426         // non-registered extension
427         try {
428             $loader->load('extensions/services4.xml');
429             $this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
430         } catch (\Exception $e) {
431             $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
432             $this->assertStringStartsWith('There is no extension able to load the configuration for "project:bar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
433         }
434     }
435
436     public function testExtensionInPhar()
437     {
438         if (extension_loaded('suhosin') && false === strpos(ini_get('suhosin.executor.include.whitelist'), 'phar')) {
439             $this->markTestSkipped('To run this test, add "phar" to the "suhosin.executor.include.whitelist" settings in your php.ini file.');
440         }
441
442         require_once self::$fixturesPath.'/includes/ProjectWithXsdExtensionInPhar.phar';
443
444         // extension with an XSD in PHAR archive
445         $container = new ContainerBuilder();
446         $container->registerExtension(new \ProjectWithXsdExtensionInPhar());
447         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
448         $loader->load('extensions/services6.xml');
449
450         // extension with an XSD in PHAR archive (does not validate)
451         try {
452             $loader->load('extensions/services7.xml');
453             $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
454         } catch (\Exception $e) {
455             $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
456             $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services7.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
457
458             $e = $e->getPrevious();
459             $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
460             $this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
461         }
462     }
463
464     public function testSupports()
465     {
466         $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator());
467
468         $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable');
469         $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
470     }
471
472     public function testNoNamingConflictsForAnonymousServices()
473     {
474         $container = new ContainerBuilder();
475
476         $loader1 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension1'));
477         $loader1->load('services.xml');
478         $services = $container->getDefinitions();
479         $this->assertCount(2, $services, '->load() attributes unique ids to anonymous services');
480         $loader2 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension2'));
481         $loader2->load('services.xml');
482         $services = $container->getDefinitions();
483         $this->assertCount(4, $services, '->load() attributes unique ids to anonymous services');
484
485         $services = $container->getDefinitions();
486         $args1 = $services['extension1.foo']->getArguments();
487         $inner1 = $services[(string) $args1[0]];
488         $this->assertEquals('BarClass1', $inner1->getClass(), '->load() uses the same configuration as for the anonymous ones');
489         $args2 = $services['extension2.foo']->getArguments();
490         $inner2 = $services[(string) $args2[0]];
491         $this->assertEquals('BarClass2', $inner2->getClass(), '->load() uses the same configuration as for the anonymous ones');
492     }
493
494     public function testDocTypeIsNotAllowed()
495     {
496         $container = new ContainerBuilder();
497
498         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
499
500         // document types are not allowed.
501         try {
502             $loader->load('withdoctype.xml');
503             $this->fail('->load() throws an InvalidArgumentException if the configuration contains a document type');
504         } catch (\Exception $e) {
505             $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
506             $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'withdoctype.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');
507
508             $e = $e->getPrevious();
509             $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
510             $this->assertSame('Document types are not allowed.', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');
511         }
512     }
513
514     public function testXmlNamespaces()
515     {
516         $container = new ContainerBuilder();
517         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
518         $loader->load('namespaces.xml');
519         $services = $container->getDefinitions();
520
521         $this->assertTrue(isset($services['foo']), '->load() parses <srv:service> elements');
522         $this->assertEquals(1, count($services['foo']->getTag('foo.tag')), '->load parses <srv:tag> elements');
523         $this->assertEquals(array(array('setBar', array('foo'))), $services['foo']->getMethodCalls(), '->load() parses the <srv:call> tag');
524     }
525
526     public function testLoadIndexedArguments()
527     {
528         $container = new ContainerBuilder();
529         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
530         $loader->load('services14.xml');
531
532         $this->assertEquals(array('index_0' => 'app'), $container->findDefinition('logger')->getArguments());
533     }
534
535     public function testLoadInlinedServices()
536     {
537         $container = new ContainerBuilder();
538         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
539         $loader->load('services21.xml');
540
541         $foo = $container->getDefinition('foo');
542
543         $fooFactory = $foo->getFactory();
544         $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $fooFactory[0]);
545         $this->assertSame('FooFactory', $fooFactory[0]->getClass());
546         $this->assertSame('createFoo', $fooFactory[1]);
547
548         $fooFactoryFactory = $fooFactory[0]->getFactory();
549         $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $fooFactoryFactory[0]);
550         $this->assertSame('Foobar', $fooFactoryFactory[0]->getClass());
551         $this->assertSame('createFooFactory', $fooFactoryFactory[1]);
552
553         $fooConfigurator = $foo->getConfigurator();
554         $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $fooConfigurator[0]);
555         $this->assertSame('Bar', $fooConfigurator[0]->getClass());
556         $this->assertSame('configureFoo', $fooConfigurator[1]);
557
558         $barConfigurator = $fooConfigurator[0]->getConfigurator();
559         $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $barConfigurator[0]);
560         $this->assertSame('Baz', $barConfigurator[0]->getClass());
561         $this->assertSame('configureBar', $barConfigurator[1]);
562     }
563
564     public function testType()
565     {
566         $container = new ContainerBuilder();
567         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
568         $loader->load('services22.xml');
569
570         $this->assertEquals(array('Bar', 'Baz'), $container->getDefinition('foo')->getAutowiringTypes());
571     }
572
573     public function testAutowire()
574     {
575         $container = new ContainerBuilder();
576         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
577         $loader->load('services23.xml');
578
579         $this->assertTrue($container->getDefinition('bar')->isAutowired());
580     }
581
582     public function testArgumentWithKeyOutsideCollection()
583     {
584         $container = new ContainerBuilder();
585         $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
586         $loader->load('with_key_outside_collection.xml');
587
588         $this->assertSame(array('type' => 'foo', 'bar'), $container->getDefinition('foo')->getArguments());
589     }
590 }