<commit_before><?php

declare(strict_types=1);

namespace GraphQL\Tests\Executor;

use GraphQL\Error\InvariantViolation;
use GraphQL\Error\Warning;
use GraphQL\Executor\ExecutionResult;
use GraphQL\Executor\Executor;
use GraphQL\Language\Parser;
use GraphQL\Tests\Executor\TestClasses\Cat;
use GraphQL\Tests\Executor\TestClasses\Dog;
use GraphQL\Type\Definition\CustomScalarType;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Schema;
use PHPUnit\Framework\Error\Error;
use PHPUnit\Framework\TestCase;
use function count;

class ExecutorLazySchemaTest extends TestCase
{
    /** @var ScalarType */
    public $someScalarType;

    /** @var ObjectType */
    public $someObjectType;

    /** @var ObjectType */
    public $otherObjectType;

    /** @var ObjectType */
    public $deeperObjectType;

    /** @var UnionType */
    public $someUnionType;

    /** @var InterfaceType */
    public $someInterfaceType;

    /** @var EnumType */
    public $someEnumType;

    /** @var InputObjectType */
    public $someInputObjectType;

    /** @var ObjectType */
    public $queryType;

    /** @var string[] */
    public $calls = [];

    /** @var bool[] */
    public $loadedTypes = [];

    public function testWarnsAboutSlowIsTypeOfForLazySchema() : void
    {
        // isTypeOf used to resolve runtime type for Interface
        $petType = new InterfaceType([
            'name'   => 'Pet',
            'fields' => static function () {
                return [
                    'name' => ['type' => Type::string()],
                ];
            },
        ]);

        // Added to interface type when defined
        $dogType = new ObjectType([
            'name'       => 'Dog',
            'interfaces' => [$petType],
            'isTypeOf'   => static function ($obj) {
                return $obj instanceof Dog;
            },
            'fields'     => static function () {
                return [
                    'name'  => ['type' => Type::string()],
                    'woofs' => ['type' => Type::boolean()],
                ];
            },
        ]);

        $catType = new ObjectType([
            'name'       => 'Cat',
            'interfaces' => [$petType],
            'isTypeOf'   => static function ($obj) {
                return $obj instanceof Cat;
            },
            'fields'     => static function () {
                return [
                    'name'  => ['type' => Type::string()],
                    'meows' => ['type' => Type::boolean()],
                ];
            },
        ]);

        $schema = new Schema([
            'query'      => new ObjectType([
                'name'   => 'Query',
                'fields' => [
                    'pets' => [
                        'type'    => Type::listOf($petType),
                        'resolve' => static function () {
                            return [new Dog('Odie', true), new Cat('Garfield', false)];
                        },
                    ],
                ],
            ]),
            'types'      => [$catType, $dogType],
            'typeLoader' => static function ($name) use ($dogType, $petType, $catType) {
                switch ($name) {
                    case 'Dog':
                        return $dogType;
                    case 'Pet':
                        return $petType;
                    case 'Cat':
                        return $catType;
                }
            },
        ]);

        $query = '{
          pets {
            name
            ... on Dog {
              woofs
            }
            ... on Cat {
              meows
            }
          }
        }';

        $expected = new ExecutionResult([
            'pets' => [
                ['name' => 'Odie', 'woofs' => true],
                ['name' => 'Garfield', 'meows' => false],
            ],
        ]);

        Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
        $result = Executor::execute($schema, Parser::parse($query));
        self::assertEquals($expected, $result);

        Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
        $result = Executor::execute($schema, Parser::parse($query));
        self::assertEquals(1, count($result->errors));
        self::assertInstanceOf(Error::class, $result->errors[0]->getPrevious());

