1<?php
2
3namespace Doctrine\Tests\Common\Lexer;
4
5class AbstractLexerTest extends \PHPUnit_Framework_TestCase
6{
7    /**
8     * @var ConcreteLexer
9     */
10    private $concreteLexer;
11
12    public function setUp()
13    {
14        $this->concreteLexer = new ConcreteLexer();
15    }
16
17    public function dataProvider()
18    {
19        return array(
20            array(
21                'price=10',
22                array(
23                    array(
24                        'value' => 'price',
25                        'type' => 'string',
26                        'position' => 0,
27                    ),
28                    array(
29                        'value' => '=',
30                        'type' => 'operator',
31                        'position' => 5,
32                    ),
33                    array(
34                        'value' => 10,
35                        'type' => 'int',
36                        'position' => 6,
37                    ),
38                ),
39            ),
40        );
41    }
42
43    public function testResetPeek()
44    {
45        $expectedTokens = array(
46            array(
47                'value' => 'price',
48                'type' => 'string',
49                'position' => 0,
50            ),
51            array(
52                'value' => '=',
53                'type' => 'operator',
54                'position' => 5,
55            ),
56            array(
57                'value' => 10,
58                'type' => 'int',
59                'position' => 6,
60            ),
61        );
62
63        $this->concreteLexer->setInput('price=10');
64
65        $this->assertEquals($expectedTokens[0], $this->concreteLexer->peek());
66        $this->assertEquals($expectedTokens[1], $this->concreteLexer->peek());
67        $this->concreteLexer->resetPeek();
68        $this->assertEquals($expectedTokens[0], $this->concreteLexer->peek());
69    }
70
71    public function testResetPosition()
72    {
73        $expectedTokens = array(
74            array(
75                'value' => 'price',
76                'type' => 'string',
77                'position' => 0,
78            ),
79            array(
80                'value' => '=',
81                'type' => 'operator',
82                'position' => 5,
83            ),
84            array(
85                'value' => 10,
86                'type' => 'int',
87                'position' => 6,
88            ),
89        );
90
91        $this->concreteLexer->setInput('price=10');
92        $this->assertNull($this->concreteLexer->lookahead);
93
94        $this->assertTrue($this->concreteLexer->moveNext());
95        $this->assertEquals($expectedTokens[0], $this->concreteLexer->lookahead);
96
97        $this->assertTrue($this->concreteLexer->moveNext());
98        $this->assertEquals($expectedTokens[1], $this->concreteLexer->lookahead);
99
100        $this->concreteLexer->resetPosition(0);
101
102        $this->assertTrue($this->concreteLexer->moveNext());
103        $this->assertEquals($expectedTokens[0], $this->concreteLexer->lookahead);
104    }
105
106    /**
107     * @dataProvider dataProvider
108     *
109     * @param $input
110     * @param $expectedTokens
111     */
112    public function testMoveNext($input, $expectedTokens)
113    {
114        $this->concreteLexer->setInput($input);
115        $this->assertNull($this->concreteLexer->lookahead);
116
117        for ($i = 0; $i < count($expectedTokens); $i++) {
118            $this->assertTrue($this->concreteLexer->moveNext());
119            $this->assertEquals($expectedTokens[$i], $this->concreteLexer->lookahead);
120        }
121
122        $this->assertFalse($this->concreteLexer->moveNext());
123        $this->assertNull($this->concreteLexer->lookahead);
124    }
125
126    public function testSkipUntil()
127    {
128        $this->concreteLexer->setInput('price=10');
129
130        $this->assertTrue($this->concreteLexer->moveNext());
131        $this->concreteLexer->skipUntil('operator');
132
133        $this->assertEquals(
134            array(
135                'value' => '=',
136                'type' => 'operator',
137                'position' => 5,
138            ),
139            $this->concreteLexer->lookahead
140        );
141    }
142
143    public function testUtf8Mismatch()
144    {
145        $this->concreteLexer->setInput("\xE9=10");
146
147        $this->assertTrue($this->concreteLexer->moveNext());
148
149        $this->assertEquals(
150            array(
151                'value' => "\xE9=10",
152                'type' => 'string',
153                'position' => 0,
154            ),
155            $this->concreteLexer->lookahead
156        );
157    }
158
159    /**
160     * @dataProvider dataProvider
161     *
162     * @param $input
163     * @param $expectedTokens
164     */
165    public function testPeek($input, $expectedTokens)
166    {
167        $this->concreteLexer->setInput($input);
168        foreach ($expectedTokens as $expectedToken) {
169            $this->assertEquals($expectedToken, $this->concreteLexer->peek());
170        }
171
172        $this->assertNull($this->concreteLexer->peek());
173    }
174
175    /**
176     * @dataProvider dataProvider
177     *
178     * @param $input
179     * @param $expectedTokens
180     */
181    public function testGlimpse($input, $expectedTokens)
182    {
183        $this->concreteLexer->setInput($input);
184
185        foreach ($expectedTokens as $expectedToken) {
186            $this->assertEquals($expectedToken, $this->concreteLexer->glimpse());
187            $this->concreteLexer->moveNext();
188        }
189
190        $this->assertNull($this->concreteLexer->peek());
191    }
192
193    public function inputUntilPositionDataProvider()
194    {
195        return array(
196            array('price=10', 5, 'price'),
197        );
198    }
199
200    /**
201     * @dataProvider inputUntilPositionDataProvider
202     *
203     * @param $input
204     * @param $position
205     * @param $expectedInput
206     */
207    public function testGetInputUntilPosition($input, $position, $expectedInput)
208    {
209        $this->concreteLexer->setInput($input);
210
211        $this->assertSame($expectedInput, $this->concreteLexer->getInputUntilPosition($position));
212    }
213
214    /**
215     * @dataProvider dataProvider
216     *
217     * @param $input
218     * @param $expectedTokens
219     */
220    public function testIsNextToken($input, $expectedTokens)
221    {
222        $this->concreteLexer->setInput($input);
223
224        $this->concreteLexer->moveNext();
225        for ($i = 0; $i < count($expectedTokens); $i++) {
226            $this->assertTrue($this->concreteLexer->isNextToken($expectedTokens[$i]['type']));
227            $this->concreteLexer->moveNext();
228        }
229    }
230
231    /**
232     * @dataProvider dataProvider
233     *
234     * @param $input
235     * @param $expectedTokens
236     */
237    public function testIsNextTokenAny($input, $expectedTokens)
238    {
239        $allTokenTypes = array_map(function ($token) {
240            return $token['type'];
241        }, $expectedTokens);
242
243        $this->concreteLexer->setInput($input);
244
245        $this->concreteLexer->moveNext();
246        for ($i = 0; $i < count($expectedTokens); $i++) {
247            $this->assertTrue($this->concreteLexer->isNextTokenAny(array($expectedTokens[$i]['type'])));
248            $this->assertTrue($this->concreteLexer->isNextTokenAny($allTokenTypes));
249            $this->concreteLexer->moveNext();
250        }
251    }
252
253    public function testGetLiteral()
254    {
255        $this->assertSame('Doctrine\Tests\Common\Lexer\ConcreteLexer::INT', $this->concreteLexer->getLiteral('int'));
256        $this->assertSame('fake_token', $this->concreteLexer->getLiteral('fake_token'));
257    }
258
259    public function testIsA()
260    {
261        $this->assertTrue($this->concreteLexer->isA(11, 'int'));
262        $this->assertTrue($this->concreteLexer->isA(1.1, 'int'));
263        $this->assertTrue($this->concreteLexer->isA('=', 'operator'));
264        $this->assertTrue($this->concreteLexer->isA('>', 'operator'));
265        $this->assertTrue($this->concreteLexer->isA('<', 'operator'));
266        $this->assertTrue($this->concreteLexer->isA('fake_text', 'string'));
267    }
268}
269