2812033bdf0688245a5be83541b73b0a43c3dcd8
[yaffs-website] / vendor / symfony / dependency-injection / Tests / Loader / YamlFileLoaderTest.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\Argument\IteratorArgument;
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\DependencyInjection\Loader\PhpFileLoader;
22 use Symfony\Component\Config\Loader\LoaderResolver;
23 use Symfony\Component\Config\FileLocator;
24 use Symfony\Component\Config\Resource\FileResource;
25 use Symfony\Component\Config\Resource\GlobResource;
26 use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar;
27 use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface;
28 use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
29 use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
30 use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
31 use Symfony\Component\ExpressionLanguage\Expression;
32
33 class YamlFileLoaderTest extends TestCase
34 {
35     protected static $fixturesPath;
36
37     public static function setUpBeforeClass()
38     {
39         self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
40         require_once self::$fixturesPath.'/includes/foo.php';
41         require_once self::$fixturesPath.'/includes/ProjectExtension.php';
42     }
43
44     /**
45      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
46      * @expectedExceptionMessageRegExp /The file ".+" does not exist./
47      */
48     public function testLoadUnExistFile()
49     {
50         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
51         $r = new \ReflectionObject($loader);
52         $m = $r->getMethod('loadFile');
53         $m->setAccessible(true);
54
55         $m->invoke($loader, 'foo.yml');
56     }
57
58     /**
59      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
60      * @expectedExceptionMessageRegExp /The file ".+" does not contain valid YAML./
61      */
62     public function testLoadInvalidYamlFile()
63     {
64         $path = self::$fixturesPath.'/ini';
65         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator($path));
66         $r = new \ReflectionObject($loader);
67         $m = $r->getMethod('loadFile');
68         $m->setAccessible(true);
69
70         $m->invoke($loader, $path.'/parameters.ini');
71     }
72
73     /**
74      * @dataProvider provideInvalidFiles
75      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
76      */
77     public function testLoadInvalidFile($file)
78     {
79         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
80
81         $loader->load($file.'.yml');
82     }
83
84     public function provideInvalidFiles()
85     {
86         return array(
87             array('bad_parameters'),
88             array('bad_imports'),
89             array('bad_import'),
90             array('bad_services'),
91             array('bad_service'),
92             array('bad_calls'),
93             array('bad_format'),
94             array('nonvalid1'),
95             array('nonvalid2'),
96         );
97     }
98
99     public function testLoadParameters()
100     {
101         $container = new ContainerBuilder();
102         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
103         $loader->load('services2.yml');
104         $this->assertEquals(array('foo' => 'bar', 'mixedcase' => array('MixedCaseKey' => 'value'), 'values' => array(true, false, 0, 1000.3, PHP_INT_MAX), 'bar' => 'foo', 'escape' => '@escapeme', 'foo_bar' => new Reference('foo_bar')), $container->getParameterBag()->all(), '->load() converts YAML keys to lowercase');
105     }
106
107     public function testLoadImports()
108     {
109         $container = new ContainerBuilder();
110         $resolver = new LoaderResolver(array(
111             new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/ini')),
112             new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
113             new PhpFileLoader($container, new FileLocator(self::$fixturesPath.'/php')),
114             $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
115         ));
116         $loader->setResolver($resolver);
117         $loader->load('services4.yml');
118
119         $actual = $container->getParameterBag()->all();
120         $expected = array(
121             'foo' => 'bar',
122             'values' => array(true, false, PHP_INT_MAX),
123             'bar' => '%foo%',
124             'escape' => '@escapeme',
125             'foo_bar' => new Reference('foo_bar'),
126             'mixedcase' => array('MixedCaseKey' => 'value'),
127             'imported_from_ini' => true,
128             'imported_from_xml' => true,
129             'with_wrong_ext' => 'from yaml',
130         );
131         $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');
132         $this->assertTrue($actual['imported_from_ini']);
133
134         // Bad import throws no exception due to ignore_errors value.
135         $loader->load('services4_bad_import.yml');
136     }
137
138     public function testLoadServices()
139     {
140         $container = new ContainerBuilder();
141         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
142         $loader->load('services6.yml');
143         $services = $container->getDefinitions();
144         $this->assertArrayHasKey('foo', $services, '->load() parses service elements');
145         $this->assertFalse($services['not_shared']->isShared(), '->load() parses the shared flag');
146         $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Definition', $services['foo'], '->load() converts service element to Definition instances');
147         $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute');
148         $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag');
149         $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags');
150         $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag');
151         $this->assertEquals(array(new Reference('baz'), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag');
152         $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag');
153         $this->assertEquals(array(array('setBar', 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');
154         $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
155         $this->assertEquals('factory', $services['new_factory1']->getFactory(), '->load() parses the factory tag');
156         $this->assertEquals(array(new Reference('baz'), 'getClass'), $services['new_factory2']->getFactory(), '->load() parses the factory tag');
157         $this->assertEquals(array('BazClass', 'getInstance'), $services['new_factory3']->getFactory(), '->load() parses the factory tag');
158         $this->assertSame(array(null, 'getInstance'), $services['new_factory4']->getFactory(), '->load() accepts factory tag without class');
159         $this->assertEquals(array('foo', new Reference('baz')), $services['Acme\WithShortCutArgs']->getArguments(), '->load() parses short service definition');
160
161         $aliases = $container->getAliases();
162         $this->assertArrayHasKey('alias_for_foo', $aliases, '->load() parses aliases');
163         $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
164         $this->assertTrue($aliases['alias_for_foo']->isPublic());
165         $this->assertArrayHasKey('another_alias_for_foo', $aliases);
166         $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
167         $this->assertFalse($aliases['another_alias_for_foo']->isPublic());
168         $this->assertTrue(isset($aliases['another_third_alias_for_foo']));
169         $this->assertEquals('foo', (string) $aliases['another_third_alias_for_foo']);
170         $this->assertTrue($aliases['another_third_alias_for_foo']->isPublic());
171
172         $this->assertEquals(array('decorated', null, 0), $services['decorator_service']->getDecoratedService());
173         $this->assertEquals(array('decorated', 'decorated.pif-pouf', 0), $services['decorator_service_with_name']->getDecoratedService());
174         $this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService());
175     }
176
177     public function testLoadFactoryShortSyntax()
178     {
179         $container = new ContainerBuilder();
180         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
181         $loader->load('services14.yml');
182         $services = $container->getDefinitions();
183
184         $this->assertEquals(array(new Reference('baz'), 'getClass'), $services['factory']->getFactory(), '->load() parses the factory tag with service:method');
185         $this->assertEquals(array('FooBacFactory', 'createFooBar'), $services['factory_with_static_call']->getFactory(), '->load() parses the factory tag with Class::method');
186     }
187
188     public function testLoadConfiguratorShortSyntax()
189     {
190         $container = new ContainerBuilder();
191         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
192         $loader->load('services_configurator_short_syntax.yml');
193         $services = $container->getDefinitions();
194
195         $this->assertEquals(array(new Reference('foo_bar_configurator'), 'configure'), $services['foo_bar']->getConfigurator(), '->load() parses the configurator tag with service:method');
196         $this->assertEquals(array('FooBarConfigurator', 'configureFooBar'), $services['foo_bar_with_static_call']->getConfigurator(), '->load() parses the configurator tag with Class::method');
197     }
198
199     public function testExtensions()
200     {
201         $container = new ContainerBuilder();
202         $container->registerExtension(new \ProjectExtension());
203         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
204         $loader->load('services10.yml');
205         $container->compile();
206         $services = $container->getDefinitions();
207         $parameters = $container->getParameterBag()->all();
208
209         $this->assertArrayHasKey('project.service.bar', $services, '->load() parses extension elements');
210         $this->assertArrayHasKey('project.parameter.bar', $parameters, '->load() parses extension elements');
211
212         $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
213         $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');
214
215         try {
216             $loader->load('services11.yml');
217             $this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
218         } catch (\Exception $e) {
219             $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
220             $this->assertStringStartsWith('There is no extension able to load the configuration for "foobarfoobar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
221         }
222     }
223
224     public function testExtensionWithNullConfig()
225     {
226         $container = new ContainerBuilder();
227         $container->registerExtension(new \ProjectExtension());
228         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
229         $loader->load('null_config.yml');
230         $container->compile();
231
232         $this->assertSame(array(null), $container->getParameter('project.configs'));
233     }
234
235     public function testSupports()
236     {
237         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator());
238
239         $this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable');
240         $this->assertTrue($loader->supports('foo.yaml'), '->supports() returns true if the resource is loadable');
241         $this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable');
242         $this->assertTrue($loader->supports('with_wrong_ext.xml', 'yml'), '->supports() returns true if the resource with forced type is loadable');
243         $this->assertTrue($loader->supports('with_wrong_ext.xml', 'yaml'), '->supports() returns true if the resource with forced type is loadable');
244     }
245
246     public function testNonArrayTagsThrowsException()
247     {
248         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
249         try {
250             $loader->load('badtag1.yml');
251             $this->fail('->load() should throw an exception when the tags key of a service is not an array');
252         } catch (\Exception $e) {
253             $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tags key is not an array');
254             $this->assertStringStartsWith('Parameter "tags" must be an array for service', $e->getMessage(), '->load() throws an InvalidArgumentException if the tags key is not an array');
255         }
256     }
257
258     public function testTagWithoutNameThrowsException()
259     {
260         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
261         try {
262             $loader->load('badtag2.yml');
263             $this->fail('->load() should throw an exception when a tag is missing the name key');
264         } catch (\Exception $e) {
265             $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag is missing the name key');
266             $this->assertStringStartsWith('A "tags" entry is missing a "name" key for service ', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag is missing the name key');
267         }
268     }
269
270     public function testNameOnlyTagsAreAllowedAsString()
271     {
272         $container = new ContainerBuilder();
273         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
274         $loader->load('tag_name_only.yml');
275
276         $this->assertCount(1, $container->getDefinition('foo_service')->getTag('foo'));
277     }
278
279     public function testTagWithAttributeArrayThrowsException()
280     {
281         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
282         try {
283             $loader->load('badtag3.yml');
284             $this->fail('->load() should throw an exception when a tag-attribute is not a scalar');
285         } catch (\Exception $e) {
286             $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar');
287             $this->assertStringStartsWith('A "tags" attribute must be of a scalar-type for service "foo_service", tag "foo", attribute "bar"', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar');
288         }
289     }
290
291     public function testLoadYamlOnlyWithKeys()
292     {
293         $container = new ContainerBuilder();
294         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
295         $loader->load('services21.yml');
296
297         $definition = $container->getDefinition('manager');
298         $this->assertEquals(array(array('setLogger', array(new Reference('logger'))), array('setClass', array('User'))), $definition->getMethodCalls());
299         $this->assertEquals(array(true), $definition->getArguments());
300         $this->assertEquals(array('manager' => array(array('alias' => 'user'))), $definition->getTags());
301     }
302
303     /**
304      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
305      * @expectedExceptionMessageRegExp /The tag name for service ".+" in .+ must be a non-empty string/
306      */
307     public function testTagWithEmptyNameThrowsException()
308     {
309         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
310         $loader->load('tag_name_empty_string.yml');
311     }
312
313     /**
314      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
315      * @expectedExceptionMessageREgExp /The tag name for service "\.+" must be a non-empty string/
316      */
317     public function testTagWithNonStringNameThrowsException()
318     {
319         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
320         $loader->load('tag_name_no_string.yml');
321     }
322
323     /**
324      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
325      */
326     public function testTypesNotArray()
327     {
328         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
329         $loader->load('bad_types1.yml');
330     }
331
332     /**
333      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
334      */
335     public function testTypeNotString()
336     {
337         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
338         $loader->load('bad_types2.yml');
339     }
340
341     /**
342      * @group legacy
343      */
344     public function testTypes()
345     {
346         $container = new ContainerBuilder();
347         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
348         $loader->load('services22.yml');
349
350         $this->assertEquals(array('Foo', 'Bar'), $container->getDefinition('foo_service')->getAutowiringTypes());
351         $this->assertEquals(array('Foo'), $container->getDefinition('baz_service')->getAutowiringTypes());
352     }
353
354     public function testParsesIteratorArgument()
355     {
356         $container = new ContainerBuilder();
357         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
358         $loader->load('services9.yml');
359
360         $lazyDefinition = $container->getDefinition('lazy_context');
361
362         $this->assertEquals(array(new IteratorArgument(array('k1' => new Reference('foo.baz'), 'k2' => new Reference('service_container'))), new IteratorArgument(array())), $lazyDefinition->getArguments(), '->load() parses lazy arguments');
363     }
364
365     public function testAutowire()
366     {
367         $container = new ContainerBuilder();
368         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
369         $loader->load('services23.yml');
370
371         $this->assertTrue($container->getDefinition('bar_service')->isAutowired());
372     }
373
374     public function testClassFromId()
375     {
376         $container = new ContainerBuilder();
377         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
378         $loader->load('class_from_id.yml');
379         $container->compile();
380
381         $this->assertEquals(CaseSensitiveClass::class, $container->getDefinition(CaseSensitiveClass::class)->getClass());
382     }
383
384     public function testPrototype()
385     {
386         $container = new ContainerBuilder();
387         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
388         $loader->load('services_prototype.yml');
389
390         $ids = array_keys($container->getDefinitions());
391         sort($ids);
392         $this->assertSame(array(Prototype\Foo::class, Prototype\Sub\Bar::class, 'service_container'), $ids);
393
394         $resources = $container->getResources();
395
396         $fixturesDir = dirname(__DIR__).DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR;
397         $this->assertTrue(false !== array_search(new FileResource($fixturesDir.'yaml'.DIRECTORY_SEPARATOR.'services_prototype.yml'), $resources));
398         $this->assertTrue(false !== array_search(new GlobResource($fixturesDir.'Prototype', '', true), $resources));
399         $resources = array_map('strval', $resources);
400         $this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo', $resources);
401         $this->assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar', $resources);
402     }
403
404     public function testPrototypeWithNamespace()
405     {
406         $container = new ContainerBuilder();
407         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
408         $loader->load('services_prototype_namespace.yml');
409
410         $ids = array_keys($container->getDefinitions());
411         sort($ids);
412
413         $this->assertSame(array(
414             Prototype\OtherDir\Component1\Dir1\Service1::class,
415             Prototype\OtherDir\Component1\Dir2\Service2::class,
416             Prototype\OtherDir\Component2\Dir1\Service4::class,
417             Prototype\OtherDir\Component2\Dir2\Service5::class,
418             'service_container',
419         ), $ids);
420
421         $this->assertTrue($container->getDefinition(Prototype\OtherDir\Component1\Dir1\Service1::class)->hasTag('foo'));
422         $this->assertTrue($container->getDefinition(Prototype\OtherDir\Component2\Dir1\Service4::class)->hasTag('foo'));
423         $this->assertFalse($container->getDefinition(Prototype\OtherDir\Component1\Dir1\Service1::class)->hasTag('bar'));
424         $this->assertFalse($container->getDefinition(Prototype\OtherDir\Component2\Dir1\Service4::class)->hasTag('bar'));
425
426         $this->assertTrue($container->getDefinition(Prototype\OtherDir\Component1\Dir2\Service2::class)->hasTag('bar'));
427         $this->assertTrue($container->getDefinition(Prototype\OtherDir\Component2\Dir2\Service5::class)->hasTag('bar'));
428         $this->assertFalse($container->getDefinition(Prototype\OtherDir\Component1\Dir2\Service2::class)->hasTag('foo'));
429         $this->assertFalse($container->getDefinition(Prototype\OtherDir\Component2\Dir2\Service5::class)->hasTag('foo'));
430     }
431
432     /**
433      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
434      * @expectedExceptionMessageRegExp /A "resource" attribute must be set when the "namespace" attribute is set for service ".+" in .+/
435      */
436     public function testPrototypeWithNamespaceAndNoResource()
437     {
438         $container = new ContainerBuilder();
439         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
440         $loader->load('services_prototype_namespace_without_resource.yml');
441     }
442
443     public function testDefaults()
444     {
445         $container = new ContainerBuilder();
446         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
447         $loader->load('services28.yml');
448
449         $this->assertFalse($container->getDefinition('with_defaults')->isPublic());
450         $this->assertSame(array('foo' => array(array())), $container->getDefinition('with_defaults')->getTags());
451         $this->assertTrue($container->getDefinition('with_defaults')->isAutowired());
452         $this->assertArrayNotHasKey('public', $container->getDefinition('with_defaults')->getChanges());
453         $this->assertArrayNotHasKey('autowire', $container->getDefinition('with_defaults')->getChanges());
454
455         $this->assertFalse($container->getAlias('with_defaults_aliased')->isPublic());
456         $this->assertFalse($container->getAlias('with_defaults_aliased_short')->isPublic());
457
458         $this->assertFalse($container->getDefinition('Acme\WithShortCutArgs')->isPublic());
459         $this->assertSame(array('foo' => array(array())), $container->getDefinition('Acme\WithShortCutArgs')->getTags());
460         $this->assertTrue($container->getDefinition('Acme\WithShortCutArgs')->isAutowired());
461
462         $container->compile();
463
464         $this->assertTrue($container->getDefinition('with_null')->isPublic());
465         $this->assertTrue($container->getDefinition('no_defaults')->isPublic());
466
467         // foo tag is inherited from defaults
468         $this->assertSame(array('foo' => array(array())), $container->getDefinition('with_null')->getTags());
469         $this->assertSame(array('foo' => array(array())), $container->getDefinition('no_defaults')->getTags());
470
471         $this->assertTrue($container->getDefinition('with_null')->isAutowired());
472         $this->assertFalse($container->getDefinition('no_defaults')->isAutowired());
473
474         $this->assertTrue($container->getDefinition('child_def')->isPublic());
475         $this->assertSame(array('foo' => array(array())), $container->getDefinition('child_def')->getTags());
476         $this->assertFalse($container->getDefinition('child_def')->isAutowired());
477     }
478
479     public function testNamedArguments()
480     {
481         $container = new ContainerBuilder();
482         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
483         $loader->load('services_named_args.yml');
484
485         $this->assertEquals(array(null, '$apiKey' => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
486         $this->assertEquals(array('$apiKey' => 'ABCD', CaseSensitiveClass::class => null), $container->getDefinition('another_one')->getArguments());
487
488         $container->compile();
489
490         $this->assertEquals(array(null, 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
491         $this->assertEquals(array(null, 'ABCD'), $container->getDefinition('another_one')->getArguments());
492         $this->assertEquals(array(array('setApiKey', array('123'))), $container->getDefinition('another_one')->getMethodCalls());
493     }
494
495     public function testInstanceof()
496     {
497         $container = new ContainerBuilder();
498         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
499         $loader->load('services_instanceof.yml');
500         $container->compile();
501
502         $definition = $container->getDefinition(Bar::class);
503         $this->assertTrue($definition->isAutowired());
504         $this->assertTrue($definition->isLazy());
505         $this->assertSame(array('foo' => array(array()), 'bar' => array(array())), $definition->getTags());
506     }
507
508     /**
509      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
510      * @expectedExceptionMessage The service "child_service" cannot use the "parent" option in the same file where "_instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.
511      */
512     public function testInstanceOfAndChildDefinitionNotAllowed()
513     {
514         $container = new ContainerBuilder();
515         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
516         $loader->load('services_instanceof_with_parent.yml');
517         $container->compile();
518     }
519
520     /**
521      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
522      * @expectedExceptionMessage The service "child_service" cannot have a "parent" and also have "autoconfigure". Try setting "autoconfigure: false" for the service.
523      */
524     public function testAutoConfigureAndChildDefinitionNotAllowed()
525     {
526         $container = new ContainerBuilder();
527         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
528         $loader->load('services_autoconfigure_with_parent.yml');
529         $container->compile();
530     }
531
532     /**
533      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
534      * @expectedExceptionMessage Attribute "autowire" on service "child_service" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.
535      */
536     public function testDefaultsAndChildDefinitionNotAllowed()
537     {
538         $container = new ContainerBuilder();
539         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
540         $loader->load('services_defaults_with_parent.yml');
541         $container->compile();
542     }
543
544     /**
545      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
546      * @expectedExceptionMessage The value of the "decorates" option for the "bar" service must be the id of the service without the "@" prefix (replace "@foo" with "foo").
547      */
548     public function testDecoratedServicesWithWrongSyntaxThrowsException()
549     {
550         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
551         $loader->load('bad_decorates.yml');
552     }
553
554     /**
555      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
556      * @expectedExceptionMessageRegExp /Parameter "tags" must be an array for service "Foo\\Bar" in .+services31_invalid_tags\.yml\. Check your YAML syntax./
557      */
558     public function testInvalidTagsWithDefaults()
559     {
560         $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
561         $loader->load('services31_invalid_tags.yml');
562     }
563
564     /**
565      * @group legacy
566      * @expectedDeprecation Service names that start with an underscore are deprecated since Symfony 3.3 and will be reserved in 4.0. Rename the "_foo" service or define it in XML instead.
567      */
568     public function testUnderscoreServiceId()
569     {
570         $container = new ContainerBuilder();
571         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
572         $loader->load('services_underscore.yml');
573     }
574
575     public function testAnonymousServices()
576     {
577         $container = new ContainerBuilder();
578         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
579         $loader->load('anonymous_services.yml');
580
581         $definition = $container->getDefinition('Foo');
582         $this->assertTrue($definition->isAutowired());
583
584         // Anonymous service in an argument
585         $args = $definition->getArguments();
586         $this->assertCount(1, $args);
587         $this->assertInstanceOf(Reference::class, $args[0]);
588         $this->assertTrue($container->has((string) $args[0]));
589         $this->assertRegExp('/^\d+_Bar[._A-Za-z0-9]{7}$/', (string) $args[0]);
590
591         $anonymous = $container->getDefinition((string) $args[0]);
592         $this->assertEquals('Bar', $anonymous->getClass());
593         $this->assertFalse($anonymous->isPublic());
594         $this->assertTrue($anonymous->isAutowired());
595
596         // Anonymous service in a callable
597         $factory = $definition->getFactory();
598         $this->assertInternalType('array', $factory);
599         $this->assertInstanceOf(Reference::class, $factory[0]);
600         $this->assertTrue($container->has((string) $factory[0]));
601         $this->assertRegExp('/^\d+_Quz[._A-Za-z0-9]{7}$/', (string) $factory[0]);
602         $this->assertEquals('constructFoo', $factory[1]);
603
604         $anonymous = $container->getDefinition((string) $factory[0]);
605         $this->assertEquals('Quz', $anonymous->getClass());
606         $this->assertFalse($anonymous->isPublic());
607         $this->assertFalse($anonymous->isAutowired());
608     }
609
610     public function testAnonymousServicesInDifferentFilesWithSameNameDoNotConflict()
611     {
612         $container = new ContainerBuilder();
613
614         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml/foo'));
615         $loader->load('services.yml');
616
617         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml/bar'));
618         $loader->load('services.yml');
619
620         $this->assertCount(5, $container->getDefinitions());
621     }
622
623     public function testAnonymousServicesInInstanceof()
624     {
625         $container = new ContainerBuilder();
626         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
627         $loader->load('anonymous_services_in_instanceof.yml');
628
629         $definition = $container->getDefinition('Dummy');
630
631         $instanceof = $definition->getInstanceofConditionals();
632         $this->assertCount(3, $instanceof);
633         $this->assertArrayHasKey('DummyInterface', $instanceof);
634
635         $args = $instanceof['DummyInterface']->getProperties();
636         $this->assertCount(1, $args);
637         $this->assertInstanceOf(Reference::class, $args['foo']);
638         $this->assertTrue($container->has((string) $args['foo']));
639
640         $anonymous = $container->getDefinition((string) $args['foo']);
641         $this->assertEquals('Anonymous', $anonymous->getClass());
642         $this->assertFalse($anonymous->isPublic());
643         $this->assertEmpty($anonymous->getInstanceofConditionals());
644
645         $this->assertFalse($container->has('Bar'));
646     }
647
648     /**
649      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
650      * @expectedExceptionMessageRegExp /Creating an alias using the tag "!service" is not allowed in ".+anonymous_services_alias\.yml"\./
651      */
652     public function testAnonymousServicesWithAliases()
653     {
654         $container = new ContainerBuilder();
655         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
656         $loader->load('anonymous_services_alias.yml');
657     }
658
659     /**
660      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
661      * @expectedExceptionMessageRegExp /Using an anonymous service in a parameter is not allowed in ".+anonymous_services_in_parameters\.yml"\./
662      */
663     public function testAnonymousServicesInParameters()
664     {
665         $container = new ContainerBuilder();
666         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
667         $loader->load('anonymous_services_in_parameters.yml');
668     }
669
670     public function testAutoConfigureInstanceof()
671     {
672         $container = new ContainerBuilder();
673         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
674         $loader->load('services_autoconfigure.yml');
675
676         $this->assertTrue($container->getDefinition('use_defaults_settings')->isAutoconfigured());
677         $this->assertFalse($container->getDefinition('override_defaults_settings_to_false')->isAutoconfigured());
678     }
679
680     /**
681      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
682      * @expectedExceptionMessageRegExp /Service "_defaults" key must be an array, "NULL" given in ".+bad_empty_defaults\.yml"\./
683      */
684     public function testEmptyDefaultsThrowsClearException()
685     {
686         $container = new ContainerBuilder();
687         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
688         $loader->load('bad_empty_defaults.yml');
689     }
690
691     /**
692      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
693      * @expectedExceptionMessageRegExp /Service "_instanceof" key must be an array, "NULL" given in ".+bad_empty_instanceof\.yml"\./
694      */
695     public function testEmptyInstanceofThrowsClearException()
696     {
697         $container = new ContainerBuilder();
698         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
699         $loader->load('bad_empty_instanceof.yml');
700     }
701
702     public function testBindings()
703     {
704         $container = new ContainerBuilder();
705         $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
706         $loader->load('services_bindings.yml');
707         $container->compile();
708
709         $definition = $container->getDefinition('bar');
710         $this->assertEquals(array(
711             'NonExistent' => null,
712             BarInterface::class => new Reference(Bar::class),
713             '$foo' => array(null),
714             '$quz' => 'quz',
715             '$factory' => 'factory',
716         ), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings()));
717         $this->assertEquals(array(
718             'quz',
719             null,
720             new Reference(Bar::class),
721             array(null),
722         ), $definition->getArguments());
723
724         $definition = $container->getDefinition(Bar::class);
725         $this->assertEquals(array(
726             null,
727             'factory',
728         ), $definition->getArguments());
729         $this->assertEquals(array(
730             'NonExistent' => null,
731             '$quz' => 'quz',
732             '$factory' => 'factory',
733         ), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings()));
734     }
735 }