Skip to content

Commit

Permalink
Add broken unit tests for PHP8.0-PHP8.2 files and SelfValueTransformer
Browse files Browse the repository at this point in the history
  • Loading branch information
lisachenko committed Apr 14, 2024
1 parent 6bcf76b commit 452a023
Show file tree
Hide file tree
Showing 4 changed files with 386 additions and 24 deletions.
66 changes: 42 additions & 24 deletions tests/Go/Instrument/Transformer/SelfValueTransformerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use Go\Core\AspectContainer;
use Go\Core\AspectKernel;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -43,15 +44,7 @@ public function setUp(): void
*/
protected function getKernelMock(array $options): AspectKernel
{
$mock = $this->getMockForAbstractClass(
AspectKernel::class,
[],
'',
false,
true,
true,
['getOptions', 'getContainer']
);
$mock = $this->createMock(AspectKernel::class);
$mock
->method('getOptions')
->willReturn($options);
Expand All @@ -63,23 +56,48 @@ protected function getKernelMock(array $options): AspectKernel
return $mock;
}

public function testTransformerReplacesAllSelfPlaces(): void
{
$testFile = fopen(__DIR__ . '/_files/file-with-self.php', 'rb');
$content = stream_get_contents($testFile);
$metadata = new StreamMetaData($testFile, $content);
$this->transformer->transform($metadata);
$expected = file_get_contents(__DIR__ . '/_files/file-with-self-transformed.php');
$this->assertSame($expected, (string) $metadata->source);
#[DataProvider("filesDataProvider")]
public function testTransformerProcessFiles(
string $sourceFileWithContent,
string $fileWithExpectedContent,
): void {
try {
$sourceFile = fopen($sourceFileWithContent, 'rb');
$sourceContent = stream_get_contents($sourceFile);
$sourceMetadata = new StreamMetaData($sourceFile, $sourceContent);
$this->transformer->transform($sourceMetadata);

$expected = file_get_contents($fileWithExpectedContent);
$this->assertSame($expected, $sourceMetadata->source);

} finally {
if (isset($sourceFile) && is_resource($sourceFile)) {
fclose($sourceFile);
}
}
}

public function testTransformerReplacesAllSelfPlacesWithoutNamespace(): void
public static function filesDataProvider(): \Generator
{
$testFile = fopen(__DIR__ . '/_files/file-with-self-no-namespace.php', 'rb');
$content = stream_get_contents($testFile);
$metadata = new StreamMetaData($testFile, $content);
$this->transformer->transform($metadata);
$expected = file_get_contents(__DIR__ . '/_files/file-with-self-no-namespace-transformed.php');
$this->assertSame($expected, (string) $metadata->source);
yield 'file-with-self.php' => [
__DIR__ . '/_files/file-with-self.php',
__DIR__ . '/_files/file-with-self-transformed.php'
];
yield 'file-with-self-no-namespace.php' => [
__DIR__ . '/_files/file-with-self-no-namespace.php',
__DIR__ . '/_files/file-with-self-no-namespace-transformed.php'
];
yield 'php80-file.php' => [
__DIR__ . '/_files/php80-file.php',
__DIR__ . '/_files/php80-file-transformed.php'
];
yield 'php81-file.php' => [
__DIR__ . '/_files/php81-file.php',
__DIR__ . '/_files/php81-file-transformed.php'
];
yield 'php82-file.php' => [
__DIR__ . '/_files/php82-file.php',
__DIR__ . '/_files/php82-file-transformed.php'
];
}
}
131 changes: 131 additions & 0 deletions tests/Go/Instrument/Transformer/_files/php80-file.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php
/**
* Parser Reflection API
*
* @copyright Copyright 2016, Lisachenko Alexander <[email protected]>
*
* This source file is subject to the license that is bundled
* with this source code in the file LICENSE.
*/
declare(strict_types=1);

namespace Go\ParserReflection\Stub;

use Attribute;
use Go\ParserReflection\{ReflectionMethod, ReflectionProperty as P};

class ClassWithPhp80Features
{
public function acceptsStringArrayDefaultToNull(array|string $iterable = null) : array {}
}

/**
* @see https://php.watch/versions/8.0/named-parameters
*/
class ClassWithPHP80NamedCall
{
public static function foo(string $key1 = '', string $key2 = ''): string
{
return $key1 . ':' . $key2;
}

public static function namedCall(): array
{
return [
'key1' => self::foo(key1: 'bar'),
'key2' => self::foo(key2: 'baz'),
'keys' => self::foo(key1: 'A', key2: 'B'),
'reverseKeys' => self::foo(key2: 'A', key1: 'B'),
'unpack' => self::foo(...['key1' => 'C', 'key2' => 'D']),
];
}
}

