Valinor/tests/Functional/Definition/Repository/Cache/Compiler/ClassDefinitionCompilerTest.php
Romain Canon 2d70efbfbb feat: extract file watching feature in own cache implementation
When the application runs in a development environment, the cache
implementation should be decorated with `FileWatchingCache` to prevent
invalid cache entries states, which can result in the library not
behaving as expected (missing property value, callable with outdated
signature, …).

```php
$cache = new \CuyZ\Valinor\Cache\FileSystemCache('path/to/cache-dir');

if ($isApplicationInDevelopmentEnvironment) {
    $cache = new \CuyZ\Valinor\Cache\FileWatchingCache($cache);
}

(new \CuyZ\Valinor\MapperBuilder())
    ->withCache($cache)
    ->mapper()
    ->map(SomeClass::class, [/* … */]);
```

This behavior now forces to explicitly inject `FileWatchingCache`, when
it was done automatically before; but because it shouldn't be used in
a production environment, it will increase overall performance.
2022-05-23 20:28:02 +02:00

114 lines
3.7 KiB
PHP

<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Tests\Functional\Definition\Repository\Cache\Compiler;
use CuyZ\Valinor\Definition\ClassDefinition;
use CuyZ\Valinor\Definition\Repository\Cache\Compiler\ClassDefinitionCompiler;
use CuyZ\Valinor\Tests\Fake\Definition\FakeClassDefinition;
use CuyZ\Valinor\Tests\Fixture\Object\ObjectWithParameterDefaultObjectValue;
use CuyZ\Valinor\Type\Types\NativeStringType;
use Error;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use function get_class;
use function implode;
final class ClassDefinitionCompilerTest extends TestCase
{
private ClassDefinitionCompiler $compiler;
protected function setUp(): void
{
parent::setUp();
$this->compiler = new ClassDefinitionCompiler();
}
public function test_class_definition_is_compiled_correctly(): void
{
$object =
new class () {
public string $property = 'Some property default value';
public static function method(string $parameter = 'Some parameter default value', string ...$variadic): string
{
return $parameter . implode(' / ', $variadic);
}
};
$class = FakeClassDefinition::fromReflection(new ReflectionClass($object));
$className = get_class($object);
$class = $this->eval($this->compiler->compile($class));
self::assertInstanceOf(ClassDefinition::class, $class);
self::assertSame($className, $class->name());
self::assertSame($className, $class->type()->className());
$properties = $class->properties();
self::assertTrue($properties->has('property'));
$property = $properties->get('property');
self::assertSame('property', $property->name());
self::assertSame('Signature::property', $property->signature());
self::assertSame(NativeStringType::get(), $property->type());
self::assertTrue($property->hasDefaultValue());
self::assertSame('Some property default value', $property->defaultValue());
self::assertTrue($property->isPublic());
$method = $class->methods()->get('method');
self::assertSame('method', $method->name());
self::assertSame('Signature::method', $method->signature());
self::assertTrue($method->isStatic());
self::assertTrue($method->isPublic());
self::assertSame(NativeStringType::get(), $method->returnType());
$parameter = $method->parameters()->get('parameter');
self::assertSame('parameter', $parameter->name());
self::assertSame('Signature::parameter', $parameter->signature());
self::assertSame(NativeStringType::get(), $parameter->type());
self::assertTrue($parameter->isOptional());
self::assertFalse($parameter->isVariadic());
self::assertSame('Some parameter default value', $parameter->defaultValue());
$variadic = $method->parameters()->get('variadic');
self::assertTrue($variadic->isVariadic());
}
/**
* @PHP8.1 move to test above
*
* @requires PHP >= 8.1
*/
public function test_parameter_with_object_default_value_is_compiled_correctly(): void
{
$class = FakeClassDefinition::fromReflection(new ReflectionClass(ObjectWithParameterDefaultObjectValue::class));
$class = $this->eval($this->compiler->compile($class));
self::assertInstanceOf(ClassDefinition::class, $class);
self::assertSame(ObjectWithParameterDefaultObjectValue::class, $class->name());
}
/**
* @return mixed
*/
private function eval(string $code)
{
try {
return eval("return $code;");
} catch (Error $exception) {
self::fail($exception->getMessage());
}
}
}