packages/sql-parser/tests/Unit/Lexer/CursorTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Lexer;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\Small;
9use PHPUnit\Framework\TestCase;
10use SqlParser\Lexer\Cursor;
11
12#[CoversClass(Cursor::class)]
13#[Small]
14final class CursorTest extends TestCase
15{
16    public function testEof(): void
17    {
18        $cursor = new Cursor('ab');
19        $cursor->take(2);
20
21        self::assertTrue($cursor->eof());
22        self::assertFalse((new Cursor('a'))->eof());
23    }
24
25    public function testPeek(): void
26    {
27        $cursor = new Cursor('abc');
28
29        self::assertSame('a', $cursor->peek());
30        self::assertSame('c', $cursor->peek(2));
31        self::assertSame('', $cursor->peek(3));
32    }
33
34    public function testOffset(): void
35    {
36        $cursor = new Cursor('abc');
37        $cursor->take(2);
38
39        self::assertSame(2, $cursor->offset());
40    }
41
42    public function testSeek(): void
43    {
44        $cursor = new Cursor('abc');
45        $cursor->seek(1);
46
47        self::assertSame('b', $cursor->peek());
48    }
49
50    public function testStartsWith(): void
51    {
52        $cursor = new Cursor('SELECT');
53        $cursor->take(2);
54
55        self::assertTrue($cursor->startsWith('LE'));
56        self::assertFalse($cursor->startsWith('le'));
57    }
58
59    public function testStartsWithIgnoringCase(): void
60    {
61        self::assertTrue((new Cursor('Select'))->startsWithIgnoringCase('SEL'));
62        self::assertFalse((new Cursor('Select'))->startsWithIgnoringCase('SET'));
63    }
64
65    public function testTake(): void
66    {
67        $cursor = new Cursor('abc');
68
69        self::assertSame('ab', $cursor->take(2));
70        self::assertSame('c', $cursor->take(5));
71        self::assertSame(3, $cursor->offset());
72    }
73
74    public function testMatch(): void
75    {
76        $cursor = new Cursor('abc123');
77
78        self::assertSame('abc', $cursor->match('[a-z]+'));
79        self::assertNull($cursor->match('[a-z]+'));
80        self::assertSame('123', $cursor->match('[0-9~]+'));
81    }
82
83    public function testLookingAt(): void
84    {
85        $cursor = new Cursor('abc');
86
87        self::assertTrue($cursor->lookingAt('ab'));
88        self::assertFalse($cursor->lookingAt('bc'));
89        self::assertSame(0, $cursor->offset());
90    }
91
92    public function testSkipPastOrEnd(): void
93    {
94        $cursor = new Cursor('a*/b');
95
96        self::assertTrue($cursor->skipPastOrEnd('*/'));
97        self::assertSame(3, $cursor->offset());
98        self::assertFalse($cursor->skipPastOrEnd('*/'));
99        self::assertTrue($cursor->eof());
100    }
101
102    public function testTakeQuoted(): void
103    {
104        $cursor = new Cursor("'it''s' rest");
105
106        self::assertSame("'it''s'", $cursor->takeQuoted("'"));
107        self::assertSame(' rest', $cursor->take(5));
108    }
109
110    public function testTakeQuotedWithBackslashEscapes(): void
111    {
112        $cursor = new Cursor("'a\\'b' x");
113
114        self::assertSame("'a\\'b'", $cursor->takeQuoted("'", true));
115        self::assertNull((new Cursor("'open"))->takeQuoted("'"));
116        self::assertNull((new Cursor("'open\\'"))->takeQuoted("'", true));
117    }
118}
119