--- /dev/null
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\ServiceLocator;
+use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
+
+class ServiceLocatorTest extends TestCase
+{
+ public function testHas()
+ {
+ $locator = new ServiceLocator(array(
+ 'foo' => function () { return 'bar'; },
+ 'bar' => function () { return 'baz'; },
+ function () { return 'dummy'; },
+ ));
+
+ $this->assertTrue($locator->has('foo'));
+ $this->assertTrue($locator->has('bar'));
+ $this->assertFalse($locator->has('dummy'));
+ }
+
+ public function testGet()
+ {
+ $locator = new ServiceLocator(array(
+ 'foo' => function () { return 'bar'; },
+ 'bar' => function () { return 'baz'; },
+ ));
+
+ $this->assertSame('bar', $locator->get('foo'));
+ $this->assertSame('baz', $locator->get('bar'));
+ }
+
+ public function testGetDoesNotMemoize()
+ {
+ $i = 0;
+ $locator = new ServiceLocator(array(
+ 'foo' => function () use (&$i) {
+ ++$i;
+
+ return 'bar';
+ },
+ ));
+
+ $this->assertSame('bar', $locator->get('foo'));
+ $this->assertSame('bar', $locator->get('foo'));
+ $this->assertSame(2, $i);
+ }
+
+ /**
+ * @expectedException \Psr\Container\NotFoundExceptionInterface
+ * @expectedExceptionMessage Service "dummy" not found: the container inside "Symfony\Component\DependencyInjection\Tests\ServiceLocatorTest" is a smaller service locator that only knows about the "foo" and "bar" services.
+ */
+ public function testGetThrowsOnUndefinedService()
+ {
+ $locator = new ServiceLocator(array(
+ 'foo' => function () { return 'bar'; },
+ 'bar' => function () { return 'baz'; },
+ ));
+
+ $locator->get('dummy');
+ }
+
+ /**
+ * @expectedException \Psr\Container\NotFoundExceptionInterface
+ * @expectedExceptionMessage The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.
+ */
+ public function testThrowsOnUndefinedInternalService()
+ {
+ $locator = new ServiceLocator(array(
+ 'foo' => function () use (&$locator) { return $locator->get('bar'); },
+ ));
+
+ $locator->get('foo');
+ }
+
+ /**
+ * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
+ * @expectedExceptionMessage Circular reference detected for service "bar", path: "bar -> baz -> bar".
+ */
+ public function testThrowsOnCircularReference()
+ {
+ $locator = new ServiceLocator(array(
+ 'foo' => function () use (&$locator) { return $locator->get('bar'); },
+ 'bar' => function () use (&$locator) { return $locator->get('baz'); },
+ 'baz' => function () use (&$locator) { return $locator->get('bar'); },
+ ));
+
+ $locator->get('foo');
+ }
+
+ /**
+ * @expectedException \Psr\Container\NotFoundExceptionInterface
+ * @expectedExceptionMessage Service "foo" not found: even though it exists in the app's container, the container inside "caller" is a smaller service locator that only knows about the "bar" service. Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "SomeServiceSubscriber::getSubscribedServices()".
+ */
+ public function testThrowsInServiceSubscriber()
+ {
+ $container = new Container();
+ $container->set('foo', new \stdClass());
+ $subscriber = new SomeServiceSubscriber();
+ $subscriber->container = new ServiceLocator(array('bar' => function () {}));
+ $subscriber->container = $subscriber->container->withContext('caller', $container);
+
+ $subscriber->getFoo();
+ }
+
+ public function testInvoke()
+ {
+ $locator = new ServiceLocator(array(
+ 'foo' => function () { return 'bar'; },
+ 'bar' => function () { return 'baz'; },
+ ));
+
+ $this->assertSame('bar', $locator('foo'));
+ $this->assertSame('baz', $locator('bar'));
+ $this->assertNull($locator('dummy'), '->__invoke() should return null on invalid service');
+ }
+}
+
+class SomeServiceSubscriber implements ServiceSubscriberinterface
+{
+ public $container;
+
+ public function getFoo()
+ {
+ return $this->container->get('foo');
+ }
+
+ public static function getSubscribedServices()
+ {
+ return array('bar' => 'stdClass');
+ }
+}