File: ParserTest.php

package info (click to toggle)
doctrine 3.5.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 11,552 kB
  • sloc: php: 108,302; xml: 1,340; makefile: 35; sh: 14
file content (130 lines) | stat: -rw-r--r-- 4,298 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Query;

use Doctrine\ORM\Query;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\Query\TokenType;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\OrmTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RequiresPhpunit;
use stdClass;

#[RequiresPhpunit('< 12')]
class ParserTest extends OrmTestCase
{
    #[Group('DDC-3715')]
    public function testAbstractSchemaNameSupportsFQCN(): void
    {
        $parser = $this->createParser(CmsUser::class);

        self::assertEquals(CmsUser::class, $parser->AbstractSchemaName());
    }

    #[Group('DDC-3715')]
    public function testAbstractSchemaNameSupportsClassnamesWithLeadingBackslash(): void
    {
        $parser = $this->createParser('\\' . CmsUser::class);

        self::assertEquals('\\' . CmsUser::class, $parser->AbstractSchemaName());
    }

    #[Group('DDC-3715')]
    public function testAbstractSchemaNameSupportsIdentifier(): void
    {
        $parser = $this->createParser(stdClass::class);

        self::assertEquals(stdClass::class, $parser->AbstractSchemaName());
    }

    #[DataProvider('validMatches')]
    #[Group('DDC-3701')]
    #[DoesNotPerformAssertions]
    public function testMatch(TokenType $expectedToken, string $inputString): void
    {
        $parser = $this->createParser($inputString);

        $parser->match($expectedToken); // throws exception if not matched
    }

    #[DataProvider('invalidMatches')]
    #[Group('DDC-3701')]
    public function testMatchFailure(TokenType $expectedToken, string $inputString): void
    {
        $this->expectException(QueryException::class);

        $parser = $this->createParser($inputString);

        $parser->match($expectedToken);
    }

    /** @phpstan-return list<array{int, string}> */
    public static function validMatches(): array
    {
        /*
         * This only covers the special case handling in the Parser that some
         * tokens that are *not* T_IDENTIFIER are accepted as well when matching
         * identifiers.
         *
         * The basic checks that tokens are classified correctly do not belong here
         * but in LexerTest.
         */
        return [
            [TokenType::T_WHERE, 'where'], // keyword
            [TokenType::T_DOT, '.'], // token that cannot be an identifier
            [TokenType::T_IDENTIFIER, 'someIdentifier'],
            [TokenType::T_IDENTIFIER, 'from'], // also a terminal string (the "FROM" keyword) as in DDC-505
            [TokenType::T_IDENTIFIER, 'comma'],
            // not even a terminal string, but the name of a constant in the Lexer (whitebox test)
        ];
    }

    /** @phpstan-return list<array{int, string}> */
    public static function invalidMatches(): array
    {
        return [
            [TokenType::T_DOT, 'ALL'], // ALL is a terminal string (reserved keyword) and also possibly an identifier
            [TokenType::T_DOT, ','], // "," is a token on its own, but cannot be used as identifier
            [TokenType::T_WHERE, 'WITH'], // as in DDC-3697
            [TokenType::T_WHERE, '.'],

            // The following are qualified or aliased names and must not be accepted where only an Identifier is expected
            [TokenType::T_IDENTIFIER, '\\Some\\Class'],
            [TokenType::T_IDENTIFIER, 'Some\\Class'],
        ];
    }

    /**
     * PHP 7.4 would fail with Notice: Trying to access array offset on value of type null.
     *
     * @see https://github.com/doctrine/orm/pull/7934
     */
    #[Group('GH7934')]
    public function testNullLookahead(): void
    {
        $query = new Query($this->getTestEntityManager());
        $query->setDQL('SELECT CURRENT_TIMESTAMP()');

        $parser = new Parser($query);

        $this->expectException(QueryException::class);
        $parser->match(TokenType::T_SELECT);
    }

    private function createParser(string $dql): Parser
    {
        $query = new Query($this->getTestEntityManager());
        $query->setDQL($dql);

        $parser = new Parser($query);
        $parser->getLexer()->moveNext();

        return $parser;
    }
}