Completed
Push — 2.7 ( a416a9...c9e41d )
by Luís
26s queued 20s
created

testAbstractSchemaNameSupportsClassnamesWithLeadingBackslash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Doctrine\Tests\ORM\Query;
4
5
use Doctrine\ORM\Query;
6
use Doctrine\ORM\Query\Lexer;
7
use Doctrine\ORM\Query\Parser;
8
use Doctrine\ORM\Query\QueryException;
9
use Doctrine\Tests\Models\CMS\CmsUser;
10
use Doctrine\Tests\OrmTestCase;
11
12
class ParserTest extends OrmTestCase
13
{
14
15
    /**
16
     * @covers \Doctrine\ORM\Query\Parser::AbstractSchemaName
17
     * @group DDC-3715
18
     */
19
    public function testAbstractSchemaNameSupportsFQCN()
20
    {
21
        $parser = $this->createParser(CmsUser::class);
22
23
        $this->assertEquals(CmsUser::class, $parser->AbstractSchemaName());
24
    }
25
26
    /**
27
     * @covers Doctrine\ORM\Query\Parser::AbstractSchemaName
28
     * @group DDC-3715
29
     */
30
    public function testAbstractSchemaNameSupportsClassnamesWithLeadingBackslash()
31
    {
32
        $parser = $this->createParser('\\' . CmsUser::class);
33
34
        $this->assertEquals('\\' . CmsUser::class, $parser->AbstractSchemaName());
35
    }
36
37
    /**
38
     * @covers \Doctrine\ORM\Query\Parser::AbstractSchemaName
39
     * @group DDC-3715
40
     */
41
    public function testAbstractSchemaNameSupportsIdentifier()
42
    {
43
        $parser = $this->createParser(\stdClass::class);
44
45
        $this->assertEquals(\stdClass::class, $parser->AbstractSchemaName());
46
    }
47
48
    /**
49
     * @covers \Doctrine\ORM\Query\Parser::AbstractSchemaName
50
     * @group DDC-3715
51
     */
52
    public function testAbstractSchemaNameSupportsNamespaceAlias()
53
    {
54
        $parser = $this->createParser('CMS:CmsUser');
55
56
        $parser->getEntityManager()->getConfiguration()->addEntityNamespace('CMS', 'Doctrine\Tests\Models\CMS');
57
58
        $this->assertEquals(CmsUser::class, $parser->AbstractSchemaName());
59
    }
60
61
    /**
62
     * @covers \Doctrine\ORM\Query\Parser::AbstractSchemaName
63
     * @group DDC-3715
64
     */
65
    public function testAbstractSchemaNameSupportsNamespaceAliasWithRelativeClassname()
66
    {
67
        $parser = $this->createParser('Model:CMS\CmsUser');
68
69
        $parser->getEntityManager()->getConfiguration()->addEntityNamespace('Model', 'Doctrine\Tests\Models');
70
71
        $this->assertEquals(CmsUser::class, $parser->AbstractSchemaName());
72
    }
73
74
    /**
75
     * @dataProvider validMatches
76
     * @covers Doctrine\ORM\Query\Parser::match
77
     * @group DDC-3701
78
     */
79
    public function testMatch($expectedToken, $inputString)
80
    {
81
        $parser = $this->createParser($inputString);
82
83
        $parser->match($expectedToken); // throws exception if not matched
84
85
        $this->addToAssertionCount(1);
86
    }
87
88
    /**
89
     * @dataProvider invalidMatches
90
     * @covers Doctrine\ORM\Query\Parser::match
91
     * @group DDC-3701
92
     */
93
    public function testMatchFailure($expectedToken, $inputString)
94
    {
95
        $this->expectException(QueryException::class);
96
97
        $parser = $this->createParser($inputString);
98
99
        $parser->match($expectedToken);
100
    }
101
102
    public function validMatches()
103
    {
104
        /*
105
         * This only covers the special case handling in the Parser that some
106
         * tokens that are *not* T_IDENTIFIER are accepted as well when matching
107
         * identifiers.
108
         *
109
         * The basic checks that tokens are classified correctly do not belong here
110
         * but in LexerTest.
111
         */
112
        return [
113
            [Lexer::T_WHERE, 'where'], // keyword
114
            [Lexer::T_DOT, '.'], // token that cannot be an identifier
115
            [Lexer::T_IDENTIFIER, 'someIdentifier'],
116
            [Lexer::T_IDENTIFIER, 'from'], // also a terminal string (the "FROM" keyword) as in DDC-505
117
            [Lexer::T_IDENTIFIER, 'comma']
118
            // not even a terminal string, but the name of a constant in the Lexer (whitebox test)
119
        ];
120
    }
121
122
    public function invalidMatches()
123
    {
124
        return [
125
            [Lexer::T_DOT, 'ALL'], // ALL is a terminal string (reserved keyword) and also possibly an identifier
126
            [Lexer::T_DOT, ','], // "," is a token on its own, but cannot be used as identifier
127
            [Lexer::T_WHERE, 'WITH'], // as in DDC-3697
128
            [Lexer::T_WHERE, '.'],
129
130
            // The following are qualified or aliased names and must not be accepted where only an Identifier is expected
131
            [Lexer::T_IDENTIFIER, '\\Some\\Class'],
132
            [Lexer::T_IDENTIFIER, 'Some\\Class'],
133
            [Lexer::T_IDENTIFIER, 'Some:Name'],
134
        ];
135
    }
136
137
    /**
138
     * PHP 7.4 would fail with Notice: Trying to access array offset on value of type null.
139
     *
140
     * @see https://github.com/doctrine/orm/pull/7934
141
     *
142
     * @group GH7934
143
     */
144
    public function testNullLookahead() : void
145
    {
146
        $query = new Query($this->_getTestEntityManager());
147
        $query->setDQL('SELECT CURRENT_TIMESTAMP()');
148
149
        $parser = new Parser($query);
150
151
        $this->expectException(QueryException::class);
152
        $parser->match(Lexer::T_SELECT);
153
    }
154
155
    private function createParser($dql)
156
    {
157
        $query = new Query($this->_getTestEntityManager());
158
        $query->setDQL($dql);
159
160
        $parser = new Parser($query);
161
        $parser->getLexer()->moveNext();
162
163
        return $parser;
164
    }
165
}
166