        self::assertEquals(
            'GraphQL Interface Type `Pet` returned `null` from it`s `resolveType` function for value: instance of ' .
            'GraphQL\Tests\Executor\TestClasses\Dog. Switching to slow resolution method using `isTypeOf` of all possible ' .
            'implementations. It requires full schema scan and degrades query performance significantly.  ' .
            'Make sure your `resolveType` always returns valid implementation or throws.',
            $result->errors[0]->getMessage()
        );
    }

    public function testHintsOnConflictingTypeInstancesInDefinitions() : void
    {
        $calls      = [];
        $typeLoader = static function ($name) use (&$calls) {
            $calls[] = $name;
            switch ($name) {
                case 'Test':
                    return new ObjectType([
                        'name'   => 'Test',
                        'fields' => static function () {
                            return [
                                'test' => Type::string(),
                            ];
                        },
                    ]);
                default:<commit_msg>Fixing test for possessive/contraction "its" change<commit_after><?php

declare(strict_types=1);

namespace GraphQL\Tests\Executor;

use GraphQL\Error\InvariantViolation;
use GraphQL\Error\Warning;
use GraphQL\Executor\ExecutionResult;
use GraphQL\Executor\Executor;
use GraphQL\Language\Parser;
use GraphQL\Tests\Executor\TestClasses\Cat;
use GraphQL\Tests\Executor\TestClasses\Dog;
use GraphQL\Type\Definition\CustomScalarType;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Schema;
use PHPUnit\Framework\Error\Error;
use PHPUnit\Framework\TestCase;
use function count;

class ExecutorLazySchemaTest extends TestCase
{
    /** @var ScalarType */
    public $someScalarType;

    /** @var ObjectType */
    public $someObjectType;

    /** @var ObjectType */
    public $otherObjectType;

    /** @var ObjectType */
    public $deeperObjectType;

    /** @var UnionType */
    public $someUnionType;

    /** @var InterfaceType */
    public $someInterfaceType;

    /** @var EnumType */
    public $someEnumType;

    /** @var InputObjectType */
    public $someInputObjectType;

    /** @var ObjectType */
    public $queryType;

    /** @var string[] */
    public $calls = [];

    /** @var bool[] */
    public $loadedTypes = [];

    public function testWarnsAboutSlowIsTypeOfForLazySchema() : void
    {
        // isTypeOf used to resolve runtime type for Interface
        $petType = new InterfaceType([
            'name'   => 'Pet',
            'fields' => static function () {
                return [
                    'name' => ['type' => Type::string()],
                ];
            },
        ]);

        // Added to interface type when defined
        $dogType = new ObjectType([
            'name'       => 'Dog',
            'interfaces' => [$petType],
            'isTypeOf'   => static function ($obj) {
                return $obj instanceof Dog;
            },
            'fields'     => static function () {
                return [
                    'name'  => ['type' => Type::string()],
                    'woofs' => ['type' => Type::boolean()],
                ];
            },
        ]);

        $catType = new ObjectType([
            'name'       => 'Cat',
            'interfaces' => [$petType],
            'isTypeOf'   => static function ($obj) {
                return $obj instanceof Cat;
            },
            'fields'     => static function () {
                return [
                    'name'  => ['type' => Type::string()],
                    'meows' => ['type' => Type::boolean()],
                ];
            },
        ]);

        $schema = new Schema([
            'query'      => new ObjectType([
                'name'   => 'Query',
                'fields' => [
                    'pets' => [
                        'type'    => Type::listOf($petType),
                        'resolve' => static function () {
                            return [new Dog('Odie', true), new Cat('Garfield', false)];
                        },
                    ],
                ],
            ]),
            'types'      => [$catType, $dogType],
            'typeLoader' => static function ($name) use ($dogType, $petType, $catType) {
                switch ($name) {
                    case 'Dog':
                        return $dogType;
                    case 'Pet':
                        return $petType;
                    case 'Cat':
                        return $catType;
                }
            },
        ]);

        $query = '{
          pets {
            name
            ... on Dog {
              woofs
            }
            ... on Cat {
              meows
            }
          }
        }';

        $expected = new ExecutionResult([
            'pets' => [
                ['name' => 'Odie', 'woofs' => true],
                ['name' => 'Garfield', 'meows' => false],
            ],
        ]);

        Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
        $result = Executor::execute($schema, Parser::parse($query));
        self::assertEquals($expected, $result);

        Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
        $result = Executor::execute($schema, Parser::parse($query));
        self::assertEquals(1, count($result->errors));
        self::assertInstanceOf(Error::class, $result->errors[0]->getPrevious());

        self::assertEquals(
            'GraphQL Interface Type `Pet` returned `null` from its `resolveType` function for value: instance of ' .
            'GraphQL\Tests\Executor\TestClasses\Dog. Switching to slow resolution method using `isTypeOf` of all possible ' .
            'implementations. It requires full schema scan and degrades query performance significantly.  ' .
            'Make sure your `resolveType` always returns valid implementation or throws.',
            $result->errors[0]->getMessage()
        );
    }

    public function testHintsOnConflictingTypeInstancesInDefinitions() : void
    {
        $calls      = [];
        $typeLoader = static function ($name) use (&$calls) {
            $calls[] = $name;
            switch ($name) {
                case 'Test':
                    return new ObjectType([
                        'name'   => 'Test',
                        'fields' => static function () {
                            return [
                                'test' => Type::string(),
                            ];
                        },
                    ]);
                default:
{'fraction_non_alphanumeric': 0.13117621337997376, 'fraction_numerical': 0.0006996064713598601, 'mean_word_length': 1.5306483735339678, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 85, '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': '5551733', 'n_tokens_mistral': 3031, 'n_tokens_neox': 2898, 'n_words': 664}