/**
* @see https://php.watch/versions/8.0/attributes
*/
#[Attribute(Attribute::TARGET_ALL | Attribute::IS_REPEATABLE)]
readonly class ClassPHP80Attribute
{
private string $value;

public function __construct(string $value)
{
$this->value = $value;
}

public function getValue(): string
{
return $this->value;
}
}

/**
* @see https://php.watch/versions/8.0/attributes
*/
#[ClassPHP80Attribute('class')]
class ClassPHP80WithAttribute
{
#[ClassPHP80Attribute('first')]
#[ClassPHP80Attribute('second')]
public const PUBLIC_CONST = 1;

#[ClassPHP80Attribute('property')]
private string $privateProperty = 'foo';

#[ClassPHP80Attribute('method')]
public function bar(#[ClassPHP80Attribute('parameter')] $parameter)
{}
}

/**
* @see https://php.watch/versions/8.0/constructor-property-promotion
*/
class ClassPHP80WithPropertyPromotion
{
public function __construct(
private string $privateStringValue,
private $privateNonTypedValue,
protected int $protectedIntValue = 42,
public array $publicArrayValue = [M_PI, M_E],
) {}
}

/**
* @see https://php.watch/versions/8.0/union-types
*/
class ClassWithPHP80UnionTypes
{
public string|int|float|bool $scalarValue;

public array|object|null $complexValueOrNull = null;

/**
* Special case, internally iterable should be replaced with Traversable|array
*/
public iterable|object $iterableOrObject;

public static function returnsUnionType(): object|array|null {}

public static function acceptsUnionType(\stdClass|\Traversable|array $iterable): void {}
}

/**
* @see https://php.watch/versions/8.0/mixed-type
*/
class ClassWithPHP80MixedType
{
public mixed $someMixedPublicProperty;

public static function returnsMixed(): mixed {}

public static function acceptsMixed(mixed $value): void {}
}

/**
* @see https://php.watch/versions/8.0/static-return-type
*/
class ClassWithPHP80StaticReturnType
{
public static function create(): static {}
}
119 changes: 119 additions & 0 deletions tests/Go/Instrument/Transformer/_files/php81-file.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php
/**
* Parser Reflection API
*
* @copyright Copyright 2024, Lisachenko Alexander <[email protected]>
*
* This source file is subject to the license that is bundled
* with this source code in the file LICENSE.
*/
declare(strict_types=1);

namespace Go\ParserReflection\Stub;

/**
* @see https://php.watch/versions/8.1/readonly
*/
class ClassWithPhp81ReadOnlyProperties
{
public readonly int $publicReadonlyInt;

protected readonly array $protectedReadonlyArray;

private readonly object $privateReadonlyObject;
}

/**
* @see https://php.watch/versions/8.1/enums
*/
enum SimplePhp81EnumWithSuit {
case Clubs;
case Diamonds;
case Hearts;
case Spades;
}

/**
* @see https://php.watch/versions/8.1/enums#enums-backed
*/
enum BackedPhp81EnumHTTPMethods: string
{
case GET = 'get';
case POST = 'post';
}

/**
* @see https://php.watch/versions/8.1/enums#enum-methods
*/
enum BackedPhp81EnumHTTPStatusWithMethod: int
{
case OK = 200;
case ACCESS_DENIED = 403;
case NOT_FOUND = 404;

public function label(): string {
return static::getLabel($this);
}

public static function getLabel(self $value): string {
return match ($value) {
self::OK => 'OK',
self::ACCESS_DENIED => 'Access Denied',
self::NOT_FOUND => 'Page Not Found',
};
}
}

/**
* @see https://php.watch/versions/8.1/intersection-types
*/
class ClassWithPhp81IntersectionType implements \Countable
{
private \Iterator&\Countable $countableIterator;

public function __construct(\Iterator&\Countable $countableIterator)
{
$this->countableIterator = $countableIterator;
}

public function count(): int
{
return count($this->countableIterator);
}
}

/**
* @see https://php.watch/versions/8.1/intersection-types
*/
function functionWithPhp81IntersectionType(\Iterator&\Countable $value): \Iterator&\Countable {
foreach($value as $val) {}
count($value);

return $value;
}

/**
* @see https://php.watch/versions/8.1/never-return-type
*/
class ClassWithPhp81NeverReturnType
{
public static function doThis(): never
{
throw new \RuntimeException('Not implemented');
}
}

/**
* @see https://php.watch/versions/8.1/never-return-type
*/
function functionWithPhp81NeverReturnType(): never
{
throw new \RuntimeException('Not implemented');
}

/**
* @see https://php.watch/versions/8.1/final-class-const
*/
class ClassWithPhp81FinalClassConst {
final public const TEST = '1';
}
Loading

0 comments on commit 452a023

Please sign in to comment.