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