<commit_before><?php

namespace DoctrineTest\InstantiatorTest;

use ArrayObject;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Doctrine\Instantiator\Instantiator;
use Doctrine\Instantiator\InstantiatorInterface;
use DoctrineTest\InstantiatorTestAsset\AbstractClassAsset;
use DoctrineTest\InstantiatorTestAsset\ArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\ExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\FinalExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\PharExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\SerializableArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\SerializableFinalInternalChildAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleEnumAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleSerializableAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleTraitAsset;
use DoctrineTest\InstantiatorTestAsset\UnCloneableAsset;
use DoctrineTest\InstantiatorTestAsset\UnserializeExceptionArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\WakeUpNoticesAsset;
use DoctrineTest\InstantiatorTestAsset\XMLReaderAsset;
use Exception;
use Generator;
use PDORow;
use PharException;
use PHPUnit\Framework\TestCase;
use stdClass;

use function str_replace;
use function uniqid;

use const PHP_VERSION_ID;

/**
 * Tests for {@see \Doctrine\Instantiator\Instantiator}
 *
 * @covers \Doctrine\Instantiator\Instantiator
 */
class InstantiatorTest extends TestCase
{
    /** @var Instantiator */
    private $instantiator;

    protected function setUp(): void
    {
        parent::setUp();

        $this->instantiator = new Instantiator();
    }

    /**
     * @phpstan-param class-string $className
     *
     * @dataProvider getInstantiableClasses
     */
    public function testCanInstantiate(string $className): void
    {
        self::assertInstanceOf($className, $this->instantiator->instantiate($className));
    }

    /**
     * @phpstan-param class-string $className
     *
     * @dataProvider getInstantiableClasses
     */
    public function testInstantiatesSeparateInstances(string $className): void
    {
        $instance1 = $this->instantiator->instantiate($className);
        $instance2 = $this->instantiator->instantiate($className);

        self::assertEquals($instance1, $instance2);
        self::assertNotSame($instance1, $instance2);
    }

    public function testExceptionOnUnSerializationException(): void
    {
        $this->expectException(UnexpectedValueException::class);

        $this->instantiator->instantiate(PDORow::class);
    }

    /**
     * @phpstan-param class-string $invalidClassName
     *
     * @dataProvider getInvalidClassNames
     */
    public function testInstantiationFromNonExistingClass(string $invalidClassName): void
    {
        $this->expectException(InvalidArgumentException::class);

        $this->instantiator->instantiate($invalidClassName);
    }

    public function testInstancesAreNotCloned(): void
    {
        $className = 'TemporaryClass' . str_replace('.', '', uniqid('', true));

        eval('namespace ' . __NAMESPACE__ . '; class ' . $className . '{}');

        /**
         * @phpstan-var class-string
         */
        $classNameWithNamespace = __NAMESPACE__ . '\\' . $className;

        $instance = $this->instantiator->instantiate($classNameWithNamespace);

        $instance->foo = 'bar';

        $instance2 = $this->instantiator->instantiate($classNameWithNamespace);

        self::assertObjectNotHasAttribute('foo', $instance2);
    }

    /**
     * Provides a list of instantiable classes (existing)
     *
     * @return string[][]<commit_msg>Fix tests on PHP 8.2 (#91)<commit_after><?php

namespace DoctrineTest\InstantiatorTest;

use ArrayObject;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Doctrine\Instantiator\Instantiator;
use Doctrine\Instantiator\InstantiatorInterface;
use DoctrineTest\InstantiatorTestAsset\AbstractClassAsset;
use DoctrineTest\InstantiatorTestAsset\ArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\ExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\FinalExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\PharExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\SerializableArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\SerializableFinalInternalChildAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleEnumAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleSerializableAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleTraitAsset;
use DoctrineTest\InstantiatorTestAsset\UnCloneableAsset;
use DoctrineTest\InstantiatorTestAsset\UnserializeExceptionArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\WakeUpNoticesAsset;
use DoctrineTest\InstantiatorTestAsset\XMLReaderAsset;
use Exception;
use Generator;
use PDORow;
use PharException;
use PHPUnit\Framework\TestCase;
use stdClass;

use function str_replace;
use function uniqid;

use const PHP_VERSION_ID;

/**
 * Tests for {@see \Doctrine\Instantiator\Instantiator}
 *
 * @covers \Doctrine\Instantiator\Instantiator
 */
class InstantiatorTest extends TestCase
{
    /** @var Instantiator */
    private $instantiator;

    protected function setUp(): void
    {
        parent::setUp();

        $this->instantiator = new Instantiator();
    }

    /**
     * @phpstan-param class-string $className
     *
     * @dataProvider getInstantiableClasses
     */
    public function testCanInstantiate(string $className): void
    {
        self::assertInstanceOf($className, $this->instantiator->instantiate($className));
    }

    /**
     * @phpstan-param class-string $className
     *
     * @dataProvider getInstantiableClasses
     */
    public function testInstantiatesSeparateInstances(string $className): void
    {
        $instance1 = $this->instantiator->instantiate($className);
        $instance2 = $this->instantiator->instantiate($className);

        self::assertEquals($instance1, $instance2);
        self::assertNotSame($instance1, $instance2);
    }

    public function testExceptionOnUnSerializationException(): void
    {
        $this->expectException(UnexpectedValueException::class);

        $this->instantiator->instantiate(PDORow::class);
    }

    /**
     * @phpstan-param class-string $invalidClassName
     *
     * @dataProvider getInvalidClassNames
     */
    public function testInstantiationFromNonExistingClass(string $invalidClassName): void
    {
        $this->expectException(InvalidArgumentException::class);

        $this->instantiator->instantiate($invalidClassName);
    }

    public function testInstancesAreNotCloned(): void
    {
        $namespace = __NAMESPACE__;
        $className = 'TemporaryClass' . str_replace('.', '', uniqid('', true));

        eval(<<< PHP
namespace $namespace;
#[\AllowDynamicProperties]
class $className {}
PHP
        );

        /**
         * @phpstan-var class-string
         */
        $classNameWithNamespace = $namespace . '\\' . $className;

        $instance = $this->instantiator->instantiate($classNameWithNamespace);

        $instance->foo = 'bar';

        $instance2 = $this->instantiator->instantiate($classNameWithNamespace);

        self::assertObjectNotHasAttribute('foo', $instance2);
    }

    /**
     * Provides a list of instantiable classes (existing)
     *
     * @return string[][]
{'fraction_non_alphanumeric': 0.10342041475895503, 'fraction_numerical': 0.00269323996768112, 'mean_word_length': 4.286120996441281, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3224132', 'n_tokens_mistral': 2161, 'n_tokens_neox': 2033, 'n_words': 344}