You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nextcloud-server/tests/lib/AppFramework/Utility/SimpleContainerTest.php

260 lines
7.4 KiB

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Test\AppFramework\Utility;
use OC\AppFramework\Utility\SimpleContainer;
use OCP\AppFramework\QueryException;
use Psr\Container\NotFoundExceptionInterface;
interface TestInterface {
}
class ClassEmptyConstructor implements IInterfaceConstructor {
}
class ClassSimpleConstructor implements IInterfaceConstructor {
public function __construct(
public $test,
) {
}
}
class ClassComplexConstructor {
public function __construct(
public ClassSimpleConstructor $class,
public $test,
) {
}
}
class ClassNullableUntypedConstructorArg {
public function __construct(
public $class,
) {
}
}
class ClassNullableTypedConstructorArg {
public function __construct(
public ?\Some\Class $class,
) {
}
}
interface IInterfaceConstructor {
}
class ClassInterfaceConstructor {
public function __construct(
public IInterfaceConstructor $class,
public $test,
) {
}
}
class SimpleContainerTest extends \Test\TestCase {
private $container;
protected function setUp(): void {
$this->container = new SimpleContainer();
}
public function testRegister(): void {
$this->container->registerParameter('test', 'abc');
$this->assertEquals('abc', $this->container->query('test'));
}
/**
* Test querying a class that is not registered without autoload enabled
*/
public function testNothingRegistered(): void {
try {
$this->container->query('something really hard', false);
$this->fail('Expected `QueryException` exception was not thrown');
} catch (\Throwable $exception) {
$this->assertInstanceOf(QueryException::class, $exception);
$this->assertInstanceOf(NotFoundExceptionInterface::class, $exception);
}
}
/**
* Test querying a class that is not registered with autoload enabled
*/
public function testNothingRegistered_autoload(): void {
try {
$this->container->query('something really hard');
$this->fail('Expected `QueryException` exception was not thrown');
} catch (\Throwable $exception) {
$this->assertInstanceOf(QueryException::class, $exception);
$this->assertInstanceOf(NotFoundExceptionInterface::class, $exception);
}
}
public function testNotAClass(): void {
$this->expectException(QueryException::class);
$this->container->query('Test\AppFramework\Utility\TestInterface');
}
public function testNoConstructorClass(): void {
$object = $this->container->query('Test\AppFramework\Utility\ClassEmptyConstructor');
$this->assertTrue($object instanceof ClassEmptyConstructor);
}
public function testInstancesOnlyOnce(): void {
$object = $this->container->query('Test\AppFramework\Utility\ClassEmptyConstructor');
$object2 = $this->container->query('Test\AppFramework\Utility\ClassEmptyConstructor');
$this->assertSame($object, $object2);
}
public function testConstructorSimple(): void {
$this->container->registerParameter('test', 'abc');
$object = $this->container->query(
'Test\AppFramework\Utility\ClassSimpleConstructor'
);
$this->assertTrue($object instanceof ClassSimpleConstructor);
$this->assertEquals('abc', $object->test);
}
public function testConstructorComplex(): void {
$this->container->registerParameter('test', 'abc');
$object = $this->container->query(
'Test\AppFramework\Utility\ClassComplexConstructor'
);
$this->assertTrue($object instanceof ClassComplexConstructor);
$this->assertEquals('abc', $object->class->test);
$this->assertEquals('abc', $object->test);
}
public function testConstructorComplexInterface(): void {
$this->container->registerParameter('test', 'abc');
$this->container->registerService(
'Test\AppFramework\Utility\IInterfaceConstructor', function ($c) {
return $c->query('Test\AppFramework\Utility\ClassSimpleConstructor');
});
$object = $this->container->query(
'Test\AppFramework\Utility\ClassInterfaceConstructor'
);
$this->assertTrue($object instanceof ClassInterfaceConstructor);
$this->assertEquals('abc', $object->class->test);
$this->assertEquals('abc', $object->test);
}
public function testOverrideService(): void {
$this->container->registerService(
'Test\AppFramework\Utility\IInterfaceConstructor', function ($c) {
return $c->query('Test\AppFramework\Utility\ClassSimpleConstructor');
});
$this->container->registerService(
'Test\AppFramework\Utility\IInterfaceConstructor', function ($c) {
return $c->query('Test\AppFramework\Utility\ClassEmptyConstructor');
});
$object = $this->container->query(
'Test\AppFramework\Utility\IInterfaceConstructor'
);
$this->assertTrue($object instanceof ClassEmptyConstructor);
}
public function testRegisterAliasParamter(): void {
$this->container->registerParameter('test', 'abc');
$this->container->registerAlias('test1', 'test');
$this->assertEquals('abc', $this->container->query('test1'));
}
public function testRegisterAliasService(): void {
$this->container->registerService('test', function () {
return new \StdClass;
}, true);
$this->container->registerAlias('test1', 'test');
$this->assertSame(
$this->container->query('test'), $this->container->query('test'));
$this->assertSame(
$this->container->query('test1'), $this->container->query('test1'));
$this->assertSame(
$this->container->query('test'), $this->container->query('test1'));
}
public static function sanitizeNameProvider(): array {
return [
['ABC\\Foo', 'ABC\\Foo'],
['\\ABC\\Foo', '\\ABC\\Foo'],
['\\ABC\\Foo', 'ABC\\Foo'],
['ABC\\Foo', '\\ABC\\Foo'],
];
}
#[\PHPUnit\Framework\Attributes\DataProvider('sanitizeNameProvider')]
public function testSanitizeName($register, $query): void {
$this->container->registerService($register, function () {
return 'abc';
});
$this->assertEquals('abc', $this->container->query($query));
}
public function testConstructorComplexNoTestParameterFound(): void {
$this->expectException(QueryException::class);
$object = $this->container->query(
'Test\AppFramework\Utility\ClassComplexConstructor'
);
/* Use the object to trigger DI on PHP >= 8.4 */
get_object_vars($object);
}
public function testRegisterFactory(): void {
$this->container->registerService('test', function () {
return new \StdClass();
}, false);
$this->assertNotSame(
$this->container->query('test'), $this->container->query('test'));
}
public function testRegisterAliasFactory(): void {
$this->container->registerService('test', function () {
return new \StdClass();
}, false);
$this->container->registerAlias('test1', 'test');
$this->assertNotSame(
$this->container->query('test'), $this->container->query('test'));
$this->assertNotSame(
$this->container->query('test1'), $this->container->query('test1'));
$this->assertNotSame(
$this->container->query('test'), $this->container->query('test1'));
}
public function testQueryUntypedNullable(): void {
$this->expectException(QueryException::class);
$object = $this->container->query(
ClassNullableUntypedConstructorArg::class
);
/* Use the object to trigger DI on PHP >= 8.4 */
get_object_vars($object);
}
public function testQueryTypedNullable(): void {
/** @var ClassNullableTypedConstructorArg $service */
$service = $this->container->query(ClassNullableTypedConstructorArg::class);
self::assertNull($service->class);
}
}